xref: /openbmc/linux/arch/openrisc/lib/string.S (revision 2874c5fd)
12874c5fdSThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-or-later */
2224cd129SJonas Bonn/*
3224cd129SJonas Bonn * OpenRISC string.S
4224cd129SJonas Bonn *
5224cd129SJonas Bonn * Linux architectural port borrowing liberally from similar works of
6224cd129SJonas Bonn * others.  All original copyrights apply as per the original source
7224cd129SJonas Bonn * declaration.
8224cd129SJonas Bonn *
9224cd129SJonas Bonn * Modifications for the OpenRISC architecture:
10224cd129SJonas Bonn * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
11224cd129SJonas Bonn * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
12224cd129SJonas Bonn */
13224cd129SJonas Bonn
14224cd129SJonas Bonn#include <linux/linkage.h>
15224cd129SJonas Bonn#include <asm/errno.h>
16224cd129SJonas Bonn
17224cd129SJonas Bonn	/*
18224cd129SJonas Bonn	 * this can be optimized by doing gcc inline assemlby with
19224cd129SJonas Bonn	 * proper constraints (no need to save args registers...)
20224cd129SJonas Bonn	 *
21224cd129SJonas Bonn	 */
22224cd129SJonas Bonn
23224cd129SJonas Bonn
24224cd129SJonas Bonn/*
25224cd129SJonas Bonn *
26224cd129SJonas Bonn * int __copy_tofrom_user(void *to, const void *from, unsigned long size);
27224cd129SJonas Bonn *
28224cd129SJonas Bonn * NOTE: it returns number of bytes NOT copied !!!
29224cd129SJonas Bonn *
30224cd129SJonas Bonn */
31224cd129SJonas Bonn	.global	__copy_tofrom_user
32224cd129SJonas Bonn__copy_tofrom_user:
33224cd129SJonas Bonn	l.addi  r1,r1,-12
34224cd129SJonas Bonn	l.sw    0(r1),r6
35224cd129SJonas Bonn	l.sw    4(r1),r4
36224cd129SJonas Bonn	l.sw    8(r1),r3
37224cd129SJonas Bonn
38224cd129SJonas Bonn	l.addi  r11,r5,0
39224cd129SJonas Bonn2:  	l.sfeq  r11,r0
40224cd129SJonas Bonn	l.bf    1f
41224cd129SJonas Bonn	l.addi  r11,r11,-1
42224cd129SJonas Bonn8:    	l.lbz   r6,0(r4)
43224cd129SJonas Bonn9:    	l.sb    0(r3),r6
44224cd129SJonas Bonn	l.addi  r3,r3,1
45224cd129SJonas Bonn	l.j     2b
46224cd129SJonas Bonn	l.addi  r4,r4,1
47224cd129SJonas Bonn1:
48224cd129SJonas Bonn	l.addi  r11,r11,1               // r11 holds the return value
49224cd129SJonas Bonn
50224cd129SJonas Bonn	l.lwz   r6,0(r1)
51224cd129SJonas Bonn	l.lwz   r4,4(r1)
52224cd129SJonas Bonn	l.lwz   r3,8(r1)
53224cd129SJonas Bonn	l.jr    r9
54224cd129SJonas Bonn	l.addi  r1,r1,12
55224cd129SJonas Bonn
56224cd129SJonas Bonn	.section .fixup, "ax"
57224cd129SJonas Bonn99:
58224cd129SJonas Bonn		l.j     1b
59224cd129SJonas Bonn		l.nop
60224cd129SJonas Bonn	.previous
61224cd129SJonas Bonn
62224cd129SJonas Bonn	.section __ex_table, "a"
63224cd129SJonas Bonn		.long 8b, 99b		// read fault
64224cd129SJonas Bonn		.long 9b, 99b		// write fault
65224cd129SJonas Bonn	.previous
66224cd129SJonas Bonn
67224cd129SJonas Bonn/*
68224cd129SJonas Bonn * unsigned long clear_user(void *addr, unsigned long size) ;
69224cd129SJonas Bonn *
70224cd129SJonas Bonn * NOTE: it returns number of bytes NOT cleared !!!
71224cd129SJonas Bonn */
72224cd129SJonas Bonn	.global	__clear_user
73224cd129SJonas Bonn__clear_user:
74224cd129SJonas Bonn	l.addi  r1,r1,-8
75224cd129SJonas Bonn	l.sw    0(r1),r4
76224cd129SJonas Bonn	l.sw    4(r1),r3
77224cd129SJonas Bonn
78224cd129SJonas Bonn2:	l.sfeq	r4,r0
79224cd129SJonas Bonn	l.bf	1f
80224cd129SJonas Bonn	l.addi	r4,r4,-1
81224cd129SJonas Bonn9:	l.sb	0(r3),r0
82224cd129SJonas Bonn	l.j	2b
83224cd129SJonas Bonn	l.addi  r3,r3,1
84224cd129SJonas Bonn
85224cd129SJonas Bonn1:
86224cd129SJonas Bonn	l.addi  r11,r4,1
87224cd129SJonas Bonn
88224cd129SJonas Bonn	l.lwz	r4,0(r1)
89224cd129SJonas Bonn	l.lwz	r3,4(r1)
90224cd129SJonas Bonn	l.jr	r9
91224cd129SJonas Bonn	l.addi	r1,r1,8
92224cd129SJonas Bonn
93224cd129SJonas Bonn	.section .fixup, "ax"
94224cd129SJonas Bonn99:
95224cd129SJonas Bonn		l.j     1b
96224cd129SJonas Bonn		l.nop
97224cd129SJonas Bonn	.previous
98224cd129SJonas Bonn
99224cd129SJonas Bonn	.section __ex_table, "a"
100224cd129SJonas Bonn		.long 9b, 99b		// write fault
101224cd129SJonas Bonn	.previous
102