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