1373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan/*
2373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan * User address space access functions.
3373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan * The non-inlined parts of asm-metag/uaccess.h are here.
4373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
5373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan * Copyright (C) 2006, Imagination Technologies.
6373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan * Copyright (C) 2000, Axis Communications AB.
7373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
8373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan * Written by Hans-Peter Nilsson.
9373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan * Pieces used from memcpy, originally by Kenny Ranerup long time ago.
10373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan * Modified for Meta by Will Newton.
11373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan */
12373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
139da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James Hogan#include <linux/export.h>
14373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#include <linux/uaccess.h>
15373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#include <asm/cache.h>			/* def of L1_CACHE_BYTES */
16373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
17373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define USE_RAPF
18373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define RAPF_MIN_BUF_SIZE	(3*L1_CACHE_BYTES)
19373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
20373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
21373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan/* The "double write" in this code is because the Meta will not fault
22373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan * immediately unless the memory pipe is forced to by e.g. a data stall or
23373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan * another memory op. The second write should be discarded by the write
24373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan * combiner so should have virtually no cost.
25373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan */
26373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
27373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \
28373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (						 \
29373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		COPY						 \
30373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"						 \
31373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section .fixup,\"ax\"\n"		 \
32373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV D1Ar1,#0\n"				 \
33373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		FIXUP						 \
34373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D1Ar1,#HI(1b)\n"		 \
35373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D1Ar1,#LO(1b)\n"		 \
36373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"				 \
37373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section __ex_table,\"a\"\n"		 \
38373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		TENTRY						 \
39373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"				 \
40373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r" (to), "=r" (from), "=r" (ret)		 \
41373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "0" (to), "1" (from), "2" (ret)		 \
42373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D1Ar1", "memory")
43373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
44373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
45373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_1(to, from, ret)	\
46373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_user_cont(to, from, ret,	\
47373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"	\
48373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0],D1Ar1\n"	\
49373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETB [%0++],D1Ar1\n",	\
50373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %2,%2,#1\n",	\
51373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n")
52373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
53373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
54373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_user_cont(to, from, ret,		\
55373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETW D1Ar1,[%1++]\n"		\
56373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%0],D1Ar1\n"		\
57373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETW [%0++],D1Ar1\n" COPY,	\
58373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %2,%2,#2\n" FIXUP,		\
59373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n" TENTRY)
60373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
61373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_2(to, from, ret) \
62373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
63373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
64373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_3(to, from, ret) \
65373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_2x_cont(to, from, ret,	\
66373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
67373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0],D1Ar1\n"		\
68373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:	SETB [%0++],D1Ar1\n",		\
69373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"5:	ADD  %2,%2,#1\n",		\
70373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 4b,5b\n")
71373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
72373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
73373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_user_cont(to, from, ret,		\
74373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETD D1Ar1,[%1++]\n"		\
75373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0],D1Ar1\n"		\
76373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETD [%0++],D1Ar1\n" COPY,	\
77373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %2,%2,#4\n" FIXUP,		\
78373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n" TENTRY)
79373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
80373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_4(to, from, ret) \
81373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
82373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
83373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_5(to, from, ret) \
84373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_4x_cont(to, from, ret,	\
85373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
86373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0],D1Ar1\n"		\
87373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:	SETB [%0++],D1Ar1\n",		\
88373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"5:	ADD  %2,%2,#1\n",		\
89373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 4b,5b\n")
90373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
91373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
92373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_4x_cont(to, from, ret,	\
93373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETW D1Ar1,[%1++]\n"		\
94373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%0],D1Ar1\n"		\
95373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:	SETW [%0++],D1Ar1\n" COPY,	\
96373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"5:	ADD  %2,%2,#2\n" FIXUP,		\
97373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 4b,5b\n" TENTRY)
98373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
99373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_6(to, from, ret) \
100373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
101373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
102373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_7(to, from, ret) \
103373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_6x_cont(to, from, ret,	\
104373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
105373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0],D1Ar1\n"		\
106373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"6:	SETB [%0++],D1Ar1\n",		\
107373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"7:	ADD  %2,%2,#1\n",		\
108373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 6b,7b\n")
109373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
110373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
111373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_4x_cont(to, from, ret,	\
112373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETD D1Ar1,[%1++]\n"		\
113373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0],D1Ar1\n"		\
114373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:	SETD [%0++],D1Ar1\n" COPY,	\
115373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"5:	ADD  %2,%2,#4\n"  FIXUP,	\
116373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 4b,5b\n" TENTRY)
117373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
118373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_8(to, from, ret) \
119373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
120373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
121373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_9(to, from, ret) \
122373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_8x_cont(to, from, ret,	\
123373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
124373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0],D1Ar1\n"		\
125373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"6:	SETB [%0++],D1Ar1\n",		\
126373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"7:	ADD  %2,%2,#1\n",		\
127373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 6b,7b\n")
128373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
129373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
130373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_8x_cont(to, from, ret,	\
131373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETW D1Ar1,[%1++]\n"		\
132373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%0],D1Ar1\n"		\
133373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"6:	SETW [%0++],D1Ar1\n" COPY,	\
134373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"7:	ADD  %2,%2,#2\n" FIXUP,		\
135373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 6b,7b\n" TENTRY)
136373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
137373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_10(to, from, ret) \
138373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
139373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
140373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_11(to, from, ret) \
141373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_10x_cont(to, from, ret,	\
142373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
143373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0],D1Ar1\n"		\
144373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"8:	SETB [%0++],D1Ar1\n",		\
145373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"9:	ADD  %2,%2,#1\n",		\
146373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 8b,9b\n")
147373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
148373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
149373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_8x_cont(to, from, ret,	\
150373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETD D1Ar1,[%1++]\n"		\
151373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0],D1Ar1\n"		\
152373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"6:	SETD [%0++],D1Ar1\n" COPY,	\
153373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"7:	ADD  %2,%2,#4\n" FIXUP,		\
154373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 6b,7b\n" TENTRY)
155373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_12(to, from, ret) \
156373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
157373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
158373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_13(to, from, ret) \
159373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_12x_cont(to, from, ret,	\
160373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
161373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0],D1Ar1\n"		\
162373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"8:	SETB [%0++],D1Ar1\n",		\
163373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"9:	ADD  %2,%2,#1\n",		\
164373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 8b,9b\n")
165373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
166373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
167373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_12x_cont(to, from, ret,	\
168373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETW D1Ar1,[%1++]\n"		\
169373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%0],D1Ar1\n"		\
170373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"8:	SETW [%0++],D1Ar1\n" COPY,	\
171373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"9:	ADD  %2,%2,#2\n" FIXUP,		\
172373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 8b,9b\n" TENTRY)
173373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
174373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_14(to, from, ret) \
175373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
176373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
177373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_15(to, from, ret) \
178373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_14x_cont(to, from, ret,	\
179373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
180373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0],D1Ar1\n"		\
181373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"10:	SETB [%0++],D1Ar1\n",		\
182373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"11:	ADD  %2,%2,#1\n",		\
183373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 10b,11b\n")
184373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
185373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
186373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_to_user_12x_cont(to, from, ret,	\
187373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETD D1Ar1,[%1++]\n"		\
188373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0],D1Ar1\n"		\
189373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"8:	SETD [%0++],D1Ar1\n" COPY,	\
190373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"9:	ADD  %2,%2,#4\n" FIXUP,		\
191373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 8b,9b\n" TENTRY)
192373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
193373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_16(to, from, ret) \
194373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
195373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
196373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_8x64(to, from, ret) \
197373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (					\
198373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETL D0Ar2,D1Ar1,[%1++]\n"	\
199373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETL [%0],D0Ar2,D1Ar1\n"	\
200373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETL [%0++],D0Ar2,D1Ar1\n"	\
201373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"					\
202373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section .fixup,\"ax\"\n"	\
203373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %2,%2,#8\n"		\
204373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0Ar2,#HI(1b)\n"	\
205373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0Ar2,#LO(1b)\n"	\
206373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"			\
207373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section __ex_table,\"a\"\n"	\
208373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n"			\
209373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"			\
210373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r" (to), "=r" (from), "=r" (ret)	\
211373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "0" (to), "1" (from), "2" (ret)	\
212373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D1Ar1", "D0Ar2", "memory")
213373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
214373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan/*
215373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	optimized copying loop using RAPF when 64 bit aligned
216373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
217373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	n		will be automatically decremented inside the loop
218373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	ret		will be left intact. if error occurs we will rewind
219373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			so that the original non optimized code will fill up
220373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			this value correctly.
221373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
222373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	on fault:
223373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		>	n will hold total number of uncopied bytes
224373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
225373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		>	{'to','from'} will be rewind back so that
226373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			the non-optimized code will do the proper fix up
227373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
228373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	DCACHE drops the cacheline which helps in reducing cache
229373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	pollution.
230373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
231373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	We introduce an extra SETL at the end of the loop to
232373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	ensure we don't fall off the loop before we catch all
233373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	erros.
234373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
235373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	NOTICE:
236373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		LSM_STEP in TXSTATUS must be cleared in fix up code.
237373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		since we're using M{S,G}ETL, a fault might happen at
238373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		any address in the middle of M{S,G}ETL causing
239373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		the value of LSM_STEP to be incorrect which can
240373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		cause subsequent use of M{S,G}ET{L,D} to go wrong.
241373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		ie: if LSM_STEP was 1 when a fault occurs, the
242373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		next call to M{S,G}ET{L,D} will skip the first
243373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		copy/getting as it think that the first 1 has already
244373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		been done.
245373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
246373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan */
247373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_user_64bit_rapf_loop(				\
248373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		to, from, ret, n, id, FIXUP)				\
249373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (							\
250373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".balign 8\n"						\
251373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MOV	RAPF, %1\n"					\
252373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETL	[A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n"	\
253373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MOV	D0Ar6, #0\n"					\
254373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"LSR	D1Ar5, %3, #6\n"				\
255373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	TXRPT, D1Ar5, #2\n"				\
256373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MOV	RAPF, %1\n"					\
257373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"$Lloop"id":\n"						\
258373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"ADD	RAPF, %1, #64\n"				\
259373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"21:\n"							\
260373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
261373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"22:\n"							\
262373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
263373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #32\n"					\
264373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"23:\n"							\
265373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
266373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"24:\n"							\
267373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
268373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #32\n"					\
269373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"DCACHE	[%1+#-64], D0Ar6\n"				\
270373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"BR	$Lloop"id"\n"					\
271373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan									\
272373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MOV	RAPF, %1\n"					\
273373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"25:\n"							\
274373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
275373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"26:\n"							\
276373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
277373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #32\n"					\
278373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"27:\n"							\
279373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETL	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
280373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"28:\n"							\
281373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETL	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
282373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%0, %0, #8\n"					\
283373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"29:\n"							\
284373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SETL	[%0++], D0.7, D1.7\n"				\
285373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #32\n"					\
286373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:"							\
287373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"DCACHE	[%1+#-64], D0Ar6\n"				\
288373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"GETL    D0Ar6, D1Ar5, [A0StP+#-40]\n"			\
289373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"GETL    D0FrT, D1RtP, [A0StP+#-32]\n"			\
290373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"GETL    D0.5, D1.5, [A0StP+#-24]\n"			\
291373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"GETL    D0.6, D1.6, [A0StP+#-16]\n"			\
292373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"GETL    D0.7, D1.7, [A0StP+#-8]\n"			\
293373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB A0StP, A0StP, #40\n"				\
294373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section .fixup,\"ax\"\n"			\
295373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:\n"							\
296373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	ADD	%0, %0, #8\n"				\
297373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:\n"							\
298373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV	D0Ar2, TXSTATUS\n"			\
299373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV	D1Ar1, TXSTATUS\n"			\
300373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	AND	D1Ar1, D1Ar1, #0xFFFFF8FF\n"		\
301373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV	TXSTATUS, D1Ar1\n"			\
302373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			FIXUP						\
303373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0Ar2,#HI(1b)\n"			\
304373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0Ar2,#LO(1b)\n"			\
305373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"					\
306373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section __ex_table,\"a\"\n"			\
307373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 21b,3b\n"					\
308373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 22b,3b\n"					\
309373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 23b,3b\n"					\
310373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 24b,3b\n"					\
311373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 25b,3b\n"					\
312373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 26b,3b\n"					\
313373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 27b,3b\n"					\
314373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 28b,3b\n"					\
315373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 29b,4b\n"					\
316373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"					\
317373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r" (to), "=r" (from), "=r" (ret), "=d" (n)		\
318373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "0" (to), "1" (from), "2" (ret), "3" (n)		\
319373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D1Ar1", "D0Ar2", "memory")
320373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
321373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan/*	rewind 'to' and 'from'  pointers when a fault occurs
322373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
323373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	Rationale:
324373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		A fault always occurs on writing to user buffer. A fault
325373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		is at a single address, so we need to rewind by only 4
326373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		bytes.
327373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		Since we do a complete read from kernel buffer before
328373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		writing, we need to rewind it also. The amount to be
329373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		rewind equals the number of faulty writes in MSETD
330373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		which is: [4 - (LSM_STEP-1)]*8
331373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		LSM_STEP is bits 10:8 in TXSTATUS which is already read
332373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		and stored in D0Ar2
333373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
334373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		NOTE: If a fault occurs at the last operation in M{G,S}ETL
335373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			LSM_STEP will be 0. ie: we do 4 writes in our case, if
336373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			a fault happens at the 4th write, LSM_STEP will be 0
337373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			instead of 4. The code copes with that.
338373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
339373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		n is updated by the number of successful writes, which is:
340373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		n = n - (LSM_STEP-1)*8
341373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan */
342373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_64bit_rapf_loop(to,	from, ret, n, id)\
343373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_user_64bit_rapf_loop(to, from, ret, n, id,		\
344373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"LSR	D0Ar2, D0Ar2, #8\n"				\
345373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"AND	D0Ar2, D0Ar2, #0x7\n"				\
346373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"ADDZ	D0Ar2, D0Ar2, #4\n"				\
347373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	D0Ar2, D0Ar2, #1\n"				\
348373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MOV	D1Ar1, #4\n"					\
349373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	D0Ar2, D1Ar1, D0Ar2\n"				\
350373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"LSL	D0Ar2, D0Ar2, #3\n"				\
351373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"LSL	D1Ar1, D1Ar1, #3\n"				\
352373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	D1Ar1, D1Ar1, D0Ar2\n"				\
353373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%0, %0, #8\n"					\
354373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%1,	%1,D0Ar2\n"				\
355373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, D1Ar1\n")
356373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
357373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan/*
358373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	optimized copying loop using RAPF when 32 bit aligned
359373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
360373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	n		will be automatically decremented inside the loop
361373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	ret		will be left intact. if error occurs we will rewind
362373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			so that the original non optimized code will fill up
363373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			this value correctly.
364373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
365373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	on fault:
366373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		>	n will hold total number of uncopied bytes
367373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
368373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		>	{'to','from'} will be rewind back so that
369373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			the non-optimized code will do the proper fix up
370373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
371373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	DCACHE drops the cacheline which helps in reducing cache
372373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	pollution.
373373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
374373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	We introduce an extra SETD at the end of the loop to
375373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	ensure we don't fall off the loop before we catch all
376373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	erros.
377373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
378373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	NOTICE:
379373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		LSM_STEP in TXSTATUS must be cleared in fix up code.
380373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		since we're using M{S,G}ETL, a fault might happen at
381373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		any address in the middle of M{S,G}ETL causing
382373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		the value of LSM_STEP to be incorrect which can
383373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		cause subsequent use of M{S,G}ET{L,D} to go wrong.
384373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		ie: if LSM_STEP was 1 when a fault occurs, the
385373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		next call to M{S,G}ET{L,D} will skip the first
386373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		copy/getting as it think that the first 1 has already
387373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		been done.
388373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
389373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan */
390373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_user_32bit_rapf_loop(				\
391373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			to,	from, ret, n, id, FIXUP)		\
392373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (							\
393373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".balign 8\n"						\
394373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MOV	RAPF, %1\n"					\
395373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETL	[A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n"	\
396373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MOV	D0Ar6, #0\n"					\
397373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"LSR	D1Ar5, %3, #6\n"				\
398373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	TXRPT, D1Ar5, #2\n"				\
399373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MOV	RAPF, %1\n"					\
400373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	"$Lloop"id":\n"							\
401373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"ADD	RAPF, %1, #64\n"				\
402373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"21:\n"							\
403373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
404373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"22:\n"							\
405373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
406373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #16\n"					\
407373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"23:\n"							\
408373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
409373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"24:\n"							\
410373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
411373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #16\n"					\
412373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"25:\n"							\
413373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
414373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"26:\n"							\
415373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
416373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #16\n"					\
417373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"27:\n"							\
418373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
419373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"28:\n"							\
420373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
421373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #16\n"					\
422373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"DCACHE	[%1+#-64], D0Ar6\n"				\
423373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"BR	$Lloop"id"\n"					\
424373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan									\
425373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MOV	RAPF, %1\n"					\
426373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"29:\n"							\
427373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
428373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"30:\n"							\
429373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
430373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #16\n"					\
431373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"31:\n"							\
432373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
433373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"32:\n"							\
434373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
435373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #16\n"					\
436373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"33:\n"							\
437373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
438373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"34:\n"							\
439373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
440373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #16\n"					\
441373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"35:\n"							\
442373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MGETD	D0FrT, D0.5, D0.6, D0.7, [%1++]\n"		\
443373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"36:\n"							\
444373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MSETD	[%0++], D0FrT, D0.5, D0.6, D0.7\n"		\
445373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%0, %0, #4\n"					\
446373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"37:\n"							\
447373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SETD	[%0++], D0.7\n"					\
448373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, #16\n"					\
449373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:"							\
450373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"DCACHE	[%1+#-64], D0Ar6\n"				\
451373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"GETL    D0Ar6, D1Ar5, [A0StP+#-40]\n"			\
452373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"GETL    D0FrT, D1RtP, [A0StP+#-32]\n"			\
453373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"GETL    D0.5, D1.5, [A0StP+#-24]\n"			\
454373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"GETL    D0.6, D1.6, [A0StP+#-16]\n"			\
455373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"GETL    D0.7, D1.7, [A0StP+#-8]\n"			\
456373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB A0StP, A0StP, #40\n"				\
457373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section .fixup,\"ax\"\n"			\
458373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:\n"							\
459373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	ADD		%0, %0, #4\n"			\
460373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:\n"							\
461373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV	D0Ar2, TXSTATUS\n"			\
462373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV	D1Ar1, TXSTATUS\n"			\
463373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	AND	D1Ar1, D1Ar1, #0xFFFFF8FF\n"		\
464373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV	TXSTATUS, D1Ar1\n"			\
465373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			FIXUP						\
466373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0Ar2,#HI(1b)\n"			\
467373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0Ar2,#LO(1b)\n"			\
468373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"					\
469373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section __ex_table,\"a\"\n"			\
470373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 21b,3b\n"					\
471373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 22b,3b\n"					\
472373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 23b,3b\n"					\
473373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 24b,3b\n"					\
474373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 25b,3b\n"					\
475373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 26b,3b\n"					\
476373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 27b,3b\n"					\
477373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 28b,3b\n"					\
478373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 29b,3b\n"					\
479373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 30b,3b\n"					\
480373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 31b,3b\n"					\
481373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 32b,3b\n"					\
482373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 33b,3b\n"					\
483373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 34b,3b\n"					\
484373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 35b,3b\n"					\
485373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 36b,3b\n"					\
486373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 37b,4b\n"					\
487373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"					\
488373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r" (to), "=r" (from), "=r" (ret), "=d" (n)		\
489373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "0" (to), "1" (from), "2" (ret), "3" (n)		\
490373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D1Ar1", "D0Ar2", "memory")
491373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
492373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan/*	rewind 'to' and 'from'  pointers when a fault occurs
493373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
494373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	Rationale:
495373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		A fault always occurs on writing to user buffer. A fault
496373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		is at a single address, so we need to rewind by only 4
497373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		bytes.
498373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		Since we do a complete read from kernel buffer before
499373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		writing, we need to rewind it also. The amount to be
500373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		rewind equals the number of faulty writes in MSETD
501373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		which is: [4 - (LSM_STEP-1)]*4
502373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		LSM_STEP is bits 10:8 in TXSTATUS which is already read
503373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		and stored in D0Ar2
504373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
505373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		NOTE: If a fault occurs at the last operation in M{G,S}ETL
506373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			LSM_STEP will be 0. ie: we do 4 writes in our case, if
507373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			a fault happens at the 4th write, LSM_STEP will be 0
508373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *			instead of 4. The code copes with that.
509373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
510373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		n is updated by the number of successful writes, which is:
511373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		n = n - (LSM_STEP-1)*4
512373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan */
513373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_to_user_32bit_rapf_loop(to, from, ret, n, id)\
514373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_user_32bit_rapf_loop(to, from, ret, n, id,		\
515373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"LSR	D0Ar2, D0Ar2, #8\n"				\
516373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"AND	D0Ar2, D0Ar2, #0x7\n"				\
517373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"ADDZ	D0Ar2, D0Ar2, #4\n"				\
518373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	D0Ar2, D0Ar2, #1\n"				\
519373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"MOV	D1Ar1, #4\n"					\
520373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	D0Ar2, D1Ar1, D0Ar2\n"				\
521373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"LSL	D0Ar2, D0Ar2, #2\n"				\
522373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"LSL	D1Ar1, D1Ar1, #2\n"				\
523373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	D1Ar1, D1Ar1, D0Ar2\n"				\
524373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%0, %0, #4\n"					\
525373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%1,	%1,	D0Ar2\n"			\
526373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%3, %3, D1Ar1\n")
527373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
528373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganunsigned long __copy_user(void __user *pdst, const void *psrc,
529373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			  unsigned long n)
530373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
531373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register char __user *dst asm ("A0.2") = pdst;
532373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register const char *src asm ("A1.2") = psrc;
533373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	unsigned long retn = 0;
534373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
535373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (n == 0)
536373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		return 0;
537373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
538373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if ((unsigned long) src & 1) {
539373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_to_user_1(dst, src, retn);
540373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n--;
541373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
542373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if ((unsigned long) dst & 1) {
543373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		/* Worst case - byte copy */
544373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		while (n > 0) {
545373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_copy_to_user_1(dst, src, retn);
546373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			n--;
547373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
548373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
549373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (((unsigned long) src & 2) && n >= 2) {
550373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_to_user_2(dst, src, retn);
551373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n -= 2;
552373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
553373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if ((unsigned long) dst & 2) {
554373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		/* Second worst case - word copy */
555373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		while (n >= 2) {
556373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_copy_to_user_2(dst, src, retn);
557373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			n -= 2;
558373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
559373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
560373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
561373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#ifdef USE_RAPF
562373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	/* 64 bit copy loop */
563373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (!(((unsigned long) src | (__force unsigned long) dst) & 7)) {
564373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		if (n >= RAPF_MIN_BUF_SIZE) {
565373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			/* copy user using 64 bit rapf copy */
566373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_copy_to_user_64bit_rapf_loop(dst, src, retn,
567373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan							n, "64cu");
568373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
569373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		while (n >= 8) {
570373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_copy_to_user_8x64(dst, src, retn);
571373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			n -= 8;
572373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
573373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
574373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (n >= RAPF_MIN_BUF_SIZE) {
575373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		/* copy user using 32 bit rapf copy */
576373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_to_user_32bit_rapf_loop(dst, src, retn, n, "32cu");
577373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
578373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#else
579373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	/* 64 bit copy loop */
580373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (!(((unsigned long) src | (__force unsigned long) dst) & 7)) {
581373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		while (n >= 8) {
582373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_copy_to_user_8x64(dst, src, retn);
583373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			n -= 8;
584373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
585373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
586373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#endif
587373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
588373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	while (n >= 16) {
589373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_to_user_16(dst, src, retn);
590373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n -= 16;
591373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
592373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
593373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	while (n >= 4) {
594373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_to_user_4(dst, src, retn);
595373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n -= 4;
596373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
597373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
598373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	switch (n) {
599373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 0:
600373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
601373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 1:
602373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_to_user_1(dst, src, retn);
603373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
604373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 2:
605373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_to_user_2(dst, src, retn);
606373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
607373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 3:
608373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_to_user_3(dst, src, retn);
609373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
610373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
611373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
612373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return retn;
613373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
6149da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__copy_user);
615373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
616373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_1(to, from, ret) \
617373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_user_cont(to, from, ret,	\
618373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"	\
619373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETB [%0++],D1Ar1\n",	\
620373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %2,%2,#1\n"	\
621373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0++],D1Ar1\n",	\
622373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n")
623373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
624373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
625373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_user_cont(to, from, ret,		\
626373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETW D1Ar1,[%1++]\n"		\
627373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETW [%0++],D1Ar1\n" COPY,	\
628373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %2,%2,#2\n"		\
629373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%0++],D1Ar1\n" FIXUP,	\
630373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n" TENTRY)
631373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
632373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_2(to, from, ret) \
633373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
634373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
635373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_3(to, from, ret)		\
636373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_2x_cont(to, from, ret,	\
637373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
638373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:	SETB [%0++],D1Ar1\n",		\
639373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"5:	ADD  %2,%2,#1\n"		\
640373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0++],D1Ar1\n",		\
641373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 4b,5b\n")
642373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
643373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
644373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_user_cont(to, from, ret,		\
645373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETD D1Ar1,[%1++]\n"		\
646373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETD [%0++],D1Ar1\n" COPY,	\
647373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %2,%2,#4\n"		\
648373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0++],D1Ar1\n" FIXUP,	\
649373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n" TENTRY)
650373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
651373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_4(to, from, ret) \
652373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
653373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
654373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_5(to, from, ret) \
655373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_4x_cont(to, from, ret,	\
656373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
657373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:	SETB [%0++],D1Ar1\n",		\
658373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"5:	ADD  %2,%2,#1\n"		\
659373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0++],D1Ar1\n",		\
660373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 4b,5b\n")
661373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
662373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
663373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_4x_cont(to, from, ret,	\
664373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETW D1Ar1,[%1++]\n"		\
665373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:	SETW [%0++],D1Ar1\n" COPY,	\
666373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"5:	ADD  %2,%2,#2\n"		\
667373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%0++],D1Ar1\n" FIXUP,	\
668373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 4b,5b\n" TENTRY)
669373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
670373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_6(to, from, ret) \
671373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
672373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
673373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_7(to, from, ret) \
674373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_6x_cont(to, from, ret,	\
675373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
676373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"6:	SETB [%0++],D1Ar1\n",		\
677373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"7:	ADD  %2,%2,#1\n"		\
678373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0++],D1Ar1\n",		\
679373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 6b,7b\n")
680373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
681373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
682373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_4x_cont(to, from, ret,	\
683373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETD D1Ar1,[%1++]\n"		\
684373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:	SETD [%0++],D1Ar1\n" COPY,	\
685373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"5:	ADD  %2,%2,#4\n"			\
686373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0++],D1Ar1\n" FIXUP,		\
687373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 4b,5b\n" TENTRY)
688373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
689373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_8(to, from, ret) \
690373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
691373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
692373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_9(to, from, ret) \
693373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_8x_cont(to, from, ret,	\
694373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
695373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"6:	SETB [%0++],D1Ar1\n",		\
696373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"7:	ADD  %2,%2,#1\n"		\
697373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0++],D1Ar1\n",		\
698373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 6b,7b\n")
699373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
700373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
701373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_8x_cont(to, from, ret,	\
702373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETW D1Ar1,[%1++]\n"		\
703373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"6:	SETW [%0++],D1Ar1\n" COPY,	\
704373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"7:	ADD  %2,%2,#2\n"		\
705373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%0++],D1Ar1\n" FIXUP,	\
706373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 6b,7b\n" TENTRY)
707373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
708373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_10(to, from, ret) \
709373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
710373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
711373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_11(to, from, ret)		\
712373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_10x_cont(to, from, ret,	\
713373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
714373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"8:	SETB [%0++],D1Ar1\n",		\
715373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"9:	ADD  %2,%2,#1\n"		\
716373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0++],D1Ar1\n",		\
717373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 8b,9b\n")
718373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
719373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
720373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_8x_cont(to, from, ret,	\
721373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETD D1Ar1,[%1++]\n"		\
722373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"6:	SETD [%0++],D1Ar1\n" COPY,	\
723373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"7:	ADD  %2,%2,#4\n"		\
724373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0++],D1Ar1\n" FIXUP,	\
725373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 6b,7b\n" TENTRY)
726373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
727373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_12(to, from, ret) \
728373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
729373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
730373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_13(to, from, ret) \
731373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_12x_cont(to, from, ret,	\
732373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
733373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"8:	SETB [%0++],D1Ar1\n",		\
734373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"9:	ADD  %2,%2,#1\n"		\
735373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0++],D1Ar1\n",		\
736373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 8b,9b\n")
737373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
738373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
739373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_12x_cont(to, from, ret,	\
740373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETW D1Ar1,[%1++]\n"		\
741373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"8:	SETW [%0++],D1Ar1\n" COPY,	\
742373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"9:	ADD  %2,%2,#2\n"		\
743373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%0++],D1Ar1\n" FIXUP,	\
744373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 8b,9b\n" TENTRY)
745373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
746373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_14(to, from, ret) \
747373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
748373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
749373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_15(to, from, ret) \
750373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_14x_cont(to, from, ret,	\
751373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB D1Ar1,[%1++]\n"		\
752373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"10:	SETB [%0++],D1Ar1\n",		\
753373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"11:	ADD  %2,%2,#1\n"		\
754373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0++],D1Ar1\n",		\
755373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 10b,11b\n")
756373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
757373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
758373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_12x_cont(to, from, ret,	\
759373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETD D1Ar1,[%1++]\n"		\
760373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"8:	SETD [%0++],D1Ar1\n" COPY,	\
761373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"9:	ADD  %2,%2,#4\n"		\
762373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0++],D1Ar1\n" FIXUP,	\
763373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 8b,9b\n" TENTRY)
764373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
765373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_16(to, from, ret) \
766373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
767373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
768373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_8x64(to, from, ret) \
769373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (				\
770373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETL D0Ar2,D1Ar1,[%1++]\n"	\
771373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETL [%0++],D0Ar2,D1Ar1\n"	\
772373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"					\
773373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section .fixup,\"ax\"\n"	\
774373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV D1Ar1,#0\n"			\
775373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV D0Ar2,#0\n"			\
776373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %2,%2,#8\n"		\
777373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETL [%0++],D0Ar2,D1Ar1\n"	\
778373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0Ar2,#HI(1b)\n"	\
779373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0Ar2,#LO(1b)\n"	\
780373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"			\
781373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section __ex_table,\"a\"\n"	\
782373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n"			\
783373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"			\
784373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=a" (to), "=r" (from), "=r" (ret)	\
785373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "0" (to), "1" (from), "2" (ret)	\
786373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D1Ar1", "D0Ar2", "memory")
787373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
788373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan/*	rewind 'from' pointer when a fault occurs
789373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
790373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	Rationale:
791373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		A fault occurs while reading from user buffer, which is the
792373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		source. Since the fault is at a single address, we only
793373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		need to rewind by 8 bytes.
794373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		Since we don't write to kernel buffer until we read first,
795373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		the kernel buffer is at the right state and needn't be
796373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		corrected.
797373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan */
798373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_64bit_rapf_loop(to, from, ret, n, id)	\
799373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_user_64bit_rapf_loop(to, from, ret, n, id,		\
800373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%1, %1, #8\n")
801373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
802373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan/*	rewind 'from' pointer when a fault occurs
803373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *
804373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *	Rationale:
805373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		A fault occurs while reading from user buffer, which is the
806373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		source. Since the fault is at a single address, we only
807373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		need to rewind by 4 bytes.
808373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		Since we don't write to kernel buffer until we read first,
809373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		the kernel buffer is at the right state and needn't be
810373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan *		corrected.
811373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan */
812373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_copy_from_user_32bit_rapf_loop(to, from, ret, n, id)	\
813373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_copy_user_32bit_rapf_loop(to, from, ret, n, id,		\
814373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"SUB	%1, %1, #4\n")
815373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
816373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
817373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan/* Copy from user to kernel, zeroing the bytes that were inaccessible in
818373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan   userland.  The return-value is the number of bytes that were
819373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan   inaccessible.  */
820373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganunsigned long __copy_user_zeroing(void *pdst, const void __user *psrc,
821373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan				  unsigned long n)
822373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
823373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register char *dst asm ("A0.2") = pdst;
824373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register const char __user *src asm ("A1.2") = psrc;
825373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	unsigned long retn = 0;
826373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
827373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (n == 0)
828373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		return 0;
829373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
830373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if ((unsigned long) src & 1) {
831373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_from_user_1(dst, src, retn);
832373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n--;
833373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
834373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if ((unsigned long) dst & 1) {
835373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		/* Worst case - byte copy */
836373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		while (n > 0) {
837373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_copy_from_user_1(dst, src, retn);
838373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			n--;
839373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			if (retn)
840373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan				goto copy_exception_bytes;
841373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
842373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
843373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (((unsigned long) src & 2) && n >= 2) {
844373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_from_user_2(dst, src, retn);
845373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n -= 2;
846373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
847373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if ((unsigned long) dst & 2) {
848373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		/* Second worst case - word copy */
849373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		while (n >= 2) {
850373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_copy_from_user_2(dst, src, retn);
851373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			n -= 2;
852373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			if (retn)
853373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan				goto copy_exception_bytes;
854373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
855373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
856373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
857373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	/* We only need one check after the unalignment-adjustments,
858373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	   because if both adjustments were done, either both or
859373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	   neither reference had an exception.  */
860373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (retn != 0)
861373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		goto copy_exception_bytes;
862373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
863373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#ifdef USE_RAPF
864373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	/* 64 bit copy loop */
865373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (!(((unsigned long) src | (unsigned long) dst) & 7)) {
866373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		if (n >= RAPF_MIN_BUF_SIZE) {
867373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			/* Copy using fast 64bit rapf */
868373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_copy_from_user_64bit_rapf_loop(dst, src, retn,
869373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan							n, "64cuz");
870373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
871373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		while (n >= 8) {
872373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_copy_from_user_8x64(dst, src, retn);
873373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			n -= 8;
874373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			if (retn)
875373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan				goto copy_exception_bytes;
876373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
877373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
878373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
879373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (n >= RAPF_MIN_BUF_SIZE) {
880373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		/* Copy using fast 32bit rapf */
881373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_from_user_32bit_rapf_loop(dst, src, retn,
882373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan						n, "32cuz");
883373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
884373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#else
885373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	/* 64 bit copy loop */
886373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (!(((unsigned long) src | (unsigned long) dst) & 7)) {
887373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		while (n >= 8) {
888373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_copy_from_user_8x64(dst, src, retn);
889373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			n -= 8;
890373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			if (retn)
891373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan				goto copy_exception_bytes;
892373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
893373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
894373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#endif
895373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
896373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	while (n >= 4) {
897373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_from_user_4(dst, src, retn);
898373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n -= 4;
899373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
900373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		if (retn)
901373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			goto copy_exception_bytes;
902373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
903373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
904373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	/* If we get here, there were no memory read faults.  */
905373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	switch (n) {
906373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		/* These copies are at least "naturally aligned" (so we don't
907373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		   have to check each byte), due to the src alignment code.
908373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		   The *_3 case *will* get the correct count for retn.  */
909373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 0:
910373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		/* This case deliberately left in (if you have doubts check the
911373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		   generated assembly code).  */
912373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
913373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 1:
914373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_from_user_1(dst, src, retn);
915373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
916373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 2:
917373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_from_user_2(dst, src, retn);
918373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
919373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 3:
920373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_copy_from_user_3(dst, src, retn);
921373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
922373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
923373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
924373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	/* If we get here, retn correctly reflects the number of failing
925373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	   bytes.  */
926373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return retn;
927373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
928373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan copy_exception_bytes:
929373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	/* We already have "retn" bytes cleared, and need to clear the
930373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	   remaining "n" bytes.  A non-optimized simple byte-for-byte in-line
931373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	   memset is preferred here, since this isn't speed-critical code and
932373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	   we'd rather have this a leaf-function than calling memset.  */
933373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	{
934373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		char *endp;
935373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		for (endp = dst + n; dst < endp; dst++)
936373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			*dst = 0;
937373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
938373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
939373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return retn + n;
940373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
9419da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__copy_user_zeroing);
942373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
943373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_8x64(to, ret) \
944373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (					\
945373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV  D0Ar2,#0\n"		\
946373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV  D1Ar1,#0\n"		\
947373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETL [%0],D0Ar2,D1Ar1\n"	\
948373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETL [%0++],D0Ar2,D1Ar1\n"	\
949373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"					\
950373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section .fixup,\"ax\"\n"	\
951373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %1,%1,#8\n"		\
952373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0Ar2,#HI(1b)\n"	\
953373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0Ar2,#LO(1b)\n"	\
954373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"			\
955373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section __ex_table,\"a\"\n"	\
956373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n"			\
957373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"			\
958373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r" (to), "=r" (ret)	\
959373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "0" (to), "1" (ret)	\
960373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D1Ar1", "D0Ar2", "memory")
961373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
962373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan/* Zero userspace.  */
963373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
964373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \
965373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (					\
966373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV D1Ar1,#0\n"			\
967373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			CLEAR				\
968373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"					\
969373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section .fixup,\"ax\"\n"	\
970373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			FIXUP				\
971373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D1Ar1,#HI(1b)\n"	\
972373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D1Ar1,#LO(1b)\n"	\
973373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"			\
974373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section __ex_table,\"a\"\n"	\
975373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			TENTRY				\
976373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous"			\
977373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r" (to), "=r" (ret)			\
978373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "0" (to), "1" (ret)			\
979373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D1Ar1", "memory")
980373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
981373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_1(to, ret) \
982373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear(to, ret,			\
983373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%0],D1Ar1\n"	\
984373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETB [%0++],D1Ar1\n",	\
985373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %1,%1,#1\n",	\
986373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n")
987373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
988373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_2(to, ret) \
989373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear(to, ret,			\
990373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%0],D1Ar1\n"	\
991373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETW [%0++],D1Ar1\n",	\
992373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %1,%1,#2\n",	\
993373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n")
994373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
995373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_3(to, ret) \
996373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear(to, ret,			\
997373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		 "2:	SETW [%0++],D1Ar1\n"	\
998373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		 "	SETB [%0],D1Ar1\n"	\
999373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		 "3:	SETB [%0++],D1Ar1\n",	\
1000373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		 "4:	ADD  %1,%1,#2\n"	\
1001373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		 "5:	ADD  %1,%1,#1\n",	\
1002373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		 "	.long 2b,4b\n"		\
1003373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		 "	.long 3b,5b\n")
1004373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1005373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
1006373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear(to, ret,				\
1007373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0],D1Ar1\n"		\
1008373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:	SETD [%0++],D1Ar1\n" CLEAR,	\
1009373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	ADD  %1,%1,#4\n" FIXUP,		\
1010373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 2b,3b\n" TENTRY)
1011373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1012373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_4(to, ret) \
1013373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear_4x_cont(to, ret, "", "", "")
1014373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1015373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
1016373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear_4x_cont(to, ret,			\
1017373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0],D1Ar1\n"		\
1018373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"4:	SETD [%0++],D1Ar1\n" CLEAR,	\
1019373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"5:	ADD  %1,%1,#4\n" FIXUP,		\
1020373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 4b,5b\n" TENTRY)
1021373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1022373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_8(to, ret) \
1023373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear_8x_cont(to, ret, "", "", "")
1024373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1025373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
1026373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear_8x_cont(to, ret,			\
1027373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0],D1Ar1\n"		\
1028373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"6:	SETD [%0++],D1Ar1\n" CLEAR,	\
1029373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"7:	ADD  %1,%1,#4\n" FIXUP,		\
1030373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 6b,7b\n" TENTRY)
1031373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1032373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_12(to, ret) \
1033373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear_12x_cont(to, ret, "", "", "")
1034373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1035373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
1036373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear_12x_cont(to, ret,			\
1037373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%0],D1Ar1\n"		\
1038373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"8:	SETD [%0++],D1Ar1\n" CLEAR,	\
1039373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"9:	ADD  %1,%1,#4\n" FIXUP,		\
1040373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 8b,9b\n" TENTRY)
1041373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1042373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan#define __asm_clear_16(to, ret) \
1043373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	__asm_clear_16x_cont(to, ret, "", "", "")
1044373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1045373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganunsigned long __do_clear_user(void __user *pto, unsigned long pn)
1046373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
1047373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register char __user *dst asm ("D0Re0") = pto;
1048373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register unsigned long n asm ("D1Re0") = pn;
1049373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register unsigned long retn asm ("D0Ar6") = 0;
1050373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1051373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if ((unsigned long) dst & 1) {
1052373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_clear_1(dst, retn);
1053373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n--;
1054373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
1055373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1056373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if ((unsigned long) dst & 2) {
1057373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_clear_2(dst, retn);
1058373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n -= 2;
1059373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
1060373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1061373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	/* 64 bit copy loop */
1062373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (!((__force unsigned long) dst & 7)) {
1063373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		while (n >= 8) {
1064373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			__asm_clear_8x64(dst, retn);
1065373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan			n -= 8;
1066373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		}
1067373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
1068373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1069373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	while (n >= 16) {
1070373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_clear_16(dst, retn);
1071373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n -= 16;
1072373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
1073373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1074373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	while (n >= 4) {
1075373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_clear_4(dst, retn);
1076373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		n -= 4;
1077373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
1078373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1079373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	switch (n) {
1080373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 0:
1081373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
1082373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 1:
1083373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_clear_1(dst, retn);
1084373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
1085373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 2:
1086373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_clear_2(dst, retn);
1087373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
1088373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	case 3:
1089373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		__asm_clear_3(dst, retn);
1090373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		break;
1091373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	}
1092373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1093373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return retn;
1094373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
10959da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__do_clear_user);
1096373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1097373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganunsigned char __get_user_asm_b(const void __user *addr, long *err)
1098373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
1099373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register unsigned char x asm ("D0Re0") = 0;
1100373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (
1101373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB %0,[%2]\n"
1102373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"
1103373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETB %0,[%2]\n"
1104373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:\n"
1105373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section .fixup,\"ax\"\n"
1106373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	MOV     D0FrT,%3\n"
1107373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD    [%1],D0FrT\n"
1108373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0FrT,#HI(2b)\n"
1109373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0FrT,#LO(2b)\n"
1110373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"
1111373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section __ex_table,\"a\"\n"
1112373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 1b,3b\n"
1113373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"
1114373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r" (x)
1115373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "r" (err), "r" (addr), "P" (-EFAULT)
1116373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D0FrT");
1117373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return x;
1118373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
11199da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__get_user_asm_b);
1120373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1121373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganunsigned short __get_user_asm_w(const void __user *addr, long *err)
1122373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
1123373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register unsigned short x asm ("D0Re0") = 0;
1124373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (
1125373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETW %0,[%2]\n"
1126373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"
1127373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETW %0,[%2]\n"
1128373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:\n"
1129373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section .fixup,\"ax\"\n"
1130373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	MOV     D0FrT,%3\n"
1131373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD    [%1],D0FrT\n"
1132373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0FrT,#HI(2b)\n"
1133373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0FrT,#LO(2b)\n"
1134373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"
1135373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section __ex_table,\"a\"\n"
1136373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 1b,3b\n"
1137373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"
1138373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r" (x)
1139373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "r" (err), "r" (addr), "P" (-EFAULT)
1140373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D0FrT");
1141373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return x;
1142373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
11439da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__get_user_asm_w);
1144373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1145373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganunsigned int __get_user_asm_d(const void __user *addr, long *err)
1146373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
1147373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register unsigned int x asm ("D0Re0") = 0;
1148373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (
1149373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETD %0,[%2]\n"
1150373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"
1151373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	GETD %0,[%2]\n"
1152373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:\n"
1153373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section .fixup,\"ax\"\n"
1154373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	MOV     D0FrT,%3\n"
1155373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD    [%1],D0FrT\n"
1156373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0FrT,#HI(2b)\n"
1157373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0FrT,#LO(2b)\n"
1158373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"
1159373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.section __ex_table,\"a\"\n"
1160373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 1b,3b\n"
1161373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.previous\n"
1162373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r" (x)
1163373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "r" (err), "r" (addr), "P" (-EFAULT)
1164373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D0FrT");
1165373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return x;
1166373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
11679da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__get_user_asm_d);
1168373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1169373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganlong __put_user_asm_b(unsigned int x, void __user *addr)
1170373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
1171373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register unsigned int err asm ("D0Re0") = 0;
1172373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (
1173373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV  %0,#0\n"
1174373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%2],%1\n"
1175373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"
1176373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETB [%2],%1\n"
1177373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:\n"
1178373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".section .fixup,\"ax\"\n"
1179373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	MOV     %0,%3\n"
1180373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0FrT,#HI(2b)\n"
1181373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0FrT,#LO(2b)\n"
1182373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".previous\n"
1183373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".section __ex_table,\"a\"\n"
1184373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 1b,3b\n"
1185373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".previous"
1186373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r"(err)
1187373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "d" (x), "a" (addr), "P"(-EFAULT)
1188373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D0FrT");
1189373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return err;
1190373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
11919da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__put_user_asm_b);
1192373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1193373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganlong __put_user_asm_w(unsigned int x, void __user *addr)
1194373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
1195373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register unsigned int err asm ("D0Re0") = 0;
1196373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (
1197373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV  %0,#0\n"
1198373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%2],%1\n"
1199373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"
1200373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETW [%2],%1\n"
1201373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:\n"
1202373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".section .fixup,\"ax\"\n"
1203373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	MOV     %0,%3\n"
1204373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0FrT,#HI(2b)\n"
1205373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0FrT,#LO(2b)\n"
1206373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".previous\n"
1207373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".section __ex_table,\"a\"\n"
1208373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 1b,3b\n"
1209373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".previous"
1210373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r"(err)
1211373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "d" (x), "a" (addr), "P"(-EFAULT)
1212373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D0FrT");
1213373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return err;
1214373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
12159da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__put_user_asm_w);
1216373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1217373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganlong __put_user_asm_d(unsigned int x, void __user *addr)
1218373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
1219373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register unsigned int err asm ("D0Re0") = 0;
1220373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (
1221373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV  %0,#0\n"
1222373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%2],%1\n"
1223373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"
1224373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETD [%2],%1\n"
1225373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:\n"
1226373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".section .fixup,\"ax\"\n"
1227373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	MOV     %0,%3\n"
1228373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0FrT,#HI(2b)\n"
1229373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0FrT,#LO(2b)\n"
1230373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".previous\n"
1231373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".section __ex_table,\"a\"\n"
1232373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 1b,3b\n"
1233373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".previous"
1234373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r"(err)
1235373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "d" (x), "a" (addr), "P"(-EFAULT)
1236373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D0FrT");
1237373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return err;
1238373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
12399da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__put_user_asm_d);
1240373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1241373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganlong __put_user_asm_l(unsigned long long x, void __user *addr)
1242373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
1243373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	register unsigned int err asm ("D0Re0") = 0;
1244373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile (
1245373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOV  %0,#0\n"
1246373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETL [%2],%1,%t1\n"
1247373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"1:\n"
1248373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	SETL [%2],%1,%t1\n"
1249373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"2:\n"
1250373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".section .fixup,\"ax\"\n"
1251373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"3:	MOV     %0,%3\n"
1252373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	MOVT    D0FrT,#HI(2b)\n"
1253373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	JUMP    D0FrT,#LO(2b)\n"
1254373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".previous\n"
1255373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".section __ex_table,\"a\"\n"
1256373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		"	.long 1b,3b\n"
1257373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		".previous"
1258373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "=r"(err)
1259373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "d" (x), "a" (addr), "P"(-EFAULT)
1260373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		: "D0FrT");
1261373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return err;
1262373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
12639da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__put_user_asm_l);
1264373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1265373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganlong strnlen_user(const char __user *src, long count)
1266373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
1267373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	long res;
1268373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1269373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (!access_ok(VERIFY_READ, src, 0))
1270373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		return 0;
1271373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1272373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile ("	MOV     D0Ar4, %1\n"
1273373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	MOV     D0Ar6, %2\n"
1274373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "0:\n"
1275373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	SUBS    D0FrT, D0Ar6, #0\n"
1276373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	SUB     D0Ar6, D0Ar6, #1\n"
1277373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	BLE     2f\n"
1278373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	GETB    D0FrT, [D0Ar4+#1++]\n"
1279373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "1:\n"
1280373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	TST     D0FrT, #255\n"
1281373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	BNE     0b\n"
1282373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "2:\n"
1283373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	SUB     %0, %2, D0Ar6\n"
1284373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "3:\n"
1285373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	.section .fixup,\"ax\"\n"
1286373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "4:\n"
1287373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	MOV     %0, #0\n"
1288373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	MOVT    D0FrT,#HI(3b)\n"
1289373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	JUMP    D0FrT,#LO(3b)\n"
1290373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	.previous\n"
1291373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	.section __ex_table,\"a\"\n"
1292373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	.long 1b,4b\n"
1293373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	.previous\n"
1294373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      : "=r" (res)
1295373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      : "r" (src), "r" (count)
1296373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      : "D0FrT", "D0Ar4", "D0Ar6", "cc");
1297373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1298373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return res;
1299373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
13009da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(strnlen_user);
1301373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1302373cd784d0fc83f076c899ca7da50ecca7286e42James Hoganlong __strncpy_from_user(char *dst, const char __user *src, long count)
1303373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan{
1304373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	long res;
1305373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1306373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	if (count == 0)
1307373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		return 0;
1308373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1309373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	/*
1310373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
1311373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *  So do we.
1312373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *
1313373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *  This code is deduced from:
1314373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *
1315373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *      char tmp2;
1316373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *      long tmp1, tmp3;
1317373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *      tmp1 = count;
1318373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *      while ((*dst++ = (tmp2 = *src++)) != 0
1319373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *             && --tmp1)
1320373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *        ;
1321373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *
1322373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *      res = count - tmp1;
1323373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *
1324373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 *  with tweaks.
1325373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	 */
1326373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1327373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	asm volatile ("	MOV  %0,%3\n"
1328373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "1:\n"
1329373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	GETB D0FrT,[%2++]\n"
1330373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "2:\n"
1331373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	CMP  D0FrT,#0\n"
1332373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	SETB [%1++],D0FrT\n"
1333373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	BEQ  3f\n"
1334373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	SUBS %0,%0,#1\n"
1335373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	BNZ  1b\n"
1336373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "3:\n"
1337373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	SUB  %0,%3,%0\n"
1338373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "4:\n"
1339373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	.section .fixup,\"ax\"\n"
1340373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "5:\n"
1341373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	MOV  %0,%7\n"
1342373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	MOVT    D0FrT,#HI(4b)\n"
1343373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	JUMP    D0FrT,#LO(4b)\n"
1344373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	.previous\n"
1345373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	.section __ex_table,\"a\"\n"
1346373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	.long 2b,5b\n"
1347373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      "	.previous"
1348373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      : "=r" (res), "=r" (dst), "=r" (src), "=r" (count)
1349373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      : "3" (count), "1" (dst), "2" (src), "P" (-EFAULT)
1350373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan		      : "D0FrT", "memory", "cc");
1351373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan
1352373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan	return res;
1353373cd784d0fc83f076c899ca7da50ecca7286e42James Hogan}
13549da3ee9aa8a9c9fcf94188d4c0ae280afbeb63c1James HoganEXPORT_SYMBOL(__strncpy_from_user);
1355