GEXPR386.C
上传用户:hlzzc88
上传日期:2007-01-06
资源大小:220k
文件大小:86k
源码类别:

编译器/解释器

开发平台:

Others

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