home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / languages / northc_384 / top / inst.c < prev    next >
C/C++ Source or Header  |  1990-08-30  |  7KB  |  404 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Tony Andrews
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  */
  11.  
  12. /*
  13.  * Routines dealing with the parsing and output of instructions.
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18. static    void    getarg();
  19. static    int    isreg();
  20.  
  21. /*
  22.  * addinst(bp, op, args) - add an instruction to block 'bp'
  23.  */
  24. void
  25. addinst(bp, op, args)
  26. register BLOCK    *bp;
  27. char    *op, *args;
  28. {
  29.     register INST    *ni;
  30.     register int    i;
  31.     register char    *s;
  32.     char    *arg2 = "";
  33.  
  34.     if (*op == '\0')    /* no instruction there */
  35.         return;
  36.  
  37.     ni = (INST *) alloc(sizeof(INST));
  38.  
  39.     ni->flags = 0;
  40.     ni->opcode = -1;
  41.     ni->next = NULL;
  42.     ni->prev = NULL;
  43.     ni->live = 0;
  44.     ni->rref = ni->rset = 0;
  45.  
  46.     ni->src.areg = ni->dst.areg = 0;
  47.     ni->src.ireg = ni->dst.ireg = 0;
  48.     ni->src.disp = ni->dst.disp = 0;
  49.     ni->src.astr = ni->dst.astr = NULL;
  50.     ni->src.amode = ni->dst.amode = NONE;
  51.  
  52.     /*
  53.      * Link into the block appropriately
  54.      */
  55.     if (bp->first == NULL) {
  56.         bp->first = bp->last = ni;
  57.     } else {
  58.         bp->last->next = ni;
  59.         ni->prev = bp->last;
  60.  
  61.         bp->last = ni;
  62.     }
  63.  
  64.     for (s = op; *s ;s++) {
  65.         /*
  66.          * Pseudo-ops start with a period, so the length
  67.          * specifier can't be the first character.
  68.          */
  69.         if (*s == '.' && s != op) {    /* length specifier */
  70.             *s++ = '\0';
  71.             switch (*s) {
  72.             case 'b': case 'B':
  73.                 ni->flags |= LENB;
  74.                 break;
  75.             case 'w': case 'W':
  76.                 ni->flags |= LENW;
  77.                 break;
  78.             case 'l': case 'L':
  79.                 ni->flags |= LENL;
  80.                 break;
  81.             default:
  82.                 fprintf(stderr, "Bad length spec '%c'\n", *s);
  83.                 exit(EXIT_FAILURE);
  84.             }
  85.         }
  86.     }
  87.  
  88.     for (i=0; opnames[i] ;i++) {
  89.         if (stricmp(op, opnames[i]) == 0) {
  90.             ni->opcode = i;
  91.             break;
  92.         }
  93.     }
  94.  
  95.     if (ni->opcode < 0) {
  96.         fprintf(stderr, "Unknown op '%s'\n", op);
  97.         exit(EXIT_FAILURE);
  98.     }
  99.  
  100.     for (s = args; *s ;s++) {
  101.         /*
  102.          * skip chars in parens, since an operand split can't
  103.          * occur within.
  104.          */
  105.         if (*s == '(') {
  106.             while (*s != ')')
  107.                 s++;
  108.         }
  109.         if (*s == ',') {
  110.             *s++ = '\0';
  111.             arg2 = s;
  112.             break;
  113.         }
  114.     }
  115.  
  116.     getarg(&ni->src, args);
  117.     getarg(&ni->dst, arg2);
  118. }
  119.  
  120. /*
  121.  * delinst(bp, ip) - delete instruction 'ip' in block 'bp'
  122.  */
  123. void
  124. delinst(bp, ip)
  125. BLOCK    *bp;
  126. INST    *ip;
  127. {
  128.     INST    *pi, *ni;    /* previous and next instructions */
  129.  
  130.     pi = ip->prev;
  131.     ni = ip->next;
  132.  
  133.     if (pi != NULL)
  134.         pi->next = ni;
  135.     else
  136.         bp->first = ni;
  137.  
  138.     if (ni != NULL)
  139.         ni->prev = pi;
  140.     else
  141.         bp->last = pi;
  142.  
  143.     /*
  144.      * Free space used by the instruction.
  145.      */
  146.     if (ip->src.astr != NULL)
  147.         free(ip->src.astr);
  148.     if (ip->dst.astr != NULL)
  149.         free(ip->dst.astr);
  150.     free(ip);
  151. }
  152.  
  153. static    void
  154. getarg(op, s)
  155. register struct    opnd    *op;
  156. register char    *s;
  157. {
  158. #ifndef NORTHC
  159.         /* In NorthC atol() is a macro !! */
  160.     extern    long    atol();
  161. #endif
  162.     register int    reg;
  163.     register char    *p;
  164.  
  165.     if (*s == '\0') {
  166.         op->amode = NONE;
  167.         return;
  168.     }
  169.  
  170.     if (*s == '#') {                /* immediate data */
  171.         op->amode = IMM;
  172.         s += 1;
  173.         if (isdigit(s[0]) || s[0] == '-')
  174.             op->disp  = atol(s);
  175.         else {
  176.             op->amode |= SYMB;
  177.             op->astr = strsave(s);
  178.         }
  179.         return;
  180.     } else if ((reg = isreg(s)) >= 0) {        /* reg. direct */
  181.         op->amode = REG;
  182.         op->areg = reg;
  183.     } else if (s[0] == '(' || (s[0] == '-' && s[1] == '(')) {
  184.         op->amode = REGI;
  185.         if (s[0] == '-') {
  186.             op->amode |= DEC;
  187.             s++;
  188.         }
  189.         s++;        /* skip the left paren */
  190.         if ((op->areg = isreg(s)) < 0) {
  191.             fprintf(stderr, "bad reg. '%s'\n", s);
  192.             exit(EXIT_FAILURE);
  193.         }
  194.         s += 3;        /* skip the register and right paren */
  195.  
  196.         if (s[0] == '+')
  197.             op->amode |= INC;
  198.     } else if (!isdigit(s[0]) && (s[0] != '-')) {
  199.         op->amode = ABS;
  200.         op->astr = strsave(s);
  201.     } else {
  202.         for (p=s; isdigit(*p) || *p == '-' ;p++)
  203.             ;
  204.         if (*p != '(') {
  205.             /*
  206.              * Must have been absolute, but with an
  207.              * address instead of a symbol.
  208.              */
  209.             op->amode = ABS;
  210.             op->astr = strsave(s);
  211.             return;
  212.         }
  213.         *p++ = '\0';
  214.         op->disp = atol(s);
  215.         s = p;
  216.         if (s[0] == 'p' && s[1] == 'c') {    /* PC relative */
  217.             if (s[2] == ')') {
  218.                 op->amode = PCD;
  219.                 return;
  220.             }
  221.             op->amode = PCDX;
  222.             op->ireg = isreg(s+3);
  223.             if (s[6] == 'l')
  224.                 op->amode |= XLONG;
  225.         } else if ((reg = isreg(s)) >= 0) {
  226.             op->areg = reg;
  227.             if (s[2] == ')') {
  228.                 op->amode = REGID;
  229.                 return;
  230.             }
  231.             op->amode = REGIDX;
  232.             op->ireg = isreg(s+3);
  233.             if (s[6] == 'l')
  234.                 op->amode |= XLONG;
  235.         } else {
  236.             fprintf(stderr, "bad reg. '%s' after disp\n", s);
  237.             exit(EXIT_FAILURE);
  238.         }
  239.     }
  240. }
  241.  
  242. /*
  243.  * characters that can terminate a register name
  244.  */
  245. #define    isterm(c) ((c) == '\0' || (c) == ')' || (c) == ',' || (c) == '.')
  246.  
  247. static    int
  248. isreg(s)
  249. char    *s;
  250. {
  251.     if (s[0] == 'd' && isdigit(s[1]) && isterm(s[2]))
  252.         return D0 + (s[1] - '0');
  253.     if (s[0] == 'a' && isdigit(s[1]) && isterm(s[2]))
  254.         return A0 + (s[1] - '0');
  255.     if (s[0] == 's' && s[1] == 'p' && isterm(s[2]))
  256.         return SP;
  257.  
  258.     return -1;
  259. }
  260.  
  261.  
  262. /*
  263.  * Routines for printing out instructions
  264.  */
  265.  
  266. static    char    *rstr();
  267. static    void    putop();
  268.  
  269. void
  270. putinst(ip)
  271. register INST    *ip;
  272. {
  273.     char    c;
  274.  
  275.     fprintf(ofp, "\t%s", opnames[ip->opcode]);
  276.  
  277.     switch (ip->flags) {
  278.     case LENB:
  279.         c = 'b';
  280.         break;
  281.     case LENW:
  282.         c = 'w';
  283.         break;
  284.     case LENL:
  285.         c = 'l';
  286.         break;
  287.     default:
  288.         c = '\0';
  289.         break;
  290.     }
  291.     if (c)
  292.         fprintf(ofp, ".%c", c);
  293.  
  294.     if (ip->src.amode != NONE) {
  295.         fprintf(ofp, "\t");
  296.         putop(&ip->src);
  297.     }
  298.  
  299.     if (ip->dst.amode != NONE) {
  300.         fprintf(ofp, ",");
  301.         putop(&ip->dst);
  302.     }
  303. #ifdef    DEBUG
  304.     if (debug)
  305.         fprintf(ofp, "\t\t; ref(%04x), set(%04x), live(%04x)",
  306.             reg_ref(ip), reg_set(ip), ip->live);
  307. #endif
  308.     fprintf(ofp, "\n");
  309. }
  310.  
  311. static    void
  312. putop(op)
  313. register struct    opnd    *op;
  314. {
  315.     switch (op->amode & MMASK) {
  316.     case NONE:
  317.         break;
  318.     case REG:
  319.         fprintf(ofp, "%s", rstr(op->areg));
  320.         break;
  321.     case IMM:
  322.         if (op->amode & SYMB)
  323.             fprintf(ofp, "#%s", op->astr);
  324.         else
  325.             fprintf(ofp, "#%ld", op->disp);
  326.         break;
  327.     case ABS:
  328.         fprintf(ofp, "%s", op->astr);
  329.         break;
  330.     case REGI:
  331.         if (op->amode & DEC)
  332.             fprintf(ofp, "-");
  333.         fprintf(ofp, "(%s)", rstr(op->areg));
  334.         if (op->amode & INC)
  335.             fprintf(ofp, "+");
  336.         break;
  337.     case REGID:
  338.         fprintf(ofp, "%ld(%s)", op->disp, rstr(op->areg));
  339.         break;
  340.     case REGIDX:
  341.         fprintf(ofp, "%ld(%s,", op->disp, rstr(op->areg));
  342.         fprintf(ofp, "%s.%c)", rstr(op->ireg),
  343.             (op->amode & XLONG) ? 'l' : 'w');
  344.         break;
  345.     case PCD:
  346.         fprintf(ofp, "%ld(pc)", op->disp);
  347.         break;
  348.     case PCDX:
  349.         fprintf(ofp, "%ld(pc,%s.%c)", op->disp, rstr(op->ireg),
  350.             (op->amode & XLONG) ? 'l' : 'w');
  351.         break;
  352.     default:
  353.         fprintf(stderr, "bad addr. mode in putop: %d\n", op->amode);
  354.         exit(EXIT_FAILURE);
  355.     }
  356. }
  357.  
  358. #ifdef NORTHC
  359. static    char    buf[3];
  360. #endif
  361.  
  362. static    char *
  363. rstr(r)
  364. register char    r;
  365. {
  366. #ifndef NORTHC
  367.     static    char    buf[3];
  368. #endif
  369.     if (r == SP) {
  370.         buf[0] = 's';
  371.         buf[1] = 'p';
  372.     } else if (r >= A0 && r <= A6) {
  373.         buf[0] = 'a';
  374.         buf[1] = '0' + (r - A0);
  375.     } else {
  376.         buf[0] = 'd';
  377.         buf[1] = '0' + (r - D0);
  378.     }
  379.     buf[2] = '\0';
  380.  
  381.     return buf;
  382. }
  383.  
  384. /*
  385.  * opeq(op1, op2) - test equality of the two instruction operands
  386.  */
  387. bool
  388. opeq(op1, op2)
  389. struct    opnd    *op1, *op2;
  390. {
  391.     if (op1->amode != op2->amode || op1->areg != op2->areg ||
  392.         op1->ireg  != op2->ireg  || op1->disp != op2->disp)
  393.         return FALSE;
  394.  
  395.     if (op1->astr == NULL)
  396.         return (op2->astr == NULL);
  397.     else {
  398.         if (op2->astr == NULL)
  399.             return FALSE;
  400.  
  401.         return (stricmp(op1->astr, op2->astr) == 0);
  402.     }
  403. }
  404.