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

编译器/解释器

开发平台:

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        "gen68.h"
  26. #include  "diag.h"
  27. extern long lc_maxauto;
  28. extern int linkreg;
  29. extern long framedepth;
  30. extern TYP              stdfunc;
  31. extern struct amode     push[], pop[];
  32. extern OCODE *peep_tail, *peep_head, *peep_insert;
  33. extern long stackdepth;
  34. extern SYM *currentfunc;
  35. extern int prm_cplusplus,prm_linkreg, prm_phiform, prm_68020, prm_68010;
  36. extern int prm_rel, prm_smallcode;
  37. extern long firstlabel, nextlabel;
  38. extern int global_flag;
  39. extern int save_mask, fsave_mask;
  40. extern TABLE gsyms;
  41. static int  diddef;
  42. static int     breaklab;
  43. static int     contlab;
  44. static int     retlab;
  45. static long gswitchbottom, gswitchcount;
  46. static long gswitchtop;
  47. void genstmtini(void)
  48. {
  49. }
  50. AMODE    *makedreg(int r)
  51. /*
  52.  *      make an address reference to a data register.
  53.  */
  54. {       AMODE    *ap;
  55.         ap = xalloc(sizeof(AMODE));
  56.         ap->mode = am_dreg;
  57.         ap->preg = r;
  58.         return ap;
  59. }
  60. AMODE    *makeareg(int r)
  61. /*
  62.  *      make an address reference to an address register.
  63.  */
  64. {       AMODE    *ap;
  65.         ap = xalloc(sizeof(AMODE));
  66.         ap->mode = am_areg;
  67.         ap->preg = r;
  68.         return ap;
  69. }
  70. AMODE    *makefreg(int r)
  71. /*
  72.  *      make an address reference to a data register.
  73.  */
  74. {       AMODE    *ap;
  75.         ap = xalloc(sizeof(AMODE));
  76.         ap->mode = am_freg;
  77.         ap->preg = r;
  78.         return ap;
  79. }
  80. AMODE    *make_mask(int mask, int reverse, int floatflag)
  81. /*
  82.  *      generate the mask address structure.
  83.  */
  84. {       AMODE    *ap;
  85.         ap = xalloc(sizeof(AMODE));
  86. if (floatflag)
  87.          ap->mode = am_fmask;
  88.         else
  89. ap->mode = am_mask;
  90. ap->preg = reverse;
  91.         ap->offset = (ENODE *)mask;
  92.         return ap;
  93. }
  94. AMODE    *make_direct(int i)
  95. /*
  96.  *      make a direct reference to an immediate value.
  97.  */
  98. {       return make_offset(makenode(en_icon,(char *)i,0));
  99. }
  100. AMODE    *make_strlab(char *s)
  101. /*
  102.  *      generate a direct reference to a string label.
  103.  */
  104. {       AMODE    *ap;
  105.         ap = xalloc(sizeof(AMODE));
  106.         ap->mode = am_direct;
  107.         ap->offset = makenode(en_nacon,s,0);
  108.         return ap;
  109. }
  110. void genwhile(SNODE *stmt)
  111. /*
  112.  *      generate code to evaluate a while statement.
  113.  */
  114. {       int     lab1, lab2, lab3;
  115.         initstack();            /* initialize temp registers */
  116.         lab1 = contlab;         /* save old continue label */
  117.         contlab = nextlabel++;  /* new continue label */
  118.         if( stmt->s1 != 0 )      /* has block */
  119.                 {
  120.          lab2 = breaklab;        /* save old break label */
  121.                 breaklab = nextlabel++;
  122. gen_code(op_bra,0,make_label(contlab),0);
  123. lab3 = nextlabel++;
  124. gen_label(lab3);
  125.                 genstmt(stmt->s1);
  126. gen_label(contlab);
  127.                 initstack();
  128. if (stmt->lst)
  129.   gen_line(stmt->lst);
  130.                 truejp(stmt->exp,lab3);
  131.                 gen_label(breaklab);
  132.                 breaklab = lab2;        /* restore old break label */
  133.                 }
  134.         else         /* no loop code */
  135.                 {
  136. if (stmt->lst)
  137.   gen_line(stmt->lst);
  138.          gen_label(contlab);
  139.                 initstack();
  140.                 truejp(stmt->exp,contlab);
  141.                 }
  142.         contlab = lab1;         /* restore old continue label */
  143. }
  144. void gen_for(SNODE *stmt)
  145. /*
  146.  *      generate code to evaluate a for loop
  147.  */
  148. {       int     old_break, old_cont, exit_label, loop_label;
  149.         old_break = breaklab;
  150.         old_cont = contlab;
  151.         loop_label = nextlabel++;
  152.         exit_label = nextlabel++;
  153.         contlab = nextlabel++;
  154.         initstack();
  155.         if( stmt->label != 0 )
  156.                 gen_expr(stmt->label,F_ALL | F_NOVALUE
  157.                         ,natural_size(stmt->label));
  158.         gen_code(op_bra,0,make_label(contlab),0);
  159.         gen_label(loop_label);
  160.         if( stmt->s1 != 0 ) {
  161. breaklab = exit_label;
  162.                 genstmt(stmt->s1);
  163. }
  164.         initstack();
  165.         if( stmt->s2 != 0 )
  166.                 gen_expr(stmt->s2,F_ALL | F_NOVALUE,natural_size(stmt->s2));
  167. gen_label(contlab);
  168. if (stmt->lst)
  169.   gen_line(stmt->lst);
  170.         initstack();
  171.         if( stmt->exp != 0 )
  172.                 truejp(stmt->exp,loop_label);
  173. else
  174. gen_code(op_bra,0,make_label(loop_label),0);
  175. gen_label(exit_label);
  176.   breaklab = old_break;
  177. contlab = old_cont;
  178. }
  179. void genif(SNODE *stmt)
  180. /*
  181.  *      generate code to evaluate an if statement.
  182.  */
  183. {       int     lab1, lab2;
  184.         lab1 = nextlabel++;     /* else label */
  185.         lab2 = nextlabel++;     /* exit label */
  186.         initstack();            /* clear temps */
  187.         falsejp(stmt->exp,lab1);
  188.         genstmt(stmt->s1);
  189.         if( stmt->s2 != 0 )             /* else part exists */
  190.                 {
  191.                 gen_code(op_bra,0,make_label(lab2),0);
  192.                 gen_label(lab1);
  193.                 genstmt(stmt->s2);
  194.                 gen_label(lab2);
  195.                 }
  196.         else                            /* no else code */
  197.                 gen_label(lab1);
  198. }
  199. void gendo(SNODE *stmt)
  200. /*
  201.  *      generate code for a do - while loop.
  202.  */
  203. {       int     oldcont, oldbreak;
  204.         oldcont = contlab;
  205.         oldbreak = breaklab;
  206.         contlab = nextlabel++;
  207.         gen_label(contlab);
  208.         if( stmt->s1 != 0 && stmt->s1->next != 0 )
  209.                 {
  210.                 breaklab = nextlabel++;
  211.                 genstmt(stmt->s1);      /* generate body */
  212.                 initstack();
  213.                 truejp(stmt->exp,contlab);
  214.                 gen_label(breaklab);
  215.                 }
  216.         else
  217.                 {
  218.                 genstmt(stmt->s1);
  219.                 initstack();
  220.                 truejp(stmt->exp,contlab);
  221.                 }
  222.         breaklab = oldbreak;
  223.         contlab = oldcont;
  224. }
  225. void gen_genword(SNODE *stmt)
  226. /*
  227.  * Generate data in the code stream
  228.  */
  229. {
  230. gen_code(op_genword,2,make_immed((int)stmt->exp),0);
  231. }
  232. AMODE *set_symbol(char *name, int isproc)
  233. /*
  234.  *      generate a call to a library routine.
  235.  */
  236. {       SYM     *sp;
  237.         AMODE *result;
  238.         sp = gsearch(name);
  239.         if( sp == 0 )
  240.                 {
  241.                 ++global_flag;
  242.                 sp = xalloc(sizeof(SYM));
  243.                 sp->tp = &stdfunc;
  244.                 sp->name = name;
  245. if (isproc)
  246.                  sp->storage_class = sc_externalfunc;
  247. else
  248.                  sp->storage_class = sc_external;
  249. sp->extflag = TRUE;
  250.                 insert(sp,&gsyms);
  251.                 --global_flag;
  252.                 }
  253. result = make_strlab(name);
  254. return result;
  255. }
  256. AMODE *flush_for_libcall()
  257. {
  258.         AMODE *result = temp_addr();
  259.         temp_addr();                    /* push any used addr temps */
  260.         freeop(result); freeop(result);
  261.         result = temp_data();
  262.         temp_data(); temp_data();      /* push any used data registers */
  263.         freeop(result); freeop(result); freeop(result);
  264. }
  265. AMODE *call_library(char *lib_name,int size)
  266. /*
  267.  *      generate a call to a library routine.
  268.  */
  269. {       
  270.         AMODE *result;
  271. result = set_symbol(lib_name,1);
  272.         gen_code(op_bsr,0,result,0);
  273. if (size)
  274.          gen_code(op_add,4,make_immed(size),makeareg(7));
  275. result = temp_data();
  276. if (result->preg != 0)
  277.          gen_code(op_move,4,makedreg(0),result);
  278. result->tempflag = TRUE;
  279. return result;
  280. }
  281. int analyzeswitch(SNODE *stmt)
  282. /* 
  283.  * Decide whitch type of switch statement to use
  284.  */
  285. {
  286. gswitchbottom = 0x7fffffff;
  287. gswitchtop = -0x80000000;
  288. gswitchcount = 0;
  289. stmt = stmt->s1;
  290. while (stmt) {
  291. if (!stmt->s2) {
  292. gswitchcount++;
  293. if ((int)stmt->label < gswitchbottom)
  294. gswitchbottom = (int)stmt->label;
  295. if ((int)stmt->label > gswitchtop)
  296. gswitchtop = (int)stmt->label;
  297. }
  298. stmt = stmt->next;
  299. }
  300. gswitchtop++;
  301. if (gswitchcount == 0)
  302. return(0);
  303. if (gswitchcount > 3)
  304. if (gswitchcount*10/(gswitchtop-gswitchbottom) >= 8)
  305. return(1);
  306. return(2);
  307. }
  308. void bingen(int lower, int avg, int higher,AMODE *ap1, int deflab, int size, long *switchids, int *switchlabels, int *switchbinlabels)
  309. /*
  310.  * Recursively output the compare/jump tree for a type of binary search
  311.  * on the case value
  312.  */
  313. {
  314. AMODE *ap2 = make_immed(switchids[avg]);
  315. AMODE *ap3 = make_label(switchlabels[avg]);
  316. if (switchbinlabels[avg] != -1)
  317. gen_label(switchbinlabels[avg]);
  318. gen_code(op_cmp,4,ap2,ap1);
  319. gen_code(op_beq,0,ap3,0);
  320. if (avg == lower) {
  321. ap3 = make_label(deflab);
  322. gen_code(op_bra,0,ap3,0);
  323. }
  324. else {
  325. int avg1 = (lower + avg)/2;
  326. int avg2 = (higher + avg+1)/2;
  327. if (avg+1 < higher) 
  328. ap3 = make_label(switchbinlabels[avg2]=nextlabel++);
  329. else
  330. ap3 = make_label(deflab);
  331. if (size < 0)
  332. gen_code(op_bgt,0,ap3,0);
  333. else
  334. gen_code(op_bhi,0,ap3,0);
  335. bingen(lower,avg1,avg,ap1,deflab,size,switchids,switchlabels,switchbinlabels);
  336. if (avg+1 < higher)
  337. bingen(avg+1,avg2,higher,ap1,deflab,size,switchids,switchlabels,switchbinlabels);
  338. }
  339. }
  340. void genbinaryswitch(SNODE *stmt, int deflab)
  341. /*
  342.  * Main routine for handling the binary switch setup
  343.  */
  344. {
  345. int curlab, i=0,j,size = natural_size(stmt->exp);
  346. AMODE *ap1;
  347.   long switchbottom=gswitchbottom, switchcount=gswitchcount;
  348.   long switchtop=gswitchtop;
  349.   int *switchlabels=0;
  350.   long *switchids=0;
  351.   int *switchbinlabels=0;
  352. curlab = nextlabel++;
  353.   initstack();
  354.   ap1 = gen_expr(stmt->exp,F_DREG,4);
  355. global_flag++;
  356. switchlabels = xalloc((switchcount) * sizeof(int));
  357. switchbinlabels = xalloc((switchcount) * sizeof(int));
  358. switchids = xalloc((switchcount) * sizeof(long));
  359. global_flag--;
  360. stmt = stmt->s1;
  361. while (stmt) {
  362.                 if( stmt->s2 )          /* default case ? */
  363.                         {
  364.                         stmt->label = (SNODE *) deflab;
  365. diddef = TRUE;
  366.                         }
  367.                 else
  368.                         {
  369. switchlabels[i] = curlab;
  370. switchbinlabels[i] = -1;
  371. switchids[i++] = (int)stmt->label;
  372. stmt->label = (SNODE *)curlab;
  373.                         }
  374.                 if( stmt->next != 0 )
  375.                         curlab = nextlabel++;
  376.                 stmt = stmt->next;
  377.                 }
  378. for (i=0; i < switchcount; i++)
  379. for (j=i+1; j < switchcount; j++)
  380. if (switchids[j] < switchids[i]) {
  381. int temp = switchids[i];
  382. switchids[i] = switchids[j];
  383. switchids[j] = temp;
  384. temp = switchlabels[i];
  385. switchlabels[i] = switchlabels[j];
  386. switchlabels[j] = temp;
  387. }
  388. bingen(0,(switchcount)/2,switchcount,ap1,deflab,size,switchids,switchlabels,switchbinlabels);
  389. }
  390. void gencompactswitch(SNODE *stmt, int deflab)
  391. /*
  392.  * Generate a table lookup mechanism if the switch table isn't too sparse
  393.  */
  394. {       int             tablab,curlab,i;
  395.         AMODE    *ap,*ap1,*ap2,*ap3;
  396.    long switchbottom=gswitchbottom, switchcount=gswitchcount;
  397.   long switchtop=gswitchtop;
  398.    int *switchlabels=0;
  399. tablab = nextlabel++;
  400.         curlab = nextlabel++;
  401.         initstack();
  402.         ap = gen_expr(stmt->exp,F_DREG | F_VOL,4);
  403. initstack();
  404. if (switchbottom) {
  405. gen_code(op_sub,4,make_immed(switchbottom),ap);
  406. gen_code(op_blo,0,make_label(deflab),0);
  407. }
  408. gen_code(op_cmp,4,make_immed(switchtop-switchbottom),ap);
  409. gen_code(op_bhs,0,make_label(deflab),0);
  410. ap1= temp_addr();
  411. ap2 = xalloc(sizeof(AMODE));
  412. if (prm_rel) {
  413. ap2->preg = ap1->preg;
  414. ap2->mode = am_pcindx;
  415. }
  416. else {
  417. ap2->mode = am_adirect;
  418. if (prm_smallcode)
  419. ap2->preg = 2;
  420. else
  421. ap2->preg = 4;
  422. }
  423. ap2->offset = makenode(en_labcon,(char *)tablab,0);
  424. gen_code(op_lea,0,ap2,ap1);
  425. if (prm_rel || prm_smallcode)
  426. gen_code(op_asl,4,make_immed(1),ap);
  427. else
  428. gen_code(op_asl,4,make_immed(2),ap);
  429. if (prm_rel) {
  430. gen_code(op_add,4,ap,ap1);
  431. ap2->mode = am_ind;
  432. gen_code(op_add,2,ap2,ap1);
  433. }
  434. else {
  435. ap3->sreg = ap->preg;
  436. ap3->preg = ap1->preg;
  437. ap3->scale = 0;
  438. ap3->offset = makenode(en_icon,0,0);
  439. ap3->mode = am_baseindxdata;
  440. gen_code(op_move,4,ap3,ap1);
  441. }
  442. ap1->mode = am_ind;
  443. gen_code(op_jmp,0,ap1,0);
  444. initstack();
  445. gen_label(tablab);
  446. switchlabels = xalloc((switchtop-switchbottom) * sizeof(int));
  447. for (i=switchbottom; i < switchtop; i++) {
  448. switchlabels[i-switchbottom] = deflab;
  449. }
  450. stmt = stmt->s1;
  451. while (stmt) {
  452.                 if( stmt->s2 )          /* default case ? */
  453.                         {
  454.                         stmt->label = (SNODE *)deflab;
  455. diddef = TRUE;
  456.                         }
  457.                 else
  458.                         {
  459. switchlabels[(int)stmt->label-switchbottom] = curlab;
  460. stmt->label = (SNODE *)curlab;
  461.                         }
  462.                 if( stmt->next != 0 )
  463.                         curlab = nextlabel++;
  464.                 stmt = stmt->next;
  465.                 }
  466. for (i=0; i < switchtop-switchbottom; i++)
  467. if (prm_smallcode || prm_rel)
  468. gen_code(op_dcl,2,make_label(switchlabels[i]),0);
  469. else
  470. gen_code(op_dcl,4,make_label(switchlabels[i]),0);
  471. }
  472. void gencase(SNODE *stmt)
  473. /*
  474.  *      generate all cases for a switch statement.
  475.  */
  476. {       while( stmt != 0 )
  477.                 {
  478.                 gen_label((int)stmt->label);
  479.                 if( stmt->s1 != 0 )
  480.                         {
  481.                         genstmt(stmt->s1);
  482.                         }
  483.                 stmt = stmt->next;
  484.                 }
  485. }
  486. void genxswitch(SNODE *stmt)
  487. /*
  488.  *      analyze and generate best switch statement.
  489.  */
  490. {       int     oldbreak;
  491. int olddiddef = diddef;
  492. int deflab = nextlabel++;
  493.         oldbreak = breaklab;
  494.         breaklab = nextlabel++;
  495. diddef = FALSE;
  496. switch (analyzeswitch(stmt)) {
  497.    case 2:
  498. genbinaryswitch(stmt,deflab);
  499. break;
  500. case 1:
  501. gencompactswitch(stmt,deflab);
  502. break;
  503. case 0:
  504. if (stmt->s1)
  505. stmt->s1->label = (SNODE *) nextlabel++;
  506. break;
  507. }
  508.         gencase(stmt->s1);
  509.         gen_label(breaklab);
  510. if (!diddef)
  511.          gen_label(deflab);
  512.         breaklab = oldbreak;
  513. diddef = olddiddef;
  514. }
  515. void genreturn(SNODE *stmt,int flag)
  516. /*
  517.  *      generate a return statement.
  518.  */
  519. {       AMODE    *ap,*ap1,*ap2,*ap3;
  520. int size;
  521.         if( stmt != 0 && stmt->exp != 0 )
  522.         {
  523.                 initstack();
  524. if (currentfunc->tp->btp && currentfunc->tp->btp->type != bt_void && (currentfunc->tp->btp->type == bt_struct || currentfunc->tp->btp->type == bt_union)) {
  525. int lbl;
  526. lbl = nextlabel++;
  527. size = currentfunc->tp->btp->size;
  528.                  ap = gen_expr(stmt->exp,F_AREG | F_VOL,4);
  529. ap2 = xalloc(sizeof(AMODE));
  530. if (prm_linkreg && !currentfunc->intflag) {
  531. if (currentfunc->pascaldefn && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1) {
  532. ap2->preg = linkreg;
  533. ap2->mode = am_indx;
  534. ap2->offset = makenode(en_icon,(char *)(currentfunc->tp->lst.head->value.i + ((currentfunc->tp->lst.head->tp->size +3) &0xFFFFFFFCL)),0);
  535. }
  536. else {
  537. ap2->preg = linkreg;
  538. ap2->mode = am_indx;
  539. ap2->offset = makenode(en_icon,(char *)8,0);
  540. }
  541. }
  542. else if ( prm_phiform || currentfunc->intflag) {
  543. if (currentfunc->pascaldefn && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1) {
  544. ap2->preg = linkreg;
  545. ap2->mode = am_indx;
  546. ap2->offset = makenode(en_icon,(char *)(currentfunc->tp->lst.head->value.i + ((currentfunc->tp->lst.head->tp->size +3) &0xFFFFFFFCL)),0);
  547. }
  548. else {
  549.   ap2->preg = linkreg;
  550. ap2->mode = am_ind;
  551. }
  552. }
  553. else {
  554. if (currentfunc->pascaldefn && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1) {
  555. ap2->preg = 7;
  556. ap2->mode = am_indx;
  557. ap2->offset = makenode(en_icon,(char *)(framedepth+stackdepth+currentfunc->tp->lst.head->value.i + ((currentfunc->tp->lst.head->tp->size+3) & 0xfffffffcL)),0);
  558. }
  559. else {
  560. ap2->preg = 7;
  561. ap2->mode = am_indx;
  562. ap2->offset = makenode(en_icon,(char *)(framedepth+stackdepth),0);
  563. }
  564. }
  565. ap3 = temp_addr();
  566. ap1 = temp_data();
  567. gen_code(op_move,4,ap2,ap3);
  568. ap->mode = am_ainc;
  569. ap3->mode = am_ainc;
  570. gen_code(op_move,4,make_immed(size),ap1);
  571. gen_label(lbl);
  572. gen_code(op_move,1,ap,ap3);
  573. gen_code(op_sub,4,make_immed(1),ap1);
  574. gen_code(op_bne,0,make_label(lbl),0);
  575. gen_code(op_move,4,ap2,makedreg(0));
  576. freeop(ap1);
  577. freeop(ap3);
  578. freeop(ap);
  579. }
  580. else {
  581. size = currentfunc->tp->btp->size;
  582.                  ap = gen_expr(stmt->exp,F_ALL,size);
  583. if (size > 4) {
  584.                   if( ap->mode != am_freg || ap->preg != 0 )
  585.                          gen_codef(op_fmove,size,ap,makefreg(0));
  586. }
  587.                  else
  588.                   if( ap->mode != am_dreg || ap->preg != 0 )
  589.                          gen_code(op_move,size,ap,makedreg(0));
  590. }
  591.         }
  592. if (flag) {
  593.          if( retlab != -1 )
  594.                 gen_label(retlab);
  595. if ((!prm_linkreg || currentfunc->intflag) && (lc_maxauto))
  596. if (lc_maxauto > 8) {
  597. AMODE *ap = xalloc(sizeof(AMODE)); 
  598. ap->mode = am_indx;
  599. ap->offset = makenode(en_icon,(char *)lc_maxauto,0);
  600. ap->preg = 7;
  601.                gen_code(op_lea,0,ap,makeareg(7));
  602. }
  603. else
  604.               gen_code(op_add,4,make_immed(lc_maxauto),makeareg(7));
  605.           if( fsave_mask != 0 )
  606.             gen_code(op_fmovem,10,pop,make_mask(fsave_mask,1,1));
  607.           if( save_mask != 0 )
  608.             gen_code(op_movem,4,pop,make_mask(save_mask,1,0));
  609. if (prm_linkreg && !currentfunc->intflag && (currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1 || lc_maxauto)) {
  610. gen_code(op_unlk,0,makeareg(linkreg),0);
  611. }
  612. if (currentfunc->intflag)
  613.             gen_code(op_rte,0,0,0);
  614. else
  615. if (currentfunc->pascaldefn) {
  616. long retsize = 0;
  617. if (currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1) {
  618. retsize = currentfunc->tp->lst.head->value.i + ((currentfunc->tp->lst.head->tp->size +3) & 0xfffffffcl);
  619. if (prm_linkreg)
  620. retsize -= 8;
  621. if (currentfunc->tp->btp && currentfunc->tp->btp->type != bt_void && (currentfunc->tp->btp->type == bt_struct || currentfunc->tp->btp->type == bt_union)) 
  622. retsize +=4;
  623. if (retsize) {
  624. if (prm_68020 || prm_68010)
  625. gen_code(op_rtd,0,make_immed(retsize),0);
  626. else {
  627. ap = temp_addr();
  628. freeop(ap);
  629. gen_code(op_move,4,pop,ap);
  630. if (retsize > 8) {
  631. ap1 = xalloc(sizeof(AMODE));
  632. ap1->mode = am_indx;
  633. ap1->offset = makenode(en_icon,(char *)retsize,0);
  634. ap1->preg = 7;
  635.                  gen_code(op_lea,0,ap1,makeareg(7));
  636. }
  637. else
  638.                  gen_code(op_add,4,make_immed(retsize),makeareg(7));
  639. ap->mode = am_ind;
  640. gen_code(op_jmp,0,ap,0);
  641. }
  642. return;
  643. }
  644. }
  645.             gen_code(op_rts,0,0,0);
  646.         }
  647.         else {
  648. if (retlab == -1)
  649. retlab = nextlabel++;
  650.           gen_code(op_bra,0,make_label(retlab),0);
  651. }
  652. }
  653. void genstmt(SNODE *stmt)
  654. /*
  655.  *      genstmt will generate a statement and follow the next pointer
  656.  *      until the block is generated.
  657.  */
  658. {
  659.    while( stmt != 0 )
  660.                 {
  661.                 switch( stmt->stype )
  662.                         {
  663. case st_block:
  664. genstmt(stmt->exp);
  665. break;
  666.                         case st_label:
  667.                                 gen_label((int)stmt->label);
  668.                                 break;
  669.                         case st_goto:
  670.                                 gen_code(op_bra,0,make_label((int)stmt->label),0);
  671.                                 break;
  672.                         case st_expr:
  673.                                 initstack();
  674.                                 gen_expr(stmt->exp,F_ALL | F_NOVALUE,
  675.                                         natural_size(stmt->exp));
  676.                                 break;
  677.                         case st_return:
  678.                                 genreturn(stmt,0);
  679.                                 break;
  680.                         case st_if:
  681.                                 genif(stmt);
  682.                                 break;
  683.                         case st_while:
  684.                                 genwhile(stmt);
  685.                                 break;
  686.                         case st_do:
  687.                                 gendo(stmt);
  688.                                 break;
  689.                         case st_for:
  690.                                 gen_for(stmt);
  691.                                 break;
  692. case st_line:
  693. gen_line(stmt);
  694. break;
  695.                         case st_continue:
  696.                                 gen_code(op_bra,0,make_label(contlab),0);
  697.                                 break;
  698.                         case st_break:
  699.   gen_code(op_bra,0,make_label(breaklab),0);
  700.                                 break;
  701.                         case st_switch:
  702.                                 genxswitch(stmt);
  703.                                 break;
  704. case st__genword:
  705. gen_genword(stmt);
  706. break;
  707.                         default:
  708.                                 DIAG("unknown statement.");
  709.                                 break;
  710.                         }
  711.                 stmt = stmt->next;
  712.                 }
  713. }
  714. #ifdef CPLUSPLUS
  715. void scppinit(void)
  716. /*
  717.  * Call C++ reference variable and class initializers
  718.  */
  719. {
  720. if (!strcmp(currentfunc->name,"_main")) {
  721. AMODE *ap1,*ap2,*ap3,*ap4;
  722. int lbl = nextlabel++;
  723. initstack();
  724. ap1 = temp_addr();
  725. ap4 = xalloc(sizeof(AMODE));
  726. ap4->preg = ap1->preg;
  727. ap4->mode = am_ind;
  728. ap2 = set_symbol("CPPSTART",0);
  729. ap3 = set_symbol("CPPEND",0);
  730. gen_code(op_lea,4,ap2,ap1);
  731. gen_label(lbl);
  732. gen_code(op_move,4,ap1,push);
  733. gen_code(op_jsr,4,ap4,0);
  734. gen_code(op_move,4,pop,ap1);
  735. gen_code(op_add,4,make_immed(4),ap1);
  736. gen_code(op_cmp,4,ap3,ap1);
  737. gen_code(op_bhi,0,make_label(lbl),0);
  738. freeop(ap1);
  739. }
  740. }
  741. #endif
  742. void genfunc(SNODE *stmt)
  743. /*
  744.  *      generate a function body.
  745.  */
  746. {       retlab = contlab = breaklab = -1;
  747. stackdepth = 0;
  748. if (stmt->stype == st_line) {
  749. gen_line(stmt);
  750. stmt = stmt->next;
  751. }
  752. gen_codelab(currentfunc);  /* name of function */
  753.         opt1(stmt); /* push args & Also loads link reg and subtracts SP */
  754. #ifdef CPLUSPLUS
  755. if (prm_cplusplus) {
  756. scppinit();
  757. }
  758. #endif
  759.         genstmt(stmt);
  760.         genreturn(0,1);
  761. }