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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
/*
* memmove routine for Z8000
* Copyright (C) 2004 Christian Groessler <chris@groessler.org>
*
* Permission to use, copy, modify, and distribute this file
* for any purpose is hereby granted without fee, provided that
* the above copyright notice and this notice appears in all
* copies.
*
* This file is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* void *memmove(void *dest, const void *src, size_t length);
*/
name "memmove.S"
.text
even
global _memmove
_memmove:
#ifdef __Z8001__
segm
#ifdef __STD_CALL__
ldl rr6,rr14(#4)
ldl rr4,rr14(#8)
ldl rr2,rr14(#12)
#else
pushl @rr14,rr6
#endif
/* rr2 - length (high word ignored)
* rr4 - src
* rr6 - dest
*/
testl rr2
jr z,finish
/* check for destructive overlap (src < dest && dest < src + length) */
cpl rr6,rr4
jp ule,memmove_entry /* non-destructive, let memcpy do the work */
ldl rr0,rr2
addl rr0,rr4 /* rr0 = src + length */
cpl rr0,rr6
jp ult,memmove_entry /* non-destructive, let memcpy do the work */
/* set-up pointers to copy backwards, add (length - 1) */
addl rr4,rr2 /* src + length */
addl rr6,rr2 /* dest + length */
subl rr4,#1
subl rr6,#1
/* check alignment */
bitb rl7,#0 /* odd destination address? */
jr z,testsrc
bitb rl5,#0 /* odd source address? */
jr z,odd_copy
jr even_copy
testsrc:
bitb rl5,#0
jr nz,odd_copy /* src even, dest odd */
lddb @rr6,@rr4,r3
jr ov,finish /* jump if r5 is zero now */
/* copy words */
even_copy:
ld r2,r3 /* remember length */
srl r3,#1
/* jr z,no_words it cannot be zero here */
dec r5,#1
dec r7,#1
lddr @rr6,@rr4,r3
no_words:
bitb rl2,#0 /* odd length? */
jr z,finish
inc r5,#1
inc r7,#1
lddb @rr6,@rr4,r2 /* yes, copy last byte */
jr finish
/* copy bytes */
odd_copy:
lddrb @rr6,@rr4,r3
finish:
#ifdef __STD_CALL__
ldl rr6,rr14(#4)
#else
popl rr2,@rr14
#endif
#else /* above Z8001, below Z8002 */
unsegm
#ifdef __STD_CALL__
ld r7,r15(#2)
ld r6,r15(#4)
ld r5,r15(#6)
#else
ld r2,r7 /* buffer pointer return value */
#endif
/* r5 - length
* r6 - src
* r7 - dest
*/
test r5
jr z,finish
/* check for destructive overlap (src < dest && dest < src + length) */
cp r7,r6
jp ule,memmove_entry /* non-destructive, let memcpy do the work */
ld r0,r5
add r0,r6 /* r0 = src + length */
cp r0,r7
jp ult,memmove_entry /* non-destructive, let memcpy do the work */
/* set-up pointers to copy backwards, add (length - 1) */
add r6,r5 /* src + length */
add r7,r5 /* dest + length */
dec r6,#1
dec r7,#1
/* check alignment */
bitb rl7,#0 /* odd destination address? */
jr z,testsrc
bitb rl6,#0 /* odd source address? */
jr z,odd_copy
jr even_copy
testsrc:
bitb rl6,#0
jr nz,odd_copy /* src even, dest odd */
lddb @r7,@r6,r5
jr ov,finish /* jump if r5 is zero now */
/* copy words */
even_copy:
ld r4,r5 /* remember length */
srl r5,#1
/* jr z,no_words it cannot be zero here */
dec r6,#1
dec r7,#1
lddr @r7,@r6,r5
no_words:
bitb rl4,#0 /* odd length? */
jr z,finish
inc r6,#1
inc r7,#1
lddb @r7,@r6,r4 /* yes, copy last byte */
jr finish
/* copy bytes */
odd_copy:
lddrb @r7,@r6,r5
finish:
#ifdef __STD_CALL__
ld r7,r15(#2)
#endif
#endif /* Z8002 */
ret
.end
|