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