xref: /plan9/sys/src/libc/arm/memmove.s (revision 6ca8a7e31df69aa273b57c9a8727a3aa1ead4d4b)
17dd7cddfSDavid du ColombierTS = 0
27dd7cddfSDavid du ColombierTE = 1
37dd7cddfSDavid du ColombierFROM = 2
47dd7cddfSDavid du ColombierN = 3
57dd7cddfSDavid du ColombierTMP = 3					/* N and TMP don't overlap */
67dd7cddfSDavid du ColombierTMP1 = 4
77dd7cddfSDavid du Colombier
8*6ca8a7e3SDavid du ColombierTEXT memcpy(SB), $0
97dd7cddfSDavid du Colombier	B	_memmove
10*6ca8a7e3SDavid du ColombierTEXT memmove(SB), $0
117dd7cddfSDavid du Colombier_memmove:
127dd7cddfSDavid du Colombier	MOVW	R(TS), to+0(FP)		/* need to save for return value */
137dd7cddfSDavid du Colombier	MOVW	from+4(FP), R(FROM)
147dd7cddfSDavid du Colombier	MOVW	n+8(FP), R(N)
157dd7cddfSDavid du Colombier
167dd7cddfSDavid du Colombier	ADD	R(N), R(TS), R(TE)	/* to end pointer */
177dd7cddfSDavid du Colombier
187dd7cddfSDavid du Colombier	CMP	R(FROM), R(TS)
197dd7cddfSDavid du Colombier	BLS	_forward
207dd7cddfSDavid du Colombier
217dd7cddfSDavid du Colombier_back:
227dd7cddfSDavid du Colombier	ADD	R(N), R(FROM)		/* from end pointer */
237dd7cddfSDavid du Colombier	CMP	$4, R(N)		/* need at least 4 bytes to copy */
247dd7cddfSDavid du Colombier	BLT	_b1tail
257dd7cddfSDavid du Colombier
267dd7cddfSDavid du Colombier_b4align:				/* align destination on 4 */
277dd7cddfSDavid du Colombier	AND.S	$3, R(TE), R(TMP)
287dd7cddfSDavid du Colombier	BEQ	_b4aligned
297dd7cddfSDavid du Colombier
307dd7cddfSDavid du Colombier	MOVBU.W	-1(R(FROM)), R(TMP)	/* pre-indexed */
317dd7cddfSDavid du Colombier	MOVBU.W	R(TMP), -1(R(TE))	/* pre-indexed */
327dd7cddfSDavid du Colombier	B	_b4align
337dd7cddfSDavid du Colombier
347dd7cddfSDavid du Colombier_b4aligned:				/* is source now aligned? */
357dd7cddfSDavid du Colombier	AND.S	$3, R(FROM), R(TMP)
367dd7cddfSDavid du Colombier	BNE	_bunaligned
377dd7cddfSDavid du Colombier
387dd7cddfSDavid du Colombier	ADD	$31, R(TS), R(TMP)	/* do 32-byte chunks if possible */
397dd7cddfSDavid du Colombier_b32loop:
407dd7cddfSDavid du Colombier	CMP	R(TMP), R(TE)
417dd7cddfSDavid du Colombier	BLS	_b4tail
427dd7cddfSDavid du Colombier
4351480713SDavid du Colombier	MOVM.DB.W (R(FROM)), [R4-R7]
4451480713SDavid du Colombier	MOVM.DB.W [R4-R7], (R(TE))
4551480713SDavid du Colombier	MOVM.DB.W (R(FROM)), [R4-R7]
4651480713SDavid du Colombier	MOVM.DB.W [R4-R7], (R(TE))
477dd7cddfSDavid du Colombier	B	_b32loop
487dd7cddfSDavid du Colombier
497dd7cddfSDavid du Colombier_b4tail:				/* do remaining words if possible */
507dd7cddfSDavid du Colombier	ADD	$3, R(TS), R(TMP)
517dd7cddfSDavid du Colombier_b4loop:
527dd7cddfSDavid du Colombier	CMP	R(TMP), R(TE)
537dd7cddfSDavid du Colombier	BLS	_b1tail
547dd7cddfSDavid du Colombier
557dd7cddfSDavid du Colombier	MOVW.W	-4(R(FROM)), R(TMP1)	/* pre-indexed */
567dd7cddfSDavid du Colombier	MOVW.W	R(TMP1), -4(R(TE))	/* pre-indexed */
577dd7cddfSDavid du Colombier	B	_b4loop
587dd7cddfSDavid du Colombier
597dd7cddfSDavid du Colombier_b1tail:				/* remaining bytes */
607dd7cddfSDavid du Colombier	CMP	R(TE), R(TS)
617dd7cddfSDavid du Colombier	BEQ	_return
627dd7cddfSDavid du Colombier
637dd7cddfSDavid du Colombier	MOVBU.W	-1(R(FROM)), R(TMP)	/* pre-indexed */
647dd7cddfSDavid du Colombier	MOVBU.W	R(TMP), -1(R(TE))	/* pre-indexed */
657dd7cddfSDavid du Colombier	B	_b1tail
667dd7cddfSDavid du Colombier
677dd7cddfSDavid du Colombier_forward:
687dd7cddfSDavid du Colombier	CMP	$4, R(N)		/* need at least 4 bytes to copy */
697dd7cddfSDavid du Colombier	BLT	_f1tail
707dd7cddfSDavid du Colombier
717dd7cddfSDavid du Colombier_f4align:				/* align destination on 4 */
727dd7cddfSDavid du Colombier	AND.S	$3, R(TS), R(TMP)
737dd7cddfSDavid du Colombier	BEQ	_f4aligned
747dd7cddfSDavid du Colombier
757dd7cddfSDavid du Colombier	MOVBU.P	1(R(FROM)), R(TMP)	/* implicit write back */
767dd7cddfSDavid du Colombier	MOVBU.P	R(TMP), 1(R(TS))	/* implicit write back */
777dd7cddfSDavid du Colombier	B	_f4align
787dd7cddfSDavid du Colombier
797dd7cddfSDavid du Colombier_f4aligned:				/* is source now aligned? */
807dd7cddfSDavid du Colombier	AND.S	$3, R(FROM), R(TMP)
817dd7cddfSDavid du Colombier	BNE	_funaligned
827dd7cddfSDavid du Colombier
837dd7cddfSDavid du Colombier	SUB	$31, R(TE), R(TMP)	/* do 32-byte chunks if possible */
847dd7cddfSDavid du Colombier_f32loop:
857dd7cddfSDavid du Colombier	CMP	R(TMP), R(TS)
867dd7cddfSDavid du Colombier	BHS	_f4tail
877dd7cddfSDavid du Colombier
8851480713SDavid du Colombier	MOVM.IA.W (R(FROM)), [R4-R7]
8951480713SDavid du Colombier	MOVM.IA.W [R4-R7], (R(TS))
9051480713SDavid du Colombier	MOVM.IA.W (R(FROM)), [R4-R7]
9151480713SDavid du Colombier	MOVM.IA.W [R4-R7], (R(TS))
927dd7cddfSDavid du Colombier	B	_f32loop
937dd7cddfSDavid du Colombier
947dd7cddfSDavid du Colombier_f4tail:
957dd7cddfSDavid du Colombier	SUB	$3, R(TE), R(TMP)	/* do remaining words if possible */
967dd7cddfSDavid du Colombier_f4loop:
977dd7cddfSDavid du Colombier	CMP	R(TMP), R(TS)
987dd7cddfSDavid du Colombier	BHS	_f1tail
997dd7cddfSDavid du Colombier
1007dd7cddfSDavid du Colombier	MOVW.P	4(R(FROM)), R(TMP1)	/* implicit write back */
1017dd7cddfSDavid du Colombier	MOVW.P	R4, 4(R(TS))		/* implicit write back */
1027dd7cddfSDavid du Colombier	B	_f4loop
1037dd7cddfSDavid du Colombier
1047dd7cddfSDavid du Colombier_f1tail:
1057dd7cddfSDavid du Colombier	CMP	R(TS), R(TE)
1067dd7cddfSDavid du Colombier	BEQ	_return
1077dd7cddfSDavid du Colombier
1087dd7cddfSDavid du Colombier	MOVBU.P	1(R(FROM)), R(TMP)	/* implicit write back */
1097dd7cddfSDavid du Colombier	MOVBU.P	R(TMP), 1(R(TS))	/* implicit write back */
1107dd7cddfSDavid du Colombier	B	_f1tail
1117dd7cddfSDavid du Colombier
1127dd7cddfSDavid du Colombier_return:
1137dd7cddfSDavid du Colombier	MOVW	to+0(FP), R0
1147dd7cddfSDavid du Colombier	RET
1157dd7cddfSDavid du Colombier
1167dd7cddfSDavid du ColombierRSHIFT = 4
1177dd7cddfSDavid du ColombierLSHIFT = 5
11851480713SDavid du ColombierOFFSET = 11
1197dd7cddfSDavid du Colombier
12051480713SDavid du ColombierBR0 = 6
12151480713SDavid du ColombierBW0 = 7
12251480713SDavid du ColombierBR1 = 7
12351480713SDavid du ColombierBW1 = 8
1247dd7cddfSDavid du Colombier
1257dd7cddfSDavid du Colombier_bunaligned:
1267dd7cddfSDavid du Colombier	CMP	$2, R(TMP)		/* is R(TMP) < 2 ? */
1277dd7cddfSDavid du Colombier
1287dd7cddfSDavid du Colombier	MOVW.LT	$8, R(RSHIFT)		/* (R(n)<<24)|(R(n-1)>>8) */
1297dd7cddfSDavid du Colombier	MOVW.LT	$24, R(LSHIFT)
1307dd7cddfSDavid du Colombier	MOVW.LT	$1, R(OFFSET)
1317dd7cddfSDavid du Colombier
1327dd7cddfSDavid du Colombier	MOVW.EQ	$16, R(RSHIFT)		/* (R(n)<<16)|(R(n-1)>>16) */
1337dd7cddfSDavid du Colombier	MOVW.EQ	$16, R(LSHIFT)
1347dd7cddfSDavid du Colombier	MOVW.EQ	$2, R(OFFSET)
1357dd7cddfSDavid du Colombier
1367dd7cddfSDavid du Colombier	MOVW.GT	$24, R(RSHIFT)		/* (R(n)<<8)|(R(n-1)>>24) */
1377dd7cddfSDavid du Colombier	MOVW.GT	$8, R(LSHIFT)
1387dd7cddfSDavid du Colombier	MOVW.GT	$3, R(OFFSET)
1397dd7cddfSDavid du Colombier
14051480713SDavid du Colombier	ADD	$8, R(TS), R(TMP)	/* do 8-byte chunks if possible */
1417dd7cddfSDavid du Colombier	CMP	R(TMP), R(TE)
1427dd7cddfSDavid du Colombier	BLS	_b1tail
1437dd7cddfSDavid du Colombier
14451480713SDavid du Colombier	BIC	$3, R(FROM)		/* align source */
1457dd7cddfSDavid du Colombier	MOVW	(R(FROM)), R(BR0)	/* prime first block register */
1467dd7cddfSDavid du Colombier
14751480713SDavid du Colombier_bu8loop:
1487dd7cddfSDavid du Colombier	CMP	R(TMP), R(TE)
1497dd7cddfSDavid du Colombier	BLS	_bu1tail
1507dd7cddfSDavid du Colombier
15151480713SDavid du Colombier	MOVW	R(BR0)<<R(LSHIFT), R(BW1)
15251480713SDavid du Colombier	MOVM.DB.W (R(FROM)), [R(BR0)-R(BR1)]
1537dd7cddfSDavid du Colombier	ORR	R(BR1)>>R(RSHIFT), R(BW1)
1547dd7cddfSDavid du Colombier
1557dd7cddfSDavid du Colombier	MOVW	R(BR1)<<R(LSHIFT), R(BW0)
1567dd7cddfSDavid du Colombier	ORR	R(BR0)>>R(RSHIFT), R(BW0)
1577dd7cddfSDavid du Colombier
15851480713SDavid du Colombier	MOVM.DB.W [R(BW0)-R(BW1)], (R(TE))
15951480713SDavid du Colombier	B	_bu8loop
1607dd7cddfSDavid du Colombier
1617dd7cddfSDavid du Colombier_bu1tail:
1627dd7cddfSDavid du Colombier	ADD	R(OFFSET), R(FROM)
1637dd7cddfSDavid du Colombier	B	_b1tail
1647dd7cddfSDavid du Colombier
16551480713SDavid du ColombierRSHIFT = 4
16651480713SDavid du ColombierLSHIFT = 5
16751480713SDavid du ColombierOFFSET = 11
16851480713SDavid du Colombier
16951480713SDavid du ColombierFW0 = 6
17051480713SDavid du ColombierFR0 = 7
17151480713SDavid du ColombierFW1 = 7
17251480713SDavid du ColombierFR1 = 8
1737dd7cddfSDavid du Colombier
1747dd7cddfSDavid du Colombier_funaligned:
1757dd7cddfSDavid du Colombier	CMP	$2, R(TMP)
1767dd7cddfSDavid du Colombier
1777dd7cddfSDavid du Colombier	MOVW.LT	$8, R(RSHIFT)		/* (R(n+1)<<24)|(R(n)>>8) */
1787dd7cddfSDavid du Colombier	MOVW.LT	$24, R(LSHIFT)
1797dd7cddfSDavid du Colombier	MOVW.LT	$3, R(OFFSET)
1807dd7cddfSDavid du Colombier
1817dd7cddfSDavid du Colombier	MOVW.EQ	$16, R(RSHIFT)		/* (R(n+1)<<16)|(R(n)>>16) */
1827dd7cddfSDavid du Colombier	MOVW.EQ	$16, R(LSHIFT)
1837dd7cddfSDavid du Colombier	MOVW.EQ	$2, R(OFFSET)
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier	MOVW.GT	$24, R(RSHIFT)		/* (R(n+1)<<8)|(R(n)>>24) */
1867dd7cddfSDavid du Colombier	MOVW.GT	$8, R(LSHIFT)
1877dd7cddfSDavid du Colombier	MOVW.GT	$1, R(OFFSET)
1887dd7cddfSDavid du Colombier
18951480713SDavid du Colombier	SUB	$8, R(TE), R(TMP)	/* do 8-byte chunks if possible */
1907dd7cddfSDavid du Colombier	CMP	R(TMP), R(TS)
1917dd7cddfSDavid du Colombier	BHS	_f1tail
1927dd7cddfSDavid du Colombier
19351480713SDavid du Colombier	BIC	$3, R(FROM)		/* align source */
19451480713SDavid du Colombier	MOVW.P	4(R(FROM)), R(FR1)	/* prime last block register, implicit write back */
1957dd7cddfSDavid du Colombier
19651480713SDavid du Colombier_fu8loop:
1977dd7cddfSDavid du Colombier	CMP	R(TMP), R(TS)
1987dd7cddfSDavid du Colombier	BHS	_fu1tail
1997dd7cddfSDavid du Colombier
20051480713SDavid du Colombier	MOVW	R(FR1)>>R(RSHIFT), R(FW0)
20151480713SDavid du Colombier	MOVM.IA.W (R(FROM)), [R(FR0)-R(FR1)]
2027dd7cddfSDavid du Colombier	ORR	R(FR0)<<R(LSHIFT), R(FW0)
2037dd7cddfSDavid du Colombier
2047dd7cddfSDavid du Colombier	MOVW	R(FR0)>>R(RSHIFT), R(FW1)
2057dd7cddfSDavid du Colombier	ORR	R(FR1)<<R(LSHIFT), R(FW1)
2067dd7cddfSDavid du Colombier
20751480713SDavid du Colombier	MOVM.IA.W [R(FW0)-R(FW1)], (R(TS))
20851480713SDavid du Colombier	B	_fu8loop
2097dd7cddfSDavid du Colombier
2107dd7cddfSDavid du Colombier_fu1tail:
2117dd7cddfSDavid du Colombier	SUB	R(OFFSET), R(FROM)
2127dd7cddfSDavid du Colombier	B	_f1tail
213