home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume26 / pico / part01 / mipsgen.c < prev    next >
C/C++ Source or Header  |  1991-12-14  |  9KB  |  471 lines

  1. #include <sys/cachectl.h>
  2. #include <a.out.h>
  3. #include <unistd.h>
  4. #include <string.h>
  5. #include "pico.h"
  6.  
  7. typedef unsigned long Inst;
  8.  
  9. static void gen(Tree *t);
  10. static void binop(Tree *t, int s1, int s2, int d);
  11. static void binconst(Tree *t, int s1, int s2, int d);
  12. static void dodump(Inst *, int);
  13. static void clearregs(void);
  14. static void freereg(int);
  15. static int findreg(void);
  16.  
  17. static Inst *code;
  18. static boolean, last = 8, regs[8], spp, sppmax, result;
  19.  
  20. #define zero    0
  21. #define tmp    1
  22. #define base    4    /* first arg */
  23. #define offset    5    /* second arg */
  24. #define rx    16    /* first saved reg */
  25. #define ry    17
  26. #define sp    29
  27. #define ra    31
  28.  
  29. #define RTYPE(a,b,c,d)    (d|(c<<11)|(b<<16)|(a<<21))
  30. #define STYPE(a,b,c,d)    (d|(c<<11)|(b<<6)|(a<<16))
  31. #define ITYPE(a,b,c,d)    ((d<<26)|(a<<21)|(b&0xffff)|(c<<16))
  32.  
  33. #define _ADDU(a,b,c)    *code++ = RTYPE(a,b,c,041)
  34. #define _SUBU(a,b,c)    *code++ = RTYPE(a,b,c,043)
  35. #define _MULTU(a,b)    *code++ = RTYPE(a,b,0,031)
  36. #define _DIVU(a,b)    *code++ = RTYPE(a,b,0,033)
  37. #define _MFLO(a)    *code++ = RTYPE(0,0,a,022)
  38. #define _MFHI(a)    *code++ = RTYPE(0,0,a,020)
  39. #define _SLTU(a,b,c)    *code++ = RTYPE(a,b,c,053)
  40. #define _XOR(a,b,c)    *code++ = RTYPE(a,b,c,046)
  41. #define _OR(a,b,c)    *code++ = RTYPE(a,b,c,045)
  42. #define _NOR(a,b,c)    *code++ = RTYPE(a,b,c,047)
  43. #define _AND(a,b,c)    *code++ = RTYPE(a,b,c,044)
  44. #define _ANDI(a,b,c)    *code++ = ITYPE(a,b,c,014)
  45. #define _XORI(a,b,c)    *code++ = ITYPE(a,b,c,016)
  46. #define _ORI(a,b,c)    *code++ = ITYPE(a,b,c,015)
  47. #define _ADDIU(a,b,c)    *code++ = ITYPE(a,b,c,011)
  48. #define _SLTIU(a,b,c)    *code++ = ITYPE(a,b,c,013)
  49. #define _LBU(a,b,c)    *code++ = ITYPE(b,c,a,044)
  50. #define _SB(a,b,c)    *code++ = ITYPE(b,c,a,050)
  51. #define _LW(a,b,c)    *code++ = ITYPE(b,c,a,043)
  52. #define _SW(a,b,c)    *code++ = ITYPE(b,c,a,053)
  53. #define _LUI(a,b)    *code++ = ITYPE(0,b,a,017)
  54. #define _BNE(a,b,c)          ITYPE(b,c,a,005)
  55. #define _BEQ(a,b,c)          ITYPE(b,c,a,004)
  56. #define _JR(a)        *code++ = RTYPE(a,0,0,010)
  57. #define _SLL(a,b,c)    *code++ = STYPE(a,b,c,000)
  58. #define _SRL(a,b,c)    *code++ = STYPE(a,b,c,002)
  59. #define _SRLV(a,b,c)    *code++ = RTYPE(a,b,c,006)
  60. #define _SLLV(a,b,c)    *code++ = RTYPE(b,a,c,004)
  61. #define _SRLV(a,b,c)    *code++ = RTYPE(a,b,c,006)
  62. #define _NOP        *code++ = 0x0
  63.  
  64. #define _PUSH(a) {\
  65.     _SW(a,sp,spp);\
  66.     spp += 4;\
  67.     if (spp > sppmax)\
  68.         sppmax = spp;\
  69. }
  70.  
  71. #define _POP(a) {\
  72.     spp -= 4;\
  73.     _LW(a,sp,spp);\
  74. }
  75.  
  76. static void loadimm(int i, int j) {
  77.     if (j < 0 && j >= -32768) {
  78.         _ADDIU(zero,j,i);
  79.     } else if ((Inst) j > 65535) {
  80.         Inst k = (Inst) j >> 16;
  81.         Inst l = (Inst) j & 65535;
  82.         _LUI(i,k);
  83.         if (l != 0)
  84.             _ORI(i,l,i);
  85.     } else {
  86.         _ORI(zero,((Inst)j),i);
  87.     }
  88. }
  89.  
  90. extern void compile(Tree *t) {
  91.     Inst prog[1024], *remem1, *remem2;
  92.     void (*progp)() = (void (*)()) prog;
  93.     code = prog;
  94.     clearregs();
  95.     last = findreg();
  96.     code = prog;
  97.     _ADDIU(sp,0,sp); /* value is or'ed in later */
  98.     _PUSH(rx);
  99.     _PUSH(ry);
  100.     loadimm(ry,DEF_Y-1);
  101.     remem1 = code;
  102.     loadimm(rx,DEF_X-1);
  103.     remem2 = code;
  104.     gen(t);
  105.     _ADDU(base,offset,tmp);
  106.     _SB(result,tmp,0);
  107.     _ADDIU(offset,-1,offset);
  108.     *code = _BNE(zero,rx,remem2-code-1); code++;
  109.     _ADDIU(rx,-1,rx);
  110.     *code = _BNE(zero,ry,remem1-code-1); code++;
  111.     _ADDIU(ry,-1,ry);
  112.     _POP(ry);
  113.     _POP(rx);
  114.     _JR(ra);
  115.     _ADDIU(sp,sppmax,sp);
  116.     *prog |= (-sppmax)&0xffff;
  117.     dodump(prog, (code - prog) * sizeof (Inst));
  118.     cacheflush(prog, sizeof prog, ICACHE);
  119.     progp(buf[0].data, (DEF_X*DEF_Y) - 1);
  120. }
  121.  
  122. static void gen(Tree *t) {
  123.     Inst *remem;
  124.     int i, saved, b1, b2;
  125.     switch (t->t) {
  126.     case Num:
  127.         if (t->i == 0) {
  128.             result = zero;
  129.             boolean = 1;
  130.         } else {
  131.             loadimm(result = last, t->i);
  132.             boolean = !(t->i & ~1);
  133.         }
  134.         break;
  135.     case Xcoord:
  136.         result = rx;
  137.         boolean = 0;
  138.         break;
  139.     case Ycoord:
  140.         result = ry;
  141.         boolean = 0;
  142.         break;
  143.     case Bang:
  144.         gen(t->kids[0]);
  145.         _SLTIU(result,1,last);
  146.         result = last;
  147.         boolean = 1;
  148.         break;
  149.     case Not:
  150.         gen(t->kids[0]);
  151.         _NOR(result,0,last);
  152.         result = last;
  153.         boolean = 0;
  154.         break;
  155.     case Neg:
  156.         gen(t->kids[0]);
  157.         _SUBU(zero,result,last);
  158.         result = last;
  159.         boolean = 0;
  160.         break;
  161.     case Cond:
  162.         gen(t->kids[0]);        /* test */
  163.         remem = code;
  164.         *code++ = _BEQ(zero,result,0);
  165.         _NOP;
  166.         gen(t->kids[1]);        /* iftrue */
  167.         b1 = boolean;
  168.         if (result != last)
  169.             _ADDU(result,zero,last);
  170.         *remem |= code - remem;
  171.         remem = code - 1;
  172.         *code = code[-1];
  173.         code[-1] = _BEQ(zero,zero,0);    /* fill delay slot */
  174.         code++;
  175.         gen(t->kids[2]);        /* iffalse */
  176.         b2 = boolean;
  177.         if (result != last)
  178.             _ADDU(result,zero,last);
  179.         result = last;
  180.         boolean = (b1 & b2);
  181.         *remem |= code - remem - 1;
  182.         break;
  183.     case Andalso:
  184.     case Orelse:
  185.         gen(t->kids[0]);
  186.         b1 = boolean;
  187.         if (result != last)
  188.             _ADDU(result,zero,last);
  189.         saved = last;
  190.         remem = code;
  191.         if (t->t == Andalso)
  192.             *code++ = _BEQ(zero,last,0);
  193.         else
  194.             *code++ = _BNE(zero,last,0);
  195.         _NOP;
  196.         gen(t->kids[1]);
  197.         b2 = boolean;
  198.         if (result != saved)
  199.             _ADDU(result,zero,saved);
  200.         *remem |= code - remem - 1;
  201.         if (!(b1&b2))
  202.             _SLTU(zero,last,last);        /* "normalize" expr to {0,1} */
  203.         result = saved;
  204.         boolean = 1;
  205.         break;
  206.     case Coordpair:
  207.         if (t->i > nfiles || t->i < 0)
  208.             error("no such buffer");
  209.         if (t->kids[0] != NULL) {
  210.             gen(t->kids[0]);
  211.             i = last;
  212.         } else
  213.             i = offset;
  214.         loadimm(tmp,(int)buf[t->i].data);
  215.         _ADDU(tmp,i,last);
  216.         _LBU(last,last,0);
  217.         _NOP;
  218.         result = last;
  219.         boolean = 0;
  220.         break;
  221.     default:
  222.         gen(t->kids[0]);
  223.         saved = result;
  224.         if (((Tree *)t->kids[1])->t == Num && (i = ((Tree *)t->kids[1])->i) < 32768 && i > -32768) {
  225.             binconst(t,result,i,last);
  226.         } else {
  227.             if (saved != rx && saved != ry && (last = findreg()) == -1) {
  228.                 last = saved;
  229.                 saved = -1;
  230.                 _PUSH(last);
  231.             }
  232.             gen(t->kids[1]);
  233.             if (saved == -1) {
  234.                 _POP(tmp);
  235.                 _NOP;
  236.                 binop(t,tmp,result,last);
  237.             } else {
  238.                 binop(t,saved,result,last);
  239.                 if (saved != rx && saved != ry)
  240.                     freereg(saved);
  241.             }
  242.         }
  243.         result = last;
  244.     }
  245. }
  246.  
  247. static void binop(Tree *t, int s1, int s2, int d) {
  248.     boolean = 0;
  249.     switch (t->t) {
  250.     default:
  251.         error("not a binop in binop!");
  252.     case Add:
  253.         _ADDU(s1,s2,d);
  254.         break;
  255.     case Sub:
  256.         _SUBU(s1,s2,d);
  257.         break;
  258.     case Mult:
  259.         _MULTU(s1,s2);
  260.         _MFLO(d);
  261.         break;
  262.     case Div:
  263.         _DIVU(s1,s2);
  264.         _MFLO(d);
  265.         break;
  266.     case Mod:
  267.         _DIVU(s1,s2);
  268.         _MFHI(d);
  269.         break;
  270.     case Gt:
  271.         _SLTU(s2,s1,d);
  272.         boolean = 1;
  273.         break;
  274.     case Lt:
  275.         _SLTU(s1,s2,d);
  276.         boolean = 1;
  277.         break;
  278.     case Ge:
  279.         _SLTU(s1,s2,d);
  280.         _XORI(d,1,d);
  281.         boolean = 1;
  282.         break;
  283.     case Le:
  284.         _SLTU(s2,s1,d);
  285.         _XORI(d,1,d);
  286.         boolean = 1;
  287.         break;
  288.     case Eq:
  289.         _XOR(s1,s2,d);
  290.         _SLTIU(d,1,d);
  291.         boolean = 1;
  292.         break;
  293.     case Ne:
  294.         _XOR(s1,s2,d);
  295.         _SLTIU(d,0,d);
  296.         boolean = 1;
  297.         break;
  298.     case Xor:
  299.         _XOR(s1,s2,d);
  300.         break;
  301.     case And:
  302.         _AND(s1,s2,d);
  303.         break;
  304.     case Or:
  305.         _OR(s1,s2,d);
  306.         break;
  307.     case Ll:
  308.         _SLLV(s1,s2,d);
  309.         break;
  310.     case Rr:
  311.         _SRLV(s1,s2,d);
  312.         break;
  313.     }
  314. }
  315.  
  316. static void binconst(Tree *t, int s1, int s2, int d) {
  317.     int shift;
  318.     boolean = 0;
  319.     switch (t->t) {
  320.     default:
  321.         error("not a binop in binconst!");
  322.     case Add:
  323.         _ADDIU(s1,s2,d);
  324.         break;
  325.     case Sub:
  326.         _ADDIU(s1,-s2,d);
  327.         break;
  328.     case Mult:
  329.     case Div:
  330.         if (s2 < 0 || s2 & (s2 - 1) != 0) {
  331.             loadimm(tmp,s2);
  332.             if (t->t == Mult)
  333.                 _MULTU(s1,tmp);
  334.             else
  335.                 _DIVU(s1,tmp);
  336.         _MFLO(d);
  337.         } else {
  338.             for (shift = 0; s2 != 0; shift++, s2 >>= 1)
  339.                 ;
  340.             if (shift == 0) {
  341.                 if (t->t == Mult)
  342.                     loadimm(d,0);
  343.                 else
  344.                     error("division by zero");
  345.                 return;
  346.             } else if (t->t == Mult) {
  347.                 _SLL(s1,--shift,d);
  348.             } else {
  349.                 _SRL(s1,--shift,d);
  350.             }
  351.         }
  352.         break;
  353.     case Mod:
  354.         loadimm(tmp,s2);
  355.         _DIVU(s1,tmp);
  356.         _MFHI(d);
  357.         break;
  358.     case Gt:
  359.         if (s2 != 0) {
  360.             loadimm(tmp,s2);
  361.             _SLTU(tmp,s1,d);
  362.         } else
  363.             _SLTU(zero,s1,d);
  364.         boolean = 1;
  365.         break;
  366.     case Lt:
  367.         _SLTIU(s1,s2,d);
  368.         boolean = 1;
  369.         break;
  370.     case Ge:
  371.         _SLTIU(s1,s2,d);
  372.         _XORI(d,1,d);
  373.         boolean = 1;
  374.         break;
  375.     case Le:
  376.         if (s2 != 0) {
  377.             loadimm(tmp,s2);
  378.             _SLTU(tmp,s1,d);
  379.         } else
  380.             _SLTU(zero,s1,d);
  381.         _XORI(d,1,d);
  382.         boolean = 1;
  383.         break;
  384.     case Eq:
  385.         if (s2 != 0) {
  386.             _XORI(s1,s2,d);
  387.             _SLTIU(d,1,d);
  388.         } else
  389.             _SLTIU(s1,1,d);
  390.         boolean = 1;
  391.         break;
  392.     case Ne:
  393.         if (s2 != 0) {
  394.             _XORI(s1,s2,d);
  395.             _SLTIU(d,0,d);
  396.         } else
  397.             _SLTIU(s1,0,d);
  398.         boolean = 1;
  399.         break;
  400.     case Xor:
  401.         _XORI(s1,s2,d);
  402.         break;
  403.     case And:
  404.         _ANDI(s1,s2,d);
  405.         break;
  406.     case Or:
  407.         _ORI(s1,s2,d);
  408.         break;
  409.     case Ll:
  410.         _SLL(s1,s2,d);
  411.         break;
  412.     case Rr:
  413.         _SRL(s1,s2,d);
  414.         break;
  415.     }
  416. }
  417.  
  418. static void dodump(Inst *prog, int size) {
  419.     if (debug) {
  420.         struct filehdr f;
  421.         struct scnhdr s;
  422.         int fd = creat(DUMPFILE, 0644);
  423.         if (fd < 0) {
  424.             perror(DUMPFILE);
  425.             exit(1);
  426.         }
  427.         f.f_magic = MIPSEBMAGIC;
  428.         f.f_nscns = 1;
  429.         f.f_timdat = 0;
  430.         f.f_symptr = 0;
  431.         f.f_nsyms = 0;
  432.         f.f_opthdr = 0;
  433.         f.f_flags = F_RELFLG | F_EXEC | F_LNNO | F_LSYMS | F_MINMAL;
  434.         strcpy(s.s_name, ".text");
  435.         s.s_paddr = 0;
  436.         s.s_vaddr = 0;
  437.         s.s_size = size;
  438.         s.s_scnptr = sizeof s + sizeof f;
  439.         s.s_relptr = 0;
  440.         s.s_lnnoptr = 0;
  441.         s.s_nreloc = 0;
  442.         s.s_nlnno = 0;
  443.         s.s_flags = 0;
  444.         write(fd, &f, sizeof f);
  445.         write(fd, &s, sizeof s);
  446.         write(fd, prog, size);
  447.         close(fd);
  448.     }
  449. }
  450.  
  451. static void clearregs() {
  452.     int i;
  453.     for (i = 0; i < 8; i++)
  454.         regs[i] = 0;
  455. }
  456.  
  457. static void freereg(int i) {
  458.     regs[i-8] = 0;
  459. }
  460.  
  461. static int findreg() {
  462.     int i;
  463.     for (i = 0; i < 8; i++)
  464.         if (regs[i] == 0)
  465.             break;
  466.     if (i == 8)
  467.         return -1;
  468.     regs[i] = 1;
  469.     return i+8;
  470. }
  471.