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