home *** CD-ROM | disk | FTP | other *** search
/ CD Shareware Magazine 1996 December / CD_shareware_12-96.iso / DOS / Programa / CCDL122.ZIP / SOURCE / GCODE386.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-25  |  73.4 KB  |  2,312 lines

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