home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / language / sozobon2 / out_st.c < prev    next >
C/C++ Source or Header  |  1993-10-23  |  13KB  |  799 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    out.c
  12.  *
  13.  *    Code generation output routines.
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include "param.h"
  18. #include "nodes.h"
  19. #include "flags.h"
  20. #include "bstok.h"
  21. #include "tytok.h"
  22. #include "gen.h"
  23.  
  24. #if dLibs
  25. #include <ctype.h>
  26. #endif
  27.  
  28. #if MMCC
  29. overlay "pass2"
  30. #endif
  31.  
  32. #if CC68
  33. FILE *fopen();
  34. #endif
  35.  
  36. #if NEEDBUF
  37. char my_obuf[BUFSIZ];
  38. #endif
  39.  
  40. #define T_SEG    0
  41. #define D_SEG    1
  42. #define B_SEG    2
  43.  
  44. #define TO_TEXT    to_seg(T_SEG)
  45. #define TO_DATA    to_seg(D_SEG)
  46. #define TO_BSS    to_seg(B_SEG)
  47.  
  48. #define isareg(np)    ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  49.  
  50. extern FILE *output;
  51.  
  52. static int in_seg;
  53. static int lblnum;
  54. static int dat_size;
  55.  
  56. out_start(outs)
  57. char *outs;
  58. {
  59.     register int len;
  60.     char suff;
  61. #ifdef MINIX
  62.     extern char tmpdir[];
  63. #endif
  64.     char oname[128];
  65.  
  66.     len = strlen(outs);
  67.     if (len >= 2 && outs[len-2] == '.') {
  68.         suff = outs[len-1];
  69.         if (suff != 'c' && suff != 'C')
  70.             fatals("Invalid suffix", outs);
  71. #ifdef MINIX
  72.         sprintf(oname, "%s/%s", tmpdir, outs);
  73.         len = strlen(oname);
  74. #else
  75.         strcpy(oname, outs);
  76. #endif
  77.         oname[len-1] = 's';
  78.         output = fopen(oname, "w");
  79.         if (output == NULL)
  80.             fatals("Cant open", oname);
  81. #if NEEDBUF
  82.         setbuf(output, my_obuf);
  83. #endif
  84.     } else
  85.         output = stdout;
  86.  
  87.     in_seg = -1;
  88.     lblnum = 0;
  89.     dat_size = 0;
  90. }
  91.  
  92. out_end()
  93. {
  94.     if (output != stdout)
  95.         fclose(output);
  96. }
  97.  
  98. static char *sg_go[] = {
  99.     ".text",
  100.     ".data",
  101.     ".bss"
  102. };
  103.  
  104. to_text()
  105. {
  106.     TO_TEXT;
  107. }
  108.  
  109. to_seg(sg)
  110. {
  111.     if (sg == in_seg)
  112.         return;
  113.     fprintf(output, "\t%s\n", sg_go[sg]);
  114.     in_seg = sg;
  115. }
  116.  
  117. o_aln(x)
  118. {
  119.     if (x && (dat_size & 1)) {
  120.         dat_size++;
  121.         TO_DATA;
  122.         fprintf(output, "\t.even\n");
  123.     }
  124. }
  125.  
  126. char *rnms[] = {
  127.     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  128.     "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",
  129. };
  130.  
  131. char *regnm(n)
  132. {
  133.     return rnms[n];
  134. }
  135.  
  136. #define regnm(x)    rnms[x]
  137.  
  138. char *
  139. init_str(n)
  140. {
  141.     char *s;
  142.  
  143.     switch (n) {
  144.     case 1:
  145.         s = ".dc.b";    break;
  146.     case 2:
  147.         s = ".dc.w";    break;
  148.     default:
  149.         s = ".dc.l";    break;
  150.     }
  151.     return s;
  152. }
  153.  
  154. tlen(n)
  155. {
  156.     switch (n) {
  157.     case 1:
  158.         return 'b';
  159.     case 2:
  160.         return 'w';
  161.     default:
  162.         return 'l';
  163.     }
  164. }
  165.  
  166. o_vinit(tp, xp)
  167. NODEP tp, xp;
  168. {
  169.     fprintf(output, "\t%s\t", init_str((int)tp->t_size));
  170.     dat_size += tp->t_size;
  171.  
  172.     p2_expr(&xp);
  173.     asn_chk(tp, xp);
  174.     to_init(xp, tp);
  175.  
  176.     fputc('\n', output);
  177. }
  178.  
  179. to_init(np, typ)
  180. NODEP np, typ;
  181. {
  182.     NODEP tp;
  183.  
  184.     tp = allocnode();
  185.     tp->e_token = TCONV;
  186.     tp->n_tptr = typ;
  187.     tp->n_flags |= N_COPYT;
  188.     tp->n_left = np;
  189.     tp->e_type = E_UNARY;
  190.     strcpy(tp->n_name, "i cast");
  191.  
  192.     genx(tp, FORINIT);
  193. }
  194.  
  195. out_advice(np)
  196. NODEP np;
  197. {
  198.     long size;
  199.  
  200.     size = np->n_tptr->t_size;
  201.     if (size == 0)
  202.         return;
  203.  
  204.     switch (np->e_sc) {
  205.     case K_AUTO:
  206.         fprintf(output, ";var\t%d\t%d\t", (int)size,
  207.             (int)np->e_offs);
  208.         break;
  209.     case K_REGISTER:
  210.         fprintf(output, ";reg\t%d\t%s\t", (int)size,
  211.             regnm(np->e_rno));
  212.         break;
  213.     default:
  214.         return;
  215.     }
  216.     out_nm(np);
  217.     fputc('\n', output);
  218. }
  219.  
  220. out_argreg(np)
  221. NODEP np;
  222. {
  223.     fprintf(output, "\tmove.%c\t%d(%s),%s\n",
  224.         tlen((int)np->n_tptr->t_size), (int)np->e_offs,
  225.         regnm(FRAMEP), regnm(np->e_rno));
  226. }
  227.  
  228. out_fstart(np)
  229. NODEP np;
  230. {
  231.     extern    int    pflag;
  232.  
  233.     TO_TEXT;
  234.     if (np->e_sc != K_STATIC) {
  235.         fprintf(output, "\t.globl\t");
  236.         und_nnm(np);
  237.         fputc('\n', output);
  238.     }
  239.     und_nnm(np);
  240.     fprintf(output, ":\n");    
  241.  
  242.     if (pflag) {
  243.         int    tlab = new_lbl();
  244.  
  245.         TO_BSS;
  246.         fprintf(output, "L%d:\t.ds.l\t1\n", tlab);
  247.         TO_TEXT;
  248.         fprintf(output, "\tmove.l\t#");
  249.         und_nnm(np);
  250.         fprintf(output, ",a0\n");
  251.  
  252.         fprintf(output, "\tmove.l\t#L%d,a1\n", tlab);
  253.         fprintf(output,    "\tjsr\tmcount\n");
  254.     }
  255. }
  256.  
  257. static char rbuf[30];
  258.  
  259. char *
  260. regstr(regs)
  261. {
  262.     int lod, hid, loa, hia;
  263.     register i;
  264.     char *bp = rbuf;
  265.  
  266.     lod = 999;
  267.     hid = -1;
  268.     for (i=DRV_START; i<=DRV_END; i++)
  269.         if (regs & (1<<i)) {
  270.             if (i < lod)  lod = i;
  271.             if (i > hid)  hid = i;
  272.         }
  273.     loa = 999;
  274.     hia = -1;
  275.     for (i=ARV_START; i<=ARV_END; i++)
  276.         if (regs & (1<<i)) {
  277.             if (i < loa)  loa = i;
  278.             if (i > hia)  hia = i;
  279.         }
  280.     if (lod < 999) {
  281.         if (lod != hid)
  282.             sprintf(bp, "%s-%s", rnms[lod], rnms[hid]);
  283.         else
  284.             sprintf(bp, "%s", rnms[lod]);
  285.         if (loa < 999) {
  286.             bp += strlen(rbuf);
  287.             *bp++ = '/';
  288.         }
  289.     }
  290.     if (loa < 999) {
  291.         if (loa != hia)
  292.             sprintf(bp, "%s-%s", rnms[loa], rnms[hia]);
  293.         else
  294.             sprintf(bp, "%s", rnms[loa]);
  295.     }
  296.     return rbuf;
  297. }
  298.  
  299. out_fend(regs, lsize)
  300. long lsize;
  301. {
  302.     if (lsize < 0x7fff)
  303.         fprintf(output, "\tlink\t%s,#-%d\n", rnms[FRAMEP], (int)lsize);
  304.     else
  305.         fprintf(output, "\tlink\t%s,#0\n\tsub.l\t#%ld,sp\n",
  306.             rnms[FRAMEP], lsize);
  307.     if (regs)
  308.         fprintf(output, "\tmovem.l\t%s,-(sp)\n", regstr(regs));
  309. }
  310.  
  311. out_fret(regs, strl)
  312. {
  313.     if (regs)
  314.         fprintf(output, "\tmovem.l\t(sp)+,%s\n", regstr(regs));
  315.     if (strl)
  316.         fprintf(output, "\tmove.l\t#L%d,a0\n", strl);
  317.     fprintf(output, "\tunlk\t%s\n\trts\n", rnms[FRAMEP]);
  318. }
  319.  
  320. out_fs(strl, size)
  321. long size;
  322. {
  323.     TO_BSS;
  324.     def_lbl(strl);
  325.     if (size & 1)
  326.         fprintf(output, "\t.ds.b\t%ld\n", size);
  327.     else
  328.         fprintf(output, "\t.ds.w\t%ld\n", size/2);
  329. }
  330.  
  331. out_gv(np, isbss)
  332. register NODEP np;
  333. {
  334.     long sz;
  335.     char c;
  336.  
  337.     if (np->e_sc == K_STATIC) {
  338.         np->e_offs = lblnum++;
  339.     }
  340.     if (np->e_sc != K_EXTERN) {
  341.         to_seg(isbss ? B_SEG : D_SEG);
  342.         if (np->e_sc != K_STATIC) {
  343.             fprintf(output, "\t.globl\t");
  344.             out_nm(np);
  345.             fputc('\n', output);
  346.         }
  347.         if (isbss) {
  348.             if (np->e_sc == K_STATIC) {
  349.                 out_nm(np);
  350.                 sz = np->n_tptr->t_size;
  351.                 c = 'b';
  352.                 if (np->n_tptr->t_aln) {
  353.                     c = 'w';
  354.                     sz /= 2;
  355.                 }
  356.                 fprintf(output, ":\t.ds.%c\t%ld\n", c, sz);
  357.             } else {
  358.                 fprintf(output, "\t.comm\t");
  359.                 out_nm(np);
  360.                 sz = np->n_tptr->t_size;
  361.                 if (sz & 1) sz++;  /* ALCYON hack */
  362.                 fprintf(output, ",%ld\n", sz);
  363.             }
  364.         } else {
  365.             out_nm(np);
  366.             fprintf(output, ":\n");
  367.         }
  368.     }
  369. }
  370.  
  371. new_lbl()
  372. {
  373.     return lblnum++;
  374. }
  375.  
  376. def_lbl(l)
  377. {
  378.     fprintf(output, "L%d:\n", l);
  379. }
  380.  
  381. out_br(l)
  382. {
  383.     if (l < 0)
  384.         error("bad branch");
  385.     else
  386.         fprintf(output, "\tbra\tL%d\n", l);
  387. }
  388.  
  389. static char *bnm[] = {
  390.     "",
  391.     "beq",
  392.     "bne",
  393.     "blt",
  394.     "bge",
  395.     "ble",
  396.     "bgt",
  397.     "bra",
  398.     "nop",
  399.     "bcs",
  400.     "bcc",
  401.     "bls",
  402.     "bhi"
  403. };
  404.  
  405. static char *snm[] = {
  406.     "",
  407.     "seq",
  408.     "sne",
  409.     "slt",
  410.     "sge",
  411.     "sle",
  412.     "sgt",
  413.     "",
  414.     "",
  415.     "scs",
  416.     "scc",
  417.     "sls",
  418.     "shi"
  419. };
  420.  
  421. out_b(key, l)
  422. {
  423.     if (key != B_NO)
  424.         fprintf(output, "\t%s\tL%d\n", bnm[key], l);
  425. }
  426.  
  427. out_bnol(key)
  428. {
  429.     fprintf(output, "\t%s\t", bnm[key]);
  430. }
  431.  
  432. out_snol(key)
  433. {
  434.     fprintf(output, "\t%s\t", snm[key]);
  435. }
  436.  
  437. out_d0cmp(x)
  438. {
  439.     fprintf(output, "\tcmp.w\t#%d,d0\n", x);
  440. }
  441.  
  442. out_d0sub(x)
  443. {
  444.     fprintf(output, "\tsub.w\t#%d,d0\n", x);
  445. }
  446.  
  447. out_tlbl(l)
  448. {
  449.     fprintf(output, "\t.dc.l\tL%d\n", l);
  450. }
  451.  
  452. out_tsw()
  453. {
  454.     fprintf(output, "\text.l\td0\n");
  455.     fprintf(output, "\tasl.l\t#2,d0\n");
  456.     fprintf(output, "\tmove.l\t4(pc,d0.l),a0\n");
  457.     fprintf(output, "\tjmp\t(a0)\n");
  458. }
  459.  
  460. out_nm(np)
  461. NODEP np;
  462. {
  463.     if (np->e_sc == K_STATIC)
  464.         fprintf(output, "L%d", (int)np->e_offs);
  465.     else
  466.         und_nnm(np);
  467. }
  468.  
  469. out_zi(tp)
  470. NODEP tp;
  471. {
  472.     char *s;
  473. /*
  474.     switch (tp->t_token) {
  475.     case K_FLOAT:
  476.         fprintf(output, "\t.float\t0.0\n");    return;
  477.     case K_DOUBLE:
  478.         fprintf(output, "\t.double\t0.0\n");    return;
  479.     }
  480. */
  481.     dat_size += tp->t_size;
  482.     s = init_str((int)tp->t_size);
  483.     fprintf(output, "\t%s\t0\n", s);
  484. }
  485.  
  486. o_nz(sz, aln)
  487. long sz;
  488. {
  489.     dat_size += sz;
  490.     if (aln) {
  491.         if (sz & 1)
  492.             fprintf(output, "\t.ds.b\t1\n");
  493.         sz >>= 1;
  494.         fprintf(output, "\t.ds.w\t%ld\n", sz);
  495.     } else {
  496.         fprintf(output, "\t.ds.b\t%ld\n", sz);
  497.     }
  498. }
  499.  
  500. dumpstrs(np)
  501. NODEP np;
  502. {
  503.     TO_DATA;
  504. more:
  505.     if (np == NULL)
  506.         return;
  507.     fprintf(output, "L%d:", (int)np->g_offs);
  508.     out_scon(np);
  509.     np = np->n_next;
  510.     goto more;
  511. }
  512.  
  513. int see_esc;
  514.  
  515. out_scon(np)
  516. NODEP np;
  517. {
  518.     int len = 0;
  519.  
  520.     if (np == NULL)
  521.         return 0;
  522.     see_esc = 0;
  523. more:
  524.     if (np->n_name[0]) {
  525.         fprintf(output, "\t.dc.b\t");
  526.         len += out_str(np->n_name);
  527.         putc('\n', output);
  528.     }
  529.     np = np->n_nmx;
  530.     if (np)
  531.         goto more;
  532.  
  533.     fprintf(output, "\t.dc.b\t0\n");
  534.     len++;
  535.     dat_size += len;
  536.     return len;
  537. }
  538.  
  539. out_str(s)
  540. char *s;
  541. {
  542.     int len;
  543.     register c;
  544.  
  545.     len = 0;
  546.     for ( ; c = *s; s++) {
  547.         if (see_esc) {    /* allow null */
  548.             c--;
  549.             see_esc = 0;
  550.         } else if (c == 1) {
  551.             see_esc = 1;
  552.             continue;
  553.         }
  554.         if (len) {
  555.             if ((len & 15) == 0)
  556.                 fprintf(output, "\n\t.dc.b\t");
  557.             else
  558.                 putc(',', output);
  559.         }
  560.         out_1c(c);
  561.         len++;
  562.     }
  563.     return len;
  564. }
  565.  
  566. out_asm(np)
  567. NODEP np;
  568. {
  569.     putc('\t', output);
  570. more:
  571.     fprintf(output, "%s", np->n_name);    /* no \0 or \1 please! */
  572.     np = np->n_nmx;
  573.     if (np)
  574.         goto more;
  575.     putc('\n', output);
  576. }
  577.  
  578. und_nnm(np)
  579. NODEP np;
  580. {
  581.     fputc('_', output);
  582.     fput_nnm(np);
  583. }
  584.  
  585. out_1c(c)
  586. char c;
  587. {
  588.     fprintf(output, "$%x", c & 0xff);
  589. }
  590.  
  591. outcode(np)
  592. register NODEP np;
  593. {
  594.     NODEP tp;
  595.  
  596.     if (np == NULL) return;
  597.  
  598.     switch (np->g_type) {
  599.     case EV_NONE:
  600.         break;
  601.     case EV_RL:
  602.         outcode(np->n_right);
  603.         outsub(np->g_betw, np);
  604.         /* fall through */
  605.     case EV_LEFT:
  606.         outcode(np->n_left);
  607.         break;
  608.     case EV_LR:
  609.     case EV_LRSEP:
  610.         outcode(np->n_left);
  611.         outsub(np->g_betw, np);
  612.         /* fall through */
  613.     case EV_RIGHT:
  614.         outcode(np->n_right);
  615.         break;
  616.     default:
  617.         printf("bad eval %d ", np->g_type);
  618.     }
  619.     if (np->n_flags & N_COPYT)    /* g_code is a char * */
  620.         outsub(np->g_code, np);
  621.     else                /* g_code is a list of nodes */
  622.         for (tp=np->g_code; tp != NULL; tp = tp->g_code)
  623.             outsub(tp->n_name, np);
  624. }
  625.  
  626. outsub(cp, np)
  627. register char *cp;
  628. register NODEP np;
  629. {
  630.     register char c;
  631.  
  632.     if (cp == NULL) return;
  633.     while (c = *cp++)
  634.         if (c == '<')
  635.             out_let(*cp++, np->n_left);
  636.         else if (c == '>')
  637.             out_let(*cp++, np->n_right);
  638.         else if (c == '\'') {
  639.             c = *cp++;
  640.             fputc(c, output);
  641.         } else if (c == 'L')
  642.             seelab(*cp++, np);
  643.         else if (c == 'R')
  644.             seereg(np, *cp++);
  645.         else if (c >= 'A' && c <= 'Z') {
  646.             out_let(c, np);
  647.         } else
  648.             fputc(c, output);
  649. }
  650.  
  651. seereg(np, c)
  652. NODEP np;
  653. {
  654.     int i;
  655.  
  656.     switch (c) {
  657.     case '0':    i = np->g_rno;  break;
  658.     case '1':    i = np->g_r1;   break;
  659.     case '2':    i = np->g_r2;   break;
  660.     }
  661.     fprintf(output, regnm(i));    
  662. }
  663.  
  664. out_let(c, np)
  665. register NODEP np;
  666. {
  667.     int i;
  668.  
  669.     switch (c) {
  670.     case 'A':
  671.         if (np->g_flags & IMMEDID)
  672.             fputc('#', output);
  673.         out_a(np, output);
  674.         break;
  675.     case 'E':
  676.     case 'F':    /* branch if false */
  677.         i = cctok(np);
  678.         i = (i&1) ? i+1 : i-1;    /* reverse truth */
  679.         if (c == 'F')
  680.             out_bnol(i);
  681.         else
  682.             out_snol(i);
  683.         break;
  684.     case 'H':    /* last a reg (for struct assign) */
  685.         fprintf(output, regnm(ARV_START-1));
  686.         break;
  687.     case 'K':
  688.         fprintf(output, "%ld", np->g_bsize);
  689.         break;
  690.     case 'N':
  691.         fprintf(output, "%s", np->n_name);
  692.         break;
  693.     case 'O':
  694.         fprintf(output, "%ld", np->g_offs);
  695.         break;
  696.     case 'Q':
  697.         if (np->g_flags & IMMEDID) {
  698.             warn("constant test expr");
  699.             if (np->g_token == ICON && np->g_offs == 0)
  700.                 fprintf(output, "\tor\t#$FF,ccr\n");
  701.             else
  702.                 fprintf(output, "\tand\t#0,ccr\n");
  703.             return;
  704.         }
  705.         fprintf(output, "\t%s.%c\t", isareg(np) ? "cmp" : "tst",
  706.             tlen(np->g_sz));
  707.         if (isareg(np))
  708.             fprintf(output, "#0,");
  709.         out_let('A', np);
  710.         fputc('\n', output);
  711.         break;
  712.     case 'S':
  713.         fputc(tlen(np->g_sz), output);
  714.         break;
  715.     case 'T':    /* branch if true */
  716.         out_bnol(cctok(np));
  717.         break;
  718.     case 'U':
  719.         fputc(np->g_ty == ET_U ? 'u' : 's', output);
  720.         break;
  721.     case 'W':    /* field width 1's */
  722.         fprintf(output, "$%x", ones(np->g_fldw));
  723.         break;
  724.     case 'X':    /* ~(W << offset) */
  725.         fprintf(output, "$%x", (unsigned short)
  726.                 (~(ones(np->g_fldw)<<np->g_fldo)));
  727.         break;
  728.     case 'Y':    /* field offset */
  729.         fprintf(output, "%d", np->g_fldo);
  730.         break;
  731.     case 'Z':    /* field offset - 8 */
  732.         fprintf(output, "%d", np->g_fldo - 8);
  733.         break;
  734.     default:
  735.         printf("bad out_let %c ", c);
  736.     }
  737. }
  738.  
  739. out_a(np, fd)
  740. register NODEP np;
  741. FILE *fd;
  742. {
  743.     int offs = np->g_offs;
  744.  
  745.     switch (np->g_token) {
  746.     case ICON:
  747.         fprintf(fd, "%ld", np->g_offs);
  748.         break;
  749.     case FCON:
  750.         /* works for ALCYON C */
  751.         /* otherwise depends on floating internal format */
  752.         fprintf(fd, "$%lx", np->g_offs);
  753.         break;
  754.     case ONAME:
  755.         while (np->g_flags & (CHILDNM|RCHILDNM)) {
  756.             np = (np->g_flags & CHILDNM) ? 
  757.                 np->n_left : np->n_right;
  758.         }
  759.         qput_nnm(np, fd);
  760.         if (offs)
  761.             fprintf(fd, offs > 0 ? "+%d" : "%d", offs);
  762.         break;
  763.     case PUSHER:
  764.         fprintf(fd, "(sp)+");
  765.         break;
  766.     case OREG:
  767.         if (offs)
  768.             fprintf(fd, "%d", offs);
  769.         fprintf(fd, "(%s)", regnm(np->g_rno));
  770.         break;
  771.     case REGVAR:
  772.         fprintf(fd, regnm(np->g_rno));
  773.         break;
  774.     case ',':
  775.         fputc(',', fd);        /* for debug */
  776.         break;
  777.     default:
  778.         if (np->g_token >= BR_TOK) {
  779.             fprintf(fd, "B_%s", bnm[np->g_token - BR_TOK]);
  780.             break;
  781.         }
  782.         printf("? tok %d ", np->g_token);
  783.     }
  784. }
  785.  
  786. seelab(c, np)
  787. char c;
  788. NODEP np;
  789. {
  790.     c -= '1';
  791.     fprintf(output, "L%d", (int)np->g_bsize+c);
  792. }
  793.  
  794. ones(n)
  795. {
  796.     return (1 << n) - 1;
  797. }
  798.     
  799.