123346Smckusick /* 223346Smckusick * Copyright (c) 1984 Regents of the University of California. 323346Smckusick * All rights reserved. The Berkeley software License Agreement 423346Smckusick * specifies the terms and conditions for redistribution. 523346Smckusick */ 616960Smckusick 716960Smckusick #ifndef lint 8*24396Smckusick static char sccsid[] = "@(#)machdep.c 1.7 (Berkeley) 08/22/85"; 916960Smckusick #endif not lint 1016960Smckusick 1116960Smckusick #include <stdio.h> 1216960Smckusick #include <ctype.h> 1316979Smckusick #include "inline.h" 1416960Smckusick 15*24396Smckusick extern char *strcpy(); 16*24396Smckusick extern char *strcat(); 17*24396Smckusick extern char *index(); 18*24396Smckusick 1916960Smckusick /* 2016979Smckusick * The routines and tables in this file must be rewritten 2116979Smckusick * for each new machine that this program is ported to. 2216960Smckusick */ 2316960Smckusick 2417203Smckusick #ifdef vax 2516960Smckusick /* 2616979Smckusick * Instruction stop table. 2716979Smckusick * All instructions that implicitly modify any of the temporary 2816979Smckusick * registers, change control flow, or implicitly loop must be 2916979Smckusick * listed in this table. It is used to find the end of a basic 3016979Smckusick * block when scanning backwards through the instruction stream 3116979Smckusick * trying to merge the inline expansion. 3216979Smckusick */ 3316979Smckusick struct inststoptbl inststoptable[] = { 3416979Smckusick { "jbc" }, { "jlbc" }, { "jbs" }, { "jlbs" }, { "jbcc" }, 3516979Smckusick { "jbsc" }, { "jbcs" }, { "jbss" }, { "jbr" }, { "jcc" }, 3616979Smckusick { "jcs" }, { "jvc" }, { "jvs" }, { "jlss" }, { "jlssu" }, 3716979Smckusick { "jleq" }, { "jlequ" }, { "jeql" }, { "jeqlu" }, { "jneq" }, 3816979Smckusick { "jnequ" }, { "jgeq" }, { "jgequ" }, { "jgtr" }, { "jgtru" }, 3916979Smckusick { "chmk" }, { "chme" }, { "chms" }, { "chmu" }, { "rei" }, 4016979Smckusick { "ldpctx" }, { "svpctx" }, { "xfc" }, { "bpt" }, 4116979Smckusick { "bugw" }, { "bugl" }, { "halt" }, { "pushr" }, { "popr" }, 4216979Smckusick { "polyf" }, { "polyd" }, { "polyg" }, { "polyh" }, 4316979Smckusick { "bneq" }, { "bnequ" }, { "beql" }, { "beqlu" }, { "bgtr" }, 4416979Smckusick { "bleq" }, { "bgeq" }, { "blss" }, { "bgtru" }, { "blequ" }, 4516979Smckusick { "bvc" }, { "bvs" }, { "bgequ" }, { "bcc" }, { "blssu" }, 4616979Smckusick { "bcs" }, { "brb" }, { "brw" }, { "jmp" }, 4716979Smckusick { "bbs" }, { "bbc" }, { "bbss" }, { "bbcs" }, { "bbsc" }, 4816979Smckusick { "bbcc" }, { "bbssi" }, { "bbcci" }, { "blbs" }, { "blbc" }, 4916979Smckusick { "acbb" }, { "acbw" }, { "acbl" }, { "acbf" }, { "acbd" }, 5016979Smckusick { "acbg" }, { "acbh" }, { "aoblss" }, { "aobleq" }, 5116979Smckusick { "sobgeq" }, { "sobgtr" }, { "caseb" }, { "casew" }, { "casel" }, 5216979Smckusick { "bsbb" }, { "bsbw" }, { "jsb" }, { "rsb" }, 5316979Smckusick { "callg" }, { "calls" }, { "ret" }, 5416979Smckusick { "movc3" }, { "movc5" }, { "movtc" }, { "movtuc" }, 5516979Smckusick { "cmpc3" }, { "cmpc5" }, { "scanc" }, { "spanc" }, 5616979Smckusick { "locc" }, { "skpc" }, { "matchc" }, { "crc" }, 5716979Smckusick { "movp" }, { "cmpp3" }, { "cmpp4" }, { "addp4" }, { "addp6" }, 5816979Smckusick { "subp4" }, { "subp6" }, { "mulp" }, { "divp" }, { "cvtlp" }, 5916979Smckusick { "cvtpl" }, { "cvtpt" }, { "cvttp" }, { "cvtps" }, { "cvtsp" }, 6016979Smckusick { "ashp" }, { "editpc" }, 6116979Smckusick { "escd" }, { "esce" }, { "escf" }, 6216979Smckusick { "" } 6316979Smckusick }; 6416979Smckusick 6516979Smckusick /* 6616960Smckusick * Check to see if a line is a candidate for replacement. 6716960Smckusick * Return pointer to name to be looked up in pattern table. 6816960Smckusick */ 6916960Smckusick char * 7016960Smckusick doreplaceon(cp) 7116960Smckusick char *cp; 7216960Smckusick { 7316960Smckusick 74*24396Smckusick if (bcmp(cp, "calls\t", 6) != 0) 75*24396Smckusick return (0); 76*24396Smckusick if ((cp = index(cp + 6, ',')) == 0) 77*24396Smckusick return (0); 78*24396Smckusick return (++cp); 7916960Smckusick } 8016960Smckusick 8116960Smckusick /* 82*24396Smckusick * Find out how many arguments the function is being called with. 83*24396Smckusick * A return value of -1 indicates that the count can't be determined. 84*24396Smckusick */ 85*24396Smckusick int 86*24396Smckusick countargs(cp) 87*24396Smckusick char *cp; 88*24396Smckusick { 89*24396Smckusick 90*24396Smckusick if ((cp = index(cp, '$')) == 0) 91*24396Smckusick return (-1); 92*24396Smckusick if (!isdigit(*++cp)) 93*24396Smckusick return (-1); 94*24396Smckusick return (atoi(cp)); 95*24396Smckusick } 96*24396Smckusick 97*24396Smckusick /* 9816960Smckusick * Find the next argument to the function being expanded. 9916960Smckusick */ 10016960Smckusick nextarg(argc, argv) 10116960Smckusick int argc; 10216960Smckusick char *argv[]; 10316960Smckusick { 10416960Smckusick register char *lastarg = argv[2]; 10516960Smckusick 10616960Smckusick if (argc == 3 && 10716960Smckusick bcmp(argv[0], "mov", 3) == 0 && 10816960Smckusick bcmp(argv[1], "(sp)+", 6) == 0 && 10916960Smckusick lastarg[0] == 'r' && isdigit(lastarg[1]) && lastarg[2] == '\0') 11016960Smckusick return (lastarg[1] - '0'); 11116960Smckusick return (-1); 11216960Smckusick } 11316960Smckusick 11416960Smckusick /* 11516960Smckusick * Determine whether the current line pushes an argument. 11616960Smckusick */ 117*24396Smckusick ispusharg(argc, argv) 11816960Smckusick int argc; 11916960Smckusick char *argv[]; 12016960Smckusick { 12116960Smckusick 12216960Smckusick if (argc < 2) 12316960Smckusick return (0); 12416960Smckusick if (argc == 2 && bcmp(argv[0], "push", 4) == 0) 12516960Smckusick return (1); 12616960Smckusick if (bcmp(argv[argc - 1], "-(sp)", 6) == 0) 12716960Smckusick return (1); 12816960Smckusick return (0); 12916960Smckusick } 13016960Smckusick 13116960Smckusick /* 13216960Smckusick * Determine which (if any) registers are modified 13316960Smckusick * Return register number that is modified, -1 if none are modified. 13416960Smckusick */ 13516960Smckusick modifies(argc, argv) 13616960Smckusick int argc; 13716960Smckusick char *argv[]; 13816960Smckusick { 13916960Smckusick /* 14016960Smckusick * For the VAX all we care about are r0 to r5 14116960Smckusick */ 14216960Smckusick register char *lastarg = argv[argc - 1]; 14316960Smckusick 14416960Smckusick if (lastarg[0] == 'r' && isdigit(lastarg[1]) && lastarg[2] == '\0') 14516960Smckusick return (lastarg[1] - '0'); 14616960Smckusick return (-1); 14716960Smckusick } 14816960Smckusick 14916960Smckusick /* 15016960Smckusick * Rewrite the instruction in (argc, argv) to store its 15116960Smckusick * contents into arg instead of onto the stack. The new 15216960Smckusick * instruction is placed in the buffer that is provided. 15316960Smckusick */ 15416960Smckusick rewrite(instbuf, argc, argv, target) 15516960Smckusick char *instbuf; 15616960Smckusick int argc; 15716960Smckusick char *argv[]; 15816960Smckusick int target; 15916960Smckusick { 16016960Smckusick 16116960Smckusick switch (argc) { 16216960Smckusick case 0: 16316960Smckusick instbuf[0] = '\0'; 16421192Smckusick fprintf(stderr, "blank line to rewrite?\n"); 16516960Smckusick return; 16616960Smckusick case 1: 16716960Smckusick sprintf(instbuf, "\t%s\n", argv[0]); 16816960Smckusick fprintf(stderr, "rewrite?-> %s", instbuf); 16916960Smckusick return; 17016960Smckusick case 2: 17116960Smckusick if (bcmp(argv[0], "push", 4) == 0) { 17216960Smckusick sprintf(instbuf, "\tmov%s\t%s,r%d\n", 17316960Smckusick &argv[0][4], argv[1], target); 17416960Smckusick return; 17516960Smckusick } 17616960Smckusick sprintf(instbuf, "\t%s\tr%d\n", argv[0], target); 17716960Smckusick return; 17816960Smckusick case 3: 17916960Smckusick sprintf(instbuf, "\t%s\t%s,r%d\n", argv[0], argv[1], target); 18016960Smckusick return; 18116960Smckusick case 4: 18216960Smckusick sprintf(instbuf, "\t%s\t%s,%s,r%d\n", 18316960Smckusick argv[0], argv[1], argv[2], target); 18416960Smckusick return; 18516971Smckusick case 5: 18616971Smckusick sprintf(instbuf, "\t%s\t%s,%s,%s,r%d\n", 18716971Smckusick argv[0], argv[1], argv[2], argv[3], target); 18816971Smckusick return; 18916960Smckusick default: 19016960Smckusick sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]); 19116960Smckusick argc -= 2, argv += 2; 19216960Smckusick while (argc-- > 0) { 193*24396Smckusick (void) strcat(instbuf, ","); 194*24396Smckusick (void) strcat(instbuf, *argv++); 19516960Smckusick } 196*24396Smckusick (void) strcat(instbuf, "\n"); 19716960Smckusick fprintf(stderr, "rewrite?-> %s", instbuf); 19816960Smckusick return; 19916960Smckusick } 20016960Smckusick } 20117203Smckusick 20217203Smckusick /* 20317203Smckusick * Do any necessary post expansion cleanup. 20417203Smckusick */ 205*24396Smckusick /*ARGSUSED*/ 20617203Smckusick cleanup(numargs) 20717203Smckusick int numargs; 20817203Smckusick { 20917203Smckusick 21017203Smckusick return; 21117203Smckusick } 21217203Smckusick #endif vax 21317203Smckusick 21417203Smckusick #ifdef mc68000 21517203Smckusick /* 21617203Smckusick * Instruction stop table. 21717203Smckusick * All instructions that implicitly modify any of the temporary 21817203Smckusick * registers, change control flow, or implicitly loop must be 21917203Smckusick * listed in this table. It is used to find the end of a basic 22017203Smckusick * block when scanning backwards through the instruction stream 22117203Smckusick * trying to merge the inline expansion. 22217203Smckusick */ 22317203Smckusick struct inststoptbl inststoptable[] = { 22417203Smckusick { "" } 22517203Smckusick }; 22617203Smckusick 22717203Smckusick /* 22817203Smckusick * Check to see if a line is a candidate for replacement. 22917203Smckusick * Return pointer to name to be looked up in pattern table. 23017203Smckusick */ 23117203Smckusick char * 23217203Smckusick doreplaceon(cp) 23317203Smckusick char *cp; 23417203Smckusick { 23517203Smckusick 23617203Smckusick if (bcmp(cp, "jbsr\t", 5) == 0) 23717203Smckusick return (cp + 5); 23817203Smckusick return (0); 23917203Smckusick } 24017203Smckusick 24117203Smckusick /* 242*24396Smckusick * Find out how many arguments the function is being called with. 243*24396Smckusick * A return value of -1 indicates that the count can't be determined. 244*24396Smckusick */ 245*24396Smckusick /* ARGSUSED */ 246*24396Smckusick int 247*24396Smckusick countargs(cp) 248*24396Smckusick char *cp; 249*24396Smckusick { 250*24396Smckusick 251*24396Smckusick /* 252*24396Smckusick * TODO 253*24396Smckusick * Figure out what the count should be. 254*24396Smckusick * Probably have to read the next instruction here 255*24396Smckusick * instead of in cleanup() below. 256*24396Smckusick */ 257*24396Smckusick return (-1); 258*24396Smckusick } 259*24396Smckusick 260*24396Smckusick /* 26117203Smckusick * Find the next argument to the function being expanded. 26217203Smckusick */ 26317203Smckusick nextarg(argc, argv) 26417203Smckusick int argc; 26517203Smckusick char *argv[]; 26617203Smckusick { 26717203Smckusick register char *lastarg = argv[2]; 26817203Smckusick 26917203Smckusick if (argc == 3 && 27017203Smckusick bcmp(argv[0], "movl", 5) == 0 && 27117203Smckusick bcmp(argv[1], "sp@+", 5) == 0 && 27217203Smckusick (lastarg[1] == '0' || lastarg[1] == '1') && 27317203Smckusick lastarg[2] == '\0') { 27417203Smckusick if (lastarg[0] == 'd') 27517203Smckusick return (lastarg[1] - '0'); 27617203Smckusick return (lastarg[1] - '0' + 8); 27717203Smckusick } 27817203Smckusick return (-1); 27917203Smckusick } 28017203Smckusick 28117203Smckusick /* 28217203Smckusick * Determine whether the current line pushes an argument. 28317203Smckusick */ 284*24396Smckusick ispusharg(argc, argv) 28517203Smckusick int argc; 28617203Smckusick char *argv[]; 28717203Smckusick { 28817203Smckusick 28917203Smckusick if (argc < 2) 29017203Smckusick return (0); 29117203Smckusick if (argc == 2 && bcmp(argv[0], "pea", 4) == 0) 29217203Smckusick return (1); 29317203Smckusick if (bcmp(argv[argc - 1], "sp@-", 5) == 0) 29417203Smckusick return (1); 29517203Smckusick return (0); 29617203Smckusick } 29717203Smckusick 29817203Smckusick /* 29917203Smckusick * Determine which (if any) registers are modified 30017203Smckusick * Return register number that is modified, -1 if none are modified. 30117203Smckusick */ 30217203Smckusick modifies(argc, argv) 30317203Smckusick int argc; 30417203Smckusick char *argv[]; 30517203Smckusick { 30617203Smckusick /* 30717203Smckusick * For the MC68000 all we care about are d0, d1, a0, and a1. 30817203Smckusick */ 30917203Smckusick register char *lastarg = argv[argc - 1]; 31017203Smckusick 31117203Smckusick if (lastarg[0] == 'd' && isdigit(lastarg[1]) && lastarg[2] == '\0') 31217203Smckusick return (lastarg[1] - '0'); 31317203Smckusick if (lastarg[0] == 'a' && isdigit(lastarg[1]) && lastarg[2] == '\0') 31417203Smckusick return (lastarg[1] - '0' + 8); 31517203Smckusick return (-1); 31617203Smckusick } 31717203Smckusick 31817203Smckusick /* 31917203Smckusick * Rewrite the instruction in (argc, argv) to store its 32017203Smckusick * contents into arg instead of onto the stack. The new 32117203Smckusick * instruction is placed in the buffer that is provided. 32217203Smckusick */ 32317203Smckusick rewrite(instbuf, argc, argv, target) 32417203Smckusick char *instbuf; 32517203Smckusick int argc; 32617203Smckusick char *argv[]; 32717203Smckusick int target; 32817203Smckusick { 32917203Smckusick int regno; 33017203Smckusick char regtype; 33117203Smckusick 33217203Smckusick if (target < 8) { 33317203Smckusick regtype = 'd'; 33417203Smckusick regno = target; 33517203Smckusick } else { 33617203Smckusick regtype = 'a'; 33717203Smckusick regno = target - 8; 33817203Smckusick } 33917203Smckusick switch (argc) { 34017203Smckusick case 0: 34117203Smckusick instbuf[0] = '\0'; 34221192Smckusick fprintf(stderr, "blank line to rewrite?\n"); 34317203Smckusick return; 34417203Smckusick case 1: 34517203Smckusick sprintf(instbuf, "\t%s\n", argv[0]); 34617203Smckusick fprintf(stderr, "rewrite?-> %s", instbuf); 34717203Smckusick return; 34817203Smckusick case 2: 34917203Smckusick if (bcmp(argv[0], "pea", 4) == 0) { 35017203Smckusick if (regtype == 'a') { 35117203Smckusick sprintf(instbuf, "\tlea\t%s,%c%d\n", 35217203Smckusick argv[1], regtype, regno); 35317203Smckusick return; 35417203Smckusick } 35517203Smckusick if (argv[1][0] == '_' || isdigit(argv[1][0])) { 35617203Smckusick sprintf(instbuf, "\tmovl\t#%s,%c%d\n", 35717203Smckusick argv[1], regtype, regno); 35817203Smckusick return; 35917203Smckusick } 36017203Smckusick sprintf(instbuf, 36117203Smckusick "\texg\ta0,d%d\n\tlea\t%s,a0\n\texg\ta0,d%d\n", 36217203Smckusick regno, argv[1], regno); 36317203Smckusick return; 36417203Smckusick } 36517203Smckusick sprintf(instbuf, "\t%s\t%c%d\n", argv[0], regtype, regno); 36617203Smckusick return; 36717203Smckusick case 3: 36817203Smckusick sprintf(instbuf, "\t%s\t%s,%c%d\n", 36917203Smckusick argv[0], argv[1], regtype, regno); 37017203Smckusick return; 37117203Smckusick default: 37217203Smckusick sprintf(instbuf, "\t%s\t%s", argv[0], argv[1]); 37317203Smckusick argc -= 2, argv += 2; 37417203Smckusick while (argc-- > 0) { 375*24396Smckusick (void) strcat(instbuf, ","); 376*24396Smckusick (void) strcat(instbuf, *argv++); 37717203Smckusick } 378*24396Smckusick (void) strcat(instbuf, "\n"); 37917203Smckusick fprintf(stderr, "rewrite?-> %s", instbuf); 38017203Smckusick return; 38117203Smckusick } 38217203Smckusick } 38317203Smckusick 38417203Smckusick /* 38517203Smckusick * Do any necessary post expansion cleanup. 38617203Smckusick */ 38717203Smckusick cleanup(numargs) 38817203Smckusick int numargs; 38917203Smckusick { 390*24396Smckusick extern int lineno; 39117203Smckusick 39217203Smckusick if (numargs == 0) 39317203Smckusick return; 39417203Smckusick /* 39517203Smckusick * delete instruction to pop arguments. 39617203Smckusick * TODO: 39717203Smckusick * CHECK FOR LABEL 39817203Smckusick * CHECK THAT INSTRUCTION IS A POP 39917203Smckusick */ 40017203Smckusick fgets(line[bufhead], MAXLINELEN, stdin); 401*24396Smckusick lineno++; 40217203Smckusick } 40317203Smckusick #endif mc68000 404