home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff384.lzh / NorthC / Example2.LZH / top / data.c < prev    next >
C/C++ Source or Header  |  1990-08-30  |  9KB  |  356 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 for data flow analysis of a single instruction
  14.  */
  15.  
  16. #include "top.h"
  17.  
  18. /*
  19.  * idata
  20.  *
  21.  * For each instruction, we have some global information, as well
  22.  * as flags indicating what the instruction does with its operands.
  23.  * We need to know if each operand is set and/or referenced. If the
  24.  * instruction has side-effects not directly related to its operands,
  25.  * we need to know that as well, so "special case" code can deal with
  26.  * that as well.
  27.  */
  28. struct    idata    {
  29.  
  30.     char    iflag;        /* flags regarding the entire instruction */
  31. #define        SIDE    0x01    /* inst. has side-effects */
  32. #define        CC    0x02    /* inst. munges condition codes */
  33.  
  34.     char    op1f;        /* flags for the first and second operands */
  35.     char    op2f;
  36. #define        SET    0x01    /* operand is set */
  37. #define        REF    0x02    /* operand is referenced */
  38.  
  39. } idata[] =
  40. {
  41.     { CC,        REF,        REF|SET },    /* OR */
  42.     { CC,        REF,        REF },        /* BTST */
  43.     { 0,        REF,        SET },        /* MOVEP */
  44.     { CC,        REF,        REF|SET },    /* BCHG */
  45.     { CC,        REF,        REF|SET },    /* BCLR */
  46.     { CC,        REF,        REF|SET },    /* BSET */
  47.     { CC,        REF,        REF|SET },    /* AND */
  48.     { CC,        REF,        REF|SET },    /* SUB */
  49.     { CC,        REF,        REF|SET },    /* ADD */
  50.     { CC,        REF,        REF|SET },    /* EOR */
  51.     { CC,        REF,        REF },        /* CMP */
  52.     { CC,        REF,        SET },        /* MOVE */
  53.     { CC,        REF|SET,    0 },        /* NEGX */
  54.     { CC,        REF,        REF },        /* CHK */
  55.     { 0,        REF,        SET },        /* LEA */
  56.     { CC,        SET,        0 },        /* CLR */
  57.     { CC,        REF|SET,    0 },        /* NEG */
  58.     { CC,        REF|SET,    0 },        /* NOT */
  59.     { CC,        REF|SET,    0 },        /* NBCD */
  60.     { CC,        REF|SET,    0 },        /* SWAP */
  61.     { SIDE,        REF,        0 },        /* PEA */
  62.     { CC,        REF|SET,    0 },        /* EXT */
  63.     { SIDE,        REF,        SET },        /* MOVEM */
  64.     { CC,        REF,        0 },        /* TST */
  65.     { CC,        REF|SET,    0 },        /* TAS */
  66.     { 0,        REF,        0 },        /* TRAP */
  67.     { SIDE,        REF|SET,    REF },        /* LINK */
  68.     { SIDE,        REF|SET,    0 },        /* UNLK */
  69.     { 0,        0,        0 },        /* RESET */
  70.     { 0,        0,        0 },        /* NOP */
  71.     { CC,        REF,        0 },        /* STOP */
  72.     { SIDE|CC,    0,        0 },        /* RTE */
  73.     { SIDE,        0,        0 },        /* RTS */
  74.     { 0,        0,        0 },        /* TRAPV */
  75.     { SIDE|CC,    0,        0 },        /* RTR */
  76.     { SIDE,        REF,        0 },        /* JSR */
  77.     { 0,        REF,        0 },        /* JMP */
  78.     { CC,        REF,        REF|SET },    /* ADDQ */
  79.     { 0,        SET,        0 },        /* ST */
  80.     { CC,        REF|SET,    REF },        /* DBT */
  81.     { CC,        REF,        REF|SET },    /* SUBQ */
  82.     { 0,        SET,        0 },        /* SF */
  83.     { CC,        REF|SET,    REF },        /* DBRA (dbf) */
  84.     { 0,        SET,        0 },        /* SHI */
  85.     { CC,        REF|SET,    REF },        /* DBHI */
  86.     { 0,        SET,        0 },        /* SLS */
  87.     { CC,        REF|SET,    REF },        /* DBLS */
  88.     { 0,        SET,        0 },        /* SCC */
  89.     { CC,        REF|SET,    REF },        /* DBCC */
  90.     { 0,        SET,        0 },        /* SCS */
  91.     { CC,        REF|SET,    REF },        /* DBCS */
  92.     { 0,        SET,        0 },        /* SNE */
  93.     { CC,        REF|SET,    REF },        /* DBNE */
  94.     { 0,        SET,        0 },        /* SEQ */
  95.     { CC,        REF|SET,    REF },        /* DBEQ */
  96.     { 0,        SET,        0 },        /* SVC */
  97.     { CC,        REF|SET,    REF },        /* DBVC */
  98.     { 0,        SET,        0 },        /* SVS */
  99.     { CC,        REF|SET,    REF },        /* DBVS */
  100.     { 0,        SET,        0 },        /* SPL */
  101.     { 0,        SET,        0 },        /* SMI */
  102.     { CC,        REF|SET,    REF },        /* DBMI */
  103.     { 0,        SET,        0 },        /* SGE */
  104.     { CC,        REF|SET,    REF },        /* DBGE */
  105.     { 0,        SET,        0 },        /* SLT */
  106.     { CC,        REF|SET,    REF },        /* DBLT */
  107.     { 0,        SET,        0 },        /* SGT */
  108.     { CC,        REF|SET,    REF },        /* DBGT */
  109.     { 0,        SET,        0 },        /* SLE */
  110.     { CC,        REF|SET,    REF },        /* DBLE */
  111.     { 0,        REF,        0 },        /* BRA */
  112.     { SIDE,        REF,        0 },        /* BSR */
  113.     { 0,        REF,        0 },        /* BHI */
  114.     { 0,        REF,        0 },        /* BLS */
  115.     { 0,        REF,        0 },        /* BCC */
  116.     { 0,        REF,        0 },        /* BCS */
  117.     { 0,        REF,        0 },        /* BNE */
  118.     { 0,        REF,        0 },        /* BEQ */
  119.     { 0,        REF,        0 },        /* BVC */
  120.     { 0,        REF,        0 },        /* BVS */
  121.     { 0,        REF,        0 },        /* BPL */
  122.     { 0,        REF,        0 },        /* BMI */
  123.     { 0,        REF,        0 },        /* BGE */
  124.     { 0,        REF,        0 },        /* BLT */
  125.     { 0,        REF,        0 },        /* BGT */
  126.     { 0,        REF,        0 },        /* BLE */
  127.     { CC,        REF,        SET },        /* MOVEQ */
  128.     { CC,        REF,        REF|SET },    /* DIVU */
  129.     { CC,        REF,        REF|SET },    /* SBCD */
  130.     { CC,        REF,        REF|SET },    /* DIVS */
  131.     { CC,        REF,        REF|SET },    /* SUBX */
  132.     { CC,        REF,        REF },        /* CMPM */
  133.     { CC,        REF,        REF|SET },    /* MULU */
  134.     { CC,        REF,        REF|SET },    /* ABCD */
  135.     { 0,        REF|SET,    REF|SET },    /* EXG */
  136.     { CC,        REF,        REF|SET },    /* MULS */
  137.     { CC,        REF,        REF|SET },    /* ADDX */
  138.     { CC,        REF,        REF|SET },    /* ASR */
  139.     { CC,        REF,        REF|SET },    /* LSR */
  140.     { CC,        REF,        REF|SET },    /* ROXR */
  141.     { CC,        REF,        REF|SET },    /* ROR */
  142.     { CC,        REF,        REF|SET },    /* ASL */
  143.     { CC,        REF,        REF|SET },    /* LSL */
  144.     { CC,        REF,        REF|SET },    /* ROXL */
  145.     { CC,        REF,        REF|SET },    /* ROL */
  146.     { 0,        0,        0 },        /* DC */
  147.     { 0,        0,        0 },        /* XREF */
  148.     { 0,        0,        0 },        /* XDEF */
  149. };
  150.  
  151. /*
  152.  * chkset(op) - check to see if operand 'op' sets a register
  153.  *
  154.  * This given operand is set by an instruction. Depending on the
  155.  * addressing mode used, this may set a register. If so, return
  156.  * an appropriate mask. This only happens with register direct
  157.  * addressing.
  158.  */
  159. int
  160. chkset(op)
  161. struct    opnd    *op;
  162. {
  163.     switch (M(op->amode)) {
  164.  
  165.     case REG:
  166.         return RM(op->areg);
  167.     case REGI:
  168.         if (op->amode & (INC|DEC))
  169.             return RM(op->areg);
  170.         else
  171.             return 0;
  172.  
  173.     default:
  174.         return 0;
  175.     }
  176. }
  177.  
  178. /*
  179.  * chkref(op) - check to see if operand 'op' references a register
  180.  *
  181.  * Checks for register references in source or destination
  182.  * operands, since they can occur in either.
  183.  */
  184. int
  185. chkref(op, is_src)
  186. struct    opnd    *op;
  187. bool    is_src;        /* is the operand a source? */
  188. {
  189.     switch (M(op->amode)) {
  190.  
  191.     case NONE:
  192.     case IMM:
  193.     case ABS:
  194.     case PCD:
  195.         return 0;
  196.  
  197.     case REG:
  198.         if (is_src)
  199.             return RM(op->areg);
  200.         else
  201.             return 0;
  202.  
  203.     case REGI:
  204.     case REGID:
  205.         return RM(op->areg);
  206.  
  207.     case REGIDX:
  208.         return (RM(op->areg) | RM(op->ireg));
  209.  
  210.     case PCDX:
  211.         return RM(op->ireg);
  212.  
  213.     default:
  214.         fprintf(stderr, "illegal mode in chkref() %d\n", M(op->amode));
  215.         exit(EXIT_FAILURE);
  216.     }
  217. }
  218.  
  219. /*
  220.  * chkside(ip, type) - check for side-effects of 'ip'
  221.  *
  222.  * Return a mask of registers set or referenced (depending on 'type')
  223.  * by the given instruction. For example, "pea" sets and references
  224.  * the stack pointer.
  225.  */
  226. int
  227. chkside(ip, type)
  228. INST    *ip;
  229. int    type;
  230. {
  231.     switch (ip->opcode) {
  232.     case PEA:        /* refs/sets the stack pointer */
  233.         return RM(SP);
  234.  
  235.     case LINK:        /* refs/sets SP */
  236.         return RM(SP);
  237.  
  238.     case UNLK:
  239.         if (type == SET)
  240.             return RM(SP);
  241.         else
  242.             return 0;
  243.  
  244.     case RTE:
  245.     case RTS:
  246.     case RTR:
  247.         return RM(SP);
  248.  
  249.     case JSR:
  250.     case BSR:
  251.         /*
  252.          * We have to account, here, for what the called
  253.          * routine might do. Registers D0-3 and A0-3 may
  254.          * be munged.
  255.          */
  256.         if (type == SET)
  257.             return    RM(A0)|RM(A1)|RM(A2)|RM(A3)|
  258.                 RM(D0)|RM(D1)|RM(D2)|RM(D3)|RM(SP);
  259.         else
  260.             return    RM(SP);
  261.  
  262.  
  263.     case MOVEM:
  264.         /*
  265.          * We should really check for a register mask spec.
  266.          * here and parse it. The simple solution is to assume
  267.          * that all the registers used for register variables
  268.          * are referenced or modified.
  269.          */
  270.         return RM(A4)|RM(A5)|RM(A7)|RM(D4)|RM(D5)|RM(D6)|RM(D7);
  271.  
  272.     default:
  273.         fprintf(stderr, "chkside() - unknown opcode\n");
  274.         exit(EXIT_FAILURE);
  275.     }
  276. }
  277.  
  278. /*
  279.  * reg_set(ip) - return mask of regs set by 'ip'
  280.  */
  281. int
  282. reg_set(ip)
  283. INST    *ip;
  284. {
  285.     int    mask = 0;    /* build up a register mask */
  286.  
  287.     if (idata[ip->opcode].op1f & SET)
  288.         mask |= chkset(&ip->src);
  289.     if (idata[ip->opcode].op1f & REF) {
  290.         if ((ip->src.amode & (INC|DEC)) != 0)
  291.             mask |= RM(ip->src.areg);
  292.     }
  293.  
  294.     if (idata[ip->opcode].op2f & SET)
  295.         mask |= chkset(&ip->dst);
  296.     if (idata[ip->opcode].op2f & REF) {
  297.         if ((ip->dst.amode & (INC|DEC)) != 0)
  298.             mask |= RM(ip->dst.areg);
  299.     }
  300.  
  301.     if (idata[ip->opcode].iflag & SIDE)
  302.         mask |= chkside(ip, SET);
  303.  
  304.     return mask;
  305. }
  306.  
  307. /*
  308.  * reg_ref(ip) - return mask of regs referenced by 'ip'
  309.  */
  310. int
  311. reg_ref(ip)
  312. INST    *ip;
  313. {
  314.     int    mask = 0;    /* build up a register mask */
  315.  
  316.     mask |= chkref(&ip->src, idata[ip->opcode].op1f & REF);
  317.     mask |= chkref(&ip->dst, idata[ip->opcode].op2f & REF);
  318.     if (idata[ip->opcode].iflag & SIDE)
  319.         mask |= chkside(ip, REF);
  320.  
  321.     return mask;
  322. }
  323.  
  324. /*
  325.  * sets(ip, reg) - is 'reg' set by the instruction 'ip'?
  326.  */
  327. bool
  328. sets(ip, reg)
  329. INST    *ip;
  330. int    reg;
  331. {
  332.     return ((reg_set(ip) & RM(reg)) != 0);
  333. }
  334.  
  335. /*
  336.  * refs(ip, reg) - is 'reg' referenced by the instruction 'ip'?
  337.  */
  338. bool
  339. refs(ip, reg)
  340. INST    *ip;
  341. int    reg;
  342. {
  343.     return ((reg_ref(ip) & RM(reg)) != 0);
  344. }
  345.  
  346. /*
  347.  * uses(ip, ref) - is 'reg' used by the instruction 'ip'?
  348.  */
  349. bool
  350. uses(ip, reg)
  351. INST    *ip;
  352. int    reg;
  353. {
  354.     return sets(ip, reg) || refs(ip, reg);
  355. }
  356.