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#
6#ident "@(#) m88k-move.sh 1-Sep-92"
7#
8#	This file provided by Data General, February 1990.
9#
10#	This script generates the necessary movstr library functions
11#	for the m88100.  These functions are called from the expansion
12#	of movstrsi.  There are eight modules created by this script,
13#	each with multiple entry points.  One module, moveSI64n
14#	implements a word aligned loop; the other modules, moveXINx
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
30#	parameters.
31#
32#.Revision History
33#
34#	 1-Sep-92   Stan Cox   Added moveDI96x, moveDI41x through moveDI47x.
35#	 2-Jan-92   Tom Wood   Renamed files to comply with SVR3 14 char limit.
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
58usage() {
59    echo "usage: $0 [ -abi ] [ -no-tdesc ]" 1>&2
60    exit 1
61}
62
63awk_flag="-F:";
64awk_begin="BEGIN { "
65ps=""; us="_"; tf="x"; la="@L"; fb="8"; nt="";
66do_file() {
67    echo "	file	 $1";
68}
69
70while [ $# -gt 0 ] ; do
71    case $1 in
72	-no-tdesc) awk_begin="$awk_begin no_tdesc=1;"
73	      nt=";";;
74	-abi) awk_begin="$awk_begin abi=1;"
75	      ps="#"; us=""; tf="a"; la=".L"; fb="16";
76	      do_file() {
77		echo '	version	 "03.00"';
78		echo "	file	 $1";
79	      };;
80	*) usage;;
81    esac
82    shift
83done
84
85rm -f move?I*[xn].s move?I*[xn].asm
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
94#	first value is preloaded into r4 or r5 (r4 if N/4 is odd;
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
103gen_movstrN() {
104  awk $awk_flag "$awk_begin"'
105    if (abi) {
106      ps="#"; us=""; tf="a"; la=".L"; fb=16;
107    } else {
108      ps=""; us="_"; tf="x"; la="@L"; fb=8;
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";
117    printf "\talign\t%d\n", fb;
118    printf "%sloop%s%d:\n", la, mode, count * align;
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;
134	printf "\tbcnd.n\t%sgt0,%sr6,%sloop%s%d\n", ps, ps, la, mode, count * align;
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) {
143      printf "%send%s%d:\n", la, mode, count * align;
144      printf "\tsection\t.tdesc,\"%s\"\n", tf;
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";
148      printf "\ttext\n";
149    }
150    printf "; End of awk generated code.\n";
151    exit;
152  }'
153}
154
155(do_file '"movstrSI64n.s"';
156 echo 'SI::4:16' | gen_movstrN) > moveSI64n.asm
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
174gen_movstrX0() {
175    awk $awk_flag "$awk_begin"'
176      if (abi) {
177	ps="#"; us=""; tf="a"; la=".L"; fb=16;
178      } else {
179	ps=""; us="_"; tf="x"; la="@L"; fb=8;
180      }
181    }
182    NR == 1 && NF == 4 {
183    mode = $1; suffix = $2; align = $3; bytes = $4;
184    ld = align; st = 0; count = bytes / align;
185    reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5;
186    printf "; The following was calculated using awk.\n";
187    printf "\ttext\n";
188    printf "\talign\t%d\n", fb;
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
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;
201      ld += align; st += align;
202    }
203    if (!no_tdesc) {
204      printf "%send%s%dx:\n", la, mode, count * align;
205      printf "\tsection\t.tdesc,\"%s\"\n", tf;
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";
209      printf "\ttext\n";
210    }
211    printf "; End of awk generated code.\n"
212    exit;
213  }'
214}
215
216(do_file '"movstrQI16x.s"';
217 echo 'QI:.b:1:16' | gen_movstrX0) > moveQI16x.asm
218(do_file '"movstrHI48x.s"';
219 echo 'HI:.h:2:48' | gen_movstrX0) > moveHI48x.asm
220(do_file '"movstrSI96x.s"';
221 echo 'SI::4:96'   | gen_movstrX0) > moveSI96x.asm
222(do_file '"movstrDI96x.s"';
223 echo 'DI:.d:8:96'   | gen_movstrX0) > moveDI96x.asm
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
232gen_movstrXr() {
233    awk $awk_flag "$awk_begin"'
234      if (abi) {
235	ps="#"; us=""; tf="a"; la=".L"; fb=16;
236      } else {
237	ps=""; us="_"; tf="x"; la="@L"; fb=8;
238      }
239    }
240    NR == 1 && NF == 4 {
241    mode = $1; rem = $2; most = $3; count = $4;
242    suffix[1] = ".b"; suffix[2] = ".h"; suffix[4] = ""; suffix[8] = ".d";
243
244    prev = align = most;
245    ld = align; st = 0; total = count - rem - most;
246    evenp = int(total/align) % 2;
247    reg[0] = 4; if (align == 8) reg[1] = 6; else reg[1] = 5;
248    printf "; The following was calculated using awk.\n";
249    printf "\ttext\n";
250    printf "\talign\t%d\n", fb;
251    for (bytes = total; bytes >= 0; bytes -= align) {
252      if (bytes < align) {
253	if (bytes >= 4) align = 4;
254	else if (bytes >= 2) align = 2;
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
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;
267      ld += align; st += prev; prev = align;
268      evenp = 1 - evenp;
269    }
270    if (!no_tdesc) {
271      printf "%send%s%dx:\n", la, mode, total + most;
272      printf "\tsection\t.tdesc,\"%s\"\n", tf;
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";
276      printf "\ttext\n";
277    }
278    printf "; End of awk generated code.\n"
279    exit;
280  }'
281}
282
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
298(do_file '"movstrSI47x.s"';
299 echo 'SI:1:4:48' | gen_movstrXr) > moveSI47x.asm
300(do_file '"movstrSI46x.s"';
301 echo 'SI:2:4:48' | gen_movstrXr) > moveSI46x.asm
302(do_file '"movstrSI45x.s"';
303 echo 'SI:3:4:48' | gen_movstrXr) > moveSI45x.asm
304
305(do_file '"movstrHI15x.s"';
306 echo 'HI:1:2:16' | gen_movstrXr) > moveHI15x.asm
307