]>
Commit | Line | Data |
---|---|---|
bbc83bc2 TW |
1 | #!/bin/sh |
2 | # | |
3 | # If your shell doesn't support functions (true for some BSD users), | |
4 | # you might try using GNU's bash. | |
5 | # | |
f4f0a8ee | 6 | #ident "@(#) m88k-move.sh 1-Sep-92" |
bbc83bc2 | 7 | # |
5887a3c6 | 8 | # This file provided by Data General, February 1990. |
bbc83bc2 TW |
9 | # |
10 | # This script generates the necessary movstr library functions | |
5887a3c6 | 11 | # for the m88100. These functions are called from the expansion |
bbc83bc2 | 12 | # of movstrsi. There are eight modules created by this script, |
5887a3c6 RS |
13 | # each with multiple entry points. One module, moveSI64n |
14 | # implements a word aligned loop; the other modules, moveXINx | |
bbc83bc2 TW |
15 | # implement a straight line copy of N bytes in mode XI. |
16 | # | |
17 | # By analysis of the best memcpy function, it can be determined | |
18 | # what appear to be certain magic numbers. For example, a | |
19 | # memcpy of 13 bytes, where the pointers are determined at run | |
20 | # time to be word aligned takes 28 cycles. A call to | |
21 | # __movstrQI13x13 also takes 28 cycles. The break even point | |
22 | # for a HImode copy is 38 bytes. Just to be on the safe side, | |
23 | # these are bumped to 16 and 48 respectively. | |
24 | # | |
25 | # The smaller, odd-remainder modules are provided to help | |
26 | # mitigate the overhead of copying the last bytes. | |
27 | # | |
28 | # Changes to these functions should not be taken lightly if you | |
29 | # want to be able to link programs built with older movstr | |
5887a3c6 | 30 | # parameters. |
bbc83bc2 TW |
31 | # |
32 | #.Revision History | |
33 | # | |
f4f0a8ee | 34 | # 1-Sep-92 Stan Cox Added moveDI96x, moveDI41x through moveDI47x. |
5887a3c6 | 35 | # 2-Jan-92 Tom Wood Renamed files to comply with SVR3 14 char limit. |
bbc83bc2 TW |
36 | # 26-Oct-90 Tom Wood Delete movstr.h; moved to out-m88k.c. |
37 | # 17-Oct-90 Tom Wood Files are named *.asm rather than *.s. | |
38 | # 11-Sep-90 Jeffrey Friedl | |
39 | # On my BSD 4.3 awk and my GNU-awk, only the | |
40 | # first character of an argument to -F is passed | |
41 | # through, so I can't get this to work. | |
42 | # 5-Sep-90 Ray Essick/Tom Wood | |
43 | # Added a -no-tdesc option. | |
44 | # 27-Aug-90 Vince Guarna/Tom Wood | |
45 | # Version 3 assembler syntax (-abi). | |
46 | # 16-Aug-90 Ron Guilmette | |
47 | # Avoid problems on a Sparc. The common | |
48 | # denominator among shells seems to be '...\' | |
49 | # rather than '...\\'. | |
50 | # 15-Aug-90 Ron Guilmette | |
51 | # Avoid awk syntax errors on a Sun by not using | |
52 | # the `!' operator. | |
53 | # 22-Feb-90 Tom Wood Created. | |
54 | # 20-Jun-90 Tom Wood Emit file directives. | |
55 | # | |
56 | #.End]=--------------------------------------------------------------*/ | |
57 | ||
58 | usage() { | |
59 | echo "usage: $0 [ -abi ] [ -no-tdesc ]" 1>&2 | |
60 | exit 1 | |
61 | } | |
62 | ||
63 | awk_flag="-F:"; | |
64 | awk_begin="BEGIN { " | |
f4f0a8ee | 65 | ps=""; us="_"; tf="x"; la="@L"; fb="8"; nt=""; |
bbc83bc2 TW |
66 | do_file() { |
67 | echo " file $1"; | |
68 | } | |
69 | ||
70 | while [ $# -gt 0 ] ; do | |
71 | case $1 in | |
f4f0a8ee TW |
72 | -no-tdesc) awk_begin="$awk_begin no_tdesc=1;" |
73 | nt=";";; | |
bbc83bc2 | 74 | -abi) awk_begin="$awk_begin abi=1;" |
f4f0a8ee | 75 | ps="#"; us=""; tf="a"; la=".L"; fb="16"; |
bbc83bc2 TW |
76 | do_file() { |
77 | echo ' version "03.00"'; | |
78 | echo " file $1"; | |
79 | };; | |
80 | *) usage;; | |
81 | esac | |
82 | shift | |
83 | done | |
84 | ||
5887a3c6 | 85 | rm -f move?I*[xn].s move?I*[xn].asm |
bbc83bc2 TW |
86 | |
87 | #.Implementation_continued[=----------------------------------------------- | |
88 | # | |
89 | # This generates the word aligned loop. The loop is entered | |
90 | # from the callable entry points ___movstrSI64nN, where at | |
91 | # least N bytes will be copied. r2 is the destination pointer | |
92 | # offset by 4, r3 is the source pointer offset by 4, r6 is the | |
93 | # loop count. Thus, the total bytes moved is 64 * r6 + N. The | |
38e01259 | 94 | # first value is preloaded into r4 or r5 (r4 if N/4 is odd; |
bbc83bc2 TW |
95 | # r5 if N/4 is even). Upon returning, r2 and r3 have been |
96 | # updated and may be used for the remainder bytes to move. | |
97 | # | |
98 | # The code for this loop is generated by the awk program | |
99 | # following. Edit *it*, not what it generates! | |
100 | # | |
101 | #.End]=------------------------------------------------------------------*/ | |
102 | ||
103 | gen_movstrN() { | |
104 | awk $awk_flag "$awk_begin"' | |
105 | if (abi) { | |
f4f0a8ee | 106 | ps="#"; us=""; tf="a"; la=".L"; fb=16; |
bbc83bc2 | 107 | } else { |
f4f0a8ee | 108 | ps=""; us="_"; tf="x"; la="@L"; fb=8; |
bbc83bc2 TW |
109 | } |
110 | } | |
111 | NR == 1 && NF == 4 { | |
112 | mode = $1; suffix = $2; align = $3; count = $4; | |
113 | ld = align; st = 0; | |
114 | ||
115 | printf "; The following was calculated using awk.\n"; | |
116 | printf "\ttext\n"; | |
f4f0a8ee TW |
117 | printf "\talign\t%d\n", fb; |
118 | printf "%sloop%s%d:\n", la, mode, count * align; | |
bbc83bc2 TW |
119 | printf "\taddu\t%sr3,%sr3,%d\n", ps, ps, count * align; |
120 | printf "\taddu\t%sr2,%sr2,%d\n", ps, ps, count * align; | |
121 | printf "\tsubu\t%sr6,%sr6,1\n", ps, ps; | |
122 | for (r = count + 1; r >= 1; r--) { | |
123 | evenp = r % 2; | |
124 | name = sprintf("__%smovstr%s%dn%d", us, mode, count * align, r * align); | |
125 | if (r > 1) { | |
126 | printf "\tglobal\t%s\n", name; | |
127 | printf "%s:\n", name; | |
128 | } | |
129 | if (r > 2) { | |
130 | printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; | |
131 | printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; | |
132 | } else if (r == 2) { | |
133 | printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, 4 + evenp, ps, ld; | |
f4f0a8ee | 134 | printf "\tbcnd.n\t%sgt0,%sr6,%sloop%s%d\n", ps, ps, la, mode, count * align; |
bbc83bc2 TW |
135 | printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; |
136 | printf "\tjmp.n\t%sr1\n", ps; | |
137 | } else { | |
138 | printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, 5 - evenp, ps, st; | |
139 | } | |
140 | ld += align; st += align; | |
141 | } | |
142 | if (!no_tdesc) { | |
f4f0a8ee | 143 | printf "%send%s%d:\n", la, mode, count * align; |
bbc83bc2 | 144 | printf "\tsection\t.tdesc,\"%s\"\n", tf; |
f4f0a8ee TW |
145 | printf "\tword\t0x42,1,%sloop%s%d", la, mode, count * align; |
146 | printf ",%send%s%d\n", la, mode, count * align; | |
147 | printf "\tword\t0x0100001f,0,1,0\n"; | |
bbc83bc2 TW |
148 | printf "\ttext\n"; |
149 | } | |
150 | printf "; End of awk generated code.\n"; | |
151 | exit; | |
152 | }' | |
153 | } | |
154 | ||
155 | (do_file '"movstrSI64n.s"'; | |
5887a3c6 | 156 | echo 'SI::4:16' | gen_movstrN) > moveSI64n.asm |
bbc83bc2 TW |
157 | |
158 | #.Implementation_continued[=----------------------------------------------- | |
159 | # | |
160 | # This generates the even-remainder, straight-line modules. | |
161 | # The code is entered from the callable entry points | |
162 | # ___movstrXINxM, where exactly M bytes will be copied in XI | |
163 | # mode. r2 is the destination pointer, r3 is the source | |
164 | # pointer, neither being offset. The first value is preloaded | |
165 | # into r4 or r5 (r4 if M-N/B is even; r5 if M-N/B is odd, where | |
166 | # B is the mode size of XI). Upon returning, r2 and r3 have not | |
167 | # been changed. | |
168 | # | |
169 | # The code for these cases is generated by the awk program | |
170 | # following. Edit *it*, not what it generates! | |
171 | # | |
172 | #.End]=------------------------------------------------------------------*/ | |
173 | ||
174 | gen_movstrX0() { | |
175 | awk $awk_flag "$awk_begin"' | |
176 | if (abi) { | |
f4f0a8ee | 177 | ps="#"; us=""; tf="a"; la=".L"; fb=16; |
bbc83bc2 | 178 | } else { |
f4f0a8ee | 179 | ps=""; us="_"; tf="x"; la="@L"; fb=8; |
bbc83bc2 TW |
180 | } |
181 | } | |
182 | NR == 1 && NF == 4 { | |
183 | mode = $1; suffix = $2; align = $3; bytes = $4; | |
184 | ld = align; st = 0; count = bytes / align; | |
f4f0a8ee | 185 | reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5; |
bbc83bc2 TW |
186 | printf "; The following was calculated using awk.\n"; |
187 | printf "\ttext\n"; | |
f4f0a8ee | 188 | printf "\talign\t%d\n", fb; |
bbc83bc2 TW |
189 | for (r = count; r >= 1; r--) { |
190 | evenp = r % 2; | |
191 | name = sprintf("__%smovstr%s%dx%d", us, mode, count * align, r * align); | |
192 | if (r > 1) { | |
193 | printf "\tglobal\t%s\n", name; | |
194 | printf "%s:\n", name; | |
195 | } | |
196 | if (r == 1) | |
197 | printf "\tjmp.n\t%sr1\n", ps; | |
198 | else | |
f4f0a8ee TW |
199 | printf "\tld%s\t%sr%d,%sr3,%d\n", suffix, ps, reg[evenp], ps, ld; |
200 | printf "\tst%s\t%sr%d,%sr2,%d\n", suffix, ps, reg[1-evenp], ps, st; | |
bbc83bc2 TW |
201 | ld += align; st += align; |
202 | } | |
203 | if (!no_tdesc) { | |
f4f0a8ee | 204 | printf "%send%s%dx:\n", la, mode, count * align; |
bbc83bc2 | 205 | printf "\tsection\t.tdesc,\"%s\"\n", tf; |
f4f0a8ee TW |
206 | printf "\tword\t0x42,1,__%smovstr%s%dx%d", us, mode, count * align, count * align; |
207 | printf ",%send%s%dx\n", la, mode, count * align; | |
208 | printf "\tword\t0x0100001f,0,1,0\n"; | |
bbc83bc2 TW |
209 | printf "\ttext\n"; |
210 | } | |
211 | printf "; End of awk generated code.\n" | |
212 | exit; | |
213 | }' | |
214 | } | |
215 | ||
216 | (do_file '"movstrQI16x.s"'; | |
5887a3c6 | 217 | echo 'QI:.b:1:16' | gen_movstrX0) > moveQI16x.asm |
bbc83bc2 | 218 | (do_file '"movstrHI48x.s"'; |
5887a3c6 | 219 | echo 'HI:.h:2:48' | gen_movstrX0) > moveHI48x.asm |
bbc83bc2 | 220 | (do_file '"movstrSI96x.s"'; |
5887a3c6 | 221 | echo 'SI::4:96' | gen_movstrX0) > moveSI96x.asm |
f4f0a8ee TW |
222 | (do_file '"movstrDI96x.s"'; |
223 | echo 'DI:.d:8:96' | gen_movstrX0) > moveDI96x.asm | |
bbc83bc2 TW |
224 | |
225 | #.Implementation_continued[=----------------------------------------------- | |
226 | # | |
227 | # This generates the odd-remainder, straight-line modules. The | |
228 | # interface is the same as that for the even-remainder modules. | |
229 | # | |
230 | #.End]=------------------------------------------------------------------*/ | |
231 | ||
232 | gen_movstrXr() { | |
233 | awk $awk_flag "$awk_begin"' | |
234 | if (abi) { | |
f4f0a8ee | 235 | ps="#"; us=""; tf="a"; la=".L"; fb=16; |
bbc83bc2 | 236 | } else { |
f4f0a8ee | 237 | ps=""; us="_"; tf="x"; la="@L"; fb=8; |
bbc83bc2 TW |
238 | } |
239 | } | |
240 | NR == 1 && NF == 4 { | |
241 | mode = $1; rem = $2; most = $3; count = $4; | |
f4f0a8ee | 242 | suffix[1] = ".b"; suffix[2] = ".h"; suffix[4] = ""; suffix[8] = ".d"; |
bbc83bc2 TW |
243 | |
244 | prev = align = most; | |
245 | ld = align; st = 0; total = count - rem - most; | |
246 | evenp = int(total/align) % 2; | |
f4f0a8ee | 247 | reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5; |
bbc83bc2 TW |
248 | printf "; The following was calculated using awk.\n"; |
249 | printf "\ttext\n"; | |
f4f0a8ee | 250 | printf "\talign\t%d\n", fb; |
bbc83bc2 TW |
251 | for (bytes = total; bytes >= 0; bytes -= align) { |
252 | if (bytes < align) { | |
f4f0a8ee TW |
253 | if (bytes >= 4) align = 4; |
254 | else if (bytes >= 2) align = 2; | |
bbc83bc2 TW |
255 | else align = 1; |
256 | } | |
257 | name = sprintf("__%smovstr%s%dx%d", us, mode, total + most, bytes + most); | |
258 | if (bytes > most) { | |
259 | printf "\tglobal\t%s\n", name; | |
260 | printf "%s:\n", name; | |
261 | } | |
262 | if (bytes == 0) | |
263 | printf "\tjmp.n\t%sr1\n", ps; | |
264 | else | |
f4f0a8ee TW |
265 | printf "\tld%s\t%sr%d,%sr3,%d\n", suffix[align], ps, reg[evenp], ps, ld; |
266 | printf "\tst%s\t%sr%d,%sr2,%d\n", suffix[prev], ps, reg[1-evenp], ps, st; | |
bbc83bc2 | 267 | ld += align; st += prev; prev = align; |
f4f0a8ee | 268 | evenp = 1 - evenp; |
bbc83bc2 TW |
269 | } |
270 | if (!no_tdesc) { | |
f4f0a8ee | 271 | printf "%send%s%dx:\n", la, mode, total + most; |
bbc83bc2 | 272 | printf "\tsection\t.tdesc,\"%s\"\n", tf; |
f4f0a8ee TW |
273 | printf "\tword\t0x42,1,__%smovstr%s%dx%d", us, mode, total + most, total + most; |
274 | printf ",%send%s%dx\n", la, mode, total + most; | |
275 | printf "\tword\t0x0100001f,0,1,0\n"; | |
bbc83bc2 TW |
276 | printf "\ttext\n"; |
277 | } | |
278 | printf "; End of awk generated code.\n" | |
279 | exit; | |
280 | }' | |
281 | } | |
282 | ||
f4f0a8ee TW |
283 | (do_file '"movstrDI47x.s"'; |
284 | echo 'DI:1:8:48' | gen_movstrXr) > moveDI47x.asm | |
285 | (do_file '"movstrDI46x.s"'; | |
286 | echo 'DI:2:8:48' | gen_movstrXr) > moveDI46x.asm | |
287 | (do_file '"movstrDI45x.s"'; | |
288 | echo 'DI:3:8:48' | gen_movstrXr) > moveDI45x.asm | |
289 | (do_file '"movstrDI44x.s"'; | |
290 | echo 'DI:4:8:48' | gen_movstrXr) > moveDI44x.asm | |
291 | (do_file '"movstrDI43x.s"'; | |
292 | echo 'DI:5:8:48' | gen_movstrXr) > moveDI43x.asm | |
293 | (do_file '"movstrDI42x.s"'; | |
294 | echo 'DI:6:8:48' | gen_movstrXr) > moveDI42x.asm | |
295 | (do_file '"movstrDI41x.s"'; | |
296 | echo 'DI:7:8:48' | gen_movstrXr) > moveDI41x.asm | |
297 | ||
bbc83bc2 | 298 | (do_file '"movstrSI47x.s"'; |
5887a3c6 | 299 | echo 'SI:1:4:48' | gen_movstrXr) > moveSI47x.asm |
bbc83bc2 | 300 | (do_file '"movstrSI46x.s"'; |
5887a3c6 | 301 | echo 'SI:2:4:48' | gen_movstrXr) > moveSI46x.asm |
bbc83bc2 | 302 | (do_file '"movstrSI45x.s"'; |
5887a3c6 | 303 | echo 'SI:3:4:48' | gen_movstrXr) > moveSI45x.asm |
f4f0a8ee | 304 | |
bbc83bc2 | 305 | (do_file '"movstrHI15x.s"'; |
5887a3c6 | 306 | echo 'HI:1:2:16' | gen_movstrXr) > moveHI15x.asm |