xref: /openbmc/linux/arch/sparc/lib/copy_user.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds/* copy_user.S: Sparc optimized copy_from_user and copy_to_user code.
31da177e4SLinus Torvalds *
41da177e4SLinus Torvalds *  Copyright(C) 1995 Linus Torvalds
51da177e4SLinus Torvalds *  Copyright(C) 1996 David S. Miller
61da177e4SLinus Torvalds *  Copyright(C) 1996 Eddie C. Dost
71da177e4SLinus Torvalds *  Copyright(C) 1996,1998 Jakub Jelinek
81da177e4SLinus Torvalds *
91da177e4SLinus Torvalds * derived from:
101da177e4SLinus Torvalds *	e-mail between David and Eddie.
111da177e4SLinus Torvalds *
121da177e4SLinus Torvalds * Returns 0 if successful, otherwise count of bytes not copied yet
131da177e4SLinus Torvalds */
141da177e4SLinus Torvalds
15*4cdb71b6SMasahiro Yamada#include <linux/export.h>
161da177e4SLinus Torvalds#include <asm/ptrace.h>
171da177e4SLinus Torvalds#include <asm/asmmacro.h>
181da177e4SLinus Torvalds#include <asm/page.h>
193a1d5c84SDavid S. Miller#include <asm/thread_info.h>
201da177e4SLinus Torvalds
211da177e4SLinus Torvalds/* Work around cpp -rob */
221da177e4SLinus Torvalds#define ALLOC #alloc
231da177e4SLinus Torvalds#define EXECINSTR #execinstr
24c4da8e0dSAl Viro
25c4da8e0dSAl Viro#define EX_ENTRY(l1, l2)			\
26c4da8e0dSAl Viro	.section __ex_table,ALLOC;		\
27c4da8e0dSAl Viro	.align	4;				\
28c4da8e0dSAl Viro	.word	l1, l2;				\
29c4da8e0dSAl Viro	.text;
30c4da8e0dSAl Viro
311da177e4SLinus Torvalds#define EX(x,y,a,b) 				\
321da177e4SLinus Torvalds98: 	x,y;					\
331da177e4SLinus Torvalds	.section .fixup,ALLOC,EXECINSTR;	\
341da177e4SLinus Torvalds	.align	4;				\
35c4da8e0dSAl Viro99:	retl;					\
36c4da8e0dSAl Viro	 a, b, %o0;				\
37c4da8e0dSAl Viro	EX_ENTRY(98b, 99b)
381da177e4SLinus Torvalds
391da177e4SLinus Torvalds#define EX2(x,y,c,d,e,a,b) 			\
401da177e4SLinus Torvalds98: 	x,y;					\
411da177e4SLinus Torvalds	.section .fixup,ALLOC,EXECINSTR;	\
421da177e4SLinus Torvalds	.align	4;				\
431da177e4SLinus Torvalds99:	c, d, e;				\
44c4da8e0dSAl Viro	retl;					\
45c4da8e0dSAl Viro	 a, b, %o0;				\
46c4da8e0dSAl Viro	EX_ENTRY(98b, 99b)
471da177e4SLinus Torvalds
481da177e4SLinus Torvalds#define EXO2(x,y) 				\
491da177e4SLinus Torvalds98: 	x, y;					\
50c4da8e0dSAl Viro	EX_ENTRY(98b, 97f)
511da177e4SLinus Torvalds
52c4da8e0dSAl Viro#define LD(insn, src, offset, reg, label)	\
53c4da8e0dSAl Viro98:	insn [%src + (offset)], %reg;		\
54c4da8e0dSAl Viro	.section .fixup,ALLOC,EXECINSTR;	\
55c4da8e0dSAl Viro99:	ba	label;				\
56c4da8e0dSAl Viro	 mov	offset, %g5;			\
57c4da8e0dSAl Viro	EX_ENTRY(98b, 99b)
581da177e4SLinus Torvalds
59c4da8e0dSAl Viro#define ST(insn, dst, offset, reg, label)	\
60c4da8e0dSAl Viro98:	insn %reg, [%dst + (offset)];		\
61c4da8e0dSAl Viro	.section .fixup,ALLOC,EXECINSTR;	\
62c4da8e0dSAl Viro99:	ba	label;				\
63c4da8e0dSAl Viro	 mov	offset, %g5;			\
64c4da8e0dSAl Viro	EX_ENTRY(98b, 99b)
651da177e4SLinus Torvalds
661da177e4SLinus Torvalds/* Both these macros have to start with exactly the same insn */
67c4da8e0dSAl Viro/* left: g7 + (g1 % 128) - offset */
681da177e4SLinus Torvalds#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
69c4da8e0dSAl Viro	LD(ldd, src, offset + 0x00, t0, bigchunk_fault)	\
70c4da8e0dSAl Viro	LD(ldd, src, offset + 0x08, t2, bigchunk_fault)	\
71c4da8e0dSAl Viro	LD(ldd, src, offset + 0x10, t4, bigchunk_fault)	\
72c4da8e0dSAl Viro	LD(ldd, src, offset + 0x18, t6, bigchunk_fault)	\
73c4da8e0dSAl Viro	ST(st, dst, offset + 0x00, t0, bigchunk_fault)	\
74c4da8e0dSAl Viro	ST(st, dst, offset + 0x04, t1, bigchunk_fault)	\
75c4da8e0dSAl Viro	ST(st, dst, offset + 0x08, t2, bigchunk_fault)	\
76c4da8e0dSAl Viro	ST(st, dst, offset + 0x0c, t3, bigchunk_fault)	\
77c4da8e0dSAl Viro	ST(st, dst, offset + 0x10, t4, bigchunk_fault)	\
78c4da8e0dSAl Viro	ST(st, dst, offset + 0x14, t5, bigchunk_fault)	\
79c4da8e0dSAl Viro	ST(st, dst, offset + 0x18, t6, bigchunk_fault)	\
80c4da8e0dSAl Viro	ST(st, dst, offset + 0x1c, t7, bigchunk_fault)
811da177e4SLinus Torvalds
82c4da8e0dSAl Viro/* left: g7 + (g1 % 128) - offset */
831da177e4SLinus Torvalds#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
84c4da8e0dSAl Viro	LD(ldd, src, offset + 0x00, t0, bigchunk_fault)	\
85c4da8e0dSAl Viro	LD(ldd, src, offset + 0x08, t2, bigchunk_fault)	\
86c4da8e0dSAl Viro	LD(ldd, src, offset + 0x10, t4, bigchunk_fault)	\
87c4da8e0dSAl Viro	LD(ldd, src, offset + 0x18, t6, bigchunk_fault)	\
88c4da8e0dSAl Viro	ST(std, dst, offset + 0x00, t0, bigchunk_fault)	\
89c4da8e0dSAl Viro	ST(std, dst, offset + 0x08, t2, bigchunk_fault)	\
90c4da8e0dSAl Viro	ST(std, dst, offset + 0x10, t4, bigchunk_fault)	\
91c4da8e0dSAl Viro	ST(std, dst, offset + 0x18, t6, bigchunk_fault)
921da177e4SLinus Torvalds
93c4da8e0dSAl Viro	.section .fixup,#alloc,#execinstr
94c4da8e0dSAl Virobigchunk_fault:
95c4da8e0dSAl Viro	sub	%g7, %g5, %o0
96c4da8e0dSAl Viro	and	%g1, 127, %g1
97c4da8e0dSAl Viro	retl
98c4da8e0dSAl Viro	 add	%o0, %g1, %o0
99c4da8e0dSAl Viro
100c4da8e0dSAl Viro/* left: offset + 16 + (g1 % 16) */
1011da177e4SLinus Torvalds#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \
102c4da8e0dSAl Viro	LD(ldd, src, -(offset + 0x10), t0, lastchunk_fault)	\
103c4da8e0dSAl Viro	LD(ldd, src, -(offset + 0x08), t2, lastchunk_fault)	\
104c4da8e0dSAl Viro	ST(st, dst, -(offset + 0x10), t0, lastchunk_fault)	\
105c4da8e0dSAl Viro	ST(st, dst, -(offset + 0x0c), t1, lastchunk_fault)	\
106c4da8e0dSAl Viro	ST(st, dst, -(offset + 0x08), t2, lastchunk_fault)	\
107c4da8e0dSAl Viro	ST(st, dst, -(offset + 0x04), t3, lastchunk_fault)
1081da177e4SLinus Torvalds
109c4da8e0dSAl Viro	.section .fixup,#alloc,#execinstr
110c4da8e0dSAl Virolastchunk_fault:
111c4da8e0dSAl Viro	and	%g1, 15, %g1
112c4da8e0dSAl Viro	retl
113c4da8e0dSAl Viro	 sub	%g1, %g5, %o0
114c4da8e0dSAl Viro
115c4da8e0dSAl Viro/* left: o3 + (o2 % 16) - offset */
1161da177e4SLinus Torvalds#define MOVE_HALFCHUNK(src, dst, offset, t0, t1, t2, t3) \
117c4da8e0dSAl Viro	LD(lduh, src, offset + 0x00, t0, halfchunk_fault)	\
118c4da8e0dSAl Viro	LD(lduh, src, offset + 0x02, t1, halfchunk_fault)	\
119c4da8e0dSAl Viro	LD(lduh, src, offset + 0x04, t2, halfchunk_fault)	\
120c4da8e0dSAl Viro	LD(lduh, src, offset + 0x06, t3, halfchunk_fault)	\
121c4da8e0dSAl Viro	ST(sth, dst, offset + 0x00, t0, halfchunk_fault)	\
122c4da8e0dSAl Viro	ST(sth, dst, offset + 0x02, t1, halfchunk_fault)	\
123c4da8e0dSAl Viro	ST(sth, dst, offset + 0x04, t2, halfchunk_fault)	\
124c4da8e0dSAl Viro	ST(sth, dst, offset + 0x06, t3, halfchunk_fault)
1251da177e4SLinus Torvalds
126c4da8e0dSAl Viro/* left: o3 + (o2 % 16) + offset + 2 */
1271da177e4SLinus Torvalds#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \
128c4da8e0dSAl Viro	LD(ldub, src, -(offset + 0x02), t0, halfchunk_fault)	\
129c4da8e0dSAl Viro	LD(ldub, src, -(offset + 0x01), t1, halfchunk_fault)	\
130c4da8e0dSAl Viro	ST(stb, dst, -(offset + 0x02), t0, halfchunk_fault)	\
131c4da8e0dSAl Viro	ST(stb, dst, -(offset + 0x01), t1, halfchunk_fault)
132c4da8e0dSAl Viro
133c4da8e0dSAl Viro	.section .fixup,#alloc,#execinstr
134c4da8e0dSAl Virohalfchunk_fault:
135c4da8e0dSAl Viro	and	%o2, 15, %o2
136c4da8e0dSAl Viro	sub	%o3, %g5, %o3
137c4da8e0dSAl Viro	retl
138c4da8e0dSAl Viro	 add	%o2, %o3, %o0
139c4da8e0dSAl Viro
140c4da8e0dSAl Viro/* left: offset + 2 + (o2 % 2) */
141c4da8e0dSAl Viro#define MOVE_LAST_SHORTCHUNK(src, dst, offset, t0, t1) \
142c4da8e0dSAl Viro	LD(ldub, src, -(offset + 0x02), t0, last_shortchunk_fault)	\
143c4da8e0dSAl Viro	LD(ldub, src, -(offset + 0x01), t1, last_shortchunk_fault)	\
144c4da8e0dSAl Viro	ST(stb, dst, -(offset + 0x02), t0, last_shortchunk_fault)	\
145c4da8e0dSAl Viro	ST(stb, dst, -(offset + 0x01), t1, last_shortchunk_fault)
146c4da8e0dSAl Viro
147c4da8e0dSAl Viro	.section .fixup,#alloc,#execinstr
148c4da8e0dSAl Virolast_shortchunk_fault:
149c4da8e0dSAl Viro	and	%o2, 1, %o2
150c4da8e0dSAl Viro	retl
151c4da8e0dSAl Viro	 sub	%o2, %g5, %o0
1521da177e4SLinus Torvalds
1531da177e4SLinus Torvalds	.text
1541da177e4SLinus Torvalds	.align	4
1551da177e4SLinus Torvalds
1561da177e4SLinus Torvalds	.globl  __copy_user_begin
1571da177e4SLinus Torvalds__copy_user_begin:
1581da177e4SLinus Torvalds
1591da177e4SLinus Torvalds	.globl	__copy_user
160d3867f04SAl Viro	EXPORT_SYMBOL(__copy_user)
1611da177e4SLinus Torvaldsdword_align:
1621da177e4SLinus Torvalds	andcc	%o1, 1, %g0
1631da177e4SLinus Torvalds	be	4f
1641da177e4SLinus Torvalds	 andcc	%o1, 2, %g0
1651da177e4SLinus Torvalds
1661da177e4SLinus Torvalds	EXO2(ldub [%o1], %g2)
1671da177e4SLinus Torvalds	add	%o1, 1, %o1
1681da177e4SLinus Torvalds	EXO2(stb %g2, [%o0])
1691da177e4SLinus Torvalds	sub	%o2, 1, %o2
1701da177e4SLinus Torvalds	bne	3f
1711da177e4SLinus Torvalds	 add	%o0, 1, %o0
1721da177e4SLinus Torvalds
1731da177e4SLinus Torvalds	EXO2(lduh [%o1], %g2)
1741da177e4SLinus Torvalds	add	%o1, 2, %o1
1751da177e4SLinus Torvalds	EXO2(sth %g2, [%o0])
1761da177e4SLinus Torvalds	sub	%o2, 2, %o2
1771da177e4SLinus Torvalds	b	3f
1781da177e4SLinus Torvalds	 add	%o0, 2, %o0
1791da177e4SLinus Torvalds4:
1801da177e4SLinus Torvalds	EXO2(lduh [%o1], %g2)
1811da177e4SLinus Torvalds	add	%o1, 2, %o1
1821da177e4SLinus Torvalds	EXO2(sth %g2, [%o0])
1831da177e4SLinus Torvalds	sub	%o2, 2, %o2
1841da177e4SLinus Torvalds	b	3f
1851da177e4SLinus Torvalds	 add	%o0, 2, %o0
1861da177e4SLinus Torvalds
1871da177e4SLinus Torvalds__copy_user:	/* %o0=dst %o1=src %o2=len */
1881da177e4SLinus Torvalds	xor	%o0, %o1, %o4
1891da177e4SLinus Torvalds1:
1901da177e4SLinus Torvalds	andcc	%o4, 3, %o5
1911da177e4SLinus Torvalds2:
1921da177e4SLinus Torvalds	bne	cannot_optimize
1931da177e4SLinus Torvalds	 cmp	%o2, 15
1941da177e4SLinus Torvalds
1951da177e4SLinus Torvalds	bleu	short_aligned_end
1961da177e4SLinus Torvalds	 andcc	%o1, 3, %g0
1971da177e4SLinus Torvalds
1981da177e4SLinus Torvalds	bne	dword_align
1991da177e4SLinus Torvalds3:
2001da177e4SLinus Torvalds	 andcc	%o1, 4, %g0
2011da177e4SLinus Torvalds
2021da177e4SLinus Torvalds	be	2f
2031da177e4SLinus Torvalds	 mov	%o2, %g1
2041da177e4SLinus Torvalds
2051da177e4SLinus Torvalds	EXO2(ld [%o1], %o4)
2061da177e4SLinus Torvalds	sub	%g1, 4, %g1
2071da177e4SLinus Torvalds	EXO2(st %o4, [%o0])
2081da177e4SLinus Torvalds	add	%o1, 4, %o1
2091da177e4SLinus Torvalds	add	%o0, 4, %o0
2101da177e4SLinus Torvalds2:
2111da177e4SLinus Torvalds	andcc	%g1, 0xffffff80, %g7
2121da177e4SLinus Torvalds	be	3f
2131da177e4SLinus Torvalds	 andcc	%o0, 4, %g0
2141da177e4SLinus Torvalds
2151da177e4SLinus Torvalds	be	ldd_std + 4
2161da177e4SLinus Torvalds5:
2171da177e4SLinus Torvalds	MOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
2181da177e4SLinus Torvalds	MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
2191da177e4SLinus Torvalds	MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
2201da177e4SLinus Torvalds	MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
2211da177e4SLinus Torvalds	subcc	%g7, 128, %g7
2221da177e4SLinus Torvalds	add	%o1, 128, %o1
2231da177e4SLinus Torvalds	bne	5b
2241da177e4SLinus Torvalds	 add	%o0, 128, %o0
2251da177e4SLinus Torvalds3:
2261da177e4SLinus Torvalds	andcc	%g1, 0x70, %g7
2271da177e4SLinus Torvalds	be	copy_user_table_end
2281da177e4SLinus Torvalds	 andcc	%g1, 8, %g0
2291da177e4SLinus Torvalds
2301da177e4SLinus Torvalds	sethi	%hi(copy_user_table_end), %o5
2311da177e4SLinus Torvalds	srl	%g7, 1, %o4
2321da177e4SLinus Torvalds	add	%g7, %o4, %o4
2331da177e4SLinus Torvalds	add	%o1, %g7, %o1
2341da177e4SLinus Torvalds	sub	%o5, %o4, %o5
2351da177e4SLinus Torvalds	jmpl	%o5 + %lo(copy_user_table_end), %g0
2361da177e4SLinus Torvalds	 add	%o0, %g7, %o0
2371da177e4SLinus Torvalds
2381da177e4SLinus Torvalds	MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
2391da177e4SLinus Torvalds	MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
2401da177e4SLinus Torvalds	MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
2411da177e4SLinus Torvalds	MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
2421da177e4SLinus Torvalds	MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
2431da177e4SLinus Torvalds	MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
2441da177e4SLinus Torvalds	MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
2451da177e4SLinus Torvaldscopy_user_table_end:
2461da177e4SLinus Torvalds	be	copy_user_last7
2471da177e4SLinus Torvalds	 andcc	%g1, 4, %g0
2481da177e4SLinus Torvalds
2491da177e4SLinus Torvalds	EX(ldd	[%o1], %g2, and %g1, 0xf)
2501da177e4SLinus Torvalds	add	%o0, 8, %o0
2511da177e4SLinus Torvalds	add	%o1, 8, %o1
2521da177e4SLinus Torvalds	EX(st	%g2, [%o0 - 0x08], and %g1, 0xf)
2531da177e4SLinus Torvalds	EX2(st	%g3, [%o0 - 0x04], and %g1, 0xf, %g1, sub %g1, 4)
2541da177e4SLinus Torvaldscopy_user_last7:
2551da177e4SLinus Torvalds	be	1f
2561da177e4SLinus Torvalds	 andcc	%g1, 2, %g0
2571da177e4SLinus Torvalds
2581da177e4SLinus Torvalds	EX(ld	[%o1], %g2, and %g1, 7)
2591da177e4SLinus Torvalds	add	%o1, 4, %o1
2601da177e4SLinus Torvalds	EX(st	%g2, [%o0], and %g1, 7)
2611da177e4SLinus Torvalds	add	%o0, 4, %o0
2621da177e4SLinus Torvalds1:
2631da177e4SLinus Torvalds	be	1f
2641da177e4SLinus Torvalds	 andcc	%g1, 1, %g0
2651da177e4SLinus Torvalds
2661da177e4SLinus Torvalds	EX(lduh	[%o1], %g2, and %g1, 3)
2671da177e4SLinus Torvalds	add	%o1, 2, %o1
2681da177e4SLinus Torvalds	EX(sth	%g2, [%o0], and %g1, 3)
2691da177e4SLinus Torvalds	add	%o0, 2, %o0
2701da177e4SLinus Torvalds1:
2711da177e4SLinus Torvalds	be	1f
2721da177e4SLinus Torvalds	 nop
2731da177e4SLinus Torvalds
2741da177e4SLinus Torvalds	EX(ldub	[%o1], %g2, add %g0, 1)
2751da177e4SLinus Torvalds	EX(stb	%g2, [%o0], add %g0, 1)
2761da177e4SLinus Torvalds1:
2771da177e4SLinus Torvalds	retl
2781da177e4SLinus Torvalds 	 clr	%o0
2791da177e4SLinus Torvalds
2801da177e4SLinus Torvaldsldd_std:
2811da177e4SLinus Torvalds	MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
2821da177e4SLinus Torvalds	MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
2831da177e4SLinus Torvalds	MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
2841da177e4SLinus Torvalds	MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
2851da177e4SLinus Torvalds	subcc	%g7, 128, %g7
2861da177e4SLinus Torvalds	add	%o1, 128, %o1
2871da177e4SLinus Torvalds	bne	ldd_std
2881da177e4SLinus Torvalds	 add	%o0, 128, %o0
2891da177e4SLinus Torvalds
2901da177e4SLinus Torvalds	andcc	%g1, 0x70, %g7
2911da177e4SLinus Torvalds	be	copy_user_table_end
2921da177e4SLinus Torvalds	 andcc	%g1, 8, %g0
2931da177e4SLinus Torvalds
2941da177e4SLinus Torvalds	sethi	%hi(copy_user_table_end), %o5
2951da177e4SLinus Torvalds	srl	%g7, 1, %o4
2961da177e4SLinus Torvalds	add	%g7, %o4, %o4
2971da177e4SLinus Torvalds	add	%o1, %g7, %o1
2981da177e4SLinus Torvalds	sub	%o5, %o4, %o5
2991da177e4SLinus Torvalds	jmpl	%o5 + %lo(copy_user_table_end), %g0
3001da177e4SLinus Torvalds	 add	%o0, %g7, %o0
3011da177e4SLinus Torvalds
3021da177e4SLinus Torvaldscannot_optimize:
3031da177e4SLinus Torvalds	bleu	short_end
3041da177e4SLinus Torvalds	 cmp	%o5, 2
3051da177e4SLinus Torvalds
3061da177e4SLinus Torvalds	bne	byte_chunk
3071da177e4SLinus Torvalds	 and	%o2, 0xfffffff0, %o3
3081da177e4SLinus Torvalds
3091da177e4SLinus Torvalds	andcc	%o1, 1, %g0
3101da177e4SLinus Torvalds	be	10f
3111da177e4SLinus Torvalds	 nop
3121da177e4SLinus Torvalds
3131da177e4SLinus Torvalds	EXO2(ldub [%o1], %g2)
3141da177e4SLinus Torvalds	add	%o1, 1, %o1
3151da177e4SLinus Torvalds	EXO2(stb %g2, [%o0])
3161da177e4SLinus Torvalds	sub	%o2, 1, %o2
3171da177e4SLinus Torvalds	andcc	%o2, 0xfffffff0, %o3
3181da177e4SLinus Torvalds	be	short_end
3191da177e4SLinus Torvalds	 add	%o0, 1, %o0
3201da177e4SLinus Torvalds10:
3211da177e4SLinus Torvalds	MOVE_HALFCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
3221da177e4SLinus Torvalds	MOVE_HALFCHUNK(o1, o0, 0x08, g2, g3, g4, g5)
3231da177e4SLinus Torvalds	subcc	%o3, 0x10, %o3
3241da177e4SLinus Torvalds	add	%o1, 0x10, %o1
3251da177e4SLinus Torvalds	bne	10b
3261da177e4SLinus Torvalds	 add	%o0, 0x10, %o0
3271da177e4SLinus Torvalds	b	2f
3281da177e4SLinus Torvalds	 and	%o2, 0xe, %o3
3291da177e4SLinus Torvalds
3301da177e4SLinus Torvaldsbyte_chunk:
3311da177e4SLinus Torvalds	MOVE_SHORTCHUNK(o1, o0, -0x02, g2, g3)
3321da177e4SLinus Torvalds	MOVE_SHORTCHUNK(o1, o0, -0x04, g2, g3)
3331da177e4SLinus Torvalds	MOVE_SHORTCHUNK(o1, o0, -0x06, g2, g3)
3341da177e4SLinus Torvalds	MOVE_SHORTCHUNK(o1, o0, -0x08, g2, g3)
3351da177e4SLinus Torvalds	MOVE_SHORTCHUNK(o1, o0, -0x0a, g2, g3)
3361da177e4SLinus Torvalds	MOVE_SHORTCHUNK(o1, o0, -0x0c, g2, g3)
3371da177e4SLinus Torvalds	MOVE_SHORTCHUNK(o1, o0, -0x0e, g2, g3)
3381da177e4SLinus Torvalds	MOVE_SHORTCHUNK(o1, o0, -0x10, g2, g3)
3391da177e4SLinus Torvalds	subcc	%o3, 0x10, %o3
3401da177e4SLinus Torvalds	add	%o1, 0x10, %o1
3411da177e4SLinus Torvalds	bne	byte_chunk
3421da177e4SLinus Torvalds	 add	%o0, 0x10, %o0
3431da177e4SLinus Torvalds
3441da177e4SLinus Torvaldsshort_end:
3451da177e4SLinus Torvalds	and	%o2, 0xe, %o3
3461da177e4SLinus Torvalds2:
3471da177e4SLinus Torvalds	sethi	%hi(short_table_end), %o5
3481da177e4SLinus Torvalds	sll	%o3, 3, %o4
3491da177e4SLinus Torvalds	add	%o0, %o3, %o0
3501da177e4SLinus Torvalds	sub	%o5, %o4, %o5
3511da177e4SLinus Torvalds	add	%o1, %o3, %o1
3521da177e4SLinus Torvalds	jmpl	%o5 + %lo(short_table_end), %g0
3531da177e4SLinus Torvalds	 andcc	%o2, 1, %g0
354c4da8e0dSAl Viro	MOVE_LAST_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
355c4da8e0dSAl Viro	MOVE_LAST_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
356c4da8e0dSAl Viro	MOVE_LAST_SHORTCHUNK(o1, o0, 0x08, g2, g3)
357c4da8e0dSAl Viro	MOVE_LAST_SHORTCHUNK(o1, o0, 0x06, g2, g3)
358c4da8e0dSAl Viro	MOVE_LAST_SHORTCHUNK(o1, o0, 0x04, g2, g3)
359c4da8e0dSAl Viro	MOVE_LAST_SHORTCHUNK(o1, o0, 0x02, g2, g3)
360c4da8e0dSAl Viro	MOVE_LAST_SHORTCHUNK(o1, o0, 0x00, g2, g3)
3611da177e4SLinus Torvaldsshort_table_end:
3621da177e4SLinus Torvalds	be	1f
3631da177e4SLinus Torvalds	 nop
3641da177e4SLinus Torvalds	EX(ldub	[%o1], %g2, add %g0, 1)
3651da177e4SLinus Torvalds	EX(stb	%g2, [%o0], add %g0, 1)
3661da177e4SLinus Torvalds1:
3671da177e4SLinus Torvalds	retl
3681da177e4SLinus Torvalds 	 clr	%o0
3691da177e4SLinus Torvalds
3701da177e4SLinus Torvaldsshort_aligned_end:
3711da177e4SLinus Torvalds	bne	short_end
3721da177e4SLinus Torvalds	 andcc	%o2, 8, %g0
3731da177e4SLinus Torvalds
3741da177e4SLinus Torvalds	be	1f
3751da177e4SLinus Torvalds	 andcc	%o2, 4, %g0
3761da177e4SLinus Torvalds
3771da177e4SLinus Torvalds	EXO2(ld	[%o1 + 0x00], %g2)
3781da177e4SLinus Torvalds	EXO2(ld	[%o1 + 0x04], %g3)
3791da177e4SLinus Torvalds	add	%o1, 8, %o1
3801da177e4SLinus Torvalds	EXO2(st	%g2, [%o0 + 0x00])
3811da177e4SLinus Torvalds	EX(st	%g3, [%o0 + 0x04], sub %o2, 4)
3821da177e4SLinus Torvalds	add	%o0, 8, %o0
3831da177e4SLinus Torvalds1:
3841da177e4SLinus Torvalds	b	copy_user_last7
3851da177e4SLinus Torvalds	 mov	%o2, %g1
3861da177e4SLinus Torvalds
3871da177e4SLinus Torvalds	.section .fixup,#alloc,#execinstr
3881da177e4SLinus Torvalds	.align	4
3891da177e4SLinus Torvalds97:
39031af2f36SAl Viro	retl
391c4da8e0dSAl Viro	 mov	%o2, %o0
3921da177e4SLinus Torvalds
3931da177e4SLinus Torvalds	.globl  __copy_user_end
3941da177e4SLinus Torvalds__copy_user_end:
395