18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * OpenRISC string.S 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Linux architectural port borrowing liberally from similar works of 68c2ecf20Sopenharmony_ci * others. All original copyrights apply as per the original source 78c2ecf20Sopenharmony_ci * declaration. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Modifications for the OpenRISC architecture: 108c2ecf20Sopenharmony_ci * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 118c2ecf20Sopenharmony_ci * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/linkage.h> 158c2ecf20Sopenharmony_ci#include <asm/errno.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci /* 188c2ecf20Sopenharmony_ci * this can be optimized by doing gcc inline assemlby with 198c2ecf20Sopenharmony_ci * proper constraints (no need to save args registers...) 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * int __copy_tofrom_user(void *to, const void *from, unsigned long size); 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * NOTE: it returns number of bytes NOT copied !!! 298c2ecf20Sopenharmony_ci * 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_ci .global __copy_tofrom_user 328c2ecf20Sopenharmony_ci__copy_tofrom_user: 338c2ecf20Sopenharmony_ci l.addi r1,r1,-12 348c2ecf20Sopenharmony_ci l.sw 0(r1),r6 358c2ecf20Sopenharmony_ci l.sw 4(r1),r4 368c2ecf20Sopenharmony_ci l.sw 8(r1),r3 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci l.addi r11,r5,0 398c2ecf20Sopenharmony_ci2: l.sfeq r11,r0 408c2ecf20Sopenharmony_ci l.bf 1f 418c2ecf20Sopenharmony_ci l.addi r11,r11,-1 428c2ecf20Sopenharmony_ci8: l.lbz r6,0(r4) 438c2ecf20Sopenharmony_ci9: l.sb 0(r3),r6 448c2ecf20Sopenharmony_ci l.addi r3,r3,1 458c2ecf20Sopenharmony_ci l.j 2b 468c2ecf20Sopenharmony_ci l.addi r4,r4,1 478c2ecf20Sopenharmony_ci1: 488c2ecf20Sopenharmony_ci l.addi r11,r11,1 // r11 holds the return value 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci l.lwz r6,0(r1) 518c2ecf20Sopenharmony_ci l.lwz r4,4(r1) 528c2ecf20Sopenharmony_ci l.lwz r3,8(r1) 538c2ecf20Sopenharmony_ci l.jr r9 548c2ecf20Sopenharmony_ci l.addi r1,r1,12 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci .section .fixup, "ax" 578c2ecf20Sopenharmony_ci99: 588c2ecf20Sopenharmony_ci l.j 1b 598c2ecf20Sopenharmony_ci l.nop 608c2ecf20Sopenharmony_ci .previous 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci .section __ex_table, "a" 638c2ecf20Sopenharmony_ci .long 8b, 99b // read fault 648c2ecf20Sopenharmony_ci .long 9b, 99b // write fault 658c2ecf20Sopenharmony_ci .previous 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* 688c2ecf20Sopenharmony_ci * unsigned long clear_user(void *addr, unsigned long size) ; 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * NOTE: it returns number of bytes NOT cleared !!! 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ci .global __clear_user 738c2ecf20Sopenharmony_ci__clear_user: 748c2ecf20Sopenharmony_ci l.addi r1,r1,-8 758c2ecf20Sopenharmony_ci l.sw 0(r1),r4 768c2ecf20Sopenharmony_ci l.sw 4(r1),r3 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci2: l.sfeq r4,r0 798c2ecf20Sopenharmony_ci l.bf 1f 808c2ecf20Sopenharmony_ci l.addi r4,r4,-1 818c2ecf20Sopenharmony_ci9: l.sb 0(r3),r0 828c2ecf20Sopenharmony_ci l.j 2b 838c2ecf20Sopenharmony_ci l.addi r3,r3,1 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci1: 868c2ecf20Sopenharmony_ci l.addi r11,r4,1 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci l.lwz r4,0(r1) 898c2ecf20Sopenharmony_ci l.lwz r3,4(r1) 908c2ecf20Sopenharmony_ci l.jr r9 918c2ecf20Sopenharmony_ci l.addi r1,r1,8 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci .section .fixup, "ax" 948c2ecf20Sopenharmony_ci99: 958c2ecf20Sopenharmony_ci l.j 1b 968c2ecf20Sopenharmony_ci l.nop 978c2ecf20Sopenharmony_ci .previous 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci .section __ex_table, "a" 1008c2ecf20Sopenharmony_ci .long 9b, 99b // write fault 1018c2ecf20Sopenharmony_ci .previous 102