116960Smckusick /* Copyright (c) 1984 Regents of the University of California */ 216960Smckusick 316960Smckusick #ifndef lint 4*21192Smckusick static char sccsid[] = "@(#)machdep.c 1.5 (Berkeley) 05/28/85"; 516960Smckusick #endif not lint 616960Smckusick 716960Smckusick #include <stdio.h> 816960Smckusick #include <ctype.h> 916979Smckusick #include "inline.h" 1016960Smckusick 1116960Smckusick /* 1216979Smckusick * The routines and tables in this file must be rewritten 1316979Smckusick * for each new machine that this program is ported to. 1416960Smckusick */ 1516960Smckusick 1617203Smckusick #ifdef vax 1716960Smckusick /* 1816979Smckusick * Instruction stop table. 1916979Smckusick * All instructions that implicitly modify any of the temporary 2016979Smckusick * registers, change control flow, or implicitly loop must be 2116979Smckusick * listed in this table. It is used to find the end of a basic 2216979Smckusick * block when scanning backwards through the instruction stream 2316979Smckusick * trying to merge the inline expansion. 2416979Smckusick */ 2516979Smckusick struct inststoptbl inststoptable[] = { 2616979Smckusick { "jbc" }, { "jlbc" }, { "jbs" }, { "jlbs" }, { "jbcc" }, 2716979Smckusick { "jbsc" }, { "jbcs" }, { "jbss" }, { "jbr" }, { "jcc" }, 2816979Smckusick { "jcs" }, { "jvc" }, { "jvs" }, { "jlss" }, { "jlssu" }, 2916979Smckusick { "jleq" }, { "jlequ" }, { "jeql" }, { "jeqlu" }, { "jneq" }, 3016979Smckusick { "jnequ" }, { "jgeq" }, { "jgequ" }, { "jgtr" }, { "jgtru" }, 3116979Smckusick { "chmk" }, { "chme" }, { "chms" }, { "chmu" }, { "rei" }, 3216979Smckusick { "ldpctx" }, { "svpctx" }, { "xfc" }, { "bpt" }, 3316979Smckusick { "bugw" }, { "bugl" }, { "halt" }, { "pushr" }, { "popr" }, 3416979Smckusick { "polyf" }, { "polyd" }, { "polyg" }, { "polyh" }, 3516979Smckusick { "bneq" }, { "bnequ" }, { "beql" }, { "beqlu" }, { "bgtr" }, 3616979Smckusick { "bleq" }, { "bgeq" }, { "blss" }, { "bgtru" }, { "blequ" }, 3716979Smckusick { "bvc" }, { "bvs" }, { "bgequ" }, { "bcc" }, { "blssu" }, 3816979Smckusick { "bcs" }, { "brb" }, { "brw" }, { "jmp" }, 3916979Smckusick { "bbs" }, { "bbc" }, { "bbss" }, { "bbcs" }, { "bbsc" }, 4016979Smckusick { "bbcc" }, { "bbssi" }, { "bbcci" }, { "blbs" }, { "blbc" }, 4116979Smckusick { "acbb" }, { "acbw" }, { "acbl" }, { "acbf" }, { "acbd" }, 4216979Smckusick { "acbg" }, { "acbh" }, { "aoblss" }, { "aobleq" }, 4316979Smckusick { "sobgeq" }, { "sobgtr" }, { "caseb" }, { "casew" }, { "casel" }, 4416979Smckusick { "bsbb" }, { "bsbw" }, { "jsb" }, { "rsb" }, 4516979Smckusick { "callg" }, { "calls" }, { "ret" }, 4616979Smckusick { "movc3" }, { "movc5" }, { "movtc" }, { "movtuc" }, 4716979Smckusick { "cmpc3" }, { "cmpc5" }, { "scanc" }, { "spanc" }, 4816979Smckusick { "locc" }, { "skpc" }, { "matchc" }, { "crc" }, 4916979Smckusick { "movp" }, { "cmpp3" }, { "cmpp4" }, { "addp4" }, { "addp6" }, 5016979Smckusick { "subp4" }, { "subp6" }, { "mulp" }, { "divp" }, { "cvtlp" }, 5116979Smckusick { "cvtpl" }, { "cvtpt" }, { "cvttp" }, { "cvtps" }, { "cvtsp" }, 5216979Smckusick { "ashp" }, { "editpc" }, 5316979Smckusick { "escd" }, { "esce" }, { "escf" }, 5416979Smckusick { "" } 5516979Smckusick }; 5616979Smckusick 5716979Smckusick /* 5816960Smckusick * Check to see if a line is a candidate for replacement. 5916960Smckusick * Return pointer to name to be looked up in pattern table. 6016960Smckusick */ 6116960Smckusick char * 6216960Smckusick doreplaceon(cp) 6316960Smckusick char *cp; 6416960Smckusick { 6516960Smckusick 6616960Smckusick if (bcmp(cp, "calls\t$", 7) == 0) 6716960Smckusick return (cp + 7); 6816960Smckusick return (0); 6916960Smckusick } 7016960Smckusick 7116960Smckusick /* 7216960Smckusick * Find the next argument to the function being expanded. 7316960Smckusick */ 7416960Smckusick nextarg(argc, argv) 7516960Smckusick int argc; 7616960Smckusick char *argv[]; 7716960Smckusick { 7816960Smckusick register char *lastarg = argv[2]; 7916960Smckusick 8016960Smckusick if (argc == 3 && 8116960Smckusick bcmp(argv[0], "mov", 3) == 0 && 8216960Smckusick bcmp(argv[1], "(sp)+", 6) == 0 && 8316960Smckusick lastarg[0] == 'r' && isdigit(lastarg[1]) && lastarg[2] == '\0') 8416960Smckusick return (lastarg[1] - '0'); 8516960Smckusick return (-1); 8616960Smckusick } 8716960Smckusick 8816960Smckusick /* 8916960Smckusick * Determine whether the current line pushes an argument. 9016960Smckusick */ 9116960Smckusick ispusharg(argc, argv) 9216960Smckusick int argc; 9316960Smckusick char *argv[]; 9416960Smckusick { 9516960Smckusick 9616960Smckusick if (argc < 2) 9716960Smckusick return (0); 9816960Smckusick if (argc == 2 && bcmp(argv[0], "push", 4) == 0) 9916960Smckusick return (1); 10016960Smckusick if (bcmp(argv[argc - 1], "-(sp)", 6) == 0) 10116960Smckusick return (1); 10216960Smckusick return (0); 10316960Smckusick } 10416960Smckusick 10516960Smckusick /* 10616960Smckusick * Determine which (if any) registers are modified 10716960Smckusick * Return register number that is modified, -1 if none are modified. 10816960Smckusick */ 10916960Smckusick modifies(argc, argv) 11016960Smckusick int argc; 11116960Smckusick char *argv[]; 11216960Smckusick { 11316960Smckusick /* 11416960Smckusick * For the VAX all we care about are r0 to r5 11516960Smckusick */ 11616960Smckusick register char *lastarg = argv[argc - 1]; 11716960Smckusick 11816960Smckusick if (lastarg[0] == 'r' && isdigit(lastarg[1]) && lastarg[2] == '\0') 11916960Smckusick return (lastarg[1] - '0'); 12016960Smckusick return (-1); 12116960Smckusick } 12216960Smckusick 12316960Smckusick /* 12416960Smckusick * Rewrite the instruction in (argc, argv) to store its 12516960Smckusick * contents into arg instead of onto the stack. The new 12616960Smckusick * instruction is placed in the buffer that is provided. 12716960Smckusick */ 12816960Smckusick rewrite(instbuf, argc, argv, target) 12916960Smckusick char *instbuf; 13016960Smckusick int argc; 13116960Smckusick char *argv[]; 13216960Smckusick int target; 13316960Smckusick { 13416960Smckusick 13516960Smckusick switch (argc) { 13616960Smckusick case 0: 13716960Smckusick instbuf[0] = '\0'; 138*21192Smckusick fprintf(stderr, "blank line to rewrite?\n"); 13916960Smckusick return; 14016960Smckusick case 1: 14116960Smckusick sprintf(instbuf, "\t%s\n", argv[0]); 14216960Smckusick fprintf(stderr, "rewrite?-> %s", instbuf); 14316960Smckusick return; 14416960Smckusick case 2: 14516960Smckusick if (bcmp(argv[0], "push", 4) == 0) { 14616960Smckusick sprintf(instbuf, "\tmov%s\t%s,r%d\n", 14716960Smckusick &argv[0][4], argv[1], target); 14816960Smckusick return; 14916960Smckusick } 15016960Smckusick sprintf(instbuf, "\t%s\tr%d\n", argv[0], target); 15116960Smckusick return; 15216960Smckusick case 3: 15316960Smckusick sprintf(instbuf, "\t%s\t%s,r%d\n", argv[0], argv[1], target); 15416960Smckusick return; 15516960Smckusick case 4: 15616960Smckusick sprintf(instbuf, "\t%s\t%s,%s,r%d\n", 15716960Smckusick argv[0], argv[1], argv[2], target); 15816960Smckusick return; 15916971Smckusick case 5: 16016971Smckusick sprintf(instbuf, "\t%s\t%s,%s,%s,r%d\n", 16116971Smckusick argv[0], argv[1], argv[2], argv[3], target); 16216971Smckusick return; 16316960Smckusick default: 16416960Smckusick sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]); 16516960Smckusick argc -= 2, argv += 2; 16616960Smckusick while (argc-- > 0) { 16716960Smckusick strcat(instbuf, ","); 16816960Smckusick strcat(instbuf, *argv++); 16916960Smckusick } 17016960Smckusick strcat(instbuf, "\n"); 17116960Smckusick fprintf(stderr, "rewrite?-> %s", instbuf); 17216960Smckusick return; 17316960Smckusick } 17416960Smckusick } 17517203Smckusick 17617203Smckusick /* 17717203Smckusick * Do any necessary post expansion cleanup. 17817203Smckusick */ 17917203Smckusick cleanup(numargs) 18017203Smckusick int numargs; 18117203Smckusick { 18217203Smckusick 18317203Smckusick return; 18417203Smckusick } 18517203Smckusick #endif vax 18617203Smckusick 18717203Smckusick #ifdef mc68000 18817203Smckusick /* 18917203Smckusick * Instruction stop table. 19017203Smckusick * All instructions that implicitly modify any of the temporary 19117203Smckusick * registers, change control flow, or implicitly loop must be 19217203Smckusick * listed in this table. It is used to find the end of a basic 19317203Smckusick * block when scanning backwards through the instruction stream 19417203Smckusick * trying to merge the inline expansion. 19517203Smckusick */ 19617203Smckusick struct inststoptbl inststoptable[] = { 19717203Smckusick { "" } 19817203Smckusick }; 19917203Smckusick 20017203Smckusick /* 20117203Smckusick * Check to see if a line is a candidate for replacement. 20217203Smckusick * Return pointer to name to be looked up in pattern table. 20317203Smckusick */ 20417203Smckusick char * 20517203Smckusick doreplaceon(cp) 20617203Smckusick char *cp; 20717203Smckusick { 20817203Smckusick 20917203Smckusick if (bcmp(cp, "jbsr\t", 5) == 0) 21017203Smckusick return (cp + 5); 21117203Smckusick return (0); 21217203Smckusick } 21317203Smckusick 21417203Smckusick /* 21517203Smckusick * Find the next argument to the function being expanded. 21617203Smckusick */ 21717203Smckusick nextarg(argc, argv) 21817203Smckusick int argc; 21917203Smckusick char *argv[]; 22017203Smckusick { 22117203Smckusick register char *lastarg = argv[2]; 22217203Smckusick 22317203Smckusick if (argc == 3 && 22417203Smckusick bcmp(argv[0], "movl", 5) == 0 && 22517203Smckusick bcmp(argv[1], "sp@+", 5) == 0 && 22617203Smckusick (lastarg[1] == '0' || lastarg[1] == '1') && 22717203Smckusick lastarg[2] == '\0') { 22817203Smckusick if (lastarg[0] == 'd') 22917203Smckusick return (lastarg[1] - '0'); 23017203Smckusick return (lastarg[1] - '0' + 8); 23117203Smckusick } 23217203Smckusick return (-1); 23317203Smckusick } 23417203Smckusick 23517203Smckusick /* 23617203Smckusick * Determine whether the current line pushes an argument. 23717203Smckusick */ 23817203Smckusick ispusharg(argc, argv) 23917203Smckusick int argc; 24017203Smckusick char *argv[]; 24117203Smckusick { 24217203Smckusick 24317203Smckusick if (argc < 2) 24417203Smckusick return (0); 24517203Smckusick if (argc == 2 && bcmp(argv[0], "pea", 4) == 0) 24617203Smckusick return (1); 24717203Smckusick if (bcmp(argv[argc - 1], "sp@-", 5) == 0) 24817203Smckusick return (1); 24917203Smckusick return (0); 25017203Smckusick } 25117203Smckusick 25217203Smckusick /* 25317203Smckusick * Determine which (if any) registers are modified 25417203Smckusick * Return register number that is modified, -1 if none are modified. 25517203Smckusick */ 25617203Smckusick modifies(argc, argv) 25717203Smckusick int argc; 25817203Smckusick char *argv[]; 25917203Smckusick { 26017203Smckusick /* 26117203Smckusick * For the MC68000 all we care about are d0, d1, a0, and a1. 26217203Smckusick */ 26317203Smckusick register char *lastarg = argv[argc - 1]; 26417203Smckusick 26517203Smckusick if (lastarg[0] == 'd' && isdigit(lastarg[1]) && lastarg[2] == '\0') 26617203Smckusick return (lastarg[1] - '0'); 26717203Smckusick if (lastarg[0] == 'a' && isdigit(lastarg[1]) && lastarg[2] == '\0') 26817203Smckusick return (lastarg[1] - '0' + 8); 26917203Smckusick return (-1); 27017203Smckusick } 27117203Smckusick 27217203Smckusick /* 27317203Smckusick * Rewrite the instruction in (argc, argv) to store its 27417203Smckusick * contents into arg instead of onto the stack. The new 27517203Smckusick * instruction is placed in the buffer that is provided. 27617203Smckusick */ 27717203Smckusick rewrite(instbuf, argc, argv, target) 27817203Smckusick char *instbuf; 27917203Smckusick int argc; 28017203Smckusick char *argv[]; 28117203Smckusick int target; 28217203Smckusick { 28317203Smckusick int regno; 28417203Smckusick char regtype; 28517203Smckusick 28617203Smckusick if (target < 8) { 28717203Smckusick regtype = 'd'; 28817203Smckusick regno = target; 28917203Smckusick } else { 29017203Smckusick regtype = 'a'; 29117203Smckusick regno = target - 8; 29217203Smckusick } 29317203Smckusick switch (argc) { 29417203Smckusick case 0: 29517203Smckusick instbuf[0] = '\0'; 296*21192Smckusick fprintf(stderr, "blank line to rewrite?\n"); 29717203Smckusick return; 29817203Smckusick case 1: 29917203Smckusick sprintf(instbuf, "\t%s\n", argv[0]); 30017203Smckusick fprintf(stderr, "rewrite?-> %s", instbuf); 30117203Smckusick return; 30217203Smckusick case 2: 30317203Smckusick if (bcmp(argv[0], "pea", 4) == 0) { 30417203Smckusick if (regtype == 'a') { 30517203Smckusick sprintf(instbuf, "\tlea\t%s,%c%d\n", 30617203Smckusick argv[1], regtype, regno); 30717203Smckusick return; 30817203Smckusick } 30917203Smckusick if (argv[1][0] == '_' || isdigit(argv[1][0])) { 31017203Smckusick sprintf(instbuf, "\tmovl\t#%s,%c%d\n", 31117203Smckusick argv[1], regtype, regno); 31217203Smckusick return; 31317203Smckusick } 31417203Smckusick sprintf(instbuf, 31517203Smckusick "\texg\ta0,d%d\n\tlea\t%s,a0\n\texg\ta0,d%d\n", 31617203Smckusick regno, argv[1], regno); 31717203Smckusick return; 31817203Smckusick } 31917203Smckusick sprintf(instbuf, "\t%s\t%c%d\n", argv[0], regtype, regno); 32017203Smckusick return; 32117203Smckusick case 3: 32217203Smckusick sprintf(instbuf, "\t%s\t%s,%c%d\n", 32317203Smckusick argv[0], argv[1], regtype, regno); 32417203Smckusick return; 32517203Smckusick default: 32617203Smckusick sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]); 32717203Smckusick argc -= 2, argv += 2; 32817203Smckusick while (argc-- > 0) { 32917203Smckusick strcat(instbuf, ","); 33017203Smckusick strcat(instbuf, *argv++); 33117203Smckusick } 33217203Smckusick strcat(instbuf, "\n"); 33317203Smckusick fprintf(stderr, "rewrite?-> %s", instbuf); 33417203Smckusick return; 33517203Smckusick } 33617203Smckusick } 33717203Smckusick 33817203Smckusick /* 33917203Smckusick * Do any necessary post expansion cleanup. 34017203Smckusick */ 34117203Smckusick cleanup(numargs) 34217203Smckusick int numargs; 34317203Smckusick { 34417203Smckusick 34517203Smckusick if (numargs == 0) 34617203Smckusick return; 34717203Smckusick /* 34817203Smckusick * delete instruction to pop arguments. 34917203Smckusick * TODO: 35017203Smckusick * CHECK FOR LABEL 35117203Smckusick * CHECK THAT INSTRUCTION IS A POP 35217203Smckusick */ 35317203Smckusick fgets(line[bufhead], MAXLINELEN, stdin); 35417203Smckusick } 35517203Smckusick #endif mc68000 356