xref: /plan9/sys/src/ape/lib/ap/arm/memmove.s (revision 514807136a8518a9c368e175000825c6e1429f43)
180ee5cbfSDavid du ColombierTS = 0
280ee5cbfSDavid du ColombierTE = 1
380ee5cbfSDavid du ColombierFROM = 2
480ee5cbfSDavid du ColombierN = 3
580ee5cbfSDavid du ColombierTMP = 3					/* N and TMP don't overlap */
680ee5cbfSDavid du ColombierTMP1 = 4
780ee5cbfSDavid du Colombier
880ee5cbfSDavid du ColombierTEXT memcpy(SB), $-4
980ee5cbfSDavid du Colombier	B	_memmove
1080ee5cbfSDavid du ColombierTEXT memmove(SB), $-4
1180ee5cbfSDavid du Colombier_memmove:
1280ee5cbfSDavid du Colombier	MOVW	R(TS), to+0(FP)		/* need to save for return value */
1380ee5cbfSDavid du Colombier	MOVW	from+4(FP), R(FROM)
1480ee5cbfSDavid du Colombier	MOVW	n+8(FP), R(N)
1580ee5cbfSDavid du Colombier
1680ee5cbfSDavid du Colombier	ADD	R(N), R(TS), R(TE)	/* to end pointer */
1780ee5cbfSDavid du Colombier
1880ee5cbfSDavid du Colombier	CMP	R(FROM), R(TS)
1980ee5cbfSDavid du Colombier	BLS	_forward
2080ee5cbfSDavid du Colombier
2180ee5cbfSDavid du Colombier_back:
2280ee5cbfSDavid du Colombier	ADD	R(N), R(FROM)		/* from end pointer */
2380ee5cbfSDavid du Colombier	CMP	$4, R(N)		/* need at least 4 bytes to copy */
2480ee5cbfSDavid du Colombier	BLT	_b1tail
2580ee5cbfSDavid du Colombier
2680ee5cbfSDavid du Colombier_b4align:				/* align destination on 4 */
2780ee5cbfSDavid du Colombier	AND.S	$3, R(TE), R(TMP)
2880ee5cbfSDavid du Colombier	BEQ	_b4aligned
2980ee5cbfSDavid du Colombier
3080ee5cbfSDavid du Colombier	MOVBU.W	-1(R(FROM)), R(TMP)	/* pre-indexed */
3180ee5cbfSDavid du Colombier	MOVBU.W	R(TMP), -1(R(TE))	/* pre-indexed */
3280ee5cbfSDavid du Colombier	B	_b4align
3380ee5cbfSDavid du Colombier
3480ee5cbfSDavid du Colombier_b4aligned:				/* is source now aligned? */
3580ee5cbfSDavid du Colombier	AND.S	$3, R(FROM), R(TMP)
3680ee5cbfSDavid du Colombier	BNE	_bunaligned
3780ee5cbfSDavid du Colombier
3880ee5cbfSDavid du Colombier	ADD	$31, R(TS), R(TMP)	/* do 32-byte chunks if possible */
3980ee5cbfSDavid du Colombier_b32loop:
4080ee5cbfSDavid du Colombier	CMP	R(TMP), R(TE)
4180ee5cbfSDavid du Colombier	BLS	_b4tail
4280ee5cbfSDavid du Colombier
43*51480713SDavid du Colombier	MOVM.DB.W (R(FROM)), [R4-R7]
44*51480713SDavid du Colombier	MOVM.DB.W [R4-R7], (R(TE))
45*51480713SDavid du Colombier	MOVM.DB.W (R(FROM)), [R4-R7]
46*51480713SDavid du Colombier	MOVM.DB.W [R4-R7], (R(TE))
4780ee5cbfSDavid du Colombier	B	_b32loop
4880ee5cbfSDavid du Colombier
4980ee5cbfSDavid du Colombier_b4tail:				/* do remaining words if possible */
5080ee5cbfSDavid du Colombier	ADD	$3, R(TS), R(TMP)
5180ee5cbfSDavid du Colombier_b4loop:
5280ee5cbfSDavid du Colombier	CMP	R(TMP), R(TE)
5380ee5cbfSDavid du Colombier	BLS	_b1tail
5480ee5cbfSDavid du Colombier
5580ee5cbfSDavid du Colombier	MOVW.W	-4(R(FROM)), R(TMP1)	/* pre-indexed */
5680ee5cbfSDavid du Colombier	MOVW.W	R(TMP1), -4(R(TE))	/* pre-indexed */
5780ee5cbfSDavid du Colombier	B	_b4loop
5880ee5cbfSDavid du Colombier
5980ee5cbfSDavid du Colombier_b1tail:				/* remaining bytes */
6080ee5cbfSDavid du Colombier	CMP	R(TE), R(TS)
6180ee5cbfSDavid du Colombier	BEQ	_return
6280ee5cbfSDavid du Colombier
6380ee5cbfSDavid du Colombier	MOVBU.W	-1(R(FROM)), R(TMP)	/* pre-indexed */
6480ee5cbfSDavid du Colombier	MOVBU.W	R(TMP), -1(R(TE))	/* pre-indexed */
6580ee5cbfSDavid du Colombier	B	_b1tail
6680ee5cbfSDavid du Colombier
6780ee5cbfSDavid du Colombier_forward:
6880ee5cbfSDavid du Colombier	CMP	$4, R(N)		/* need at least 4 bytes to copy */
6980ee5cbfSDavid du Colombier	BLT	_f1tail
7080ee5cbfSDavid du Colombier
7180ee5cbfSDavid du Colombier_f4align:				/* align destination on 4 */
7280ee5cbfSDavid du Colombier	AND.S	$3, R(TS), R(TMP)
7380ee5cbfSDavid du Colombier	BEQ	_f4aligned
7480ee5cbfSDavid du Colombier
7580ee5cbfSDavid du Colombier	MOVBU.P	1(R(FROM)), R(TMP)	/* implicit write back */
7680ee5cbfSDavid du Colombier	MOVBU.P	R(TMP), 1(R(TS))	/* implicit write back */
7780ee5cbfSDavid du Colombier	B	_f4align
7880ee5cbfSDavid du Colombier
7980ee5cbfSDavid du Colombier_f4aligned:				/* is source now aligned? */
8080ee5cbfSDavid du Colombier	AND.S	$3, R(FROM), R(TMP)
8180ee5cbfSDavid du Colombier	BNE	_funaligned
8280ee5cbfSDavid du Colombier
8380ee5cbfSDavid du Colombier	SUB	$31, R(TE), R(TMP)	/* do 32-byte chunks if possible */
8480ee5cbfSDavid du Colombier_f32loop:
8580ee5cbfSDavid du Colombier	CMP	R(TMP), R(TS)
8680ee5cbfSDavid du Colombier	BHS	_f4tail
8780ee5cbfSDavid du Colombier
88*51480713SDavid du Colombier	MOVM.IA.W (R(FROM)), [R4-R7]
89*51480713SDavid du Colombier	MOVM.IA.W [R4-R7], (R(TS))
90*51480713SDavid du Colombier	MOVM.IA.W (R(FROM)), [R4-R7]
91*51480713SDavid du Colombier	MOVM.IA.W [R4-R7], (R(TS))
9280ee5cbfSDavid du Colombier	B	_f32loop
9380ee5cbfSDavid du Colombier
9480ee5cbfSDavid du Colombier_f4tail:
9580ee5cbfSDavid du Colombier	SUB	$3, R(TE), R(TMP)	/* do remaining words if possible */
9680ee5cbfSDavid du Colombier_f4loop:
9780ee5cbfSDavid du Colombier	CMP	R(TMP), R(TS)
9880ee5cbfSDavid du Colombier	BHS	_f1tail
9980ee5cbfSDavid du Colombier
10080ee5cbfSDavid du Colombier	MOVW.P	4(R(FROM)), R(TMP1)	/* implicit write back */
10180ee5cbfSDavid du Colombier	MOVW.P	R4, 4(R(TS))		/* implicit write back */
10280ee5cbfSDavid du Colombier	B	_f4loop
10380ee5cbfSDavid du Colombier
10480ee5cbfSDavid du Colombier_f1tail:
10580ee5cbfSDavid du Colombier	CMP	R(TS), R(TE)
10680ee5cbfSDavid du Colombier	BEQ	_return
10780ee5cbfSDavid du Colombier
10880ee5cbfSDavid du Colombier	MOVBU.P	1(R(FROM)), R(TMP)	/* implicit write back */
10980ee5cbfSDavid du Colombier	MOVBU.P	R(TMP), 1(R(TS))	/* implicit write back */
11080ee5cbfSDavid du Colombier	B	_f1tail
11180ee5cbfSDavid du Colombier
11280ee5cbfSDavid du Colombier_return:
11380ee5cbfSDavid du Colombier	MOVW	to+0(FP), R0
11480ee5cbfSDavid du Colombier	RET
11580ee5cbfSDavid du Colombier
11680ee5cbfSDavid du ColombierRSHIFT = 4
11780ee5cbfSDavid du ColombierLSHIFT = 5
118*51480713SDavid du ColombierOFFSET = 11
11980ee5cbfSDavid du Colombier
120*51480713SDavid du ColombierBR0 = 6
121*51480713SDavid du ColombierBW0 = 7
122*51480713SDavid du ColombierBR1 = 7
123*51480713SDavid du ColombierBW1 = 8
12480ee5cbfSDavid du Colombier
12580ee5cbfSDavid du Colombier_bunaligned:
12680ee5cbfSDavid du Colombier	CMP	$2, R(TMP)		/* is R(TMP) < 2 ? */
12780ee5cbfSDavid du Colombier
12880ee5cbfSDavid du Colombier	MOVW.LT	$8, R(RSHIFT)		/* (R(n)<<24)|(R(n-1)>>8) */
12980ee5cbfSDavid du Colombier	MOVW.LT	$24, R(LSHIFT)
13080ee5cbfSDavid du Colombier	MOVW.LT	$1, R(OFFSET)
13180ee5cbfSDavid du Colombier
13280ee5cbfSDavid du Colombier	MOVW.EQ	$16, R(RSHIFT)		/* (R(n)<<16)|(R(n-1)>>16) */
13380ee5cbfSDavid du Colombier	MOVW.EQ	$16, R(LSHIFT)
13480ee5cbfSDavid du Colombier	MOVW.EQ	$2, R(OFFSET)
13580ee5cbfSDavid du Colombier
13680ee5cbfSDavid du Colombier	MOVW.GT	$24, R(RSHIFT)		/* (R(n)<<8)|(R(n-1)>>24) */
13780ee5cbfSDavid du Colombier	MOVW.GT	$8, R(LSHIFT)
13880ee5cbfSDavid du Colombier	MOVW.GT	$3, R(OFFSET)
13980ee5cbfSDavid du Colombier
140*51480713SDavid du Colombier	ADD	$8, R(TS), R(TMP)	/* do 8-byte chunks if possible */
14180ee5cbfSDavid du Colombier	CMP	R(TMP), R(TE)
14280ee5cbfSDavid du Colombier	BLS	_b1tail
14380ee5cbfSDavid du Colombier
144*51480713SDavid du Colombier	BIC	$3, R(FROM)		/* align source */
14580ee5cbfSDavid du Colombier	MOVW	(R(FROM)), R(BR0)	/* prime first block register */
14680ee5cbfSDavid du Colombier
147*51480713SDavid du Colombier_bu8loop:
14880ee5cbfSDavid du Colombier	CMP	R(TMP), R(TE)
14980ee5cbfSDavid du Colombier	BLS	_bu1tail
15080ee5cbfSDavid du Colombier
151*51480713SDavid du Colombier	MOVW	R(BR0)<<R(LSHIFT), R(BW1)
152*51480713SDavid du Colombier	MOVM.DB.W (R(FROM)), [R(BR0)-R(BR1)]
15380ee5cbfSDavid du Colombier	ORR	R(BR1)>>R(RSHIFT), R(BW1)
15480ee5cbfSDavid du Colombier
15580ee5cbfSDavid du Colombier	MOVW	R(BR1)<<R(LSHIFT), R(BW0)
15680ee5cbfSDavid du Colombier	ORR	R(BR0)>>R(RSHIFT), R(BW0)
15780ee5cbfSDavid du Colombier
158*51480713SDavid du Colombier	MOVM.DB.W [R(BW0)-R(BW1)], (R(TE))
159*51480713SDavid du Colombier	B	_bu8loop
16080ee5cbfSDavid du Colombier
16180ee5cbfSDavid du Colombier_bu1tail:
16280ee5cbfSDavid du Colombier	ADD	R(OFFSET), R(FROM)
16380ee5cbfSDavid du Colombier	B	_b1tail
16480ee5cbfSDavid du Colombier
165*51480713SDavid du ColombierRSHIFT = 4
166*51480713SDavid du ColombierLSHIFT = 5
167*51480713SDavid du ColombierOFFSET = 11
168*51480713SDavid du Colombier
169*51480713SDavid du ColombierFW0 = 6
170*51480713SDavid du ColombierFR0 = 7
171*51480713SDavid du ColombierFW1 = 7
172*51480713SDavid du ColombierFR1 = 8
17380ee5cbfSDavid du Colombier
17480ee5cbfSDavid du Colombier_funaligned:
17580ee5cbfSDavid du Colombier	CMP	$2, R(TMP)
17680ee5cbfSDavid du Colombier
17780ee5cbfSDavid du Colombier	MOVW.LT	$8, R(RSHIFT)		/* (R(n+1)<<24)|(R(n)>>8) */
17880ee5cbfSDavid du Colombier	MOVW.LT	$24, R(LSHIFT)
17980ee5cbfSDavid du Colombier	MOVW.LT	$3, R(OFFSET)
18080ee5cbfSDavid du Colombier
18180ee5cbfSDavid du Colombier	MOVW.EQ	$16, R(RSHIFT)		/* (R(n+1)<<16)|(R(n)>>16) */
18280ee5cbfSDavid du Colombier	MOVW.EQ	$16, R(LSHIFT)
18380ee5cbfSDavid du Colombier	MOVW.EQ	$2, R(OFFSET)
18480ee5cbfSDavid du Colombier
18580ee5cbfSDavid du Colombier	MOVW.GT	$24, R(RSHIFT)		/* (R(n+1)<<8)|(R(n)>>24) */
18680ee5cbfSDavid du Colombier	MOVW.GT	$8, R(LSHIFT)
18780ee5cbfSDavid du Colombier	MOVW.GT	$1, R(OFFSET)
18880ee5cbfSDavid du Colombier
189*51480713SDavid du Colombier	SUB	$8, R(TE), R(TMP)	/* do 8-byte chunks if possible */
19080ee5cbfSDavid du Colombier	CMP	R(TMP), R(TS)
19180ee5cbfSDavid du Colombier	BHS	_f1tail
19280ee5cbfSDavid du Colombier
193*51480713SDavid du Colombier	BIC	$3, R(FROM)		/* align source */
194*51480713SDavid du Colombier	MOVW.P	4(R(FROM)), R(FR1)	/* prime last block register, implicit write back */
19580ee5cbfSDavid du Colombier
196*51480713SDavid du Colombier_fu8loop:
19780ee5cbfSDavid du Colombier	CMP	R(TMP), R(TS)
19880ee5cbfSDavid du Colombier	BHS	_fu1tail
19980ee5cbfSDavid du Colombier
200*51480713SDavid du Colombier	MOVW	R(FR1)>>R(RSHIFT), R(FW0)
201*51480713SDavid du Colombier	MOVM.IA.W (R(FROM)), [R(FR0)-R(FR1)]
20280ee5cbfSDavid du Colombier	ORR	R(FR0)<<R(LSHIFT), R(FW0)
20380ee5cbfSDavid du Colombier
20480ee5cbfSDavid du Colombier	MOVW	R(FR0)>>R(RSHIFT), R(FW1)
20580ee5cbfSDavid du Colombier	ORR	R(FR1)<<R(LSHIFT), R(FW1)
20680ee5cbfSDavid du Colombier
207*51480713SDavid du Colombier	MOVM.IA.W [R(FW0)-R(FW1)], (R(TS))
208*51480713SDavid du Colombier	B	_fu8loop
20980ee5cbfSDavid du Colombier
21080ee5cbfSDavid du Colombier_fu1tail:
21180ee5cbfSDavid du Colombier	SUB	R(OFFSET), R(FROM)
21280ee5cbfSDavid du Colombier	B	_f1tail
213