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