|
|
1.1 root 1: /* Copyright (c) 1984 Regents of the University of California */
2:
3: #ifndef lint
4: static char sccsid[] = "@(#)machdep.c 1.4 (Berkeley) 9/20/84";
5: #endif not lint
6:
7: #include <stdio.h>
8: #include <ctype.h>
9: #include "inline.h"
10:
11: /*
12: * The routines and tables in this file must be rewritten
13: * for each new machine that this program is ported to.
14: */
15:
16: #ifdef vax
17: /*
18: * Instruction stop table.
19: * All instructions that implicitly modify any of the temporary
20: * registers, change control flow, or implicitly loop must be
21: * listed in this table. It is used to find the end of a basic
22: * block when scanning backwards through the instruction stream
23: * trying to merge the inline expansion.
24: */
25: struct inststoptbl inststoptable[] = {
26: { "jbc" }, { "jlbc" }, { "jbs" }, { "jlbs" }, { "jbcc" },
27: { "jbsc" }, { "jbcs" }, { "jbss" }, { "jbr" }, { "jcc" },
28: { "jcs" }, { "jvc" }, { "jvs" }, { "jlss" }, { "jlssu" },
29: { "jleq" }, { "jlequ" }, { "jeql" }, { "jeqlu" }, { "jneq" },
30: { "jnequ" }, { "jgeq" }, { "jgequ" }, { "jgtr" }, { "jgtru" },
31: { "chmk" }, { "chme" }, { "chms" }, { "chmu" }, { "rei" },
32: { "ldpctx" }, { "svpctx" }, { "xfc" }, { "bpt" },
33: { "bugw" }, { "bugl" }, { "halt" }, { "pushr" }, { "popr" },
34: { "polyf" }, { "polyd" }, { "polyg" }, { "polyh" },
35: { "bneq" }, { "bnequ" }, { "beql" }, { "beqlu" }, { "bgtr" },
36: { "bleq" }, { "bgeq" }, { "blss" }, { "bgtru" }, { "blequ" },
37: { "bvc" }, { "bvs" }, { "bgequ" }, { "bcc" }, { "blssu" },
38: { "bcs" }, { "brb" }, { "brw" }, { "jmp" },
39: { "bbs" }, { "bbc" }, { "bbss" }, { "bbcs" }, { "bbsc" },
40: { "bbcc" }, { "bbssi" }, { "bbcci" }, { "blbs" }, { "blbc" },
41: { "acbb" }, { "acbw" }, { "acbl" }, { "acbf" }, { "acbd" },
42: { "acbg" }, { "acbh" }, { "aoblss" }, { "aobleq" },
43: { "sobgeq" }, { "sobgtr" }, { "caseb" }, { "casew" }, { "casel" },
44: { "bsbb" }, { "bsbw" }, { "jsb" }, { "rsb" },
45: { "callg" }, { "calls" }, { "ret" },
46: { "movc3" }, { "movc5" }, { "movtc" }, { "movtuc" },
47: { "cmpc3" }, { "cmpc5" }, { "scanc" }, { "spanc" },
48: { "locc" }, { "skpc" }, { "matchc" }, { "crc" },
49: { "movp" }, { "cmpp3" }, { "cmpp4" }, { "addp4" }, { "addp6" },
50: { "subp4" }, { "subp6" }, { "mulp" }, { "divp" }, { "cvtlp" },
51: { "cvtpl" }, { "cvtpt" }, { "cvttp" }, { "cvtps" }, { "cvtsp" },
52: { "ashp" }, { "editpc" },
53: { "escd" }, { "esce" }, { "escf" },
54: { "" }
55: };
56:
57: /*
58: * Check to see if a line is a candidate for replacement.
59: * Return pointer to name to be looked up in pattern table.
60: */
61: char *
62: doreplaceon(cp)
63: char *cp;
64: {
65:
66: if (bcmp(cp, "calls\t$", 7) == 0)
67: return (cp + 7);
68: return (0);
69: }
70:
71: /*
72: * Find the next argument to the function being expanded.
73: * If register ends with a '#' then source may be used directly.
74: * If register ends with a '@' then source may be used if an indirect
75: * version exists.
76: */
77:
78: nextarg(argc, argv, flag)
79: int argc;
80: char *argv[];
81: int *flag;
82: {
83: register char *lastarg = argv[2];
84:
85: *flag = 0;
86:
87: if (argc == 3 &&
88: bcmp(argv[0], "mov", 3) == 0 &&
89: bcmp(argv[1], "(sp)+", 6) == 0 &&
90: lastarg[0] == 'r' && isdigit(lastarg[1])) {
91: if (lastarg[2] == '\0') {
92: return (lastarg[1] - '0');
93: } else if (lastarg[2] == '$') {
94: *flag = F_VALUE;
95: return (lastarg[1] - '0');
96: } else if (lastarg[2] == '*') {
97: *flag = F_INDIRECT;
98: return (lastarg[1] - '0');
99: }
100: }
101: return (-1);
102: }
103:
104: /*
105: * Determine whether the current line pushes an argument.
106: */
107: ispusharg(argc, argv)
108: int argc;
109: char *argv[];
110: {
111:
112: if (argc < 2)
113: return (0);
114: if (argc == 2 && bcmp(argv[0], "push", 4) == 0)
115: return (1);
116: if (bcmp(argv[argc - 1], "-(sp)", 6) == 0)
117: return (1);
118: return (0);
119: }
120:
121: /*
122: * Determine which (if any) registers are modified
123: * Return register number that is modified, -1 if none are modified.
124: */
125: modifies(argc, argv)
126: int argc;
127: char *argv[];
128: {
129: /*
130: * For the VAX all we care about are r0 to r5
131: */
132: register char *lastarg = argv[argc - 1];
133:
134: if (lastarg[0] == 'r' && isdigit(lastarg[1]) && lastarg[2] == '\0')
135: return (lastarg[1] - '0');
136: return (-1);
137: }
138:
139: checkvar(argc, argv, flag, source, mod)
140: int argc;
141: char *argv[];
142: int flag;
143: char *source;
144: {
145: register char *cp1, *cp2;
146: register int opind = 0;
147: char *indirect();
148:
149: if (flag == 0) return(0);
150:
151: if (bcmp(argv[0], "push", 4) != 0 && bcmp(argv[0], "mov", 3) != 0)
152: return(0);
153:
154: cp1 = argv[1];
155: while (*cp1) if (*cp1++ == 'r' && isdigit(*cp1) &&
156: (mod & (1 << (*cp1++ - '0'))) &&
157: (*cp1 == '\0' || *cp1 == ')' || *cp1 == ']'))
158: return(0);
159:
160: if ((argv[0][0] == 'p' && argv[0][4] == 'a') ||
161: (argv[0][0] == 'm' && argv[0][3] == 'a'))
162: opind++;
163:
164: if (flag & F_VALUE) {
165: if (opind) return(0);
166: cp1 = argv[1];
167: cp2 = source;
168: while (*cp2++ = *cp1++) ;
169: return(1);
170: }
171:
172: if (flag & F_INDIRECT) {
173: cp2 = source;
174: if (opind) {
175: cp1 = argv[1];
176: } else {
177: cp1 = indirect(argv[1]);
178: if (cp1 == NULL) return(0);
179: }
180: while (*cp2++ = *cp1++) ;
181: return(1);
182: }
183:
184: return(0);
185: }
186:
187: /*
188: * Rewrite the instruction in (argc, argv) to store its
189: * contents into arg instead of onto the stack. The new
190: * instruction is placed in the buffer that is provided.
191: */
192: rewrite(instbuf, argc, argv, target)
193: char *instbuf;
194: int argc;
195: char *argv[];
196: int target;
197: {
198:
199: switch (argc) {
200: case 0:
201: instbuf[0] = '\0';
202: fprintf("blank line to rewrite?\n");
203: return;
204: case 1:
205: sprintf(instbuf, "\t%s\n", argv[0]);
206: fprintf(stderr, "rewrite?-> %s", instbuf);
207: return;
208: case 2:
209: if (bcmp(argv[0], "push", 4) == 0) {
210: sprintf(instbuf, "\tmov%s\t%s,r%d\n",
211: &argv[0][4], argv[1], target);
212: return;
213: }
214: sprintf(instbuf, "\t%s\tr%d\n", argv[0], target);
215: return;
216: case 3:
217: sprintf(instbuf, "\t%s\t%s,r%d\n", argv[0], argv[1], target);
218: return;
219: case 4:
220: sprintf(instbuf, "\t%s\t%s,%s,r%d\n",
221: argv[0], argv[1], argv[2], target);
222: return;
223: case 5:
224: sprintf(instbuf, "\t%s\t%s,%s,%s,r%d\n",
225: argv[0], argv[1], argv[2], argv[3], target);
226: return;
227: default:
228: sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]);
229: argc -= 2, argv += 2;
230: while (argc-- > 0) {
231: strcat(instbuf, ",");
232: strcat(instbuf, *argv++);
233: }
234: strcat(instbuf, "\n");
235: fprintf(stderr, "rewrite?-> %s", instbuf);
236: return;
237: }
238: }
239:
240: /* Return indirect version of variable:
241: * $Lnn -> Lnn
242: * rn -> (rn)
243: * (rn) -> *(rn)
244: * a(rn) -> *a(rn)
245: * (rn)[rm] -> *(rn)[rm]
246: * a(rn)[rm] -> *a(rn)[rm]
247: * _foo -> *_foo
248: * _foo(rn) -> *_foo(rn)
249: * _foo(rn)[rm] -> *_foo(rn)[rm]
250: * (rn)+ -> NULL
251: * -(rn) -> NULL
252: * *<any> -> NULL
253: */
254: char *
255: indirect(cp)
256: register char *cp;
257: {
258: static char newvar[16];
259: register char *c;
260: int neg = 0;
261: int offset = 0;
262:
263: /* *<any> | -(rn) */
264: if (*cp == '*' || (*cp == '-' && *(cp+1) == '(')) return(NULL);
265:
266: /* (rn)+ | (rn)x */
267: if (*cp == '(') {
268: c = cp;
269: while (*++c != ')') ;
270: if (*++c == '+') return(NULL);
271: c = newvar;
272: *c++ = '*';
273: while (*c++ = *cp++);
274: return(newvar);
275: }
276:
277: /* $Lnn */
278: if (*cp == '$' && *(cp+1) == 'L') {
279: c = newvar;
280: cp++;
281: while (*c++ = *cp++) ;
282: return(newvar);
283: }
284:
285: /* rn */
286: if (*cp == 'r') {
287: c = newvar;
288: *c++ = '(';
289: while (*c++ = *cp++) ;
290: *(c-1) = ')';
291: *c = 0;
292: return(newvar);
293: }
294:
295: /* everything else */
296: c = newvar;
297: *c++ = '*';
298: while (*c++ = *cp++) ;
299: return(newvar);
300: }
301:
302: output_replace(replace, oparg, argno, f)
303: register char *replace;
304: struct oparg oparg[];
305: int argno;
306: FILE *f;
307: {
308: char newline[BUFSIZ];
309: register int i;
310: register int argc;
311: char *argv[MAXARGS];
312: char parsebuf[BUFSIZ];
313:
314: do {
315: replace = copyline(replace, newline);
316: argc = parseline(newline, argv, parsebuf);
317: for (i = 0; i < argno; i++)
318: replace_arg(argc, argv, oparg[i].reg, oparg[i].source);
319: buildline(argc, argv, newline);
320: fputs(newline, f);
321: } while (*replace != '\0');
322: }
323:
324: replace_arg(argc, argv, reg, source)
325: int argc;
326: char *argv[];
327: int reg;
328: char *source;
329: {
330: register int i;
331: register char *c;
332:
333: for (i = 1; i < argc; i++) {
334: c = argv[i];
335: if (*c == '(') c++;
336: if (*c++ == 'r' && (*c++ - '0') == reg && !isdigit(*c)) {
337: argv[i] = source;
338: }
339: }
340: }
341:
342: buildline(argc, argv, newline)
343: register int argc;
344: register char *argv[];
345: register char *newline;
346: {
347: register char *cp1;
348:
349: if (argc == 0) {
350: *newline++ = '\n';
351: *newline = '\0';
352: } else if (argc == 1) {
353: sprintf(newline, "%s\n", argv[0]);
354: } else {
355: sprintf(newline, "\t%s\t%s", argv[0], argv[1]);
356: argc -= 2;
357: argv += 2;
358: while (argc-- > 0) {
359: strcat(newline, ",");
360: cp1 = *argv;
361: cp1 += strlen(cp1) - 1;
362: if (*cp1 == '$' || *cp1 == '*') *cp1 = '\0';
363: strcat(newline, *argv++);
364: }
365: strcat(newline, "\n");
366: }
367: }
368:
369:
370:
371: /*
372: * Do any necessary post expansion cleanup.
373: */
374: cleanup(numargs)
375: int numargs;
376: {
377:
378: return;
379: }
380: #endif vax
381:
382: #ifdef mc68000
383: /*
384: * Instruction stop table.
385: * All instructions that implicitly modify any of the temporary
386: * registers, change control flow, or implicitly loop must be
387: * listed in this table. It is used to find the end of a basic
388: * block when scanning backwards through the instruction stream
389: * trying to merge the inline expansion.
390: */
391: struct inststoptbl inststoptable[] = {
392: { "" }
393: };
394:
395: /*
396: * Check to see if a line is a candidate for replacement.
397: * Return pointer to name to be looked up in pattern table.
398: */
399: char *
400: doreplaceon(cp)
401: char *cp;
402: {
403:
404: if (bcmp(cp, "jbsr\t", 5) == 0)
405: return (cp + 5);
406: return (0);
407: }
408:
409: /*
410: * Find the next argument to the function being expanded.
411: */
412: nextarg(argc, argv)
413: int argc;
414: char *argv[];
415: {
416: register char *lastarg = argv[2];
417:
418: if (argc == 3 &&
419: bcmp(argv[0], "movl", 5) == 0 &&
420: bcmp(argv[1], "sp@+", 5) == 0 &&
421: (lastarg[1] == '0' || lastarg[1] == '1') &&
422: lastarg[2] == '\0') {
423: if (lastarg[0] == 'd')
424: return (lastarg[1] - '0');
425: return (lastarg[1] - '0' + 8);
426: }
427: return (-1);
428: }
429:
430: /*
431: * Determine whether the current line pushes an argument.
432: */
433: ispusharg(argc, argv)
434: int argc;
435: char *argv[];
436: {
437:
438: if (argc < 2)
439: return (0);
440: if (argc == 2 && bcmp(argv[0], "pea", 4) == 0)
441: return (1);
442: if (bcmp(argv[argc - 1], "sp@-", 5) == 0)
443: return (1);
444: return (0);
445: }
446:
447: /*
448: * Determine which (if any) registers are modified
449: * Return register number that is modified, -1 if none are modified.
450: */
451: modifies(argc, argv)
452: int argc;
453: char *argv[];
454: {
455: /*
456: * For the MC68000 all we care about are d0, d1, a0, and a1.
457: */
458: register char *lastarg = argv[argc - 1];
459:
460: if (lastarg[0] == 'd' && isdigit(lastarg[1]) && lastarg[2] == '\0')
461: return (lastarg[1] - '0');
462: if (lastarg[0] == 'a' && isdigit(lastarg[1]) && lastarg[2] == '\0')
463: return (lastarg[1] - '0' + 8);
464: return (-1);
465: }
466:
467: /*
468: * Rewrite the instruction in (argc, argv) to store its
469: * contents into arg instead of onto the stack. The new
470: * instruction is placed in the buffer that is provided.
471: */
472: rewrite(instbuf, argc, argv, target)
473: char *instbuf;
474: int argc;
475: char *argv[];
476: int target;
477: {
478: int regno;
479: char regtype;
480:
481: if (target < 8) {
482: regtype = 'd';
483: regno = target;
484: } else {
485: regtype = 'a';
486: regno = target - 8;
487: }
488: switch (argc) {
489: case 0:
490: instbuf[0] = '\0';
491: fprintf("blank line to rewrite?\n");
492: return;
493: case 1:
494: sprintf(instbuf, "\t%s\n", argv[0]);
495: fprintf(stderr, "rewrite?-> %s", instbuf);
496: return;
497: case 2:
498: if (bcmp(argv[0], "pea", 4) == 0) {
499: if (regtype == 'a') {
500: sprintf(instbuf, "\tlea\t%s,%c%d\n",
501: argv[1], regtype, regno);
502: return;
503: }
504: if (argv[1][0] == '_' || isdigit(argv[1][0])) {
505: sprintf(instbuf, "\tmovl\t#%s,%c%d\n",
506: argv[1], regtype, regno);
507: return;
508: }
509: sprintf(instbuf,
510: "\texg\ta0,d%d\n\tlea\t%s,a0\n\texg\ta0,d%d\n",
511: regno, argv[1], regno);
512: return;
513: }
514: sprintf(instbuf, "\t%s\t%c%d\n", argv[0], regtype, regno);
515: return;
516: case 3:
517: sprintf(instbuf, "\t%s\t%s,%c%d\n",
518: argv[0], argv[1], regtype, regno);
519: return;
520: default:
521: sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]);
522: argc -= 2, argv += 2;
523: while (argc-- > 0) {
524: strcat(instbuf, ",");
525: strcat(instbuf, *argv++);
526: }
527: strcat(instbuf, "\n");
528: fprintf(stderr, "rewrite?-> %s", instbuf);
529: return;
530: }
531: }
532:
533: /*
534: * Do any necessary post expansion cleanup.
535: */
536: cleanup(numargs)
537: int numargs;
538: {
539:
540: if (numargs == 0)
541: return;
542: /*
543: * delete instruction to pop arguments.
544: * TODO:
545: * CHECK FOR LABEL
546: * CHECK THAT INSTRUCTION IS A POP
547: */
548: fgets(line[bufhead], MAXLINELEN, stdin);
549: }
550: #endif mc68000
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.