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