xref: /csrg-svn/sys/tahoe/inline/machdep.c (revision 25692)
1 /*
2  * Copyright (c) 1984 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)machdep.c	1.2 (Berkeley) 01/05/86";
9 #endif
10 
11 #include <stdio.h>
12 #include <ctype.h>
13 #include "inline.h"
14 
15 /*
16  * The routines and tables in this file must be rewritten
17  * for each new machine that this program is ported to.
18  */
19 
20 #if defined(vax)
21 /*
22  * Instruction stop table.
23  * All instructions that implicitly modify any of the temporary
24  * registers, change control flow, or implicitly loop must be
25  * listed in this table. It is used to find the end of a basic
26  * block when scanning backwards through the instruction stream
27  * trying to merge the inline expansion.
28  */
29 struct inststoptbl inststoptable[] = {
30 	{ "jbc" }, { "jlbc" }, { "jbs" }, { "jlbs" }, { "jbcc" },
31 	{ "jbsc" }, { "jbcs" }, { "jbss" }, { "jbr" }, { "jcc" },
32 	{ "jcs" }, { "jvc" }, { "jvs" }, { "jlss" }, { "jlssu" },
33 	{ "jleq" }, { "jlequ" }, { "jeql" }, { "jeqlu" }, { "jneq" },
34 	{ "jnequ" }, { "jgeq" }, { "jgequ" }, { "jgtr" }, { "jgtru" },
35 	{ "chmk" }, { "chme" }, { "chms" }, { "chmu" }, { "rei" },
36 	{ "ldpctx" }, { "svpctx" }, { "xfc" }, { "bpt" },
37 	{ "bugw" }, { "bugl" }, { "halt" }, { "pushr" }, { "popr" },
38 	{ "polyf" }, { "polyd" }, { "polyg" }, { "polyh" },
39 	{ "bneq" }, { "bnequ" }, { "beql" }, { "beqlu" }, { "bgtr" },
40 	{ "bleq" }, { "bgeq" }, { "blss" }, { "bgtru" }, { "blequ" },
41 	{ "bvc" }, { "bvs" }, { "bgequ" }, { "bcc" }, { "blssu" },
42 	{ "bcs" }, { "brb" }, { "brw" }, { "jmp" },
43 	{ "bbs" }, { "bbc" }, { "bbss" }, { "bbcs" }, { "bbsc" },
44 	{ "bbcc" }, { "bbssi" }, { "bbcci" }, { "blbs" }, { "blbc" },
45 	{ "acbb" }, { "acbw" }, { "acbl" }, { "acbf" }, { "acbd" },
46 	{ "acbg" }, { "acbh" }, { "aoblss" }, { "aobleq" },
47 	{ "sobgeq" }, { "sobgtr" }, { "caseb" }, { "casew" }, { "casel" },
48 	{ "bsbb" }, { "bsbw" }, { "jsb" }, { "rsb" },
49 	{ "callg" }, { "calls" }, { "ret" },
50 	{ "movc3" }, { "movc5" }, { "movtc" }, { "movtuc" },
51 	{ "cmpc3" }, { "cmpc5" }, { "scanc" }, { "spanc" },
52 	{ "locc" }, { "skpc" }, { "matchc" }, { "crc" },
53 	{ "movp" }, { "cmpp3" }, { "cmpp4" }, { "addp4" }, { "addp6" },
54 	{ "subp4" }, { "subp6" }, { "mulp" }, { "divp" }, { "cvtlp" },
55 	{ "cvtpl" }, { "cvtpt" }, { "cvttp" }, { "cvtps" }, { "cvtsp" },
56 	{ "ashp" }, { "editpc" },
57 	{ "escd" }, { "esce" }, { "escf" },
58 	{ "" }
59 };
60 
61 /*
62  * Check to see if a line is a candidate for replacement.
63  * Return pointer to name to be looked up in pattern table.
64  */
65 char *
66 doreplaceon(cp)
67 	char *cp;
68 {
69 
70 	if (bcmp(cp, "calls\t$", 7) == 0)
71 		return (cp + 7);
72 	return (0);
73 }
74 #endif
75 
76 #if defined(tahoe)
77 /*
78  * Instruction stop table.
79  * All instructions that implicitly modify any of the temporary
80  * registers, change control flow, or implicitly loop must be
81  * listed in this table. It is used to find the end of a basic
82  * block when scanning backwards through the instruction stream
83  * trying to merge the inline expansion.
84  */
85 struct inststoptbl inststoptable[] = {
86 /* control */
87 	{ "bbssi" }, { "bcc" }, { "bcs" }, { "beql" }, { "beqlu" },
88 	{ "bgeq" }, { "bgequ" }, { "bgtr" }, { "bgtru" }, { "bleq" },
89 	{ "blequ" }, { "blss" }, { "blssu" }, { "bneq" }, { "bnequ" },
90 	{ "brb" }, { "brw" }, { "bvc" }, { "bvs" }, { "jmp" },
91 /* jump versions of control */
92 	{ "jbc" }, { "jbs" }, { "jeql" }, { "jeqlu" },
93 	{ "jgeq" }, { "jgequ" }, { "jgtr" }, { "jgtru" }, { "jleq" },
94 	{ "jlequ" }, { "jlss" }, { "jlssu" }, { "jneq" }, { "jnequ" },
95 	{ "jcc" }, { "jcs" }, { "jvc" }, { "jvs" }, { "jbr" },
96 /* multiple registers */
97 	{ "loadr" },
98 /* bit field */
99 	{ "bbc" }, { "bbs" },
100 /* character string and block move */
101 	{ "cmps2" }, { "cmps3" }, { "movblk" }, { "movs2" }, { "movs3" },
102 /* procedure call */
103 	{ "callf" }, { "calls" }, { "ret" },
104 /* loop control */
105 	{ "aobleq" }, { "aoblss" }, { "casel" },
106 /* privileged and miscellaneous */
107 	{ "bpt" }, { "halt" }, { "kcall" }, { "ldpctx" }, { "rei" },
108 	{ "svpctx" },
109 	{ "" }
110 };
111 
112 /*
113  * Check to see if a line is a candidate for replacement.
114  * Return pointer to name to be looked up in pattern table.
115  */
116 char *
117 doreplaceon(cp)
118 	char *cp;
119 {
120 
121 	if (bcmp(cp, "callf\t$", 7) == 0)
122 		return (cp + 7);
123 	return (0);
124 }
125 #endif
126 
127 #if defined(vax) || defined(tahoe)
128 /*
129  * Find the next argument to the function being expanded.
130  */
131 nextarg(argc, argv)
132 	int argc;
133 	char *argv[];
134 {
135 	register char *lastarg = argv[2];
136 
137 	if (argc == 3 &&
138 	    bcmp(argv[0], "mov", 3) == 0 &&
139 	    bcmp(argv[1], "(sp)+", 6) == 0 &&
140 	    lastarg[0] == 'r' && isdigit(lastarg[1]) && lastarg[2] == '\0')
141 		return (lastarg[1] - '0');
142 	return (-1);
143 }
144 
145 /*
146  * Determine whether the current line pushes an argument.
147  */
148 ispusharg(argc, argv)
149 	int argc;
150 	char *argv[];
151 {
152 
153 	if (argc < 2)
154 		return (0);
155 	if (argc == 2 && bcmp(argv[0], "push", 4) == 0)
156 		return (1);
157 	if (bcmp(argv[argc - 1], "-(sp)", 6) == 0)
158 		return (1);
159 	return (0);
160 }
161 
162 /*
163  * Determine which (if any) registers are modified
164  * Return register number that is modified, -1 if none are modified.
165  */
166 modifies(argc, argv)
167 	int argc;
168 	char *argv[];
169 {
170 	register char *lastarg = argv[argc - 1];
171 
172 	/*
173 	 * For the VAX or TAHOE all we care about are r0 to r5
174 	 */
175 	if (lastarg[0] == 'r' && isdigit(lastarg[1]) && lastarg[2] == '\0')
176 		return (lastarg[1] - '0');
177 	return (-1);
178 }
179 
180 /*
181  * Rewrite the instruction in (argc, argv) to store its
182  * contents into arg instead of onto the stack. The new
183  * instruction is placed in the buffer that is provided.
184  */
185 rewrite(instbuf, argc, argv, target)
186 	char *instbuf;
187 	int argc;
188 	char *argv[];
189 	int target;
190 {
191 
192 	switch (argc) {
193 	case 0:
194 		instbuf[0] = '\0';
195 		fprintf(stderr, "blank line to rewrite?\n");
196 		return;
197 	case 1:
198 		sprintf(instbuf, "\t%s\n", argv[0]);
199 		fprintf(stderr, "rewrite?-> %s", instbuf);
200 		return;
201 	case 2:
202 		if (bcmp(argv[0], "push", 4) == 0) {
203 			sprintf(instbuf, "\tmov%s\t%s,r%d\n",
204 				&argv[0][4], argv[1], target);
205 			return;
206 		}
207 		sprintf(instbuf, "\t%s\tr%d\n", argv[0], target);
208 		return;
209 	case 3:
210 		sprintf(instbuf, "\t%s\t%s,r%d\n", argv[0], argv[1], target);
211 		return;
212 	case 4:
213 		sprintf(instbuf, "\t%s\t%s,%s,r%d\n",
214 			argv[0], argv[1], argv[2], target);
215 		return;
216 	case 5:
217 		sprintf(instbuf, "\t%s\t%s,%s,%s,r%d\n",
218 			argv[0], argv[1], argv[2], argv[3], target);
219 		return;
220 	default:
221 		sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]);
222 		argc -= 2, argv += 2;
223 		while (argc-- > 0) {
224 			strcat(instbuf, ",");
225 			strcat(instbuf, *argv++);
226 		}
227 		strcat(instbuf, "\n");
228 		fprintf(stderr, "rewrite?-> %s", instbuf);
229 		return;
230 	}
231 }
232 
233 /*
234  * Do any necessary post expansion cleanup.
235  */
236 cleanup(numargs)
237 	int numargs;
238 {
239 
240 	return;
241 }
242 #endif
243 
244 #if defined(mc68000)
245 /*
246  * Instruction stop table.
247  * All instructions that implicitly modify any of the temporary
248  * registers, change control flow, or implicitly loop must be
249  * listed in this table. It is used to find the end of a basic
250  * block when scanning backwards through the instruction stream
251  * trying to merge the inline expansion.
252  */
253 struct inststoptbl inststoptable[] = {
254 	{ "" }
255 };
256 
257 /*
258  * Check to see if a line is a candidate for replacement.
259  * Return pointer to name to be looked up in pattern table.
260  */
261 char *
262 doreplaceon(cp)
263 	char *cp;
264 {
265 
266 	if (bcmp(cp, "jbsr\t", 5) == 0)
267 		return (cp + 5);
268 	return (0);
269 }
270 
271 /*
272  * Find the next argument to the function being expanded.
273  */
274 nextarg(argc, argv)
275 	int argc;
276 	char *argv[];
277 {
278 	register char *lastarg = argv[2];
279 
280 	if (argc == 3 &&
281 	    bcmp(argv[0], "movl", 5) == 0 &&
282 	    bcmp(argv[1], "sp@+", 5) == 0 &&
283 	    (lastarg[1] == '0' || lastarg[1] == '1') &&
284 	    lastarg[2] == '\0') {
285 		if (lastarg[0] == 'd')
286 			return (lastarg[1] - '0');
287 		return (lastarg[1] - '0' + 8);
288 	}
289 	return (-1);
290 }
291 
292 /*
293  * Determine whether the current line pushes an argument.
294  */
295  ispusharg(argc, argv)
296 	int argc;
297 	char *argv[];
298 {
299 
300 	if (argc < 2)
301 		return (0);
302 	if (argc == 2 && bcmp(argv[0], "pea", 4) == 0)
303 		return (1);
304 	if (bcmp(argv[argc - 1], "sp@-", 5) == 0)
305 		return (1);
306 	return (0);
307 }
308 
309 /*
310  * Determine which (if any) registers are modified
311  * Return register number that is modified, -1 if none are modified.
312  */
313 modifies(argc, argv)
314 	int argc;
315 	char *argv[];
316 {
317 	/*
318 	 * For the MC68000 all we care about are d0, d1, a0, and a1.
319 	 */
320 	register char *lastarg = argv[argc - 1];
321 
322 	if (lastarg[0] == 'd' && isdigit(lastarg[1]) && lastarg[2] == '\0')
323 		return (lastarg[1] - '0');
324 	if (lastarg[0] == 'a' && isdigit(lastarg[1]) && lastarg[2] == '\0')
325 		return (lastarg[1] - '0' + 8);
326 	return (-1);
327 }
328 
329 /*
330  * Rewrite the instruction in (argc, argv) to store its
331  * contents into arg instead of onto the stack. The new
332  * instruction is placed in the buffer that is provided.
333  */
334 rewrite(instbuf, argc, argv, target)
335 	char *instbuf;
336 	int argc;
337 	char *argv[];
338 	int target;
339 {
340 	int regno;
341 	char regtype;
342 
343 	if (target < 8) {
344 		regtype = 'd';
345 		regno = target;
346 	} else {
347 		regtype = 'a';
348 		regno = target - 8;
349 	}
350 	switch (argc) {
351 	case 0:
352 		instbuf[0] = '\0';
353 		fprintf(stderr, "blank line to rewrite?\n");
354 		return;
355 	case 1:
356 		sprintf(instbuf, "\t%s\n", argv[0]);
357 		fprintf(stderr, "rewrite?-> %s", instbuf);
358 		return;
359 	case 2:
360 		if (bcmp(argv[0], "pea", 4) == 0) {
361 			if (regtype == 'a') {
362 				sprintf(instbuf, "\tlea\t%s,%c%d\n",
363 					argv[1], regtype, regno);
364 				return;
365 			}
366 			if (argv[1][0] == '_' || isdigit(argv[1][0])) {
367 				sprintf(instbuf, "\tmovl\t#%s,%c%d\n",
368 					argv[1], regtype, regno);
369 				return;
370 			}
371 			sprintf(instbuf,
372 				"\texg\ta0,d%d\n\tlea\t%s,a0\n\texg\ta0,d%d\n",
373 				regno, argv[1], regno);
374 			return;
375 		}
376 		sprintf(instbuf, "\t%s\t%c%d\n", argv[0], regtype, regno);
377 		return;
378 	case 3:
379 		sprintf(instbuf, "\t%s\t%s,%c%d\n",
380 			argv[0], argv[1], regtype, regno);
381 		return;
382 	default:
383 		sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]);
384 		argc -= 2, argv += 2;
385 		while (argc-- > 0) {
386 			strcat(instbuf, ",");
387 			strcat(instbuf, *argv++);
388 		}
389 		strcat(instbuf, "\n");
390 		fprintf(stderr, "rewrite?-> %s", instbuf);
391 		return;
392 	}
393 }
394 
395 /*
396  * Do any necessary post expansion cleanup.
397  */
398 cleanup(numargs)
399 	int numargs;
400 {
401 
402 	if (numargs == 0)
403 		return;
404 	/*
405 	 * delete instruction to pop arguments.
406 	 * TODO:
407 	 *	CHECK FOR LABEL
408 	 *	CHECK THAT INSTRUCTION IS A POP
409 	 */
410 	fgets(line[bufhead], MAXLINELEN, stdin);
411 }
412 #endif
413