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