home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / c / c68k_src / gencode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-12-10  |  36.8 KB  |  1,079 lines

  1. #include        <stdio.h>
  2. #include        "c.h"
  3. #include        "expr.h"
  4. #include        "gen.h"
  5. #include        "cglbdec.h"
  6.  
  7. /*
  8.  *    68000 C compiler
  9.  *
  10.  *    Copyright 1984, 1985, 1986 Matthew Brandt.
  11.  *  all commercial rights reserved.
  12.  *
  13.  *    This compiler is intended as an instructive tool for personal use. Any
  14.  *    use for profit without the written consent of the author is prohibited.
  15.  *
  16.  *    This compiler may be distributed freely for non-commercial use as long
  17.  *    as this notice stays intact. Please forward any enhancements or question
  18. s
  19.  *    to:
  20.  *
  21.  *        Matthew Brandt
  22.  *        Box 920337
  23.  *        Norcross, Ga 30092
  24.  */
  25.  
  26. /*
  27.  *      this module contains all of the code generation routines
  28.  *      for evaluating expressions and conditions.
  29.  */
  30.  
  31. extern struct amode     push[], pop[];
  32.  
  33. struct amode    *gen_expr();            /* forward declaration */
  34.  
  35. struct amode    *make_label(lab)
  36. /*
  37.  *      construct a reference node for an internal label number.
  38.  */
  39. int     lab;
  40. {       struct enode    *lnode;
  41.         struct amode    *ap;
  42.         lnode = xalloc(sizeof(struct enode));
  43.         lnode->nodetype = en_labcon;
  44.         lnode->v.i = lab;
  45.         ap = xalloc(sizeof(struct amode));
  46.         ap->mode = am_direct;
  47.         ap->offset = lnode;
  48.         return ap;
  49. }
  50.  
  51. struct amode    *make_immed(i)
  52. /*
  53.  *      make a node to reference an immediate value i.
  54.  */
  55. int     i;
  56. {       struct amode    *ap;
  57.         struct enode    *ep;
  58.         ep = xalloc(sizeof(struct enode));
  59.         ep->nodetype = en_icon;
  60.         ep->v.i = i;
  61.         ap = xalloc(sizeof(struct amode));
  62.         ap->mode = am_immed;
  63.         ap->offset = ep;
  64.         return ap;
  65. }
  66.  
  67. struct amode    *make_offset(node)
  68. /*
  69.  *      make a direct reference to a node.
  70.  */
  71. struct enode    *node;
  72. {       struct amode    *ap;
  73.         ap = xalloc(sizeof(struct amode));
  74.         ap->mode = am_direct;
  75.         ap->offset = node;
  76.         return ap;
  77. }
  78.  
  79. make_legal(ap,flags,size)
  80. /*
  81.  *      make_legal will coerce the addressing mode in ap1 into a
  82.  *      mode that is satisfactory for the flag word.
  83.  */
  84. struct amode    *ap;
  85. int             flags, size;
  86. {       struct amode    *ap2;
  87.         if( ((flags & F_VOL) == 0) || ap->tempflag )
  88.                 {
  89.                 switch( ap->mode )
  90.                         {
  91.                         case am_immed:
  92.                                 if( flags & F_IMMED )
  93.                                         return;         /* mode ok */
  94.                                 break;
  95.                         case am_areg:
  96.                                 if( flags & F_AREG )
  97.                                         return;
  98.                                 break;
  99.                         case am_dreg:
  100.                                 if( flags & F_DREG )
  101.                                         return;
  102.                                 break;
  103.                         case am_ind:    case am_indx:
  104.                         case am_indx2:  case am_xpc:
  105.                         case am_direct: case am_indx3:
  106.                                 if( flags & F_MEM )
  107.                                         return;
  108.                                 break;
  109.                         }
  110.                 }
  111.         if( flags & F_DREG )
  112.                 {
  113.                 freeop(ap);             /* maybe we can use it... */
  114.                 ap2 = temp_data();      /* allocate to dreg */
  115.                 gen_code(op_move,size,ap,ap2);
  116.                 ap->mode = am_dreg;
  117.                 ap->preg = ap2->preg;
  118.                 ap->deep = ap2->deep;
  119.                 ap->tempflag = 1;
  120.                 return;
  121.                 }
  122.         if( size == 1 )
  123.                 {
  124.                 freeop(ap);
  125.                 ap2 = temp_data();
  126.                 gen_code(op_move,1,ap,ap2);
  127.                 gen_code(op_ext,2,ap2,0);
  128.                 freeop(ap);
  129.                 ap->mode = ap2->mode;
  130.                 ap->preg = ap2->preg;
  131.                 ap->deep = ap2->deep;
  132.                 size = 2;
  133.                 }
  134.         freeop(ap);
  135.         ap2 = temp_addr();
  136.         gen_code(op_move,size,ap,ap2);
  137.         ap->mode = am_areg;
  138.         ap->preg = ap2->preg;
  139.         ap->deep = ap2->deep;
  140.         ap->tempflag = 1;
  141. }
  142.  
  143. do_extend(ap,isize,osize,flags)
  144. /*
  145.  *      if isize is not equal to osize then the operand ap will be
  146.  *      loaded into a register (if not already) and if osize is
  147.  *      greater than isize it will be extended to match.
  148.  */
  149. struct amode    *ap;
  150. int             isize, osize, flags;
  151. {       if( isize == osize )
  152.                 return;
  153.         if( ap->mode != am_areg && ap->mode != am_dreg )
  154.                 make_legal(ap,flags & (F_AREG | F_DREG),isize);
  155.         if( ap->mode == am_areg )
  156.                 return;         /* extend is automagic */
  157.         switch( isize )
  158.                 {
  159.                 case 1:
  160.                         gen_code(op_ext,2,ap,0);
  161.                 case 2:
  162.                         if( osize == 4 )
  163.                                 gen_code(op_ext,4,ap,0);
  164.                 }
  165. }
  166.  
  167. int     isshort(node)
  168. /*
  169.  *      return true if the node passed can be generated as a short
  170.  *      offset.
  171.  */
  172. struct enode    *node;
  173. {       return node->nodetype == en_icon &&
  174.                 (node->v.i >= -65536 && node->v.i <= 65535);
  175. }
  176.  
  177. int     isbyte(node)
  178. /*
  179.  *      return true if the node passed can be evaluated as a byte
  180.  *      offset.
  181.  */
  182. struct enode    *node;
  183. {       return node->nodetype == en_icon &&
  184.                 (-128 <= node->v.i && node->v.i <= 127);
  185. }
  186.  
  187. struct amode    *gen_index(node)
  188. /*
  189.  *      generate code to evaluate an index node (^+) and return
  190.  *      the addressing mode of the result. This routine takes no
  191.  *      flags since it always returns either am_ind or am_indx.
  192.  */
  193. struct enode    *node;
  194. {       struct amode    *ap1, *ap2;
  195.         if( node->v.p[0]->nodetype == en_tempref &&
  196.                 node->v.p[1]->nodetype == en_tempref &&
  197.                 ( node->v.p[0]->v.i >= 8 || node->v.p[1]->v.i >= 8 ))
  198.                 {       /* both nodes are registers, one is address */
  199.                 if( node->v.p[0]->v.i < 8 )
  200.                         {
  201.                         ap1 = gen_expr(node->v.p[1],F_AREG,4);
  202.                         ap1->sreg = node->v.p[0]->v.i;
  203.                         ap1->mode = am_indx2;   /* 0(Ax,Dx) */
  204.                         ap1->offset = makenode(en_icon,0,0);
  205.                         return ap1;
  206.                         }
  207.                 ap1 = gen_expr(node->v.p[0],F_AREG,4);
  208.                 ap2 = gen_expr(node->v.p[1],F_AREG | F_DREG,4);
  209.                 if( ap2->mode == am_dreg )
  210.                         {
  211.                         ap1->mode = am_indx2;
  212.                         ap1->sreg = ap2->preg;
  213.                         }
  214.                 else
  215.                         {
  216.                         ap1->mode = am_indx3;
  217.                         ap1->sreg = ap2->preg;
  218.                         }
  219.                 ap1->offset = makenode(en_icon,0,0);
  220.                 return ap1;
  221.                 }
  222.         ap1 = gen_expr(node->v.p[0],F_AREG | F_IMMED,4);
  223.         if( ap1->mode == am_immed && isshort(ap1->offset) )
  224.                 {
  225.                 ap2 = gen_expr(node->v.p[1],F_AREG,4);
  226.                 ap2->mode = am_indx;
  227.                 ap2->offset = ap1->offset;
  228.                 return ap2;
  229.                 }
  230.         ap2 = gen_expr(node->v.p[1],F_ALL,4);   /* get right op */
  231.         if( ap2->mode == am_immed && isshort(ap2->offset) &&
  232.             ap1->mode == am_areg ) /* make am_indx */
  233.                 {
  234.                 ap2->mode = am_indx;
  235.                 ap2->preg = ap1->preg;
  236.                 ap2->deep = ap1->deep;
  237.                 return ap2;
  238.                 }
  239.         validate(ap1);
  240.         make_legal(ap1,F_AREG | F_VOL,4);
  241.         gen_code(op_add,4,ap2,ap1);             /* add left to address reg */
  242.         ap1->mode = am_ind;             /* make indirect */
  243.         freeop(ap2);                    /* release any temps in ap2 */
  244.         return ap1;                     /* return indirect */
  245. }
  246.  
  247. struct amode    *gen_deref(node,flags,size)
  248. /*
  249.  *      return the addressing mode of a dereferenced node.
  250.  */
  251. struct enode    *node;
  252. int             flags, size;
  253. {       struct amode    *ap1;
  254.         int             siz1;
  255.         switch( node->nodetype )        /* get load size */
  256.                 {
  257.                 case en_b_ref:
  258.                         siz1 = 1;
  259.                         break;
  260.                 case en_w_ref:
  261.                         siz1 = 2;
  262.                         break;
  263.                 case en_l_ref:
  264.                         siz1 = 4;
  265.                         break;
  266.                 }
  267.         if( node->v.p[0]->nodetype == en_add )
  268.                 {
  269.                 ap1 = gen_index(node->v.p[0]);
  270.                 do_extend(ap1,siz1,size,flags);
  271.                 make_legal(ap1,flags,size);
  272.                 return ap1;
  273.                 }
  274.         else if( node->v.p[0]->nodetype == en_autocon )
  275.                 {
  276.                 ap1 = xalloc(sizeof(struct amode));
  277.                 ap1->mode = am_indx;
  278.                 ap1->preg = 6;
  279.                 ap1->offset = makenode(en_icon,node->v.p[0]->v.i);
  280.                 do_extend(ap1,siz1,size,flags);
  281.                 make_legal(ap1,flags,size);
  282.                 return ap1;
  283.                 }
  284.         ap1 = gen_expr(node->v.p[0],F_AREG | F_IMMED,4); /* generate address */
  285.         if( ap1->mode == am_areg )
  286.                 {
  287.                 ap1->mode = am_ind;
  288.                 do_extend(ap1,siz1,size,flags);
  289.                 make_legal(ap1,flags,size);
  290.                 return ap1;
  291.                 }
  292.         ap1->mode = am_direct;
  293.         do_extend(ap1,siz1,size,flags);
  294.         make_legal(ap1,flags,size);
  295.         return ap1;
  296. }
  297.  
  298. struct amode    *gen_unary(node,flags,size,op)
  299. /*
  300.  *      generate code to evaluate a unary minus or complement.
  301.  */
  302. struct enode    *node;
  303. int             flags, size, op;
  304. {       struct amode    *ap;
  305.         ap = gen_expr(node->v.p[0],F_DREG | F_VOL,size);
  306.         gen_code(op,size,ap,0);
  307.         make_legal(ap,flags,size);
  308.         return ap;
  309. }
  310.  
  311. struct amode    *gen_binary(node,flags,size,op)
  312. /*
  313.  *      generate code to evaluate a binary node and return
  314.  *      the addressing mode of the result.
  315.  */
  316. struct enode    *node;
  317. int             flags, size, op;
  318. {       struct amode    *ap1, *ap2;
  319.         ap1 = gen_expr(node->v.p[0],F_VOL | F_DREG | F_AREG,size);
  320.         ap2 = gen_expr(node->v.p[1],F_ALL,size);
  321.         validate(ap1);          /* in case push occurred */
  322.         gen_code(op,size,ap2,ap1);
  323.         freeop(ap2);
  324.         make_legal(ap1,flags,size);
  325.         return ap1;
  326. }
  327.  
  328. struct amode    *gen_xbin(node,flags,size,op)
  329. /*
  330.  *      generate code to evaluate a restricted binary node and return
  331.  *      the addressing mode of the result.
  332.  */
  333. struct enode    *node;
  334. int             flags, size, op;
  335. {       struct amode    *ap1, *ap2;
  336.         ap1 = gen_expr(node->v.p[0],F_VOL | F_DREG,size);
  337.         ap2 = gen_expr(node->v.p[1],F_DREG,size);
  338.         validate(ap1);          /* in case push occurred */
  339.         gen_code(op,size,ap2,ap1);
  340.         freeop(ap2);
  341.         make_legal(ap1,flags,size);
  342.         return ap1;
  343. }
  344. struct amode    *gen_shift(node,flags,size,op)
  345. /*
  346.  *      generate code to evaluate a shift node and return the
  347.  *      address mode of the result.
  348.  */
  349. struct enode    *node;
  350. int             flags, size, op;
  351. {       struct amode    *ap1, *ap2;
  352.         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,size);
  353.         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,1);
  354.         validate(ap1);
  355.         gen_code(op,size,ap2,ap1);
  356.         freeop(ap2);
  357.         make_legal(ap1,flags,size);
  358.         return ap1;
  359. }
  360.  
  361. struct amode    *gen_modiv(node,flags,size,op,modflag)
  362. /*
  363.  *      generate code to evaluate a mod operator or a divide
  364.  *      operator. these operations are done on only long
  365.  *      divisors and word dividends so that the 68000 div
  366.  *      instruction can be used.
  367.  */
  368. struct enode    *node;
  369. int             flags, op, size, modflag;
  370. {       struct amode    *ap1, *ap2;
  371.         if( node->v.p[0]->nodetype == en_icon )
  372.                 swap_nodes(node);
  373.         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,4);
  374.         ap2 = gen_expr(node->v.p[1],F_ALL,2);
  375.         validate(ap1);
  376.         gen_code(op,0,ap2,ap1);
  377.         if( modflag )
  378.                 gen_code(op_swap,0,ap1,0);
  379.         gen_code(op_ext,4,ap1,0);
  380.         make_legal(ap1,flags,4);
  381.         freeop(ap2);
  382.         return ap1;
  383. }
  384.  
  385. swap_nodes(node)
  386. /*
  387.  *      exchange the two operands in a node.
  388.  */
  389. struct enode    *node;
  390. {       struct enode    *temp;
  391.         temp = node->v.p[0];
  392.         node->v.p[0] = node->v.p[1];
  393.         node->v.p[1] = temp;
  394. }
  395.  
  396. struct amode    *gen_mul(node,flags,size,op)
  397. /*
  398.  *      generate code to evaluate a multiply node. both operands
  399.  *      are treated as words and the result is long and is always
  400.  *      in a register so that the 68000 mul instruction can be used.
  401.  */
  402. struct enode    *node;
  403. int             flags, size, op;
  404. {       struct amode    *ap1, *ap2;
  405.         if( node->v.p[0]->nodetype == en_icon )
  406.                 swap_nodes(node);
  407.         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,2);
  408.         ap2 = gen_expr(node->v.p[1],F_ALL,2);
  409.         validate(ap1);
  410.         gen_code(op,0,ap2,ap1);
  411.         freeop(ap2);
  412.         make_legal(ap1,flags,4);
  413.         return ap1;
  414. }
  415.  
  416. struct amode    *gen_hook(node,flags,size)
  417. /*
  418.  *      generate code to evaluate a condition operator node (?:)
  419.  */
  420. struct enode    *node;
  421. int             flags, size;
  422. {       struct amode    *ap1, *ap2;
  423.         int             false_label, end_label;
  424.         false_label = nextlabel++;
  425.         end_label = nextlabel++;
  426.         flags = (flags & (F_AREG | F_DREG)) | F_VOL;
  427.         falsejp(node->v.p[0],false_label);
  428.         node = node->v.p[1];
  429.         ap1 = gen_expr(node->v.p[0],flags,size);
  430.         freeop(ap1);
  431.         gen_code(op_bra,0,make_label(end_label),0);
  432.         gen_label(false_label);
  433.         ap2 = gen_expr(node->v.p[1],flags,size);
  434.         if( !equal_address(ap1,ap2) )
  435.                 {
  436.                 freeop(ap2);
  437.                 if( ap1->mode == am_dreg )
  438.                         temp_data();
  439.                 else
  440.                         temp_addr();
  441.                 gen_code(op_move,size,ap2,ap1);
  442.                 }
  443.         gen_label(end_label);
  444.         return ap1;
  445. }
  446.  
  447. struct amode    *gen_asadd(node,flags,size,op)
  448. /*
  449.  *      generate a plus equal or a minus equal node.
  450.  */
  451. struct enode    *node;
  452. int             flags,size,op;
  453. {       struct amode    *ap1, *ap2;
  454.         int             ssize, mask0, mask1;
  455.         ssize = natural_size(node->v.p[0]);
  456.         if( ssize > size )
  457.                 size = ssize;
  458.         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
  459.         ap2 = gen_expr(node->v.p[1],F_DREG | F_AREG | F_IMMED,size);
  460.         validate(ap1);
  461.         gen_code(op,ssize,ap2,ap1);
  462.         freeop(ap2);
  463.         do_extend(ap1,ssize,size);
  464.         make_legal(ap1,flags,size);
  465.         return ap1;
  466. }
  467.  
  468. struct amode    *gen_aslogic(node,flags,size,op)
  469. /*
  470.  *      generate a and equal or a or equal node.
  471.  */
  472. struct enode    *node;
  473. int             flags,size,op;
  474. {       struct amode    *ap1, *ap2, *ap3;
  475.         int             ssize, mask0, mask1;
  476.         ssize = natural_size(node->v.p[0]);
  477.         if( ssize > size )
  478.                 size = ssize;
  479.         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
  480.         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,size);
  481.         validate(ap1);
  482.         if( ap1->mode != am_areg )
  483.                 gen_code(op,ssize,ap2,ap1);
  484.         else
  485.                 {
  486.                 ap3 = temp_data();
  487.                 gen_code(op_move,4,ap1,ap3);
  488.                 gen_code(op,size,ap2,ap3);
  489.                 gen_code(op_move,size,ap3,ap1);
  490.                 freeop(ap3);
  491.                 }
  492.         freeop(ap2);
  493.         do_extend(ap1,ssize,size);
  494.         make_legal(ap1,flags,size);
  495.         return ap1;
  496. }
  497.  
  498. gen_asshift(node,flags,size,op)
  499. /*
  500.  *      generate shift equals operators.
  501.  */
  502. struct enode    *node;
  503. int             flags, size, op;
  504. {       struct amode    *ap1, *ap2, *ap3;
  505.         ap1 = gen_expr(node->v.p[0],F_ALL,size);
  506.         if( ap1->mode != am_dreg )
  507.                 {
  508.                 ap3 = temp_data();
  509.                 gen_code(op_move,size,ap1,ap3);
  510.                 }
  511.         else
  512.                 ap3 = ap1;
  513.         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,size);
  514.         validate(ap3);
  515.         gen_code(op,size,ap2,ap3);
  516.         freeop(ap2);
  517.         if( ap3 != ap1 )
  518.                 {
  519.                 gen_code(op_move,size,ap3,ap1);
  520.                 freeop(ap3);
  521.                 }
  522.         make_legal(ap1,flags,size);
  523.         return ap1;
  524. }
  525.  
  526. struct amode    *gen_asmul(node,flags,size)
  527. /*
  528.  *      generate a *= node.
  529.  */
  530. struct enode    *node;
  531. int             flags, size;
  532. {       struct amode    *ap1, *ap2, *ap3;
  533.         int             siz1;
  534.         siz1 = natural_size(node->v.p[0]);
  535.         ap1 = gen_expr(node->v.p[1],F_DREG | F_VOL,2);
  536.         ap2 = gen_expr(node->v.p[0],F_ALL,siz1);
  537.         if( siz1 == 1 || ap2->mode == am_areg )
  538.                 {
  539.                 ap3 = temp_data();
  540.                 gen_code(op_move,siz1,ap2,ap3);
  541.                 if( siz1 == 1 )
  542.                         gen_code(op_ext,2,ap3,0);
  543.                 freeop(ap3);
  544.                 }
  545.         else
  546.                 ap3 = ap2;
  547.         gen_code(op_muls,0,ap3,ap1);
  548.         gen_code(op_move,siz1,ap1,ap2);
  549.         freeop(ap2);
  550.         return ap1;
  551. }
  552.  
  553. struct amode    *gen_asmodiv(node,flags,size,op)
  554. /*
  555.  *      generate /= and %= nodes.
  556.  */
  557. struct enode    *node;
  558. int             flags, size, op;
  559. {       struct amode    *ap1, *ap2, *ap3;
  560.         int             siz1;
  561.         siz1 = natural_size(node->v.p[0]);
  562.         ap1 = temp_data();
  563.         ap2 = gen_expr(node->v.p[0],F_ALL,siz1);
  564.         validate(ap1);
  565.         gen_code(op_move,siz1,ap2,ap1);
  566.         do_extend(ap1,siz1,4);
  567.         ap3 = gen_expr(node->v.p[1],F_ALL & ~F_AREG,2);
  568.         validate(ap2);
  569.         validate(ap1);
  570.         gen_code(op_divs,0,ap3,ap1);
  571.         freeop(ap3);
  572.         if( op != op_divs )
  573.                 gen_code(op_swap,0,ap1,0);
  574.         gen_code(op_ext,4,ap1,0);
  575.         gen_code(op_move,siz1,ap1,ap2);
  576.         freeop(ap2);
  577.         make_legal(ap1,flags,size);
  578.         return ap1;
  579. }
  580.  
  581. struct amode    *gen_assign(node,flags,size)
  582. /*
  583.  *      generate code for an assignment node. if the size of the
  584.  *      assignment destination is larger than the size passed then
  585.  *      everything below this node will be evaluated with the
  586.  *      assignment size.
  587.  */
  588. struct enode    *node;
  589. int             flags, size;
  590. {       struct amode    *ap1, *ap2;
  591.         int             ssize;
  592.         switch( node->v.p[0]->nodetype )
  593.                 {
  594.                 case en_b_ref:
  595.                         ssize = 1;
  596.                         break;
  597.                 case en_w_ref:
  598.                         ssize = 2;
  599.                         break;
  600.                 case en_l_ref:
  601.                 case en_tempref:
  602.                         ssize = 4;
  603.                         break;
  604.                 }
  605.         if( ssize > size )
  606.                 size = ssize;
  607.         ap2 = gen_expr(node->v.p[1],F_ALL,size);
  608.         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
  609.         validate(ap2);
  610.         gen_code(op_move,ssize,ap2,ap1);
  611.         freeop(ap1);
  612.         return ap2;
  613. }
  614.  
  615. struct amode    *gen_aincdec(node,flags,size,op)
  616. /*
  617.  *      generate an auto increment or decrement node. op should be
  618.  *      either op_add (for increment) or op_sub (for decrement).
  619.  */
  620. struct enode    *node;
  621. int             flags, size;
  622. {       struct amode    *ap1, *ap2;
  623.         int             siz1;
  624.         siz1 = natural_size(node->v.p[0]);
  625.         if( flags & F_NOVALUE )         /* dont need result */
  626.                 {
  627.                 ap1 = gen_expr(node->v.p[0],F_ALL,siz1);
  628.                 gen_code(op,siz1,make_immed(node->v.p[1]),ap1);
  629.                 freeop(ap1);
  630.                 return ap1;
  631.                 }
  632.         if( flags & F_DREG )
  633.                 ap1 = temp_data();
  634.         else
  635.                 ap1 = temp_addr();
  636.         ap2 = gen_expr(node->v.p[0],F_ALL,siz1);
  637.         validate(ap1);
  638.         gen_code(op_move,siz1,ap2,ap1);
  639.         gen_code(op,siz1,make_immed(node->v.p[1]),ap2);
  640.         freeop(ap2);
  641.         do_extend(ap1,siz1,size);
  642.         return ap1;
  643. }
  644.  
  645. push_param(ep)
  646. /*
  647.  *      push the operand expression onto the stack.
  648.  */
  649. struct enode    *ep;
  650. {       struct amode    *ap;
  651.         ap = gen_expr(ep,F_ALL,4);
  652.         gen_code(op_move,4,ap,push);
  653.         freeop(ap);
  654. }
  655.  
  656. int     gen_parms(plist)
  657. /*
  658.  *      push a list of parameters onto the stack and return the
  659.  *      number of parameters pushed.
  660.  */
  661. struct enode    *plist;
  662. {       int     i;
  663.         i = 0;
  664.         while( plist != 0 )
  665.                 {
  666.                 push_param(plist->v.p[0]);
  667.                 plist = plist->v.p[1];
  668.                 ++i;
  669.                 }
  670.         return i;
  671. }
  672.  
  673. struct amode    *gen_fcall(node,flags)
  674. /*
  675.  *      generate a function call node and return the address mode
  676.  *      of the result.
  677.  */
  678. struct enode    *node;
  679. {       struct amode    *ap, *result;
  680.         int             i;
  681.         result = temp_addr();
  682.         temp_addr();                    /* push any used addr temps */
  683.         freeop(result); freeop(result);
  684.         result = temp_data();
  685.         temp_data(); temp_data();       /* push any used data registers */
  686.         freeop(result); freeop(result); freeop(result);
  687.         i = gen_parms(node->v.p[1]);    /* generate parameters */
  688.         if( node->v.p[0]->nodetype == en_nacon )
  689.                 gen_code(op_jsr,0,make_offset(node->v.p[0]),0);
  690.         else
  691.                 {
  692.                 ap = gen_expr(node->v.p[0],F_AREG,4);
  693.                 ap->mode = am_ind;
  694.                 freeop(ap);
  695.                 gen_code(op_jsr,0,ap,0);
  696.                 }
  697.         if( i != 0 )
  698.                 gen_code(op_add,4,make_immed(i * 4),makeareg(7));
  699.         if( flags & F_DREG )
  700.                 result = temp_data();
  701.         else
  702.                 result = temp_addr();
  703.         if( result->preg != 0 || (flags & F_DREG) == 0 )
  704.                 gen_code(op_move,4,makedreg(0),result);
  705.         return result;
  706. }
  707.  
  708. struct amode    *gen_expr(node,flags,size)
  709. /*
  710.  *      general expression evaluation. returns the addressing mode
  711.  *      of the result.
  712.  */
  713. struct enode    *node;
  714. int             flags, size;
  715. {       struct amode    *ap1, *ap2;
  716.         int             lab0, lab1;
  717.         int             natsize;
  718.         if( node == 0 )
  719.                 {
  720.                 printf("DIAG - null node in gen_expr.\n");
  721.                 return 0;
  722.                 }
  723.         switch( node->nodetype )
  724.                 {
  725.                 case en_icon:
  726.                 case en_labcon:
  727.                 case en_nacon:
  728.                         ap1 = xalloc(sizeof(struct amode));
  729.                         ap1->mode = am_immed;
  730.                         ap1->offset = node;
  731.                         make_legal(ap1,flags,size);
  732.                         return ap1;
  733.                 case en_autocon:
  734.                         ap1 = temp_addr();
  735.                         ap2 = xalloc(sizeof(struct amode));
  736.                         ap2->mode = am_indx;
  737.                         ap2->preg = 6;          /* frame pointer */
  738.                         ap2->offset = node;     /* use as constant node */
  739.                         gen_code(op_lea,0,ap2,ap1);
  740.                         make_legal(ap1,flags,size);
  741.                         return ap1;             /* return reg */
  742.                 case en_b_ref:
  743.                 case en_w_ref:
  744.                 case en_l_ref:
  745.                         return gen_deref(node,flags,size);
  746.                 case en_tempref:
  747.                         ap1 = xalloc(sizeof(struct amode));
  748.                         if( node->v.i < 8 )
  749.                                 {
  750.                                 ap1->mode = am_dreg;
  751.                                 ap1->preg = node->v.i;
  752.                                 }
  753.                         else
  754.                                 {
  755.                                 ap1->mode = am_areg;
  756.                                 ap1->preg = node->v.i - 8;
  757.                                 }
  758.                         ap1->tempflag = 0;      /* not a temporary */
  759.                         make_legal(ap1,flags,size);
  760.                         return ap1;
  761.                 case en_uminus:
  762.                         return gen_unary(node,flags,size,op_neg);
  763.                 case en_compl:
  764.                         return gen_unary(node,flags,size,op_not);
  765.                 case en_add:
  766.                         return gen_binary(node,flags,size,op_add);
  767.                 case en_sub:
  768.                         return gen_binary(node,flags,size,op_sub);
  769.                 case en_and:
  770.                         return gen_binary(node,flags,size,op_and);
  771.                 case en_or:
  772.                         return gen_binary(node,flags,size,op_or);
  773.                 case en_xor:
  774.                         return gen_xbin(node,flags,size,
  775. op_eor);
  776.                 case en_mul:
  777.                         return gen_mul(node,flags,size,op_muls);
  778.                 case en_umul:
  779.                         return gen_mul(node,flags,size,op_mulu);
  780.                 case en_div:
  781.                         return gen_modiv(node,flags,size,op_divs,0);
  782.                 case en_udiv:
  783.                         return gen_modiv(node,flags,size,op_divu,0);
  784.                 case en_mod:
  785.                         return gen_modiv(node,flags,size,op_divs,1);
  786.                 case en_umod:
  787.                         return gen_modiv(node,flags,size,op_divu,1);
  788.                 case en_lsh:
  789.                         return gen_shift(node,flags,size,op_asl);
  790.                 case en_rsh:
  791.                         return gen_shift(node,flags,size,op_asr);
  792.                 case en_asadd:
  793.                         return gen_asadd(node,flags,size,op_add);
  794.                 case en_assub:
  795.                         return gen_asadd(node,flags,size,op_sub);
  796.                 case en_asand:
  797.                         return gen_aslogic(node,flags,size,op_and);
  798.                 case en_asor:
  799.                         return gen_aslogic(node,flags,size,op_or);
  800.                 case en_aslsh:
  801.                         return gen_asshift(node,flags,size,op_asl);
  802.                 case en_asrsh:
  803.                         return gen_asshift(node,flags,size,op_asr);
  804.                 case en_asmul:
  805.                         return gen_asmul(node,flags,size);
  806.                 case en_asdiv:
  807.                         return gen_asmodiv(node,flags,size,op_divs);
  808.                 case en_asmod:
  809.                         return gen_asmodiv(node,flags,size,op_muls);
  810.                 case en_assign:
  811.                         return gen_assign(node,flags,size);
  812.                 case en_ainc:
  813.                         return gen_aincdec(node,flags,size,op_add);
  814.                 case en_adec:
  815.                         return gen_aincdec(node,flags,size,op_sub);
  816.                 case en_land:   case en_lor:
  817.                 case en_eq:     case en_ne:
  818.                 case en_lt:     case en_le:
  819.                 case en_gt:     case en_ge:
  820.                 case en_ult:    case en_ule:
  821.                 case en_ugt:    case en_uge:
  822.                 case en_not:
  823.                         lab0 = nextlabel++;
  824.                         lab1 = nextlabel++;
  825.                         falsejp(node,lab0);
  826.                         ap1 = temp_data();
  827.                         gen_code(op_moveq,0,make_immed(1),ap1);
  828.                         gen_code(op_bra,0,make_label(lab1),0);
  829.                         gen_label(lab0);
  830.                         gen_code(op_clr,4,ap1,0);
  831.                         gen_label(lab1);
  832.                         return ap1;
  833.                 case en_cond:
  834.                         return gen_hook(node,flags,size);
  835.                 case en_void:
  836.                         natsize = natural_size(node->v.p[0]);
  837.                         freeop(gen_expr(node->v.p[0],F_ALL | F_NOVALUE,natsize))
  838. ;
  839.                         return gen_expr(node->v.p[1],flags,size);
  840.                 case en_fcall:
  841.                         return gen_fcall(node,flags);
  842.                 default:
  843.                         printf("DIAG - uncoded node in gen_expr.\n");
  844.                         return 0;
  845.                 }
  846. }
  847.  
  848. int     natural_size(node)
  849. /*
  850.  *      return the natural evaluation size of a node.
  851.  */
  852. struct enode    *node;
  853. {       int     siz0, siz1;
  854.         if( node == 0 )
  855.                 return 0;
  856.         switch( node->nodetype )
  857.                 {
  858.                 case en_icon:
  859.                         if( -128 <= node->v.i && node->v.i <= 127 )
  860.                                 return 1;
  861.                         if( -32768 <= node->v.i && node->v.i <= 32767 )
  862.                                 return 2;
  863.                         return 4;
  864.                 case en_fcall:  case en_labcon:
  865.                 case en_nacon:  case en_autocon:
  866.                 case en_l_ref:  case en_tempref:
  867.                 case en_cbl:    case en_cwl:
  868.                         return 4;
  869.                 case en_b_ref:
  870.                         return 1;
  871.                 case en_cbw:
  872.                 case en_w_ref:
  873.                         return 2;
  874.                 case en_not:    case en_compl:
  875.                 case en_uminus: case en_assign:
  876.                 case en_ainc:   case en_adec:
  877.                         return natural_size(node->v.p[0]);
  878.                 case en_add:    case en_sub:
  879.                 case en_mul:    case en_div:
  880.                 case en_mod:    case en_and:
  881.                 case en_or:     case en_xor:
  882.                 case en_lsh:    case en_rsh:
  883.                 case en_eq:     case en_ne:
  884.                 case en_lt:     case en_le:
  885.                 case en_gt:     case en_ge:
  886.                 case en_land:   case en_lor:
  887.                 case en_asadd:  case en_assub:
  888.                 case en_asmul:  case en_asdiv:
  889.                 case en_asmod:  case en_asand:
  890.                 case en_asor:   case en_aslsh:
  891.                 case en_asrsh:
  892.                         siz0 = natural_size(node->v.p[0]);
  893.                         siz1 = natural_size(node->v.p[1]);
  894.                         if( siz1 > siz0 )
  895.                                 return siz1;
  896.                         else
  897.                                 return siz0;
  898.                 case en_void:   case en_cond:
  899.                         return natural_size(node->v.p[1]);
  900.                 default:
  901.                         printf("DIAG - natural size error.\n");
  902.                         break;
  903.                 }
  904.         return 0;
  905. }
  906.  
  907. gen_compare(node)
  908. /*
  909.  *      generate code to do a comparison of the two operands of
  910.  *      node.
  911.  */
  912. struct enode    *node;
  913. {       struct amode    *ap1, *ap2;
  914.         int             size;
  915.         size = natural_size(node);
  916.         ap1 = gen_expr(node->v.p[0],F_AREG | F_DREG, size);
  917.         ap2 = gen_expr(node->v.p[1],F_ALL,size);
  918.         validate(ap1);
  919.         gen_code(op_cmp,size,ap2,ap1);
  920.         freeop(ap2);
  921.         freeop(ap1);
  922. }
  923.  
  924. truejp(node,label)
  925. /*
  926.  *      generate a jump to label if the node passed evaluates to
  927.  *      a true condition.
  928.  */
  929. struct enode    *node;
  930. int             label;
  931. {       struct amode    *ap1;
  932.         int             siz1;
  933.         int             lab0;
  934.         if( node == 0 )
  935.                 return;
  936.         switch( node->nodetype )
  937.                 {
  938.                 case en_eq:
  939.                         gen_compare(node);
  940.                         gen_code(op_beq,0,make_label(label),0);
  941.                         break;
  942.                 case en_ne:
  943.                         gen_compare(node);
  944.                         gen_code(op_bne,0,make_label(label),0);
  945.                         break;
  946.                 case en_lt:
  947.                         gen_compare(node);
  948.                         gen_code(op_blt,0,make_label(label),0);
  949.                         break;
  950.                 case en_le:
  951.                         gen_compare(node);
  952.                         gen_code(op_ble,0,make_label(label),0);
  953.                         break;
  954.                 case en_gt:
  955.                         gen_compare(node);
  956.                         gen_code(op_bgt,0,make_label(label),0);
  957.                         break;
  958.                 case en_ge:
  959.                         gen_compare(node);
  960.                         gen_code(op_bge,0,make_label(label),0);
  961.                         break;
  962.                 case en_ult:
  963.                         gen_compare(node);
  964.                         gen_code(op_blo,0,make_label(label),0);
  965.                         break;
  966.                 case en_ule:
  967.                         gen_compare(node);
  968.                         gen_code(op_bls,0,make_label(label),0);
  969.                         break;
  970.                 case en_ugt:
  971.                         gen_compare(node);
  972.                         gen_code(op_bhi,0,make_label(label),0);
  973.                         break;
  974.                 case en_uge:
  975.                         gen_compare(node);
  976.                         gen_code(op_bhs,0,make_label(label),0);
  977.                         break;
  978.                 case en_land:
  979.                         lab0 = nextlabel++;
  980.                         falsejp(node->v.p[0],lab0);
  981.                         truejp(node->v.p[1],label);
  982.                         gen_label(lab0);
  983.                         break;
  984.                 case en_lor:
  985.                         truejp(node->v.p[0],label);
  986.                         truejp(node->v.p[1],label);
  987.                         break;
  988.                 case en_not:
  989.                         falsejp(node->v.p[0],label);
  990.                         break;
  991.                 default:
  992.                         siz1 = natural_size(node);
  993.                         ap1 = gen_expr(node,F_ALL,siz1);
  994.                         gen_code(op_tst,siz1,ap1,0);
  995.                         freeop(ap1);
  996.                         gen_code(op_bne,0,make_label(label),0);
  997.                         break;
  998.                 }
  999. }
  1000.  
  1001. falsejp(node,label)
  1002. /*
  1003.  *      generate code to execute a jump to label if the expression
  1004.  *      passed is false.
  1005.  */
  1006. struct enode    *node;
  1007. int             label;
  1008. {       struct amode    *ap;
  1009.         int             siz1;
  1010.         int             lab0;
  1011.         if( node == 0 )
  1012.                 return;
  1013.         switch( node->nodetype )
  1014.                 {
  1015.                 case en_eq:
  1016.                         gen_compare(node);
  1017.                         gen_code(op_bne,0,make_label(label),0);
  1018.                         break;
  1019.                 case en_ne:
  1020.                         gen_compare(node);
  1021.                         gen_code(op_beq,0,make_label(label),0);
  1022.                         break;
  1023.                 case en_lt:
  1024.                         gen_compare(node);
  1025.                         gen_code(op_bge,0,make_label(label),0);
  1026.                         break;
  1027.                 case en_le:
  1028.                         gen_compare(node);
  1029.                         gen_code(op_bgt,0,make_label(label),0);
  1030.                         break;
  1031.                 case en_gt:
  1032.                         gen_compare(node);
  1033.                         gen_code(op_ble,0,make_label(label),0);
  1034.                         break;
  1035.                 case en_ge:
  1036.                         gen_compare(node);
  1037.                         gen_code(op_blt,0,make_label(label),0);
  1038.                         break;
  1039.                 case en_ult:
  1040.                         gen_compare(node);
  1041.                         gen_code(op_bhs,0,make_label(label),0);
  1042.                         break;
  1043.                 case en_ule:
  1044.                         gen_compare(node);
  1045.                         gen_code(op_bhi,0,make_label(label),0);
  1046.                         break;
  1047.                 case en_ugt:
  1048.                         gen_compare(node);
  1049.                         gen_code(op_bls,0,make_label(label),0);
  1050.                         break;
  1051.                 case en_uge:
  1052.                         gen_compare(node);
  1053.                         gen_code(op_blo,0,make_label(label),0);
  1054.                         break;
  1055.                 case en_land:
  1056.                         falsejp(node->v.p[0],label);
  1057.                         falsejp(node->v.p[1],label);
  1058.                         break;
  1059.                 case en_lor:
  1060.                         lab0 = nextlabel++;
  1061.                         truejp(node->v.p[0],lab0);
  1062.                         falsejp(node->v.p[1],label);
  1063.                         gen_label(lab0);
  1064.                         break;
  1065.                 case en_not:
  1066.                         truejp(node->v.p[0],label);
  1067.                         break;
  1068.                 default:
  1069.                         siz1 = natural_size(node);
  1070.                         ap = gen_expr(node,F_ALL,siz1);
  1071.                         gen_code(op_tst,siz1,ap,0);
  1072.                         freeop(ap);
  1073.                         gen_code(op_beq,0,make_label(label),0);
  1074.                         break;
  1075.                 }
  1076. }
  1077.  
  1078.  
  1079.