home *** CD-ROM | disk | FTP | other *** search
/ CD Shareware Magazine 1996 December / CD_shareware_12-96.iso / DOS / Programa / CCDL122.ZIP / SOURCE / GCODE386.ASM < prev    next >
Encoding:
Assembly Source File  |  1996-06-23  |  67.3 KB  |  2,102 lines

  1. /*                                  
  2.  *    68000 C compiler
  3.  *
  4.  *    Copyright 1984, 1985, 1986 Matthew Brandt.
  5.  *      Some portions Copyright 1996 David Lindauer
  6.  *      all commercial rights reserved.
  7.  *
  8.  *    This compiler is intended as an instructive tool for personal use. Any
  9.  *    use for profit without the written consent of the authors is prohibited.
  10.  *
  11.  *    This compiler may be distributed freely for non-commercial use as long
  12.  *    as this notice stays intact. Please forward any enhancements or questions
  13.  *    to:
  14.  *
  15.  *        Matthew Brandt
  16.  *        Box 920337
  17.  *        Norcross, Ga 30092
  18.  *    or to:
  19.  *
  20.  *        David Lindauer
  21.  *        gclind01@starbase.spd.louisville.edu
  22.  */
  23. #include        <stdio.h>
  24. #include        "c.h"
  25. #include        "expr.h"
  26. #include        "gen.h"
  27. #include        "cglbdec.h"
  28.  
  29. /*
  30.  *      this module contains all of the code generation routines
  31.  *      for evaluating expressions and conditions.
  32.  */
  33.  
  34. extern int prm_largedata;
  35. extern AMODE     push[], pop[];
  36. extern int prm_68020;
  37. extern long framedepth, stackdepth;
  38. extern int regs[3];
  39.  
  40. long bittab[32] = { 1,0x3,0x7,0xf,0x1f,0x3f,0x7f,0xff,
  41.             0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff,0xffff,
  42.             0x1ffffL,0x3ffffL,0x7ffffL,0xfffffL,0x1fffffL,0x3fffffL,0x7fffffL,0xffffffL,
  43.             0x1ffffffL,0x3ffffffL,0x7ffffffL,0xfffffffL,0x1fffffffL,0x3fffffffL,0x7fffffffL,0xffffffffL
  44. };
  45.  
  46. int chksize(int lsize, int rsize)
  47. {
  48.     int l,r;
  49.     l = lsize;
  50.     r = rsize;
  51.     if (l < 0) l = - l;
  52.     if (r < 0) r = - r;
  53.     return(l > r);
  54. }
  55. AMODE *fstack(void)
  56. {
  57.     AMODE *ap = xalloc(sizeof(AMODE));
  58.     ap->mode = am_freg;
  59.     ap->preg = 1;
  60.     ap->sreg = 0;
  61.     ap->offset = 0;
  62.     ap->tempflag = TRUE;
  63.     return(ap);
  64. }
  65. AMODE        *make_muldivval(AMODE *ap)
  66. {
  67.             int temp;
  68.             AMODE *ap1 = make_label(temp = nextlabel++);
  69.             queue_muldivval(temp,ap->offset->v.i);
  70.             ap1->mode = am_direct;
  71.             return(ap1);
  72. }
  73. void make_floatconst(AMODE *ap, int size)
  74. {
  75.     int temp;
  76.     AMODE *ap1 = make_label(temp = nextlabel++);
  77.     if (ap->offset->nodetype == en_icon)
  78.         ap->offset->v.f = ap->offset->v.i;
  79.     queue_floatval(temp,ap->offset->v.f,size);
  80.     ap->mode = am_direct;
  81.     ap->offset = ap1->offset;
  82. }
  83. AMODE    *make_label(int lab)
  84. /*
  85.  *      construct a reference node for an internal label number.
  86.  */
  87. {       ENODE    *lnode;
  88.         AMODE    *ap;
  89.         lnode = xalloc(sizeof(ENODE));
  90.         lnode->nodetype = en_labcon;
  91.         lnode->v.i = lab;
  92.         ap = xalloc(sizeof(AMODE));
  93.         ap->mode = am_immed;
  94.         ap->offset = lnode;
  95.         return ap;
  96. }
  97.  
  98. AMODE    *make_immed(long i)
  99. /*
  100.  *      make a node to reference an immediate value i.
  101.  */
  102. {       AMODE    *ap;
  103.         ENODE    *ep;
  104.         ep = xalloc(sizeof(ENODE));
  105.         ep->nodetype = en_icon;
  106.         ep->v.i = i;
  107.         ap = xalloc(sizeof(AMODE));
  108.         ap->mode = am_immed;
  109.         ap->offset = ep;
  110.         return ap;
  111. }
  112.  
  113. AMODE    *make_offset(ENODE *node)
  114. /*
  115.  *      make a direct reference to a node.
  116.  */
  117. {       AMODE    *ap;
  118.         ap = xalloc(sizeof(AMODE));
  119.         ap->mode = am_direct;
  120.         ap->offset = node;
  121.         return ap;
  122. }
  123. AMODE *make_stack(int number)
  124. {
  125.     AMODE *ap = xalloc(sizeof(AMODE));        
  126.     ENODE *ep = xalloc(sizeof(ENODE));
  127.     ep->nodetype = en_icon;
  128.     ep->v.i = -number;
  129.     ap->mode = am_indisp;
  130.     ap->preg = ESP;
  131.     ap->offset = ep;
  132.     return(ap);
  133. }
  134. void make_legal(AMODE *ap,int flags,int size)
  135. /*
  136.  *      make_legal will coerce the addressing mode in ap1 into a
  137.  *      mode that is satisfactory for the flag word.
  138.  */
  139. {       AMODE    *ap2;
  140.         if( ((flags & F_VOL) == 0) || ap->tempflag )
  141.                 {
  142.                 switch( ap->mode )
  143.                         {
  144.                                                 case am_freg:
  145.                                                                 if (flags & F_FREG)
  146.                                                                         return;
  147.                                                                 break;
  148.                         case am_immed:
  149.                                                                 if (size > 4) {
  150.                                                                     make_floatconst(ap,size);
  151.                                                   if (flags & F_MEM)
  152.                                                                         return;
  153.                                                                 }
  154.                                                                 else
  155.                                     if( flags & F_IMMED )
  156.                                         return;         /* mode ok */
  157.                                                                 
  158.                                 break;
  159.                         case am_dreg:
  160.                                 if( flags & F_DREG )
  161.                                         return;
  162.                                 break;
  163.                                                 case am_indisp: case am_indispscale: 
  164.                                                                 if (flags & F_INDX)
  165.                                                                     return;
  166.                                                 case am_direct:
  167.                                 if( flags & F_MEM )
  168.                                         return;
  169.                                 break;
  170.                         }
  171.                 }
  172.                 if (size > 4) {
  173.                         if (ap->mode == am_immed) {
  174.                             make_floatconst(ap,size);
  175.                         }
  176.                         gen_codef(op_fld,size,ap,0);
  177.                         freeop(ap);
  178.                         ap->mode = am_freg;
  179.                         ap->preg = 1;
  180.                         ap->tempflag = 1;
  181.                         return;
  182.                 }
  183.         if( size == -1 )
  184.                 {
  185.                 freeop(ap);
  186.                 ap2 = temp_data();
  187.                                 if (ap->mode == am_immed && ap->offset->nodetype == en_icon) {
  188.                                     if (ap->offset->v.i & 0x80)
  189.                                         ap->offset->v.i |= 0xffffff00L;
  190.                                     else
  191.                                         ap->offset->v.i &= 0xffL;
  192.                     gen_code(op_mov,4,ap2,ap);
  193.                                 }
  194.                                 else
  195.                     gen_code2(op_movsx,4,1,ap2,ap);
  196.                 freeop(ap);
  197.                 ap->mode = ap2->mode;
  198.                 ap->preg = ap2->preg;
  199.                 ap->deep = ap2->deep;
  200.                                 ap->tempflag = TRUE;
  201.                 size = -2;
  202.                 }
  203.                 
  204.         else if( size == 1 )
  205.                 {
  206.                 freeop(ap);
  207.                 ap2 = temp_data();
  208.                                 if (ap->mode == am_immed && ap->offset->nodetype == en_icon) {
  209.                                     ap->offset->v.i &= 0xff;
  210.                     gen_code(op_mov,4,ap2,ap);
  211.                                 }
  212.                                 else
  213.                     gen_code2(op_movzx,4,1,ap2,ap);
  214.                 freeop(ap);
  215.                 ap->mode = ap2->mode;
  216.                 ap->preg = ap2->preg;
  217.                 ap->deep = ap2->deep;
  218.                                 ap->tempflag = TRUE;
  219.                 size = 2;
  220.                 }
  221.         else if( size == -2 )
  222.                 {
  223.                 freeop(ap);
  224.                                 if (ap->mode == am_immed && ap->offset->nodetype == en_icon) {
  225.                                     if (ap->offset->v.i & 0x8000)
  226.                                         ap->offset->v.i |= 0xffff0000L;
  227.                                     else
  228.                                         ap->offset->v.i &= 0xffffL;
  229.                     gen_code(op_mov,4,ap2,ap);
  230.                                 }
  231.                                 else
  232.                     ap2 = temp_data();
  233.                 gen_code2(op_movsx,4,2,ap2,ap);
  234.                 freeop(ap);
  235.                 ap->mode = ap2->mode;
  236.                 ap->preg = ap2->preg;
  237.                 ap->deep = ap2->deep;
  238.                                 ap->tempflag = TRUE;
  239.                 size = -4;
  240.                 }
  241.                 
  242.         else if( size == 2 )
  243.                 {
  244.                 freeop(ap);
  245.                 ap2 = temp_data();
  246.                                 if (ap->mode == am_immed && ap->offset->nodetype == en_icon) {
  247.                                         ap->offset->v.i &= 0xffffL;
  248.                     gen_code(op_mov,4,ap2,ap);
  249.                                 }
  250.                                 else
  251.                     gen_code2(op_movzx,4,2,ap2,ap);
  252.                 freeop(ap);
  253.                 ap->mode = ap2->mode;
  254.                 ap->preg = ap2->preg;
  255.                 ap->deep = ap2->deep;
  256.                                 ap->tempflag = TRUE;
  257.                 size = 4;
  258.                 }
  259.                 else if (size == 4 || size == -4) {
  260.             freeop(ap);
  261.             ap2 = temp_data();
  262.             gen_code(op_mov,size,ap2,ap);
  263.             ap->mode = am_dreg;
  264.             ap->preg = ap2->preg;
  265.             ap->deep = ap2->deep;
  266.             ap->tempflag = 1;
  267.                 }
  268. }
  269. void bit_legal(AMODE *ap,ENODE *node, int size)
  270. {
  271.     if (node->bits != -1) {
  272.             make_legal(ap,F_DREG | F_VOL,size);
  273.             if (node->startbit)
  274.                 gen_code(op_shr,size,ap,make_immed(node->startbit));
  275.             gen_code(op_and,4,ap,make_immed(bittab[node->bits-1]));
  276.     }
  277. }
  278. AMODE *get_bitval(AMODE *ap,ENODE *node, int size)
  279. {
  280.     AMODE *ap1 = temp_data();
  281.     ap1->tempflag = TRUE;
  282.         gen_code(op_mov,size,ap1,ap);
  283.         if (node->startbit)
  284.             gen_code(op_shr,size,ap1,make_immed(node->startbit));
  285.         gen_code(op_and,4,ap1,make_immed(bittab[node->bits-1]));
  286.         return ap1;
  287. }
  288. void bit_move(AMODE *ap2, AMODE *ap1, ENODE *node, int flags, int sizein, int sizeout)
  289. {
  290.         gen_code(op_and,sizeout,ap2,make_immed(~(bittab[node->bits-1]<<node->startbit)));
  291.         if (ap1->mode == am_immed) {
  292.             ap1->offset->v.i &= bittab[node->bits-1];
  293.             if (ap1->offset->v.i) {
  294.                 ap1->offset->v.i <<= node->startbit;
  295.                 gen_code(op_or,sizeout,ap2,ap1);
  296.                 if (!(flags & F_NOVALUE)) {
  297.                     make_legal(ap2,flags,sizeout);
  298.                     ap1->offset->v.i >>= node->startbit;
  299.                     gen_code(op_mov,sizeout,ap2,ap1);
  300.                 }
  301.             }
  302.         }
  303.         else {
  304.             make_legal(ap1,F_DREG | F_VOL,sizein);
  305.             gen_code(op_and,sizein,ap1,make_immed(bittab[node->bits-1]));
  306.             if (node->startbit)
  307.                 gen_code(op_shl,sizein,ap1,make_immed(node->startbit));
  308.             gen_code(op_or,sizeout,ap2,ap1);
  309.             if (!(flags & F_NOVALUE)) {
  310.                 if (node->startbit)
  311.                     gen_code(op_shr,sizein,ap1,make_immed(node->startbit));
  312.             }
  313.         }
  314. }
  315. void do_extend(AMODE *ap,int isize,int osize,int flags)
  316. /*
  317.  *      if isize is not equal to osize then the operand ap will be
  318.  *      loaded into a register (if not already) and if osize is
  319.  *      greater than isize it will be extended to match.
  320.  */
  321. {                AMODE *ap2;
  322.            if( isize == osize || isize == -osize)
  323.                 return;
  324.         if( ap->mode != am_dreg && isize <= 4) {
  325.                 make_legal(ap,flags & (F_AREG | F_DREG),isize);
  326.                                 if (chksize(osize,isize) && osize <=4)
  327.                                     return;
  328.                 }
  329.                 switch(isize)
  330.                                 {
  331.                                 case -1:
  332.                                 case 1:
  333.                 case -2:
  334.                                 case 2:
  335.                                 case 4:
  336.                                 case -4:
  337. doextend:
  338.                                                 if (osize ==2 || osize == -2)
  339.                                                     gen_code(op_and,4,ap,make_immed(0xffff));
  340.                                                 else if (osize == 1 || osize == -1)
  341.                                                     gen_code(op_and,4,ap,make_immed(0xff));
  342.                                                 else if (osize == 4 || osize == -4)
  343.                                                     return;
  344.                                                 else {
  345.                                                     ap2 = make_stack(0);
  346.                                                     gen_code(op_mov,4,ap2,ap);
  347.                                                     freeop(ap);
  348.                                                     gen_codef(op_fild,osize,ap2,0);
  349.                                                     ap->mode = am_freg;
  350.                                                     ap->preg = 1;
  351.                                                     ap->tempflag = TRUE;
  352.                                                 }
  353.                                                 break;
  354.                                 case 6:
  355.                                                 if (osize > isize) {
  356.                                                     if (ap->mode != am_freg) {
  357.                                                         gen_codef(op_fld,osize,ap,0);    
  358.                                                         freeop(ap);
  359.                                                         ap->mode = am_freg;
  360.                                                         ap->preg = 1;
  361.                                                         ap->tempflag = TRUE;
  362.                                                     }
  363.                                                     return;
  364.                                                 }
  365.                                                 
  366.                                 case 8: 
  367.                                                 if (ap->mode != am_freg) {
  368.                                                     freeop(ap);
  369.                                                     gen_codef(op_fld,8,ap,0);
  370.                                                     ap->mode = am_freg;
  371.                                                     ap->preg = 1;
  372.                                                     ap->tempflag = TRUE;
  373.                                                 }
  374.                                                 switch(osize) {
  375.                                                     case 1:
  376.                                                     case -1:
  377.                                                     case 2:
  378.                                                     case -2:
  379.                                                     case 4:
  380.                                                     case -4:
  381.                                                         freeop(ap);
  382.                                                         ap2 = temp_data();
  383.                                                         ap->mode = ap2->mode;
  384.                                                         ap->preg = ap2->preg;
  385.                                                         ap->deep = ap2->deep;
  386.                                                         gen_codef(op_fistp,4,ap2 = make_stack(0),0);
  387.                                                         gen_codef(op_fwait,0,0,0);
  388.                                                         gen_code(op_mov,osize,ap,ap2);
  389.                                                         goto doextend;
  390.                                                     case 6:
  391.                                                         if (ap->mode != am_freg) {
  392.                                                             gen_codef(op_fld,6,ap,0);
  393.                                                             freeop(ap);
  394.                                                             ap->mode = am_freg;
  395.                                                             ap->preg = 1;
  396.                                                             ap->tempflag = TRUE;
  397.                                                         }
  398.                                                         break;
  399.                                                 }
  400.                 }
  401. }
  402.  
  403. int     isshort(ENODE *node)
  404. /*
  405.  *      return true if the node passed can be generated as a short
  406.  *      offset.
  407.  */
  408. {       return node->nodetype == en_icon &&
  409.                 (node->v.i >= -32768L && node->v.i <= 32767L);
  410. }
  411.  
  412. int     isbyte(ENODE *node)
  413. /*
  414.  *      return true if the node passed can be evaluated as a byte
  415.  *      offset.
  416.  */
  417. {       return node->nodetype == en_icon &&
  418.                 (-128 <= node->v.i && node->v.i <= 127);
  419. }
  420.  
  421. AMODE    *gen_index(ENODE *node)
  422. /*
  423.  *      generate code to evaluate an index node (^+) and return
  424.  *      the addressing mode of the result. This routine takes no
  425.  *      flags since it always returns either am_ind or am_indx.
  426.  */
  427. {       AMODE    *ap1,*ap2;
  428.                 if (node->v.p[0]->nodetype == en_icon || node->v.p[0]->nodetype == en_add) {
  429.                     ENODE *t = node->v.p[1];
  430.                     node->v.p[1] = node->v.p[0];
  431.                     node->v.p[0] = t;
  432.                 }
  433.                 if (node->v.p[1]->nodetype == en_icon) {
  434.             if( node->v.p[0]->nodetype == en_nacon || node->v.p[0]->nodetype == en_nalabcon
  435.                        || node->v.p[0]->nodetype == en_labcon || node->v.p[0]->nodetype == en_napccon ) {
  436.                         ap1 = xalloc(sizeof(AMODE)) ;
  437.                         ap1->mode = am_direct;
  438.                         ap1->offset = makenode(en_add,node->v.p[0],node->v.p[1]);
  439.                         return ap1;
  440.                     }
  441.             if( node->v.p[0]->nodetype == en_autocon || node->v.p[0]->nodetype == en_autoreg)
  442.                 {
  443.                 ap1 = xalloc(sizeof(AMODE));
  444.                 ap1->mode = am_indisp;
  445.                                 ap1->preg = ESP;
  446.                                 if (node->v.p[0]->v.i >= 0)
  447.                     ap1->offset = makenode(en_add,makenode(en_acon,(char *)(node->v.p[0]->v.i+framedepth+stackdepth),0),node->v.p[1]);
  448.                 else
  449.                                     ap1->offset = makenode(en_add,makenode(en_acon,(char *)(node->v.p[0]->v.i+stackdepth),0),node->v.p[1]);
  450.                 return ap1;
  451.                 }
  452.                     ap1 = gen_expr(node->v.p[1],F_IMMED,4);
  453.                     ap2 = gen_deref(node,F_DREG | F_INDX,4);
  454.                     validate(ap1);
  455.                     if (ap2->mode == am_dreg) {
  456.                         ap1->mode = am_indisp;
  457.                         ap1->preg = ap2->preg;
  458.                         ap1->preg = ap2->sreg;
  459.                         ap1->deep = ap2->deep;
  460.                         return(ap1);
  461.                     }
  462.                     else {
  463.                         ap2->offset = makenode(en_add,ap2->offset,ap1->offset);
  464.                         return ap2;
  465.                     }
  466.                 }
  467.                 else {
  468.                     ap1 = gen_expr(node->v.p[0],F_ALL,4);
  469.                     ap2 = gen_expr(node->v.p[1],F_ALL,4);
  470.                     validate(ap1);
  471.                     if ((ap1->mode == am_dreg) && (ap2->mode == am_dreg)) {
  472.                         if (ap1->preg != 4) {
  473.                           ap1->sreg = ap2->preg;
  474.                           ap1->mode = am_indispscale;   /* 0(Ax,Dx) */
  475.                                                 ap1->scale = 1;
  476.                         ap1->offset = 0;
  477.                         return ap1;
  478.                         }
  479.                         else {
  480.                         ap2->sreg = ap1->preg;
  481.                         ap2->mode = am_indispscale;   /* 0(Ax,Dx) */
  482.                                                 ap2->scale = 1;
  483.                         ap2->offset = 0;
  484.                         return ap1;
  485.                         }
  486.                     }
  487.                     make_legal(ap1,F_DREG,4);
  488.                     make_legal(ap2,F_DREG,4);
  489.                     ap2->sreg = ap1->preg;
  490.                     ap2->mode = am_indispscale;
  491.                     ap2->scale = 1;
  492.                     ap2->offset = makenode(en_icon,0,0);
  493.                     return ap2;
  494.                 }
  495. }
  496.  
  497. AMODE    *gen_deref(ENODE *node, int flags,int size)
  498. /*
  499.  *      return the addressing mode of a dereferenced node.
  500.  */
  501. {       AMODE    *ap1;
  502.         int             ssize,psize;
  503.                 psize = size;
  504.                 if (psize < 0)
  505.                     psize = - psize;
  506.         switch( node->nodetype )        /* get load size */
  507.                 {
  508.                 case en_ub_ref:
  509.                         ssize = 1;
  510.                         break;
  511.                 case en_b_ref:
  512.                         ssize = -1;
  513.                         break;
  514.                 case en_uw_ref:
  515.                         ssize = 2;
  516.                         break;
  517.                 case en_w_ref:
  518.                         ssize = -2;
  519.                         break;
  520.                 case en_l_ref:
  521.                                                 ssize = -4;
  522.                                                 break;
  523.                                 case en_ul_ref:
  524.                         ssize = 4;
  525.                         break;
  526.                                 case en_floatref:
  527.                                                 ssize = 6;
  528.                                                 break;
  529.                                 case en_doubleref:
  530.                                                 ssize = 8;
  531.                                                 break;
  532.                                 case en_longdoubleref:
  533.                                                 ssize = 10;
  534.                                                 break;
  535.                 }
  536.         if( node->v.p[0]->nodetype == en_add )
  537.                 {
  538.                 ap1 = gen_index(node->v.p[0]);
  539.                 do_extend(ap1,ssize,size,flags);
  540.                 make_legal(ap1,flags,psize);
  541.                 return ap1;
  542.                 }
  543.         else if( node->v.p[0]->nodetype == en_autocon  || node->v.p[0]->nodetype == en_autoreg)
  544.                 {
  545.                 ap1 = xalloc(sizeof(AMODE));
  546.                 ap1->mode = am_indisp;
  547.                                 ap1->preg = ESP;
  548.                                 if (node->v.p[0]->v.i >= 0)
  549.                     ap1->offset = makenode(en_acon,(char *)(node->v.p[0]->v.i+framedepth+stackdepth),0);
  550.                 else
  551.                                     ap1->offset = makenode(en_acon,(char *)(node->v.p[0]->v.i+stackdepth),0);
  552.                 do_extend(ap1,ssize,size,flags);
  553.                 make_legal(ap1,flags,psize);
  554.                 return ap1;
  555.                 }
  556.         else if( node->v.p[0]->nodetype == en_nacon || node->v.p[0]->nodetype == en_nalabcon)
  557.                 {
  558.                 ap1 = xalloc(sizeof(AMODE));
  559.                 ap1->offset = makenode(node->v.p[0]->nodetype,(char *)node->v.p[0]->v.i,0);
  560.                 ap1->mode = am_direct;
  561.                 do_extend(ap1,ssize,size,flags);
  562.                 make_legal(ap1,flags,psize);
  563.                 return ap1;
  564.                 }
  565.         else if( node->v.p[0]->nodetype == en_labcon || node->v.p[0]->nodetype == en_napccon)
  566.                 {
  567.                 ap1 = xalloc(sizeof(AMODE));
  568.                 ap1->mode = am_direct;
  569.                 ap1->offset = makenode(node->v.p[0]->nodetype,(char *)node->v.p[0]->v.i,0);
  570.                 do_extend(ap1,ssize,size,flags);
  571.                 make_legal(ap1,flags,psize);
  572.                 return ap1;
  573.                 }
  574.                 else if (node->v.p[0]->nodetype == en_regref) {
  575.             ap1 = gen_expr(node->v.p[0],F_ALL,4);
  576.           do_extend(ap1,ssize,size,flags);
  577.           make_legal(ap1,flags,psize);
  578.                     return ap1;
  579.                 }
  580.         ap1 = gen_expr(node->v.p[0],F_DREG | F_IMMED,4); /* generate address */
  581.         if( ap1->mode == am_dreg )
  582.                 {
  583.                 ap1->mode = am_indisp;
  584.                                 ap1->offset = makenode(en_icon,0,0);
  585.                 do_extend(ap1,ssize,size,flags);
  586.                 make_legal(ap1,flags,psize);
  587.                 return ap1;
  588.                 }
  589.         ap1->mode = am_direct;
  590.         do_extend(ap1,ssize,size,flags);
  591.         make_legal(ap1,flags,psize);
  592.         return ap1;
  593. }
  594.  
  595. AMODE    *gen_unary(ENODE *node,int flags,int size,int op, int fop)
  596. /*
  597.  *      generate code to evaluate a unary minus or complement.
  598.  */
  599. {       AMODE    *ap;
  600.         ap = gen_expr(node->v.p[0],F_FREG | F_DREG | F_VOL,size);
  601.                 if (ap->mode == am_freg) {
  602.                     gen_code(fop,0,0,0);
  603.                     ap = fstack();
  604.                 }
  605.                 else {
  606.             gen_code(op,size,ap,0);
  607.                 }
  608.         make_legal(ap,flags,size);
  609.         return ap;
  610. }
  611.  
  612. AMODE    *gen_binary(ENODE *node,int flags,int size,int op, int fop)
  613. /*
  614.  *      generate code to evaluate a binary node and return 
  615.  *      the addressing mode of the result.
  616.  */
  617. {       AMODE    *ap1, *ap2;
  618.         ap1 = gen_expr(node->v.p[0],F_VOL | F_DREG | F_FREG,size);
  619.         ap2 = gen_expr(node->v.p[1],F_ALL,size);
  620.         validate(ap1);          /* in case push occurred */
  621.                 if (size > 4) {
  622.                     if (ap2->mode == am_freg)
  623.                         gen_code(fop,0,0,0);
  624.                     else
  625.                         gen_code(fop,size,ap2,0);
  626.                     ap1 = fstack();
  627.                 }
  628.                 else
  629.             gen_code(op,size,ap1,ap2);
  630.         freeop(ap2);
  631.         make_legal(ap1,flags,size);
  632.         return ap1;
  633. }
  634.  
  635. AMODE    *gen_xbin(ENODE *node,int flags,int size,int op, int fop)
  636. /*
  637.  *      generate code to evaluate a restricted binary node and return 
  638.  *      the addressing mode of the result.
  639.  */
  640. {       AMODE    *ap1, *ap2;
  641.         ap1 = gen_expr(node->v.p[0],F_VOL | F_DREG | F_FREG,size);
  642.         ap2 = gen_expr(node->v.p[1],F_DREG| F_FREG, size);
  643.         validate(ap1);          /* in case push occurred */
  644.                 if (size > 4) {
  645.                     if (ap2->mode == am_freg)
  646.                         gen_code(fop,0,0,0);
  647.                     else
  648.                         gen_code(fop,size,ap2,0);
  649.                     ap1 = fstack();
  650.                 }
  651.                 else
  652.             gen_code(op,size,ap2,ap1);
  653.         freeop(ap2);
  654.         make_legal(ap1,flags,size);
  655.         return ap1;
  656. }
  657. void doshift(AMODE *ap1, AMODE *ap2, int size, int op)
  658. {       AMODE   *ecx = makedreg(ECX), *eax = makedreg(EAX);
  659.                 if (ap2->mode == am_immed) {
  660.                     gen_code2(op,size,1,ap1,ap2);
  661.                 }
  662.                 else
  663.                     if (ap1->mode == am_dreg && ap1->preg == ECX) {
  664.                             if (ap2->mode == am_dreg) {
  665.                                 gen_code(op_xchg,4,ap2,ap1);
  666.                                 gen_code2(op,size,1,ap2,ecx);
  667.                                 gen_code(op_xchg,4,ap2,ap1);
  668.                             }
  669.                             else {
  670.                                 if (regs[0])
  671.                                     gen_push(EAX,am_dreg,0);
  672.                                 gen_code(op_xchg,4,eax,ecx);
  673.                                 gen_code(op_mov,1,ap2,ecx);
  674.                                 gen_code2(op,size,1,eax,ecx);
  675.                                 gen_code(op_xchg,4,eax,ecx);
  676.                                 if (regs[0])
  677.                                     gen_pop(EAX,am_dreg,0);
  678.                             }
  679.                     }
  680.                     else
  681.                         if (ap2->mode == am_dreg) {
  682.                             if (ap2->preg != ECX)
  683.                                 gen_code(op_xchg,4,ap2,ecx);
  684.                             gen_code2(op,size,1,ap1,ecx);
  685.                             if (ap2->preg != ECX)
  686.                                 gen_code(op_xchg,4,ap2,ecx);
  687.                         }
  688.                         else {
  689.                             if (regs[1])
  690.                                 gen_push(ECX,am_dreg,0);
  691.                             gen_code(op_mov,1,ap2,ecx);
  692.                             gen_code2(op,size,1,ap1,ecx);
  693.                             if (regs[1])
  694.                                 gen_pop(ECX,am_dreg,0);
  695.                         }
  696. }
  697. AMODE    *gen_shift(ENODE *node, int flags, int size, int op)
  698. /*
  699.  *      generate code to evaluate a shift node and return the
  700.  *      address mode of the result.
  701.  */
  702. {       AMODE    *ap1, *ap2;
  703.         ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,size);
  704.         ap2 = gen_expr(node->v.p[1],F_DREG | F_IMMED,1);
  705.         validate(ap1);
  706.                 doshift(ap1,ap2,size,op);
  707.         freeop(ap2);
  708.         make_legal(ap1,flags,size);
  709.         return ap1;
  710. }
  711. void dodiv(AMODE *ap1, AMODE *ap2, int size, int op,int modflag)
  712. {
  713.     AMODE *eax = makedreg(EAX), *edx = makedreg(EDX), *ecx = makedreg(ECX);
  714.     if (ap2->mode == am_immed) {
  715.         ap2 = make_muldivval(ap2);
  716.     }
  717.     if (ap1->preg != EAX) {
  718.         int temp;
  719.         gen_code(op_xchg,4,eax,ap1);
  720.         if (ap1->mode == am_dreg && ap2->mode == am_dreg && ap1->preg == ap2->preg) {
  721.             gen_code(op,4,eax,0);
  722.             gen_code(op_xchg,4,eax,ap1);
  723.             return;
  724.         }
  725.         temp = regs[0];
  726.         regs[0] = regs[ap1->preg];
  727.         regs[ap1->preg] = temp;
  728.     }
  729.     if (ap2->preg == EDX) {
  730.         if (regs[1])
  731.             gen_push(ECX,am_dreg,0);
  732.         if (regs[2])
  733.             gen_push(EDX,am_dreg,0);
  734.         gen_code(op_mov,4,ecx,edx);
  735.         gen_code(op_sub,4,edx,edx);
  736.         gen_code(op,4,ecx,0);
  737.         if (modflag)
  738.             gen_code(op_xchg,4,eax,edx);
  739.         if (regs[2])
  740.             gen_pop(EDX,am_dreg,0);
  741.         if (regs[1])
  742.             gen_pop(ECX,am_dreg,0);
  743.     }
  744.     else {
  745.         if (regs[2])
  746.             gen_push(EDX,am_dreg,0);
  747.         gen_code(op_sub,4,edx,edx);
  748.         gen_code(op,4,ap2,0);
  749.         if (modflag)
  750.             gen_code(op_xchg,4,eax,edx);
  751.         if (regs[2])
  752.             gen_pop(EDX,am_dreg,0);
  753.     }
  754.     if (ap1->preg != EAX) {
  755.         int temp;
  756.         gen_code(op_xchg,4,eax,ap1);
  757.         temp = regs[0];
  758.         regs[0] = regs[ap1->preg];
  759.         regs[ap1->preg] = temp;
  760.     }
  761. }
  762. void domul(AMODE *ap1, AMODE *ap2, int size, int op)
  763. {
  764.     AMODE *eax = makedreg(EAX), *edx = makedreg(EDX), *ecx = makedreg(ECX);
  765.     if (ap2->mode == am_immed) {
  766.         ap2 = make_muldivval(ap2);
  767.     }
  768.     if (ap1->preg != EAX) {
  769.         int temp;
  770.         gen_code(op_xchg,4,eax,ap1);
  771.         if (ap1->mode == am_dreg && ap2->mode == am_dreg && ap1->preg == ap2->preg && ap1->preg != EDX) {
  772.             gen_code(op,4,eax,0);
  773.             gen_code(op_xchg,4,eax,ap1);
  774.             return;
  775.         }
  776.         temp = regs[0];
  777.         regs[0] = regs[ap1->preg];
  778.         regs[ap1->preg] = temp;
  779.     }
  780.     if (ap2->preg == EDX) {
  781.         if (regs[1])
  782.             gen_push(ECX,am_dreg,0);
  783.         if (regs[2])
  784.             gen_push(EDX,am_dreg,0);
  785.         gen_code(op_mov,4,ecx,edx);
  786.         gen_code(op_sub,4,edx,edx);
  787.         gen_code(op,4,ecx,0);
  788.         if (regs[2])
  789.             gen_pop(EDX,am_dreg,0);
  790.         if (regs[1])
  791.             gen_pop(ECX,am_dreg,0);
  792.     }
  793.     else {
  794.         if (regs[2])
  795.             gen_push(EDX,am_dreg,0);
  796.         gen_code(op,4,ap2,0);
  797.         if (regs[2])
  798.             gen_pop(EDX,am_dreg,0);
  799.     }
  800.     if (ap1->preg != EAX) {
  801.         int temp;
  802.         gen_code(op_xchg,4,eax,ap1);
  803.         temp = regs[0];
  804.         regs[0] = regs[ap1->preg];
  805.         regs[ap1->preg] = temp;
  806.     }
  807. }
  808. AMODE    *gen_modiv(ENODE *node, int flags, int size, int op, int modflag)
  809. /*
  810.  *      generate code to evaluate a mod operator or a divide
  811.  *      operator. these operations are done on only long
  812.  *      divisors and word dividends so that the 68000 div
  813.  *      instruction can be used.
  814.  */
  815. {       AMODE    *ap1, *ap2;
  816.                 
  817.                 if (size > 4) {
  818.                     ap1 = gen_expr(node->v.p[0],F_FREG | F_VOL,size);
  819.                     ap2 = gen_expr(node->v.p[1],F_ALL,size);
  820.                     if (ap2->mode == am_freg)
  821.                         gen_codef(op_fdiv,0,0,0);
  822.                     else
  823.                         gen_codef(op_fdiv,size,ap2,0);
  824.                     ap1 = fstack();
  825.                     make_legal(ap1,flags,size);
  826.                     return ap1;
  827.                 }
  828.                     if (op == op_idiv) {
  829.                 ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,-4);
  830.                     }
  831.                     else {
  832.                 ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,4);
  833.                     }
  834.                     if (op == op_idiv) {
  835.                 ap2 = gen_expr(node->v.p[1],F_ALL,-4);
  836.                     }
  837.                     else {
  838.                 ap2 = gen_expr(node->v.p[1],F_ALL,4);
  839.                     }
  840.                     validate(ap1);
  841.                     dodiv(ap1,ap2,size,op,modflag);
  842.                     freeop(ap2);
  843.                     do_extend(ap1,4,size,flags);
  844.             make_legal(ap1,flags,size);
  845.             return ap1;
  846.                     
  847. }
  848.  
  849.  
  850. void swap_nodes(ENODE *node)
  851. /*
  852.  *      exchange the two operands in a node.
  853.  */
  854. {       ENODE    *temp;
  855.         temp = node->v.p[0];
  856.         node->v.p[0] = node->v.p[1];
  857.         node->v.p[1] = temp;
  858. }
  859.  
  860. AMODE * gen_pdiv(ENODE *node, int flags, int size)
  861. {
  862.                 return gen_modiv(node,flags,size,op_div,FALSE);
  863. }            
  864. AMODE * gen_pmul(ENODE *node, int flags, int size)
  865. {
  866.                 return gen_mul(node,flags,size,op_mul);
  867. }            
  868. AMODE    *gen_mul(ENODE *node, int flags, int size, int op)
  869. /*
  870.  *      generate code to evaluate a multiply node. both operands
  871.  *      are treated as words and the result is long and is always
  872.  *      in a register so that the 68000 mul instruction can be used.
  873.  */
  874. {       AMODE    *ap1, *ap2;
  875.  
  876.                 if (node->v.p[0]->nodetype == en_icon)
  877.                     swap_nodes(node);                
  878.                 if (size > 4) {
  879.                     ap1 = gen_expr(node->v.p[0],F_FREG | F_VOL,size);
  880.                     ap2 = gen_expr(node->v.p[1],F_ALL,size);
  881.                     if (ap2->mode == am_freg)
  882.                         gen_codef(op_fmul,0,0,0);
  883.                     else 
  884.                         gen_codef(op_fmul,size,ap2,0);
  885.                     ap1 = fstack();
  886.                     make_legal(ap1,flags,size);
  887.                     return ap1;
  888.                 }
  889.                     if (op == op_imul) {
  890.                 ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,-4);
  891.                     }
  892.                     else {
  893.                 ap1 = gen_expr(node->v.p[0],F_DREG | F_VOL,4);
  894.                     }
  895.                     if (op == op_imul) {
  896.                 ap2 = gen_expr(node->v.p[1],F_ALL,-4);
  897.                     }
  898.                     else {
  899.                 ap2 = gen_expr(node->v.p[1],F_ALL,4);
  900.                     }
  901.                     validate(ap1);
  902.                     domul(ap1,ap2,size,op);
  903.                     freeop(ap2);
  904.                     do_extend(ap1,4,size,flags);
  905.             make_legal(ap1,flags,size);
  906.             return ap1;
  907. }
  908. AMODE    *gen_hook(ENODE *node, int flags, int size)
  909. /*
  910.  *      generate code to evaluate a condition operator node (?:)
  911.  */
  912. {       AMODE    *ap1, *ap2;
  913.         int             false_label, end_label;
  914.         false_label = nextlabel++;
  915.         end_label = nextlabel++;
  916.         flags = (flags & (F_AREG | F_DREG)) | F_VOL;
  917.         falsejp(node->v.p[0],false_label);
  918.         node = node->v.p[1];
  919.         ap1 = gen_expr(node->v.p[0],flags,size);
  920.         freeop(ap1);
  921.         gen_code(op_jmp,0,make_label(end_label),0);
  922.         gen_label(false_label);
  923.         ap2 = gen_expr(node->v.p[1],flags,size);
  924.         if( !equal_address(ap1,ap2) )
  925.                 {
  926.                 freeop(ap2);
  927.                 temp_data();
  928.                 gen_code(op_mov,size,ap2,ap1);
  929.                 }
  930.         gen_label(end_label);
  931.         return ap1;
  932. }
  933.  
  934. AMODE    *gen_asadd(ENODE *node, int flags, int size, int op, int fop)
  935. /*
  936.  *      generate a plus equal or a minus equal node.
  937.  */
  938. {       AMODE    *ap1, *ap2, *ap3;
  939.         int             ssize,rsize;
  940.         ssize = natural_size(node->v.p[0]);
  941.         rsize = natural_size(node->v.p[1]);
  942.                 if (ssize > 4) {
  943.                     ap2 = gen_expr(node->v.p[0],F_ALL,ssize);
  944.                     ap1 = gen_expr(node->v.p[1],F_ALL,rsize);
  945.                     ap3 = xalloc(sizeof(AMODE));
  946.                     ap3->mode = ap2->mode;
  947.                     ap3->preg = ap2->preg;
  948.                     ap3->offset = ap2->offset;
  949.                     ap3->sreg = ap2->sreg;
  950.                     if (ap2->mode == am_freg) {
  951.                         gen_code(fop,0,0,0);
  952.                         ap3 = ap2;
  953.                     }
  954.                     else  {
  955.                         ap3 = xalloc(sizeof(AMODE));
  956.                         ap3->mode = ap2->mode;
  957.                         ap3->preg = ap2->preg;
  958.                         ap3->offset = ap2->offset;
  959.                         ap3->sreg = ap2->sreg;
  960.                         make_legal(ap2,F_FREG | F_VOL, ssize);
  961.                         gen_code(fop,ssize,ap1,0);
  962.                     }
  963.                     if (!equal_address(ap2, ap3)) {
  964.                         if (flags & F_NOVALUE)
  965.                           gen_codef(op_fstp,ssize,ap3,0);
  966.                         else
  967.                           gen_codef(op_fst,ssize,ap3,0);
  968.                     }
  969.                     gen_codef(op_fwait,0,0,0);
  970.                     if (!(flags & F_NOVALUE)) {
  971.                         ap2 = fstack();
  972.                         do_extend(ap2,ssize,size,flags);
  973.                         make_legal(ap2,flags,size);
  974.                     }
  975.                     return ap2;
  976.                 }
  977.         if (chksize( ssize ,rsize ))
  978.                 rsize = ssize;
  979.             ap2 = gen_expr(node->v.p[0],F_ALL | F_NOBIT,ssize);
  980.         ap1 = gen_expr(node->v.p[1],F_DREG | F_IMMED,rsize);
  981.                 if (node->v.p[0]->nodetype == en_bits)
  982.                     ap3= get_bitval(ap2,node->v.p[0],ssize);
  983.                 validate(ap2);
  984.                 if (node->v.p[0]->nodetype == en_bits) {
  985.                     gen_code(op,ssize,ap3,ap1);
  986.                     bit_move(ap2,ap3,node->v.p[0],flags, ssize,rsize);
  987.                     freeop(ap3);
  988.                 }
  989.                 else
  990.                gen_code(op,ssize,ap2,ap1);
  991.                 freeop(ap1);
  992.                 if (flags & F_NOVALUE)
  993.                     freeop(ap2);
  994.                 else {
  995.                     do_extend(ap2,ssize,size,flags);
  996.                make_legal(ap2,flags,4);
  997.                 }
  998.         return ap2;
  999. }
  1000.  
  1001. AMODE    *gen_aslogic(ENODE *node, int flags, int size, int op)
  1002. /*
  1003.  *      generate a and equal or a or equal node.
  1004.  */
  1005. {       AMODE    *ap1, *ap2;
  1006.         int             ssize,rsize;
  1007.         ssize = natural_size(node->v.p[0]);
  1008.         rsize = natural_size(node->v.p[1]);
  1009.         if (chksize( ssize , rsize ))
  1010.                 rsize = ssize;
  1011.             
  1012.             ap2 = gen_expr(node->v.p[0],F_ALL | F_NOBIT,ssize);
  1013.         ap1 = gen_expr(node->v.p[1],F_DREG | F_IMMED,rsize);
  1014.                     validate(ap2);
  1015.                 if (node->v.p[0]->nodetype == en_bits) {
  1016.                     if (ap1->mode == am_immed) {
  1017.                         ap1->offset->v.i &= bittab[node->v.p[0]->bits-1];
  1018.                         ap1->offset->v.i <<= node->v.p[0]->startbit;
  1019.                         gen_code(op,ssize,ap2,ap1);
  1020.                     }
  1021.                     else {
  1022.                       gen_code(op_and,ssize,ap1,make_immed(bittab[node->v.p[0]->bits-1]));
  1023.                         if (node->v.p[0]->startbit)
  1024.                           gen_code(op_shl,ssize,ap1,make_immed(node->v.p[0]->startbit));
  1025.                         gen_code(op,ssize,ap2,ap1);
  1026.                         if (!(flags & F_NOVALUE)) {
  1027.                             if (node->v.p[0]->startbit)
  1028.                               gen_code(op_shr,ssize,ap1,make_immed(node->v.p[0]->startbit));
  1029.                     do_extend(ap1,ssize,size,0);
  1030.                             make_legal(ap1,F_DREG,size);
  1031.                             return(ap2);
  1032.                         }
  1033.                     }
  1034.                 }
  1035.                 else
  1036.             gen_code(op,ssize,ap2,ap1);
  1037.                     freeop(ap1);
  1038.                 if (flags & F_NOVALUE)
  1039.                     freeop(ap2);
  1040.                 else {
  1041.                     do_extend(ap2,ssize,size,flags);
  1042.             make_legal(ap2,flags,4);
  1043.                 }
  1044.         return ap2;
  1045. }
  1046.  
  1047. AMODE *gen_asshift(ENODE *node, int flags, int size, int op)
  1048. /*
  1049.  *      generate shift equals operators.
  1050.  */
  1051. {       
  1052.         AMODE    *ap1, *ap2, *ap3;
  1053.         int ssize = natural_size(node->v.p[0]);
  1054.         int rsize = natural_size(node->v.p[1]);
  1055.         if (chksize( ssize , rsize ))
  1056.                 rsize = rsize;
  1057.             ap2 = gen_expr(node->v.p[0],F_ALL | F_NOBIT,ssize);
  1058.         ap1 = gen_expr(node->v.p[1],F_DREG | F_IMMED,1);
  1059.                     validate(ap2);
  1060.                 if (node->v.p[0]->nodetype == en_bits)
  1061.                     ap3 = get_bitval(ap2,node->v.p[0],ssize);
  1062.                 else
  1063.                     ap3 = ap2;
  1064.  
  1065.                 doshift(ap3,ap1,ssize,op);
  1066.                 if (node->v.p[0]->nodetype == en_bits)
  1067.                     bit_move(ap2,ap3,node->v.p[0],flags,ssize,rsize);
  1068.                 freeop(ap1);
  1069.                 if (ap3 != ap1)
  1070.                     freeop(ap3);
  1071.                 if (flags & F_NOVALUE)
  1072.                     freeop(ap2);
  1073.                 else {
  1074.                     do_extend(ap2,ssize,size,flags);
  1075.                make_legal(ap2,flags,4);
  1076.                 }
  1077.             return ap2;
  1078. }
  1079.  
  1080. AMODE    *gen_asmul(ENODE *node, int flags, int size,int op)
  1081. /*
  1082.  *      generate a *= node.
  1083.  */
  1084. {       AMODE    *ap1, *ap2,*ap3;
  1085.         int             ssize, lsize,rsize;
  1086.         ssize = natural_size(node->v.p[0]);
  1087.         rsize = natural_size(node->v.p[1]);
  1088.                 if (ssize > 4) {
  1089.                     ap2 = gen_expr(node->v.p[0],F_ALL,ssize);
  1090.                     ap1 = gen_expr(node->v.p[1],F_ALL,rsize);
  1091.                     ap3 = xalloc(sizeof(AMODE));
  1092.                     ap3->mode = ap2->mode;
  1093.                     ap3->preg = ap2->preg;
  1094.                     ap3->offset = ap2->offset;
  1095.                     ap3->sreg = ap2->sreg;
  1096.                     if (ap2->mode == am_freg) {
  1097.                         gen_codef(op_fmul,0,0,0);
  1098.                         ap3 = ap2 = fstack();
  1099.                     }
  1100.                     else  {
  1101.                         ap3 = xalloc(sizeof(AMODE));
  1102.                         ap3->mode = ap2->mode;
  1103.                         ap3->preg = ap2->preg;
  1104.                         ap3->offset = ap2->offset;
  1105.                         ap3->sreg = ap2->sreg;
  1106.                         make_legal(ap2,F_FREG | F_VOL, ssize);
  1107.                         gen_codef(op_fmul,ssize,ap1,0);
  1108.                         ap2 = fstack();
  1109.                     }
  1110.                     if (!equal_address(ap2, ap3)) {
  1111.                         if (flags & F_NOVALUE)
  1112.                           gen_codef(op_fstp,ssize,ap3,0);
  1113.                         else
  1114.                           gen_codef(op_fst,ssize,ap3,0);
  1115.                     }
  1116.                     gen_codef(op_fwait,0,0,0);
  1117.                     if (!(flags & F_NOVALUE)) {
  1118.                         ap2 = fstack();
  1119.                         do_extend(ap2,ssize,size,flags);
  1120.                         make_legal(ap2,flags,size);
  1121.                     }
  1122.                     return ap2;
  1123.                 }
  1124.                 if (op == op_imul)
  1125.                     lsize= -4;
  1126.                 else
  1127.                     lsize = 4;
  1128.           ap2 = gen_expr(node->v.p[0],F_ALL | F_NOBIT,ssize);
  1129.           ap1 = gen_expr(node->v.p[1],F_ALL,lsize);
  1130.                 validate(ap2);
  1131.                 ap3 = xalloc(sizeof(AMODE));
  1132.                 ap3->mode = ap2->mode;
  1133.                 ap3->preg = ap2->preg;
  1134.                 ap3->sreg = ap2->sreg;
  1135.                 ap3->scale = ap2->scale;
  1136.                 ap3->offset = ap2->offset;
  1137.                 if (node->v.p[0]->nodetype == en_bits)
  1138.                     ap2 = get_bitval(ap2,node->v.p[0],ssize);
  1139.                 else {
  1140.             make_legal(ap2,F_DREG | F_VOL,4);
  1141.                     do_extend(ap2,ssize,lsize,F_DREG);
  1142.                 }
  1143.                 domul(ap2,ap1,lsize,op);
  1144.                 freeop(ap1);
  1145.                 if (!equal_address(ap2,ap3))
  1146.                     if (node->v.p[0]->nodetype == en_bits)
  1147.                         bit_move(ap3,ap2,node->v.p[0],flags,ssize,rsize);
  1148.                     else
  1149.                         gen_code(op_mov,ssize,ap3,ap2);
  1150.                 if (flags & F_NOVALUE)
  1151.                     freeop(ap2);
  1152.                 else {
  1153.                     do_extend(ap2,ssize,size,flags);
  1154.                make_legal(ap2,flags,4);
  1155.                 }
  1156.         return ap2;
  1157. }
  1158.  
  1159. AMODE    *gen_asmodiv(ENODE *node, int flags, int size, int op, int modflag)
  1160. /*
  1161.  *      generate /= and %= nodes.
  1162.  */
  1163. {       AMODE    *ap1, *ap2,*ap3;
  1164.         int             ssize,lsize,rsize;
  1165.         ssize = natural_size(node->v.p[0]);
  1166.         rsize = natural_size(node->v.p[1]);
  1167.                 if (ssize > 4) {
  1168.                     ap2 = gen_expr(node->v.p[0],F_ALL,ssize);
  1169.                     ap1 = gen_expr(node->v.p[1],F_ALL,rsize);
  1170.                     ap3 = xalloc(sizeof(AMODE));
  1171.                     ap3->mode = ap2->mode;
  1172.                     ap3->preg = ap2->preg;
  1173.                     ap3->offset = ap2->offset;
  1174.                     ap3->sreg = ap2->sreg;
  1175.                     if (ap2->mode == am_freg) {
  1176.                         gen_codef(op_fdiv,0,0,0);
  1177.                         ap3 = ap2 = fstack();
  1178.                     }
  1179.                     else  {
  1180.                         ap3 = xalloc(sizeof(AMODE));
  1181.                         ap3->mode = ap2->mode;
  1182.                         ap3->preg = ap2->preg;
  1183.                         ap3->offset = ap2->offset;
  1184.                         ap3->sreg = ap2->sreg;
  1185.                         make_legal(ap2,F_FREG | F_VOL, ssize);
  1186.                         gen_codef(op_fdiv,ssize,ap1,0);
  1187.                         ap2 = fstack();
  1188.                     }
  1189.                     if (!equal_address(ap2, ap3)) {
  1190.                         if (flags & F_NOVALUE)
  1191.                           gen_codef(op_fstp,ssize,ap3,0);
  1192.                         else
  1193.                           gen_codef(op_fst,ssize,ap3,0);
  1194.                     }
  1195.                     gen_codef(op_fwait,0,0,0);
  1196.                     if (!(flags & F_NOVALUE)) {
  1197.                         ap2 = fstack();
  1198.                         do_extend(ap2,ssize,size,flags);
  1199.                         make_legal(ap2,flags,size);
  1200.                     }
  1201.                     return ap2;
  1202.                 }                                                   
  1203.                 if (op == op_idiv)                                  
  1204.                     lsize= -4;                                        
  1205.                 else                                                
  1206.                     lsize = 4;                                        
  1207.                                                                   
  1208.            ap2 = gen_expr(node->v.p[0],F_ALL | F_NOBIT, ssize);         
  1209.            ap1 = gen_expr(node->v.p[1],F_ALL,lsize);         
  1210.                 validate(ap2);                                    
  1211.                 ap3 = xalloc(sizeof(AMODE));                      
  1212.                 ap3->mode = ap2->mode;                            
  1213.                 ap3->preg = ap2->preg;                            
  1214.                 ap3->sreg = ap2->sreg;                            
  1215.                 ap3->scale = ap2->scale;                          
  1216.                 ap3->offset = ap2->offset;
  1217.                 if (node->v.p[0]->nodetype == en_bits)
  1218.                     ap2 = get_bitval(ap2,node->v.p[0],ssize);
  1219.                 else {
  1220.             make_legal(ap2,F_DREG | F_VOL,4);
  1221.                     do_extend(ap2,ssize,lsize,F_DREG);
  1222.                 }
  1223.                 dodiv(ap2,ap1,ssize,op,modflag);                  
  1224.                 freeop(ap1);
  1225.                 if (!equal_address(ap2,ap3))
  1226.                     if (node->v.p[0]->nodetype == en_bits)
  1227.                         bit_move(ap3,ap2,node->v.p[0],flags,ssize,rsize);
  1228.                     else
  1229.                         gen_code(op_mov,ssize,ap3,ap2);
  1230.                 if (flags & F_NOVALUE)                              
  1231.                     freeop(ap2);                                      
  1232.                 else {
  1233.                     do_extend(ap2,ssize,size,flags);
  1234.                make_legal(ap2,flags,4);
  1235.                 }
  1236.            return ap2;                                       
  1237. }
  1238. AMODE *gen_moveblock(ENODE *node, int flags, int size)      
  1239. {                                                           
  1240.     AMODE *ap1, *ap2;                                         
  1241.     if (!node->size)                                          
  1242.         return(0);
  1243.     ap1 = gen_expr(node->v.p[0],F_ALL,4);                     
  1244.     ap2 = gen_expr(node->v.p[1],F_ALL,4);                     
  1245.     validate(ap1);                                            
  1246.     gen_push(ESI,am_dreg,0);                                  
  1247.     gen_push(EDI,am_dreg,0);                                  
  1248.     if (regs[1])                                              
  1249.         gen_push(ECX,am_dreg,0);                                
  1250.     gen_code(op_mov,4,makedreg(ESI),ap1);                          
  1251.     gen_code(op_mov,4,makedreg(EDI),ap2);                     
  1252.     gen_code(op_mov,4,makedreg(ECX),make_immed(node->size));  
  1253.     gen_code(op_rep,1,0,0);                                   
  1254.     gen_code(op_movsb,1,0,0);                                      
  1255.     if (regs[1])                                              
  1256.         gen_pop(ECX,am_dreg,0);
  1257.     gen_pop(EDI,am_dreg,0);
  1258.     gen_pop(ESI,am_dreg,0);
  1259.     return(ap2);
  1260. }
  1261. AMODE    *gen_assign(ENODE *node, int flags, int size)
  1262. /*
  1263.  *      generate code for an assignment node. if the size of the
  1264.  *      assignment destination is larger than the size passed then
  1265.  *      everything below this node will be evaluated with the
  1266.  *      assignment size.
  1267.  */
  1268. {       AMODE    *ap1, *ap2, *ap3;
  1269.         int             ssize,rsize;
  1270.                 rsize = natural_size(node->v.p[1]);
  1271.         switch( node->v.p[0]->nodetype )
  1272.                 {
  1273.                                 case en_bits:
  1274.                                                 ssize = natural_size(node->v.p[0]);
  1275.                                                 break;
  1276.                 case en_ub_ref:
  1277.                                 case en_cub:
  1278.                         ssize = 1;
  1279.                         break;
  1280.                 case en_b_ref:
  1281.                                 case en_cb:
  1282.                         ssize = -1;
  1283.                         break;
  1284.                 case en_uw_ref:
  1285.                                 case en_cuw:
  1286.                         ssize = 2;
  1287.                         break;
  1288.                 case en_w_ref:
  1289.                                 case en_cw:
  1290.                         ssize = -2;
  1291.                         break;
  1292.                 case en_l_ref:
  1293.                                 case en_cl:
  1294.                                                 ssize = -4;
  1295.                                                 break;
  1296.                 case en_ul_ref:
  1297.                                 case en_cul:
  1298.                                 case en_cp:
  1299.                         ssize = 4;
  1300.                         break;
  1301.                 case en_tempref:
  1302.                 case en_regref:
  1303.                                                 ssize = node->v.p[0]->v.i >> 8;
  1304.                                                 break;
  1305.                                 case en_floatref:
  1306.                                 case en_cf:
  1307.                                                 ssize = 6;
  1308.                                                 break;
  1309.                                 case en_doubleref:
  1310.                                 case en_cd:
  1311.                                                 ssize = 8;
  1312.                                                 break;
  1313.                                 case en_longdoubleref:
  1314.                                 case en_cld:
  1315.                                                 ssize = 10;
  1316.                                                 break;
  1317.                 }
  1318.         if (chksize( ssize , rsize ))
  1319.                 rsize = ssize;
  1320.         ap2 = gen_expr(node->v.p[1],F_ALL,rsize);
  1321.         ap1 = gen_expr(node->v.p[0],F_ALL | F_NOBIT,ssize);
  1322.         validate(ap2);
  1323.                 if (!equal_address(ap1,ap2)    )
  1324.                     if (ssize > 4) {
  1325.                         if (ap2->mode != am_freg) {
  1326.                             gen_codef(op_fld,ssize,ap2,0);
  1327.                         }
  1328.                         if (flags & F_NOVALUE)
  1329.                             gen_codef(op_fstp,ssize,ap1,0);
  1330.                         else
  1331.                             gen_codef(op_fst,ssize,ap1,0);
  1332.                         gen_codef(op_fwait,0,0,0);
  1333.                         ap1 = fstack();
  1334.                     }
  1335.                     else
  1336.                         if (node->v.p[0]->nodetype == en_bits)
  1337.                             bit_move(ap1,ap2,node->v.p[0],flags,ssize,rsize);
  1338.                         else
  1339.                             if (ap2->mode != am_dreg && ap2->mode != am_immed
  1340.                                         && ap1->mode != am_dreg) {
  1341.                                 ap3 = temp_data();
  1342.                         gen_code(op_mov,rsize,ap3,ap2);
  1343.                         gen_code(op_mov,ssize,ap1,ap3);
  1344.                                 freeop(ap3);
  1345.                             }
  1346.                             else
  1347.                         gen_code(op_mov,ssize,ap1,ap2);
  1348.         freeop(ap2);
  1349.                 if (flags & F_NOVALUE)
  1350.                     freeop(ap1);
  1351.                 else {
  1352.                     do_extend(ap1,ssize,size,flags);
  1353.                     make_legal(ap1,flags,size);
  1354.                 }
  1355.         return ap1;
  1356. }
  1357.  
  1358. AMODE    *gen_aincdec(ENODE *node, int flags, int size, int op)
  1359. /*
  1360.  *      generate an auto increment or decrement node. op should be
  1361.  *      either op_add (for increment) or op_sub (for decrement).
  1362.  */
  1363. {       AMODE    *ap1,*ap2;
  1364.         int             ssize,rsize;
  1365.         ssize = natural_size(node->v.p[0]);
  1366.                 if (!(flags & F_NOVALUE))
  1367.                     ap2 = temp_data();
  1368.         ap1 = gen_expr(node->v.p[0],F_ALL,ssize);
  1369.                 if (!(flags &F_NOVALUE)) {
  1370.                     validate(ap2);
  1371.                     gen_code(op_mov,ssize,ap2,ap1);
  1372.                 }
  1373.         gen_code(op,ssize,ap1,make_immed((int)node->v.p[1]));
  1374.                 freeop(ap1);
  1375.                 if (flags & F_NOVALUE)
  1376.           freeop(ap2);
  1377.                 else {
  1378.                     do_extend(ap2,ssize,size,flags);
  1379.                     make_legal(ap2,flags,size);
  1380.                 }
  1381.         return ap2;
  1382. }
  1383.  
  1384. int push_param(ENODE *ep)
  1385. /*
  1386.  *      push the operand expression onto the stack.
  1387.  */
  1388. {       AMODE    *ap, *ap2;
  1389.                 int rv;
  1390.                 switch (ep->nodetype) {
  1391.                 case en_napccon:
  1392.                 case en_labcon:
  1393.                 case en_nalabcon:
  1394.                 case en_nacon:
  1395.                         ap = xalloc(sizeof(AMODE));
  1396.                         ap->mode = am_immed;
  1397.                         ap->offset = ep;     /* use as constant node */
  1398.                         gen_code(op_push,4,ap,0);
  1399.                         make_legal(ap,F_ALL,4);
  1400.                                                 rv = 4;
  1401.                                                 break;
  1402.                                 case en_cf:
  1403.                                 case en_floatref:
  1404.                                                 ap = gen_expr(ep,F_FREG | F_VOL,6);
  1405.                                                 gen_code(op_sub,4,makedreg(ESP),make_immed(4));
  1406.                                                 ap2 = make_immed(0);
  1407.                                                 ap2->preg = ESP;
  1408.                                                 ap2->mode = am_indisp;
  1409.                                                 gen_codef(op_fstp,6,ap2,0);
  1410.                                                 gen_codef(op_fwait,0,0,0);
  1411.                                                 rv = 4;
  1412.                                                 break;
  1413.                                 case en_cd:
  1414.                                 case en_doubleref:
  1415.                                                 ap = gen_expr(ep,F_FREG | F_VOL,8);
  1416.                                                 gen_code(op_sub,4,makedreg(ESP),make_immed(8));
  1417.                                                 ap2 = make_immed(0);
  1418.                                                 ap2->preg = ESP;
  1419.                                                 ap2->mode = am_indisp;
  1420.                                                 gen_codef(op_fstp,8,ap2,0);
  1421.                                                 gen_codef(op_fwait,0,0,0);
  1422.                                                 rv = 8;
  1423.                                                 break;
  1424.                                 case en_cld:
  1425.                                 case en_longdoubleref:
  1426.                                                 ap = gen_expr(ep,F_FREG | F_VOL,8);
  1427.                                                 gen_code(op_sub,4,makedreg(ESP),make_immed(10));
  1428.                                                 ap2 = make_immed(0);
  1429.                                                 ap2->preg = ESP;
  1430.                                                 ap2->mode = am_indisp;
  1431.                                                 gen_codef(op_fstp,10,ap2,0);
  1432.                                                 gen_codef(op_fwait,0,0,0);
  1433.                                                 rv = 8;
  1434.                                                 break;
  1435.                                 default:
  1436.                                                 rv = 4;
  1437.                                         ap = gen_expr(ep,F_ALL,4);
  1438.                                                 if (ap->mode == am_freg) {
  1439.                                                     gen_code(op_sub,4,makedreg(ESP),make_immed(4));
  1440.                                                     ap2 = make_immed(0);
  1441.                                                     ap2->preg = ESP;
  1442.                                                     ap2->mode = am_indisp;
  1443.                                                     gen_codef(op_fistp,4,ap2,0);
  1444.                                                     gen_codef(op_fwait,0,0,0);
  1445.                                                 }
  1446.                                                 else
  1447.                                                     gen_code(op_push,4,ap,0);
  1448.                                                 break;
  1449.                 }
  1450.         freeop(ap);
  1451.     stackdepth += rv;
  1452.     return(rv);
  1453. }
  1454. int push_stackblock(ENODE *ep)
  1455. {
  1456.     AMODE *ap;
  1457.     int sz = (ep->size + 3) &0xfffffffcL;
  1458.     if (!sz)
  1459.         return(0);
  1460.                 switch (ep->nodetype) {
  1461.                 case en_napccon:
  1462.                 case en_labcon:
  1463.                 case en_nalabcon:
  1464.                 case en_nacon:
  1465.                         ap = xalloc(sizeof(AMODE));
  1466.                         ap->preg = EAX;          /* frame pointer */
  1467.                             ap->mode = am_direct;
  1468.                             ap->offset = ep;     /* use as constant node */
  1469.                         gen_code(op_lea,4,makedreg(EAX),ap);
  1470.                                                 break;
  1471.                                 default:
  1472.                                         ap = gen_expr(ep,F_DREG | F_VOL,4);
  1473.                                                 freeop(ap);
  1474.                                                 if (ap->preg != EAX)
  1475.                                                     gen_code(op_mov,4,makedreg(EAX),ap);
  1476.                                                 break;
  1477.                 }
  1478.     gen_code(op_mov,4,makedreg(ECX),make_immed(sz));
  1479.     call_library("_stackblock");
  1480.     stackdepth += sz;
  1481.     return(sz);
  1482. }
  1483.  
  1484. int     gen_parms(ENODE *plist)
  1485. /*
  1486.  *      push a list of parameters onto the stack and return the
  1487.  *      size of parameters pushed.
  1488.  */
  1489. {       int     i;
  1490.         i = 0;
  1491.         while( plist != 0 )
  1492.                 {             
  1493.                                 if (plist->nodetype == en_stackblock)
  1494.                                     i+=push_stackblock(plist->v.p[0]);
  1495.                                 else
  1496.                     i+=push_param(plist->v.p[0]);
  1497.                 plist = plist->v.p[1];
  1498.                 }
  1499.         return i;
  1500. }
  1501.  
  1502. AMODE    *gen_fcall(ENODE *node,int flags, int size)
  1503. /*
  1504.  *      generate a function call node and return the address mode
  1505.  *      of the result.
  1506.  */
  1507. {       AMODE    *ap, *result;
  1508.         int             i,ssize = natural_size(node->v.p[1]);
  1509.         result = temp_data();
  1510.         temp_data(); temp_data();       /* push any used data registers */
  1511.         freeop(result); freeop(result); freeop(result);
  1512.         i = gen_parms(node->v.p[1]->v.p[0]);    /* generate parameters */
  1513.                 if (node->nodetype == en_intcall) {
  1514.                     AMODE *ap2 = xalloc(sizeof(AMODE));
  1515.                     ap2->mode = am_cs;
  1516.                     gen_code(op_pushfd,0,0,0);
  1517.                     gen_code(op_push,0,ap2,0);
  1518.                 }
  1519.                     
  1520.         if( node->v.p[0]->nodetype == en_nacon || node->v.p[0]->nodetype == en_napccon ) {
  1521.                 ap = make_offset(node->v.p[0]);
  1522.                                 ap->mode = am_immed;
  1523.                 gen_code(op_call,0,ap,0);
  1524.                 }
  1525.         else
  1526.                 {
  1527.                 ap = gen_expr(node->v.p[0],F_ALL,4);
  1528.                 freeop(ap);
  1529.                 gen_code(op_call,4,ap,0);
  1530.                 }
  1531.         if( i != 0 ) {
  1532.                 gen_code(op_add,4,makedreg(4),make_immed(i));
  1533.                                 stackdepth -= i;
  1534.                 }
  1535.                 if (ssize > 4) {
  1536.                         result = fstack();
  1537.                 }
  1538.                 else {
  1539.           result = temp_data();
  1540.             if( result->preg != EAX)
  1541.                 gen_code(op_mov,4,result,makedreg(EAX));
  1542.                 }
  1543.                 do_extend(result,ssize,size,flags);
  1544.                 make_legal(result,flags,size);
  1545.         return result;
  1546. }
  1547.  
  1548. AMODE    *gen_expr(ENODE *node, int flags, int size)
  1549. /*
  1550.  *      general expression evaluation. returns the addressing mode
  1551.  *      of the result.
  1552.  */
  1553. {
  1554.                 AMODE    *ap1, *ap2;
  1555.         int             lab0, lab1;
  1556.         int             natsize;
  1557.         if( node == 0 )
  1558.                 {
  1559.                 diag("null node in gen_expr.");
  1560.                 return 0;
  1561.                 }
  1562.         switch( node->nodetype )
  1563.                 {
  1564.                                 case en_bits:
  1565.                                                 size = natural_size(node->v.p[0]);
  1566.                                                 ap1 = gen_expr(node->v.p[0],F_ALL,size);
  1567.                                                 if (!(flags & F_NOBIT))
  1568.                                                     bit_legal(ap1,node,size);
  1569.                                                 return ap1;
  1570.                                 case en_cb: 
  1571.                                 case en_cub:
  1572.                                 case en_cw: 
  1573.                                 case en_cuw:
  1574.                                 case en_cl: 
  1575.                                 case en_cul:
  1576.                                 case en_cf: 
  1577.                                 case en_cd: 
  1578.                                 case en_cld: 
  1579.                                 case en_cp:
  1580.                                                 ap1 = gen_expr(node->v.p[0],flags | F_MEM | F_DREG | F_FREG,natural_size(node));
  1581.                                                 make_legal(ap1,flags,size);
  1582.                                                 return ap1;
  1583.                 case en_labcon:
  1584.                 case en_napccon:
  1585.                                 case en_nalabcon:
  1586.                 case en_nacon:
  1587.                         ap1 = temp_data();
  1588.                         ap2 = xalloc(sizeof(AMODE));
  1589.                         ap2->mode = am_direct;
  1590.                         ap2->offset = node;     /* use as constant node */
  1591.                         gen_code(op_lea,4,ap1,ap2);
  1592.                         make_legal(ap1,flags,size);
  1593.                         return ap1;             /* return reg */
  1594.                 case en_icon:
  1595.                                 case en_rcon:
  1596.                         ap1 = xalloc(sizeof(AMODE));
  1597.                         ap1->mode = am_immed;
  1598.                         ap1->offset = node;
  1599.                         make_legal(ap1,flags,size);
  1600.                         return ap1;
  1601.                 case en_autocon:
  1602.                 case en_autoreg:
  1603.                         ap1 = temp_data();
  1604.                         ap2 = xalloc(sizeof(AMODE));
  1605.                                 ap2->mode = am_indisp;
  1606.                                                 ap2->preg = ESP;
  1607.                                                 if (node->v.p[0]->v.i >= 0)
  1608.                                     ap2->offset = makenode(en_acon,(char *)(node->v.i+framedepth+stackdepth),0);
  1609.                                 else
  1610.                                                     ap2->offset = makenode(en_acon,(char *)(node->v.i+stackdepth),0);
  1611.                         gen_code(op_lea,4,ap1,ap2);
  1612.                         make_legal(ap1,flags,size);
  1613.                         return ap1;             /* return reg */
  1614.                 case en_b_ref:
  1615.                 case en_w_ref:
  1616.                 case en_ub_ref:
  1617.                 case en_uw_ref:
  1618.                 case en_l_ref:
  1619.                 case en_ul_ref:
  1620.                                 case en_floatref:
  1621.                                 case en_doubleref:
  1622.                                 case en_longdoubleref:
  1623.                         return gen_deref(node,flags,size);
  1624.                 case en_tempref:
  1625.                 case en_regref:
  1626.                         ap1 = xalloc(sizeof(AMODE));
  1627.                         if( (node->v.i & 0xff) < 8 )
  1628.                                 {
  1629.                                 ap1->mode = am_dreg;
  1630.                                 ap1->preg = node->v.i & 0xff;
  1631.                                 }
  1632.                         else
  1633.                                                     if ((node->v.i &0xff) < 16)
  1634.                                 {
  1635.                                 ap1->mode = am_dreg;
  1636.                                 ap1->preg = (node->v.i & 0xff)- 4;
  1637.                                 }
  1638.                                                     else
  1639.                                 {
  1640.                                 ap1->mode = am_freg;
  1641.                                 ap1->preg = (node->v.i & 0xff) - 16;
  1642.                                 }
  1643.                         ap1->tempflag = 0;      /* not a temporary */
  1644.                                 do_extend(ap1,node->v.i >> 8,size,flags);
  1645.                         make_legal(ap1,flags,size);
  1646.                         return ap1;
  1647.                 case en_uminus:
  1648.                         return gen_unary(node,flags,size,op_neg, op_fchs);
  1649.                 case en_compl:
  1650.                         return gen_unary(node,flags,size,op_not, op_not);
  1651.                 case en_add:
  1652.                         return gen_binary(node,flags,size,op_add,op_fadd);
  1653.                 case en_sub:
  1654.                         return gen_binary(node,flags,size,op_sub,op_fsub);
  1655.                 case en_and:
  1656.                         return gen_binary(node,flags,size,op_and,op_and);
  1657.                 case en_or:
  1658.                         return gen_binary(node,flags,size,op_or,op_or);
  1659.                 case en_xor:
  1660.                         return gen_xbin(node,flags,size,op_xor,op_xor);
  1661.                                 case en_pmul:
  1662.                                                 return gen_pmul(node,flags,size);
  1663.                                 case en_pdiv:
  1664.                                                 return gen_pdiv(node,flags,size);
  1665.                 case en_mul:
  1666.                         return gen_mul(node,flags,size,op_imul);
  1667.                 case en_umul:
  1668.                         return gen_mul(node,flags,size,op_mul);
  1669.                 case en_div:
  1670.                         return gen_modiv(node,flags,size,op_idiv,0);
  1671.                 case en_udiv:
  1672.                         return gen_modiv(node,flags,size,op_div,0);
  1673.                 case en_mod:
  1674.                         return gen_modiv(node,flags,size,op_idiv,1);
  1675.                 case en_umod:
  1676.                         return gen_modiv(node,flags,size,op_div,1);
  1677.                 case en_alsh:
  1678.                         return gen_shift(node,flags,size,op_sal);
  1679.                 case en_arsh:
  1680.                         return gen_shift(node,flags,size,op_sar);
  1681.                 case en_lsh:
  1682.                         return gen_shift(node,flags,size,op_shl);
  1683.                 case en_rsh:
  1684.                         return gen_shift(node,flags,size,op_shr);
  1685.                 case en_asadd:
  1686.                         return gen_asadd(node,flags,size,op_add,op_fadd);
  1687.                 case en_assub:
  1688.                         return gen_asadd(node,flags,size,op_sub,op_fsub);
  1689.                 case en_asand:
  1690.                         return gen_aslogic(node,flags,size,op_and);
  1691.                 case en_asor:
  1692.                         return gen_aslogic(node,flags,size,op_or);
  1693.                 case en_aslsh:
  1694.                         return gen_asshift(node,flags,size,op_shl);
  1695.                 case en_asrsh:
  1696.                         return gen_asshift(node,flags,size,op_shr);
  1697.                 case en_asalsh:
  1698.                         return gen_asshift(node,flags,size,op_sal);
  1699.                 case en_asarsh:
  1700.                         return gen_asshift(node,flags,size,op_sar);
  1701.                 case en_asmul:
  1702.                         return gen_asmul(node,flags,size, op_imul);
  1703.                 case en_asumul:
  1704.                         return gen_asmul(node,flags,size,op_mul);
  1705.                 case en_asdiv:
  1706.                         return gen_asmodiv(node,flags,size,op_idiv,FALSE);
  1707.                 case en_asudiv:
  1708.                         return gen_asmodiv(node,flags,size,op_div,FALSE);
  1709.                 case en_asmod:
  1710.                         return gen_asmodiv(node,flags,size,op_idiv,TRUE);
  1711.                 case en_asumod:
  1712.                         return gen_asmodiv(node,flags,size,op_div,TRUE);
  1713.                 case en_assign:
  1714.                         return gen_assign(node,flags,size);
  1715.                 case en_moveblock:
  1716.                         return gen_moveblock(node,flags,size);
  1717.                 case en_ainc:
  1718.                         return gen_aincdec(node,flags,size,op_add);
  1719.                 case en_adec:
  1720.                         return gen_aincdec(node,flags,size,op_sub);
  1721.                 case en_land:   case en_lor:
  1722.                 case en_eq:     case en_ne:
  1723.                 case en_lt:     case en_le:
  1724.                 case en_gt:     case en_ge:
  1725.                 case en_ult:    case en_ule:
  1726.                 case en_ugt:    case en_uge:
  1727.                 case en_not:
  1728.                         lab0 = nextlabel++;
  1729.                         lab1 = nextlabel++;
  1730.                         falsejp(node,lab0);
  1731.                         ap1 = temp_data();
  1732.                         gen_code(op_mov,4,ap1,make_immed(1));
  1733.                         gen_code(op_jmp,0,make_label(lab1),0);
  1734.                         gen_label(lab0);
  1735.                         gen_code(op_sub,4,ap1,ap1);
  1736.                         gen_label(lab1);
  1737.                         return ap1;
  1738.                 case en_cond:
  1739.                         return gen_hook(node,flags,size);
  1740.                 case en_void:
  1741.                         natsize = natural_size(node->v.p[0]);
  1742.                         freeop(gen_expr(node->v.p[0],F_ALL | F_NOVALUE,natsize));
  1743.                         return gen_expr(node->v.p[1],flags,size);
  1744.                 case en_fcall:
  1745.                 case en_trapcall:
  1746.                                 case en_intcall:
  1747.                         return gen_fcall(node,flags,size);
  1748.                 default:
  1749.                         diag("uncoded node in gen_expr.");
  1750.                         return 0;
  1751.                 }
  1752. }
  1753.  
  1754. int     natural_size(ENODE *node)
  1755. /*
  1756.  *      return the natural evaluation size of a node.
  1757.  */
  1758. {       int     siz0, ssize;
  1759.         if( node == 0 )
  1760.                 return 0;
  1761.         switch( node->nodetype )
  1762.                 {
  1763.                                 case en_bits:
  1764.                                                 return 4;
  1765.                 case en_icon:
  1766.                         if( -128 <= node->v.i && node->v.i <= 127 )
  1767.                                 return 1;
  1768.                         if( -32768L <= node->v.i && node->v.i <= 32767L )
  1769.                                 return 2;
  1770.                         return 4;
  1771.                                 case en_rcon:
  1772.                                 case en_doubleref:
  1773.                                                 return 8;
  1774.                                 case en_longdoubleref:
  1775.                                                 return 10;
  1776.                                 case en_floatref:
  1777.                                                 return 6;
  1778.                                 case en_trapcall:
  1779.                 case en_labcon: case en_nalabcon:
  1780.                 case en_nacon:  case en_autocon:  case en_autoreg:
  1781.                 case en_l_ref:  case en_napccon:
  1782.                                 case en_cl:
  1783.                                                 return -4;
  1784.                                 case en_fcall: case en_intcall:
  1785.                                                 return natural_size(node->v.p[1]);
  1786.                                 case en_tempref:
  1787.                                 case en_regref:
  1788.                                                 return node->v.i >> 8;
  1789.                 case en_ul_ref:
  1790.                                 case en_cul:
  1791.                                 case en_cp:
  1792.                         return 4;
  1793.                 case en_ub_ref:
  1794.                                 case en_cub:
  1795.                                                 return 1;
  1796.                 case en_b_ref:
  1797.                                 case en_cb:
  1798.                         return -1;
  1799.                 case en_uw_ref:
  1800.                                 case en_cuw:
  1801.                                                 return 2;
  1802.                 case en_cw:
  1803.                 case en_w_ref:
  1804.                         return -2;
  1805.                                 case en_cd:
  1806.                                                 return 8;
  1807.                                 case en_cld:
  1808.                                                 return 10;
  1809.                                 case en_cf:
  1810.                                                 return 6;
  1811.                 case en_not:    case en_compl:
  1812.                 case en_uminus: case en_assign:
  1813.                 case en_ainc:   case en_adec:
  1814.                                 case en_moveblock: case en_stackblock:
  1815.                         return natural_size(node->v.p[0]);
  1816.                 case en_add:    case en_sub:
  1817.                                 case en_umul:        case en_udiv:    case en_umod: case en_pmul:
  1818.                 case en_mul:    case en_div:  case en_pdiv:
  1819.                 case en_mod:    case en_and:
  1820.                 case en_or:     case en_xor:
  1821.                                 case en_asalsh: case en_asarsh: case en_alsh: case en_arsh:
  1822.                 case en_lsh:    case en_rsh:
  1823.                 case en_eq:     case en_ne:
  1824.                 case en_lt:     case en_le:
  1825.                 case en_gt:     case en_ge:
  1826.                                 case en_ugt: case en_uge: case en_ult: case en_ule:
  1827.                 case en_land:   case en_lor:
  1828.                 case en_asadd:  case en_assub:
  1829.                 case en_asmul:  case en_asdiv:
  1830.                 case en_asmod:  case en_asand:
  1831.                                 case en_asumod: case en_asudiv: case en_asumul:
  1832.                 case en_asor:   case en_aslsh:
  1833.                 case en_asrsh:
  1834.                         siz0 = natural_size(node->v.p[0]);
  1835.                         ssize = natural_size(node->v.p[1]);
  1836.                         if( chksize(ssize, siz0 ))
  1837.                                 return ssize;
  1838.                         else
  1839.                                 return siz0;
  1840.                 case en_void:   case en_cond:
  1841.                         return natural_size(node->v.p[1]);
  1842.                 default:
  1843.                         diag("natural size error.");
  1844.                         break;
  1845.                 }
  1846.         return 0;
  1847. }
  1848.  
  1849. void gen_compare(ENODE *node, int btype1, int btype2, int btype3, int btype4, int label)
  1850. /*
  1851.  *      generate code to do a comparison of the two operands of
  1852.  *      node.
  1853.  */
  1854. {       AMODE    *ap1, *ap2,  *ap3;
  1855.         int             size, type = op_cmp;
  1856.                 int btype = btype1;
  1857.                 ap3 = 0;
  1858.         size = natural_size(node);
  1859.                 if (size > 4) {
  1860.                     ap1 = gen_expr(node->v.p[0],F_FREG | F_VOL, size);
  1861.                     ap2 = gen_expr(node->v.p[1],F_ALL, size);
  1862.                     if (ap2->mode == am_freg) {
  1863.                         gen_codef(op_fcompp,0,0,0);
  1864.                     }
  1865.                     else
  1866.                         gen_codef(op_fcomp,size,ap2,0);
  1867.                     if (regs[0])
  1868.                         gen_push(EAX,am_dreg,0);
  1869.                     gen_codef(op_fstsw,2,makedreg(EAX),0);
  1870.                     gen_codef(op_fwait,0,0,0);
  1871.                     gen_code(op_sahf,0,0,0);
  1872.                     if (regs[0])
  1873.                         gen_pop(EAX,am_dreg,0);
  1874.                     gen_code(btype3,0,make_label(label),0);
  1875.                     return;
  1876.  
  1877.                 }
  1878.         ap1 = gen_expr(node->v.p[0],F_ALL,size);
  1879.         ap2 = gen_expr(node->v.p[1],F_ALL,size);
  1880.                 validate(ap1);
  1881.                 if (ap1->mode != am_dreg) {
  1882.                     if (ap2->mode == am_immed)  {
  1883.                         if (ap1->mode == am_immed)
  1884.                             goto cmp2;
  1885.                     }
  1886.                     else {
  1887.                         if (ap2->mode == am_dreg) {
  1888. swapit:
  1889.                             ap3 = ap2;
  1890.                             ap2 = ap1;
  1891.                             ap1 = ap3;
  1892.                             ap3 = 0;
  1893.                             btype = btype2;
  1894.                         }
  1895.                         else  
  1896.                             if (ap1->mode == am_immed) {
  1897.                                 goto swapit;
  1898.                             }
  1899.                             else {
  1900. cmp2:
  1901.                                 ap3 = ap1;
  1902.                   ap1 = temp_data();
  1903.                                 gen_code(op_mov,size,ap1,ap3);
  1904.                   make_legal(ap1,F_DREG,size);
  1905.                             }
  1906.                     }
  1907.                 }
  1908.         validate(ap1);
  1909.         gen_code(type,size,ap1,ap2);
  1910.         gen_code(btype,0,make_label(label),0);
  1911.                 if (ap3) {
  1912.                     freeop(ap1);
  1913.                     freeop(ap2);
  1914.                     freeop(ap3);
  1915.                 }
  1916.                 else {    
  1917.             freeop(ap2);
  1918.             freeop(ap1);
  1919.                 }
  1920. }
  1921.  
  1922. void truejp(ENODE *node, int label)
  1923. /*
  1924.  *      generate a jump to label if the node passed evaluates to
  1925.  *      a true condition.
  1926.  */
  1927. {       AMODE    *ap1;
  1928.         int             ssize;
  1929.         int             lab0;
  1930.         if( node == 0 )
  1931.                 return;
  1932.         switch( node->nodetype )
  1933.                 {
  1934.                 case en_eq:
  1935.                         gen_compare(node,op_je,op_je,op_je,op_je,label);
  1936.                         break;
  1937.                 case en_ne:
  1938.                         gen_compare(node,op_jne,op_jne,op_jne,op_jne,label);
  1939.                         break;
  1940.                 case en_lt:
  1941.                         gen_compare(node,op_jl,op_jg,op_jb,op_ja,label);
  1942.                         break;
  1943.                 case en_le:
  1944.                         gen_compare(node,op_jle,op_jge,op_jbe,op_jnc,label);
  1945.                         break;
  1946.                 case en_gt:
  1947.                         gen_compare(node,op_jg,op_jl,op_ja,op_jb,label);
  1948.                         break;
  1949.                 case en_ge:
  1950.                         gen_compare(node,op_jge,op_jle,op_jnc,op_jbe,label);
  1951.                         break;
  1952.                 case en_ult:
  1953.                         gen_compare(node,op_jb,op_ja,op_jb,op_ja,label);
  1954.                         break;
  1955.                 case en_ule:
  1956.                         gen_compare(node,op_jbe,op_jnc,op_jbe,op_jnc,label);
  1957.                         break;
  1958.                 case en_ugt:
  1959.                         gen_compare(node,op_ja,op_jb,op_ja,op_jb,label);
  1960.                         break;
  1961.                 case en_uge:
  1962.                         gen_compare(node,op_jnc,op_jbe,op_jnc,op_jbe,label);
  1963.                         break;
  1964.                 case en_land:
  1965.                         lab0 = nextlabel++;
  1966.                         falsejp(node->v.p[0],lab0);
  1967.                         truejp(node->v.p[1],label);
  1968.                         gen_label(lab0);
  1969.                         break;
  1970.                 case en_lor:
  1971.                         truejp(node->v.p[0],label);
  1972.                         truejp(node->v.p[1],label);
  1973.                         break;
  1974.                 case en_not:
  1975.                         falsejp(node->v.p[0],label);
  1976.                         break;
  1977.                 default:
  1978.                         ssize = natural_size(node);    
  1979.                                                 if (node->nodetype == en_icon) {
  1980.                                                     if (node->v.i != 0) 
  1981.                                 gen_code(op_jmp,0,make_label(label),0);
  1982.                                                     break;
  1983.                                                 }
  1984.                                                 else
  1985.                                                     if (ssize > 4) {
  1986.                                                         ap1 = gen_expr(node,F_FREG | F_VOL, ssize);
  1987.                                                     }
  1988.                                                     else
  1989.                                 ap1 = gen_expr(node,F_ALL,ssize);
  1990.                                                 if (ssize > 4) {
  1991.                                                     gen_codef(op_fldz,0,0,0);
  1992.                                                     gen_codef(op_fcompp,0,0,0);
  1993.                                                     if (regs[0])
  1994.                                                         gen_push(EAX,am_dreg,0);
  1995.                                                     gen_codef(op_fstsw,2,makedreg(EAX),0);
  1996.                                                     gen_codef(op_fwait,0,0,0);
  1997.                                                     gen_code(op_sahf,0,0,0);
  1998.                                                     if (regs[0])
  1999.                                                         gen_pop(EAX,am_dreg,0);
  2000.                                                 }
  2001.                                                 else {
  2002.                                                     if (ap1->mode == am_dreg) 
  2003.                                 gen_code(op_or,ssize,ap1,ap1);
  2004.                                                     else
  2005.                                 gen_code(op_test,ssize,ap1,make_immed(0xffffffffL));
  2006.                             freeop(ap1);
  2007.                                                 }
  2008.                         gen_code(op_jne,0,make_label(label),0);
  2009.                         break;
  2010.                 }
  2011. }
  2012.  
  2013. void falsejp(ENODE *node, int label)
  2014. /*
  2015.  *      generate code to execute a jump to label if the expression
  2016.  *      passed is false.
  2017.  */
  2018. {       AMODE    *ap1;
  2019.         int             ssize;
  2020.         int             lab0;
  2021.         if( node == 0 )
  2022.                 return;
  2023.         switch( node->nodetype )
  2024.                 {
  2025.                 case en_eq:
  2026.                         gen_compare(node,op_jne,op_jne,op_jne,op_jne,label);
  2027.                         break;
  2028.                 case en_ne:
  2029.                         gen_compare(node,op_je,op_je,op_je,op_je,label);
  2030.                         break;
  2031.                 case en_lt:
  2032.                         gen_compare(node,op_jge,op_jle,op_jnc,op_jbe,label);
  2033.                         break;
  2034.                 case en_le:
  2035.                         gen_compare(node,op_jg,op_jl,op_ja,op_jb,label);
  2036.                         break;
  2037.                 case en_gt:
  2038.                         gen_compare(node,op_jle,op_jge,op_jbe,op_jnc,label);
  2039.                         break;
  2040.                 case en_ge:
  2041.                         gen_compare(node,op_jl,op_jg,op_jb,op_ja,label);
  2042.                         break;
  2043.                 case en_ult:
  2044.                         gen_compare(node,op_jnc,op_jbe,op_jnc,op_jbe,label);
  2045.                         break;
  2046.                 case en_ule:
  2047.                         gen_compare(node,op_ja,op_jb,op_ja,op_jb,label);
  2048.                         break;
  2049.                 case en_ugt:
  2050.                         gen_compare(node,op_jbe,op_jnc,op_jbe,op_jnc,label);
  2051.                         break;
  2052.                 case en_uge:
  2053.                         gen_compare(node,op_jb,op_ja,op_jb,op_ja,label);
  2054.                         break;
  2055.                 case en_land:
  2056.                         falsejp(node->v.p[0],label);
  2057.                         falsejp(node->v.p[1],label);
  2058.                         break;
  2059.                 case en_lor:
  2060.                         lab0 = nextlabel++;
  2061.                         truejp(node->v.p[0],lab0);
  2062.                         falsejp(node->v.p[1],label);
  2063.                         gen_label(lab0);
  2064.                         break;
  2065.                 case en_not:
  2066.                         truejp(node->v.p[0],label);
  2067.                         break;
  2068.                 default:
  2069.                         ssize = natural_size(node);    
  2070.                                                 if (node->nodetype == en_icon) {
  2071.                                                     if (node->v.i == 0) 
  2072.                                 gen_code(op_jmp,0,make_label(label),0);
  2073.                                                     break;
  2074.                                                 }
  2075.                                                 else
  2076.                                                     if (ssize > 4) {
  2077.                                                         ap1 = gen_expr(node,F_FREG | F_VOL, ssize);
  2078.                                                     }
  2079.                                                     else
  2080.                                 ap1 = gen_expr(node,F_ALL,ssize);
  2081.                                                 if (ssize > 4) {
  2082.                                                     gen_codef(op_fldz,0,0,0);
  2083.                                                     gen_codef(op_fcompp,0,0,0);
  2084.                                                     if (regs[0])
  2085.                                                         gen_push(EAX,am_dreg,0);
  2086.                                                     gen_codef(op_fstsw,2,makedreg(EAX),0);
  2087.                                                     gen_codef(op_fwait,0,0,0);
  2088.                                                     gen_code(op_sahf,0,0,0);
  2089.                                                     if (regs[0])
  2090.                                                         gen_pop(EAX,am_dreg,0);
  2091.                                                 }
  2092.                                                 else {
  2093.                                                     if (ap1->mode == am_dreg) 
  2094.                                 gen_code(op_or,ssize,ap1,ap1);
  2095.                                                     else
  2096.                                 gen_code(op_test,ssize,ap1,make_immed(0xffffffffL));
  2097.                             freeop(ap1);
  2098.                                                 }
  2099.                         gen_code(op_je,0,make_label(label),0);
  2100.                         break;
  2101.                 }
  2102. }