home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume26 / pico / part01 / sparcgen.c < prev   
Encoding:
C/C++ Source or Header  |  1991-12-14  |  10.5 KB  |  534 lines

  1. #include <sys/exec.h>
  2. #include <unistd.h>
  3. #include <string.h>
  4. #include "pico.h"
  5.  
  6. typedef unsigned long Inst;
  7.  
  8. static void gen(Tree *t);
  9. static void binop(Tree *t, int s1, int s2, int d);
  10. static void binconst(Tree *t, int s1, int s2, int d);
  11. static void dodump(Inst *, int);
  12. static void clearregs(void);
  13. static void freereg(int);
  14. static int findreg(void);
  15. static int mul(int,int), div(int,int), mod(int,int);
  16.  
  17. static Inst *code;
  18. static ccset, boolean, last = 18, regs[6], spp, sppmax, result;
  19.  
  20. #define zero    0
  21. #define tmp    1
  22. #define base    24    /* first arg */
  23. #define offset    25    /* etc. */
  24. #define a_mul    26
  25. #define a_div    27
  26. #define a_mod    28
  27. #define rx    16
  28. #define ry    17
  29. #define sp    14
  30. #define o0    8    /* first arg out */
  31. #define o1    9
  32.  
  33. #define OP(rd,op,rs,i,r_or_d)    ((2<<30)|(rd<<25)|(op<<19)|(rs<<14)|(i<<13)|(r_or_d&017777))
  34. #define MOP(rd,op,rs,i,r_or_d)    ((3<<30)|(rd<<25)|(op<<19)|(rs<<14)|(i<<13)|(r_or_d&017777))
  35. #define SETHI(rd,op,imm)    ((rd<<25)|(op<<22)|(imm&017777777))
  36.  
  37. #define _ADD(a,b,c)    *code++ = OP(c,000,a,0,b)
  38. #define _ADDcc(a,b,c)    *code++ = OP(c,020,a,0,b)
  39. #define _SUB(a,b,c)    *code++ = OP(c,004,a,0,b)
  40. #define _SUBcc(a,b,c)    *code++ = OP(c,024,a,0,b)
  41. #define _XOR(a,b,c)    *code++ = OP(c,003,a,0,b)
  42. #define _XORcc(a,b,c)    *code++ = OP(c,023,a,0,b)
  43. #define _OR(a,b,c)    *code++ = OP(c,002,a,0,b)
  44. #define _ORcc(a,b,c)    *code++ = OP(c,022,a,0,b)
  45. #define _AND(a,b,c)    *code++ = OP(c,001,a,0,b)
  46. #define _ANDcc(a,b,c)    *code++ = OP(c,021,a,0,b)
  47. #define _NOR(a,b,c)    *code++ = OP(c,006,a,0,b)
  48. #define _XORI(a,b,c)    *code++ = OP(c,003,a,1,b)
  49. #define _XORIcc(a,b,c)    *code++ = OP(c,023,a,1,b)
  50. #define _ORI(a,b,c)    *code++ = OP(c,002,a,1,b)
  51. #define _ORIcc(a,b,c)    *code++ = OP(c,022,a,1,b)
  52. #define _ADDI(a,b,c)    *code++ = OP(c,000,a,1,b)
  53. #define _ADDIcc(a,b,c)    *code++ = OP(c,020,a,1,b)
  54. #define _ANDI(a,b,c)    *code++ = OP(c,001,a,1,b)
  55. #define _ANDIcc(a,b,c)    *code++ = OP(c,021,a,1,b)
  56. #define _LBU(a,b,c)    *code++ = MOP(a,001,b,0,c)
  57. #define _LBIU(a,b,c)    *code++ = MOP(a,001,b,1,c)
  58. #define _SB(a,b,c)    *code++ = MOP(a,005,b,0,c)
  59. #define _SBI(a,b,c)    *code++ = MOP(a,005,b,1,c)
  60. #define _LW(a,b,c)    *code++ = MOP(a,000,b,0,c)
  61. #define _LWI(a,b,c)    *code++ = MOP(a,000,b,1,c)
  62. #define _SW(a,b,c)    *code++ = MOP(a,004,b,0,c)
  63. #define _SWI(a,b,c)    *code++ = MOP(a,004,b,1,c)
  64. #define _SETHI(a,b)    *code++ = SETHI(a,04,b>>10)
  65. #define _SLL(a,b,c)    *code++ = OP(c,045,a,0,b)
  66. #define _SRL(a,b,c)    *code++ = OP(c,046,a,0,b)
  67. #define _SLLI(a,b,c)    *code++ = OP(c,045,a,1,b)
  68. #define _SRLI(a,b,c)    *code++ = OP(c,046,a,1,b)
  69. #define _CMP(a,b)    *code++ = OP(zero,024,a,0,b)    /* _SUBcc(a,b,zero); */
  70. #define _CMPI(a,b)    *code++ = OP(zero,024,a,1,b)    /* _SUBIcc(a,b,zero); */
  71. #define _B(cond,disp)          SETHI(cond,02,disp)
  72. #define ALWAYS    010
  73. #define EQ    001
  74. #define NE    011
  75. #define GE    013
  76. #define LE    002
  77. #define GT    012
  78. #define LT    003
  79. #define _JAL(a)        *code++ = OP(15,070,a,0,zero)
  80. #define _SAVE(a)    *code++ = OP(sp,074,sp,1,a)
  81. #define _RET        *code++ = 0x81c7e008        /* jmpl        %o7+8,%g0    */
  82. #define _RESTORE    *code++ = 0x81e80000        /* restore     %g0,%g0,%g0    */
  83. #define _NOP        *code++ = SETHI(zero,04,0)
  84.  
  85. #define _PUSH(a) {\
  86.     _SW(a,sp,spp);\
  87.     spp += 4;\
  88.     if (spp > sppmax)\
  89.         sppmax = spp;\
  90. }
  91.  
  92. #define _POP(a) {\
  93.     spp -= 4;\
  94.     _LW(a,sp,spp);\
  95. }
  96.  
  97. static void loadimm(int i, int j) {
  98.     if (j > 0x1777 || j < 0) {
  99.         _SETHI(i,j);
  100.         _ORIcc(i,(j&01777),i);
  101.     } else
  102.         _ORIcc(zero,j,i);
  103. }
  104.  
  105. extern void compile(Tree *t) {
  106.     Inst prog[1024], *remem1, *remem2;
  107.     void (*progp)() = (void (*)()) prog;
  108.     code = prog;
  109.     clearregs();
  110.     last = findreg();
  111.     code = prog;
  112.     _SAVE(0); /* value is or'ed in later */
  113.     loadimm(ry,DEF_Y-1);
  114.     remem1 = code;
  115.     loadimm(rx,DEF_X-1);
  116.     remem2 = code;
  117.     gen(t);
  118.     _SB(result,base,offset);
  119.     _ADDI(offset,-1,offset);
  120.     _CMP(rx,zero);
  121.     *code = _B(NE,remem2-code); code++;
  122.     _ADDI(rx,-1,rx);
  123.     _CMP(ry,zero);
  124.     *code = _B(NE,remem1-code); code++;
  125.     _ADDI(ry,-1,ry);
  126.     _RET;
  127.     _RESTORE;
  128.     *prog |= (-(sppmax+80))&017777;
  129.     dodump(prog, (code - prog) * sizeof (Inst));
  130.     progp(buf[0].data, (DEF_X*DEF_Y) - 1, mul, div, mod);
  131. }
  132.  
  133. static int mul(int a, int b) {
  134.     return a*b;
  135. }
  136.  
  137. static int div(int a, int b) {
  138.     return a/b;
  139. }
  140.  
  141. static int mod(int a, int b) {
  142.     return a%b;
  143. }
  144.  
  145. static void gen(Tree *t) {
  146.     Inst *remem;
  147.     int i, saved, b1, b2, c1, c2;
  148.     switch (t->t) {
  149.     case Num:
  150.         if (t->i == 0) {
  151.             result = zero;
  152.             ccset = 0;
  153.             boolean = 1;
  154.         } else {
  155.             loadimm(result = last, t->i);
  156.             boolean = !(t->i & ~1);
  157.             ccset = 1;
  158.         }
  159.         break;
  160.     case Xcoord:
  161.         result = rx;
  162.         boolean = 0;
  163.         ccset = 0;
  164.         break;
  165.     case Ycoord:
  166.         result = ry;
  167.         boolean = 0;
  168.         ccset = 0;
  169.         break;
  170.     case Bang:
  171.         gen(t->kids[0]);
  172.         if (!ccset)
  173.             _CMP(result,zero);
  174.         *code++ = _B(EQ,3);
  175.         _ADDIcc(zero,1,last);
  176.         _ADDIcc(zero,0,last);
  177.         result = last;
  178.         boolean = 1;
  179.         ccset = 1;
  180.         break;
  181.     case Not:
  182.         gen(t->kids[0]);
  183.         _XORIcc(result,-1,last);
  184.         result = last;
  185.         boolean = 0;
  186.         ccset = 1;
  187.         break;
  188.     case Neg:
  189.         gen(t->kids[0]);
  190.         _SUBcc(zero,result,last);
  191.         result = last;
  192.         boolean = 0;
  193.         ccset = 1;
  194.         break;
  195.     case Cond:
  196.         gen(t->kids[0]);        /* test */
  197.         if (!ccset)
  198.             _CMP(result,zero);
  199.         remem = code;
  200.         *code++ = _B(EQ,0);
  201.         _NOP;
  202.         gen(t->kids[1]);        /* iftrue */
  203.         b1 = boolean;
  204.         c1 = ccset;
  205.         if (result != last)
  206.             _ADD(result,zero,last);
  207.         *remem |= code - remem + 1;
  208.         remem = code - 1;
  209.         *code = code[-1];
  210.         code[-1] = _B(ALWAYS,0);    /* fill delay slot */
  211.         code++;
  212.         gen(t->kids[2]);        /* iffalse */
  213.         b2 = boolean;
  214.         c2 = ccset;
  215.         if (result != last)
  216.             _ADD(result,zero,last);
  217.         result = last;
  218.         boolean = (b1 & b2);
  219.         ccset = (c1 & c2);
  220.         *remem |= code - remem;
  221.         break;
  222.     case Andalso:
  223.     case Orelse:
  224.         gen(t->kids[0]);
  225.         b1 = boolean;
  226.         if (result != last)
  227.             _ADDcc(result,zero,last);
  228.         else if (!ccset)
  229.             _CMP(result,zero);
  230.         saved = last;
  231.         remem = code;
  232.         if (t->t == Andalso)
  233.             *code++ = _B(EQ,0);
  234.         else
  235.             *code++ = _B(NE,0);
  236.         _NOP;
  237.         gen(t->kids[1]);
  238.         b2 = boolean;
  239.         if (result != saved) {
  240.             _ADDcc(result,zero,saved);
  241.             ccset = 1;
  242.         }
  243.         result = saved;
  244.         *remem |= code - remem;
  245.         if (!(b1&b2)) {        /* "normalize" expr to {0,1} */
  246.             if (!ccset)
  247.                 _CMP(result,0);
  248.             *code++ = _B(NE,3);
  249.             _ADDIcc(zero,0,result);
  250.             _ADDIcc(zero,1,result);
  251.             ccset = 1;
  252.         }
  253.         boolean = 1;
  254.         break;
  255.     case Coordpair:
  256.         if (t->i > nfiles || t->i < 0)
  257.             error("no such buffer");
  258.         if (t->kids[0] != NULL) {
  259.             gen(t->kids[0]);
  260.             i = last;
  261.         } else
  262.             i = offset;
  263.         loadimm(tmp,(int)buf[t->i].data);
  264.         _LBU(last,tmp,i);
  265.         result = last;
  266.         ccset = 0;
  267.         boolean = 0;
  268.         break;
  269.     default:
  270.         gen(t->kids[0]);
  271.         saved = result;
  272.         if (((Tree *)t->kids[1])->t == Num && (i = ((Tree *)t->kids[1])->i) < 4096 && i > -4096) {
  273.             binconst(t,result,i,last);
  274.         } else {
  275.             if (saved != rx && saved != ry && (last = findreg()) == -1) {
  276.                 last = saved;
  277.                 saved = -1;
  278.                 _PUSH(last);
  279.             }
  280.             gen(t->kids[1]);
  281.             if (saved == -1) {
  282.                 _POP(tmp);
  283.                 binop(t,tmp,result,last);
  284.             } else {
  285.                 binop(t,saved,result,last);
  286.                 if (saved != rx && saved != ry)
  287.                     freereg(saved);
  288.             }
  289.         }
  290.         result = last;
  291.     }
  292. }
  293.  
  294. static void binop(Tree *t, int s1, int s2, int d) {
  295.     boolean = 0;
  296.     ccset = 1;
  297.     switch (t->t) {
  298.     default:
  299.         error("not a binop in binop!");
  300.     case Add:
  301.         _ADDcc(s1,s2,d);
  302.         break;
  303.     case Sub:
  304.         _SUBcc(s1,s2,d);
  305.         break;
  306.     case Mult:
  307.         _ADD(zero,s1,o0);
  308.         _JAL(a_mul);
  309.         _ADD(zero,s2,o1);
  310.         _ADDcc(zero,o0,d);
  311.         break;
  312.     case Div:
  313.         _ADD(zero,s1,o0);
  314.         _JAL(a_div);
  315.         _ADD(zero,s2,o1);
  316.         _ADDcc(zero,o0,d);
  317.         break;
  318.     case Mod:
  319.         _ADD(zero,s1,o0);
  320.         _JAL(a_mod);
  321.         _ADD(zero,s2,o1);
  322.         _ADDcc(zero,o0,d);
  323.         break;
  324.     case Gt:
  325.         _CMP(s1,s2);
  326.         *code++ = _B(GT,3);
  327.         _ADDIcc(zero,0,d);
  328.         _ADDIcc(zero,1,d);
  329.         boolean = 1;
  330.         break;
  331.     case Lt:
  332.         _CMP(s1,s2);
  333.         *code++ = _B(LT,3);
  334.         _ADDIcc(zero,0,d);
  335.         _ADDIcc(zero,1,d);
  336.         boolean = 1;
  337.         break;
  338.     case Ge:
  339.         _CMP(s1,s2);
  340.         *code++ = _B(GE,3);
  341.         _ADDIcc(zero,0,d);
  342.         _ADDIcc(zero,1,d);
  343.         boolean = 1;
  344.         break;
  345.     case Le:
  346.         _CMP(s1,s2);
  347.         *code++ = _B(LE,3);
  348.         _ADDIcc(zero,0,d);
  349.         _ADDIcc(zero,1,d);
  350.         boolean = 1;
  351.         break;
  352.     case Eq:
  353.         _CMP(s1,s2);
  354.         *code++ = _B(EQ,3);
  355.         _ADDIcc(zero,0,d);
  356.         _ADDIcc(zero,1,d);
  357.         boolean = 1;
  358.         break;
  359.     case Ne:
  360.         _CMP(s1,s2);
  361.         *code++ = _B(NE,3);
  362.         _ADDIcc(zero,0,d);
  363.         _ADDIcc(zero,1,d);
  364.         boolean = 1;
  365.         break;
  366.     case Xor:
  367.         _XORcc(s1,s2,d);
  368.         break;
  369.     case And:
  370.         _ANDcc(s1,s2,d);
  371.         break;
  372.     case Or:
  373.         _ORcc(s1,s2,d);
  374.         break;
  375.     case Ll:
  376.         _SLL(s1,s2,d);
  377.         ccset = 0;
  378.         break;
  379.     case Rr:
  380.         _SRL(s1,s2,d);
  381.         ccset = 0;
  382.         break;
  383.     }
  384. }
  385.  
  386. static void binconst(Tree *t, int s1, int s2, int d) {
  387.     int shift;
  388.     boolean = 0;
  389.     ccset = 1;
  390.     switch (t->t) {
  391.     default:
  392.         error("not a binop in binconst!");
  393.     case Add:
  394.         _ADDIcc(s1,s2,d);
  395.         break;
  396.     case Sub:
  397.         _ADDIcc(s1,-s2,d);
  398.         break;
  399.     case Mult:
  400.     case Div:
  401.         if (s2 < 0 || s2 & (s2 - 1) != 0) {
  402.             loadimm(s2,o1);
  403.             _JAL(((t->t == Mult) ? a_mul : a_div));
  404.             _ADD(zero,s1,o0);
  405.             _ADDcc(zero,o0,d);
  406.         } else {
  407.             for (shift = 0; s2 != 0; shift++, s2 >>= 1)
  408.                 ;
  409.             if (shift == 0) {
  410.                 if (t->t == Mult)
  411.                     loadimm(d,0);
  412.                 else
  413.                     error("division by zero");
  414.                 return;
  415.             } else if (t->t == Mult) {
  416.                 _SLLI(s1,--shift,d);
  417.             } else {
  418.                 _SRLI(s1,--shift,d);
  419.             }
  420.             ccset = 0;
  421.         }
  422.         break;
  423.     case Mod:
  424.         loadimm(s2,o1);
  425.         _JAL(a_mod);
  426.         _ADD(zero,s1,o0);
  427.         _ADDcc(zero,o0,d);
  428.         break;
  429.     case Gt:
  430.         _CMPI(s1,s2);
  431.         *code++ = _B(GT,3);
  432.         _ADDIcc(zero,0,d);
  433.         _ADDIcc(zero,1,d);
  434.         boolean = 1;
  435.         break;
  436.     case Lt:
  437.         _CMPI(s1,s2);
  438.         *code++ = _B(LT,3);
  439.         _ADDIcc(zero,0,d);
  440.         _ADDIcc(zero,1,d);
  441.         boolean = 1;
  442.         break;
  443.     case Ge:
  444.         _CMPI(s1,s2);
  445.         *code++ = _B(GE,3);
  446.         _ADDIcc(zero,0,d);
  447.         _ADDIcc(zero,1,d);
  448.         boolean = 1;
  449.         break;
  450.     case Le:
  451.         _CMPI(s1,s2);
  452.         *code++ = _B(LE,3);
  453.         _ADDIcc(zero,0,d);
  454.         _ADDIcc(zero,1,d);
  455.         boolean = 1;
  456.         break;
  457.     case Eq:
  458.         _CMPI(s1,s2);
  459.         *code++ = _B(EQ,3);
  460.         _ADDIcc(zero,0,d);
  461.         _ADDIcc(zero,1,d);
  462.         boolean = 1;
  463.         break;
  464.     case Ne:
  465.         _CMPI(s1,s2);
  466.         *code++ = _B(NE,3);
  467.         _ADDIcc(zero,0,d);
  468.         _ADDIcc(zero,1,d);
  469.         boolean = 1;
  470.         break;
  471.     case Xor:
  472.         _XORIcc(s1,s2,d);
  473.         break;
  474.     case And:
  475.         _ANDIcc(s1,s2,d);
  476.         break;
  477.     case Or:
  478.         _ORIcc(s1,s2,d);
  479.         break;
  480.     case Ll:
  481.         _SLLI(s1,s2,d);
  482.         ccset = 0;
  483.         break;
  484.     case Rr:
  485.         _SRLI(s1,s2,d);
  486.         ccset = 0;
  487.         break;
  488.     }
  489. }
  490.  
  491. static void dodump(Inst *prog, int size) {
  492.     if (debug) {
  493.         int fd = creat("pico.out", 0644);
  494.         struct exec exec;
  495.         exec.a_machtype = M_SPARC;
  496.         exec.a_magic    = OMAGIC;
  497.         exec.a_text    = size;
  498.         exec.a_data    = 0;
  499.         exec.a_bss    = 0;
  500.         exec.a_syms    = 0;
  501.         exec.a_entry    = 0;
  502.         exec.a_trsize    = 0;
  503.         exec.a_drsize    = 0;
  504.         if (fd < 0) {
  505.             perror("pico.out");
  506.             exit(1);
  507.         }
  508.         write(fd, &exec, sizeof exec);
  509.         write(fd, prog, size);
  510.         close(fd);
  511.     }
  512. }
  513.  
  514. static void clearregs() {
  515.     int i;
  516.     for (i = 0; i < 6; i++)
  517.         regs[i] = 0;
  518. }
  519.  
  520. static void freereg(int i) {
  521.     regs[i-18] = 0;
  522. }
  523.  
  524. static int findreg() {
  525.     int i;
  526.     for (i = 0; i < 6; i++)
  527.         if (regs[i] == 0)
  528.             break;
  529.     if (i == 6)
  530.         return -1;
  531.     regs[i] = 1;
  532.     return i+18;
  533. }
  534.