summaryrefslogtreecommitdiff
path: root/sys/src/libc/68000/memcpy.s
blob: bf4b1d5df3242515c9f6ed49e035e9320e6d98f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
	TEXT	memcpy(SB), $0

	MOVL	n+8(FP), R0	/* count */
	BEQ	return
	BGT	ok
	MOVL	0, R0
ok:
	MOVL	s1+0(FP), A2	/* dest pointer */
	MOVL	s2+4(FP), A1	/* source pointer */

	CMPL	A2,A1
	BHI	back

/*
 * byte-at-a-time foreward copy to
 * get source (A1) alligned.
 */
f1:
	MOVL	A1, R1
	ANDL	$3, R1
	BEQ	f2
	SUBL	$1, R0
	BLT	return
	MOVB	(A1)+, (A2)+
	BRA	f1

/*
 * check that dest is alligned
 * if not, just go byte-at-a-time
 */
f2:
	MOVL	A2, R1
	ANDL	$3, R1
	BEQ	f3
	SUBL	$1, R0
	BLT	return
	BRA	f5
/*
 * quad-long-at-a-time forward copy
 */
f3:
	SUBL	$16, R0
	BLT	f4
	MOVL	(A1)+, (A2)+
	MOVL	(A1)+, (A2)+
	MOVL	(A1)+, (A2)+
	MOVL	(A1)+, (A2)+
	BRA	f3

/*
 * cleanup byte-at-a-time
 */
f4:
	ADDL	$15, R0
	BLT	return
f5:
	MOVB	(A1)+, (A2)+
	SUBL	$1, R0
	BGE	f5
	BRA	return

return:
	MOVL	s1+0(FP),R0
	RTS

/*
 * everything the same, but
 * copy backwards
 */
back:
	ADDL	R0, A1
	ADDL	R0, A2

/*
 * byte-at-a-time backward copy to
 * get source (A1) alligned.
 */
b1:
	MOVL	A1, R1
	ANDL	$3, R1
	BEQ	b2
	SUBL	$1, R0
	BLT	return
	MOVB	-(A1), -(A2)
	BRA	b1

/*
 * check that dest is alligned
 * if not, just go byte-at-a-time
 */
b2:
	MOVL	A2, R1
	ANDL	$3, R1
	BEQ	b3
	SUBL	$1, R0
	BLT	return
	BRA	b5
/*
 * quad-long-at-a-time backward copy
 */
b3:
	SUBL	$16, R0
	BLT	b4
	MOVL	-(A1), -(A2)
	MOVL	-(A1), -(A2)
	MOVL	-(A1), -(A2)
	MOVL	-(A1), -(A2)
	BRA	b3

/*
 * cleanup byte-at-a-time backward
 */
b4:
	ADDL	$15, R0
	BLT	return
b5:
	MOVB	-(A1), -(A2)
	SUBL	$1, R0
	BGE	b5
	BRA	return