Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2. ** Small-C Compiler -- Part 4 -- Back End.
  3. ** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix
  4. ** Copyright 1998 H T Walheim
  5. ** All rights reserved.
  6. */
  7. #include <stdio.h>
  8. #include "cc.h"
  9.  
  10. /* #define DISOPT */       /* display optimizations values */
  11.  
  12. /*************************** externals ****************************/
  13.  
  14. extern char
  15.   *cptr, *macn, *litq, *symtab, optimize, ssname[NAMESIZE];
  16.  
  17. extern int
  18.   *stage, litlab, litptr, csp, output, oldseg, usexpr,
  19.   *snext, *stail, *slast;
  20.  
  21.  
  22. /***************** optimizer command definitions ******************/
  23.  
  24.              /*     --      p-codes must not overlap these */
  25. #define any     0x00FF   /* matches any p-code */
  26. #define _pop    0x00FE   /* matches if corresponding POP2 exists */
  27. #define pfree   0x00FD   /* matches if pri register free */
  28. #define sfree   0x00FC   /* matches if sec register free */
  29. #define comm    0x00FB   /* matches if registers are commutative */
  30.  
  31.              /*     --      these digits are reserved for n */
  32. #define go      0x0100   /* go n entries */
  33. #define gc      0x0200   /* get code from n entries away */
  34. #define gv      0x0300   /* get value from n entries away */
  35. #define sum     0x0400   /* add value from nth entry away */
  36. #define neg     0x0500   /* negate the value */
  37. #define ife     0x0600   /* if value == n do commands to next 0 */
  38. #define ifl     0x0700   /* if value <  n do commands to next 0 */
  39. #define swv     0x0800   /* swap value with value n entries away */
  40. #define topop   0x0900   /* moves |code and current value to POP2 */
  41.  
  42. #define p1      0x0001   /* plus 1 */
  43. #define p2      0x0002   /* plus 2 */
  44. #define p3      0x0003   /* plus 3 */
  45. #define p4      0x0004   /* plus 4 */
  46. #define m1      0x00FF   /* minus 1 */
  47. #define m2      0x00FE   /* minus 2 */
  48. #define m3      0x00FD   /* minus 3 */
  49. #define m4      0x00FC   /* minus 4 */
  50.  
  51. #define PRI      0030    /* primary register bits */
  52. #define SEC      0003    /* secondary register bits */
  53. #define USES     0011    /* use register contents */
  54. #define ZAPS     0022    /* zap register contents */
  55. #define PUSHES   0100    /* pushes onto the stack */
  56. #define COMMUTES 0200    /* commutative p-code */
  57.  
  58. /******************** optimizer command lists *********************/
  59.  
  60. int
  61.   seq00[] = {0,ADD12,MOVE21,0,                       /* ADD21 */
  62.              go|p1,ADD21,0},
  63.  
  64.   seq01[] = {0,ADD1n,0,                              /* rINC1 or rDEC1 ? */
  65.              ifl|m2,0,ifl|0,rDEC1,neg,0,ifl|p3,rINC1,0,0},
  66.  
  67.   seq02[] = {0,ADD2n,0,                              /* rINC2 or rDEC2 ? */
  68.              ifl|m2,0,ifl|0,rDEC2,neg,0,ifl|p3,rINC2,0,0},
  69.  
  70.   seq03[] = {0,rDEC1,PUTbp1,rINC1,0,                 /* SUBbpn or DECbp */
  71.              go|p2,ife|p1,DECbp,0,SUBbpn,0},
  72.  
  73.   seq04[] = {0,rDEC1,PUTwp1,rINC1,0,                 /* SUBwpn or DECwp */
  74.              go|p2,ife|p1,DECwp,0,SUBwpn,0},
  75.  
  76.   seq05[] = {0,rDEC1,PUTbm1,rINC1,0,                 /* SUB_m_ COMMAn */
  77.              go|p1,SUB_m_,go|p1,COMMAn,go|m1,0},
  78.  
  79.   seq06[] = {0,rDEC1,PUTwm1,rINC1,0,                 /* SUB_m_ COMMAn */
  80.              go|p1,SUB_m_,go|p1,COMMAn,go|m1,0},
  81.  
  82.   seq07[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETb1p,0,  /* GETw2m GETb1p */
  83.              go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
  84.  
  85.   seq08[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETb1pu,0, /* GETw2m GETb1pu */
  86.              go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
  87.  
  88.   seq09[] = {0,GETw1m,GETw2n,ADD12,MOVE21,GETw1p,0,  /* GETw2m GETw1p */
  89.              go|p4,gv|m3,go|m1,GETw2m,gv|m3,0},
  90.  
  91.   seq10[] = {0,GETw1m,GETw2m,SWAP12,0,               /* GETw2m GETw1m */
  92.              go|p2,GETw1m,gv|m1,go|m1,gv|m1,0},
  93.  
  94.   seq11[] = {0,GETw1m,MOVE21,0,                      /* GETw2m */
  95.              go|p1,GETw2m,gv|m1,0},
  96.  
  97.   seq12[] = {0,GETw1m,PUSH1,pfree,0,                 /* PUSHm */
  98.              go|p1,PUSHm,gv|m1,0},
  99.  
  100.   seq13[] = {0,GETw1n,PUTbm1,pfree,0,                /* PUT_m_ COMMAn */
  101.              PUT_m_,go|p1,COMMAn,go|m1,swv|p1,0},
  102.  
  103.   seq14[] = {0,GETw1n,PUTwm1,pfree,0,                /* PUT_m_ COMMAn */
  104.              PUT_m_,go|p1,COMMAn,go|m1,swv|p1,0},
  105.  
  106.   seq15[] = {0,GETw1p,PUSH1,pfree,0,                 /* PUSHp */
  107.              go|p1,PUSHp,gv|m1,0},
  108.  
  109.   seq16[] = {0,GETw1s,GETw2n,ADD12,MOVE21,0,         /* GETw2s ADD2n */
  110.              go|p3,ADD2n,gv|m2,go|m1,GETw2s,gv|m2,0},
  111.  
  112.   seq17[] = {0,GETw1s,GETw2s,SWAP12,0,               /* GETw2s GETw1s */
  113.              go|p2,GETw1s,gv|m1,go|m1,GETw2s,gv|m1,0},
  114.  
  115.   seq18[] = {0,GETw1s,MOVE21,0,                      /* GETw2s */
  116.              go|p1,GETw2s,gv|m1,0},
  117.  
  118.   seq19[] = {0,GETw2m,GETw1n,SWAP12,SUB12,0,         /* GETw1m SUB1n */
  119.              go|p3,SUB1n,gv|m2,go|m1,GETw1m,gv|m2,0},
  120.  
  121.   seq20[] = {0,GETw2n,ADD12,0,                       /* ADD1n */
  122.              go|p1,ADD1n,gv|m1,0},
  123.  
  124.   seq21[] = {0,GETw2s,GETw1n,SWAP12,SUB12,0,         /* GETw1s SUB1n */
  125.              go|p3,SUB1n,gv|m2,go|m1,GETw1s,gv|m2,0},
  126.  
  127.   seq22[] = {0,rINC1,PUTbm1,rDEC1,0,                 /* ADDm_ COMMAn */
  128.              go|p1,ADDm_,go|p1,COMMAn,go|m1,0},
  129.  
  130.   seq23[] = {0,rINC1,PUTwm1,rDEC1,0,                 /* ADDm_ COMMAn */
  131.              go|p1,ADDm_,go|p1,COMMAn,go|m1,0},
  132.  
  133.   seq24[] = {0,rINC1,PUTbp1,rDEC1,0,                 /* ADDbpn or INCbp */
  134.              go|p2,ife|p1,INCbp,0,ADDbpn,0},
  135.  
  136.   seq25[] = {0,rINC1,PUTwp1,rDEC1,0,                 /* ADDwpn or INCwp */
  137.              go|p2,ife|p1,INCwp,0,ADDwpn,0},
  138.  
  139.   seq26[] = {0,MOVE21,GETw1n,SWAP12,SUB12,0,         /* SUB1n */
  140.              go|p3,SUB1n,gv|m2,0},
  141.  
  142.   seq27[] = {0,MOVE21,GETw1n,comm,0,                 /* GETw2n comm */
  143.              go|p1,GETw2n,0},
  144.  
  145.   seq28[] = {0,POINT1m,GETw2n,ADD12,MOVE21,0,        /* POINT2m_ PLUSn */
  146.              go|p3,PLUSn,gv|m2,go|m1,POINT2m_,gv|m2,0},
  147.  
  148.   seq29[] = {0,POINT1m,MOVE21,pfree,0,               /* POINT2m */
  149.              go|p1,POINT2m,gv|m1,0},
  150.  
  151.   seq30[] = {0,POINT1m,PUSH1,pfree,_pop,0,           /* ... POINT2m */
  152.              topop|POINT2m,go|p2,0},
  153.  
  154.   seq31[] = {0,POINT1s,GETw2n,ADD12,MOVE21,0,        /* POINT2s */
  155.              sum|p1,go|p3,POINT2s,gv|m3,0},
  156.  
  157.   seq32[] = {0,POINT1s,PUSH1,MOVE21,0,               /* POINT2s PUSH2 */
  158.              go|p1,POINT2s,gv|m1,go|p1,PUSH2,go|m1,0},
  159.  
  160.   seq33[] = {0,POINT1s,PUSH1,pfree,_pop,0,           /* ... POINT2s */
  161.              topop|POINT2s,go|p2,0},
  162.  
  163.   seq34[] = {0,POINT1s,MOVE21,0,                     /* POINT2s */
  164.              go|p1,POINT2s,gv|m1,0},
  165.  
  166.   seq35[] = {0,POINT2m,GETb1p,sfree,0,               /* GETb1m */
  167.              go|p1,GETb1m,gv|m1,0},
  168.  
  169.   seq36[] = {0,POINT2m,GETb1pu,sfree,0,              /* GETb1mu */
  170.              go|p1,GETb1mu,gv|m1,0},
  171.  
  172.   seq37[] = {0,POINT2m,GETw1p,sfree,0,               /* GETw1m */
  173.              go|p1,GETw1m,gv|m1,0},
  174.  
  175.   seq38[] = {0,POINT2m_,PLUSn,GETw1p,sfree,0,        /* GETw1m_ PLUSn */
  176.              go|p2,gc|m1,gv|m1,go|m1,GETw1m_,gv|m1,0},
  177.  
  178.   seq39[] = {0,POINT2s,GETb1p,sfree,0,               /* GETb1s */
  179.              sum|p1,go|p1,GETb1s,gv|m1,0},
  180.  
  181.   seq40[] = {0,POINT2s,GETb1pu,sfree,0,              /* GETb1su */
  182.              sum|p1,go|p1,GETb1su,gv|m1,0},
  183.  
  184.   seq41[] = {0,POINT2s,GETw1p,PUSH1,pfree,0,         /* PUSHs */
  185.              sum|p1,go|p2,PUSHs,gv|m2,0},
  186.  
  187.   seq42[] = {0,POINT2s,GETw1p,sfree,0,               /* GETw1s */
  188.              sum|p1,go|p1,GETw1s,gv|m1,0},
  189.  
  190.   seq43[] = {0,PUSH1,any,POP2,0,                     /* MOVE21 any */
  191.              go|p2,gc|m1,gv|m1,go|m1,MOVE21,0},
  192.  
  193.   seq44[] = {0,PUSHm,_pop,0,                         /* ... GETw2m */
  194.              topop|GETw2m,go|p1,0},
  195.  
  196.   seq45[] = {0,PUSHp,any,POP2,0,                     /* GETw2p ... */
  197.              go|p2,gc|m1,gv|m1,go|m1,GETw2p,gv|m1,0},
  198.  
  199.   seq46[] = {0,PUSHs,_pop,0,                         /* ... GETw2s */
  200.              topop|GETw2s,go|p1,0},
  201.  
  202.   seq47[] = {0,SUB1n,0,                              /* rDEC1 or rINC1 ? */
  203.              ifl|m2,0,ifl|0,rINC1,neg,0,ifl|p3,rDEC1,0,0};
  204.  
  205. #define HIGH_SEQ  47
  206. int seq[HIGH_SEQ + 1];  
  207. setseq() {
  208.   seq[ 0] = seq00;  seq[ 1] = seq01;  seq[ 2] = seq02;  seq[ 3] = seq03;
  209.   seq[ 4] = seq04;  seq[ 5] = seq05;  seq[ 6] = seq06;  seq[ 7] = seq07;
  210.   seq[ 8] = seq08;  seq[ 9] = seq09;  seq[10] = seq10;  seq[11] = seq11;
  211.   seq[12] = seq12;  seq[13] = seq13;  seq[14] = seq14;  seq[15] = seq15;
  212.   seq[16] = seq16;  seq[17] = seq17;  seq[18] = seq18;  seq[19] = seq19;
  213.   seq[20] = seq20;  seq[21] = seq21;  seq[22] = seq22;  seq[23] = seq23;
  214.   seq[24] = seq24;  seq[25] = seq25;  seq[26] = seq26;  seq[27] = seq27;
  215.   seq[28] = seq28;  seq[29] = seq29;  seq[30] = seq30;  seq[31] = seq31;
  216.   seq[32] = seq32;  seq[33] = seq33;  seq[34] = seq34;  seq[35] = seq35;
  217.   seq[36] = seq36;  seq[37] = seq37;  seq[38] = seq38;  seq[39] = seq39;
  218.   seq[40] = seq40;  seq[41] = seq41;  seq[42] = seq42;  seq[43] = seq43;
  219.   seq[44] = seq44;  seq[45] = seq45;  seq[46] = seq46;  seq[47] = seq47;
  220.   }
  221.  
  222. /***************** assembly-code strings ******************/
  223.  
  224. int code[PCODES];
  225.  
  226. /*
  227. ** First byte contains flag bits indicating:
  228. **    the value in ax is needed (010) or zapped (020)
  229. **    the value in bx is needed (001) or zapped (002)
  230. */
  231. setcodes() {
  232.   setseq();
  233.   code[ADD12]   = "\211ADD EAX,EBX\15\n";
  234.   code[ADD1n]   = "\010?ADD EAX,<n>\15\n??";
  235.   code[ADD21]   = "\211ADD EBX,EAX\15\n";
  236.   code[ADD2n]   = "\010?ADD EBX,<n>\15\n??";
  237.   code[ADDbpn]  = "\001ADD BYTE [EBX],<n>\15\n";
  238.   code[ADDwpn]  = "\001ADD WORD [EBX],<n>\15\n";
  239.   code[ADDm_]   = "\000ADD <m>";
  240.   code[ADDSP]   = "\000?ADD ESP,<n>\15\n??";
  241.   code[AND12]   = "\211AND EAX,EBX\15\n";
  242.   code[ANEG1]   = "\010NEG EAX\15\n";
  243.   code[ARGCNTn] = "\000?MOV CL,<n>?XOR CL,CL?\15\n";
  244.   code[ASL12]   = "\011MOV ECX,EAX\15\nMOV EAX,EBX\15\nSAL EAX,CL\15\n";
  245.   code[ASR12]   = "\011MOV ECX,EAX\15\nMOV EAX,EBX\15\nSAR EAX,CL\15\n";
  246.   code[CALL1]   = "\010CALL EAX\15\n";
  247.   code[CALLm]   = "\020CALL <m>\15\n";
  248.   code[BYTE_]   = "\000 DB ";
  249.   code[BYTEn]   = "\000 RESB <n>\15\n";
  250.   code[BYTEr0]  = "\000 TIMES <n> DB 0\15\n";
  251.   code[COM1]    = "\010NOT EAX\15\n";
  252.   code[COMMAn]  = "\000,<n>\15\n";
  253.   code[DBL1]    = "\010SHL EAX,1\15\n";
  254.   code[DBL2]    = "\001SHL EBX,1\15\n";
  255.   code[DECbp]   = "\001DEC BYTE [EBX]\15\n";
  256.   code[DECwp]   = "\001DEC WORD [EBX]\15\n";
  257.   code[DIV12]   = "\011CDQ\15\nIDIV EBX\15\n";                 /* see gen() */
  258.   code[DIV12u]  = "\011XOR EDX,EDX\15\nDIV EBX\15\n";            /* see gen() */
  259.  
  260.   code[DWORD_]   = "\000 DD ";
  261.   code[DWORDn]   = "\000 DD <n>\15\n";
  262.   code[DWORDr0]  = "\000 TIMES <n> DD 0\15\n";
  263.  
  264.   code[ENTER]   = "\100PUSH EBP\15\nMOV EBP,ESP\15\n";
  265.   code[EQ10f]   = "\010<g>OR EAX,EAX\15\nJE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
  266.   code[EQ12]    = "\211CALL __eq\15\n";
  267.   code[GE10f]   = "\010<g>OR EAX,EAX\15\nJGE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
  268.   code[GE12]    = "\011CALL __ge\15\n";
  269.   code[GE12u]   = "\011CALL __uge\15\n";
  270.   code[GETb1m]  = "\020MOVSX EAX,BYTE [<m>]\15\n";
  271.   code[GETb1mu] = "\020MOVZX EAX,BYTE [<m>]\15\n";
  272.   code[GETb1p]  = "\021MOVSX EAX,BYTE [EBX?<o>??]\15\n";       /* see gen() */
  273.   code[GETb1pu] = "\021MOVZX EAX,BYTE [EBX?<o>??]\15\n"; /* see gen() */
  274.   code[GETb1s]  = "\020MOVSX EAX,BYTE [EBP<o>]\15\n";
  275.   code[GETb1su] = "\020MOVZX EAX,BYTE [EBP<o>]\15\n";
  276.  
  277.   code[GETd1m]  = "\020MOV EAX,[<m>]\15\n";
  278.   code[GETd1n]  = "\020?MOV EAX,<n>?XOR EAX,EAX?\15\n";
  279.   code[GETd1p]  = "\021MOV EAX, [EBX?<o>??]\15\n";            /* see gen() */
  280.   code[GETd2n]  = "\002?MOV EBX,<n>?XOR EBX,EBX?\15\n";
  281.  
  282.   code[GETw1m]  = "\020MOVSX EAX,WORD [<m>]\15\n";
  283.   code[GETw1m_] = "\020MOVSX EAX,WORD [<m>]";
  284.   code[GETw1n]  = "\020?MOV  EAX,<n>?XOR EAX,EAX?\15\n";
  285.   code[GETw1p]  = "\021MOVSX EAX, WORD [EBX?<o>??]\15\n";            /* see gen() */
  286.   code[GETw1s]  = "\020MOVSX EAX, WORD [EBP<o>]\15\n";
  287.   code[GETw2m]  = "\002MOVSX EBX,WORD <m>\15\n";
  288.   code[GETw2n]  = "\002?MOV EBX,<n>?XOR EBX,EBX?\15\n";
  289.   code[GETw2p]  = "\021MOVSX EBX,WORD [EBX?<o>??]\15\n";
  290.   code[GETw2s]  = "\002MOVSX EBX,WORD [EBP<o>]\15\n";
  291.   code[GT10f]   = "\010<g>OR EAX,EAX\15\nJG _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
  292.   code[GT12]    = "\010CALL __gt\15\n";
  293.   code[GT12u]   = "\011CALL __ugt\15\n";
  294.   code[INCbp]   = "\001INC BYTE [EBX]\15\n";
  295.   code[INCwp]   = "\001INC WORD [EBX]\15\n";
  296.   code[WORD_]   = "\000 DW ";
  297.   code[WORDn]   = "\000 RESW <n>\15\n";
  298.   code[WORDr0]  = "\000 TIMES <n> DW 0\15\n";
  299.   code[JMPm]    = "\000JMP _<n>\15\n";
  300.   code[LABm]    = "\000_<n>:\15\n";
  301.   code[LE10f]   = "\010<g>OR EAX,EAX\15\nJLE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
  302.   code[LE12]    = "\011CALL __le\15\n";
  303.   code[LE12u]   = "\011CALL __ule\15\n";
  304.   code[LNEG1]   = "\010CALL __lneg\15\n";
  305.   code[LT10f]   = "\010<g>OR EAX,EAX\15\nJL _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
  306.   code[LT12]    = "\011CALL __lt\15\n";
  307.   code[LT12u]   = "\011CALL __ult\15\n";
  308.   code[MOD12]   = "\011CDQ\15\nIDIV EBX\15\nMOV EAX,EDX\15\n";      /* see gen() */
  309.   code[MOD12u]  = "\011XOR EDX,EDX\15\nDIV EBX\15\nMOV EAX,EDX\15\n"; /* see gen() */
  310.   code[MOVE21]  = "\012MOV EBX,EAX\15\n";
  311.   code[MUL12]   = "\211IMUL EBX\15\n";
  312.   code[MUL12u]  = "\211MUL EBX\15\n";
  313.   code[NE10f]   = "\010<g>OR EAX,EAX\15\nJNE _<d>\15\nJMP _<n>\15\n_<d>:\15\n";
  314.   code[NE12]    = "\211CALL __ne\15\n";
  315.   code[NEARm]   = "\000 DD _<n>\15\n";
  316.   code[OR12]    = "\211OR EAX,EBX\15\n";
  317.   code[PLUSn]   = "\000?+<n>??\15\n";
  318.   code[POINT1l] = "\020MOV EAX,_<l>+<n>\15\n";
  319.   code[POINT1m] = "\020MOV EAX,<m>\15\n";
  320.   code[POINT1s] = "\020LEA EAX,[EBP<o>]\15\n";
  321.   code[POINT2m] = "\002MOV EBX,<m>\15\n";
  322.   code[POINT2m_]= "\002MOV EBX,<m>";
  323.   code[POINT2s] = "\002LEA EBX,[EBP<o>]\15\n";
  324.   code[POP2]    = "\002POP EBX\15\n";
  325.   code[PUSH1]   = "\110PUSH EAX\15\n";
  326.   code[PUSH2]   = "\101PUSH EBX\15\n";
  327.   code[PUSHm]   = "\100PUSH <m>\15\n";
  328.   code[PUSHp]   = "\100PUSH [EBX?<o>??]\15\n";
  329.   code[PUSHs]   = "\100PUSH [EBP?<o>??]\15\n";
  330.   code[PUT_m_]  = "\000MOV <m>";
  331.   code[PUTbm1]  = "\010MOV BYTE [<m>],AL\15\n";
  332.   code[PUTbp1]  = "\011MOV [EBX],AL\15\n";
  333.   code[PUTdm1]  = "\010MOV DWORD [<m>],EAX\15\n";
  334.   code[PUTdp1]  = "\011MOV [EBX],EAX\15\n";
  335.   code[PUTwm1]  = "\010MOV WORD [<m>],AX\15\n";
  336.   code[PUTwp1]  = "\011MOV [EBX],AX\15\n";
  337.   code[rDEC1]   = "\010#DEC EAX\15\n#";
  338.   code[rDEC2]   = "\010#DEC EBX\15\n#";
  339.   code[REFm]    = "\000_<n>";
  340.   code[RETURN]  = "\000?MOV ESP,EBP\15\n??POP EBP\15\nRET\15\n";
  341.   code[rINC1]   = "\010#INC EAX\15\n#";
  342.   code[rINC2]   = "\010#INC EBX\15\n#";
  343.   code[SUB_m_]  = "\000SUB <m>";
  344.   code[SUB12]   = "\011SUB EAX,EBX\15\n";                    /* see gen() */
  345.   code[SUB1n]   = "\010?SUB EAX,<n>\15\n??";
  346.   code[SUBbpn]  = "\001SUB [EBX],<n>\15\n";
  347.   code[SUBwpn]  = "\001SUB [EBX],<n>\15\n";
  348.   code[SWAP12]  = "\011XCHG EAX,EBX\15\n";
  349.   code[SWAP1s]  = "\012POP EBX\15\nXCHG EAX,EBX\15\nPUSH EBX\15\n";
  350.   code[SWITCH]  = "\012CALL __switch\15\n";
  351.   code[XOR12]   = "\211XOR EAX,EBX\15\n";
  352.   }
  353.  
  354. /***************** code generation functions *****************/
  355.  
  356. /*
  357. ** print all assembler info before any code is generated
  358. ** and ensure that the segments appear in the correct order.
  359. */
  360. header()  {
  361. /*  outline("  .386");
  362.   outline("  .MODEL FLAT");
  363. */  toseg(CODESEG);
  364.  
  365. /* - FASM  
  366.   outline("EXTERN __eq");
  367.   outline("EXTERN __ne");
  368.   outline("EXTERN __le");
  369.   outline("EXTERN __lt");
  370.   outline("EXTERN __ge");
  371.   outline("EXTERN __gt");
  372.   outline("EXTERN __ule");
  373.   outline("EXTERN __ult");
  374.   outline("EXTERN __uge");
  375.   outline("EXTERN __ugt");
  376.   outline("EXTERN __lneg");
  377.   outline("EXTERN __switch");
  378. */
  379.  
  380.   /* outline("dw 0"); *//* force non-zero code pointers, word alignment */
  381.   toseg(DATASEG);
  382.   /* outline("dw 0"); *//* force non-zero data pointers, word alignment */
  383.   }
  384.  
  385. /*
  386. ** print any assembler stuff needed at the end
  387. */
  388. trailer()  {  
  389.   char *cp;
  390.   cptr = STARTGLB;
  391.   while(cptr < ENDGLB) {
  392.     if(cptr[IDENT] == FUNCTION && cptr[CLASS] == AUTOEXT)
  393.       external(cptr + NAME, 0, FUNCTION);
  394.     cptr += SYMMAX;
  395.     }
  396. /*
  397.   if((cp = findglb("main")) && cp[CLASS]==STATIC)
  398.     external("_main", 0, FUNCTION);
  399. */
  400.   toseg(NULL);
  401. /* outline("END"); */
  402. #ifdef DISOPT
  403.     {
  404.     int i, *count;
  405.     printf(";opt   count\n");
  406.     for(i = -1; ++i <= HIGH_SEQ; ) {
  407.       count = seq[i];
  408.       printf("; %2u   %5u\n", i, *count);
  409.       }
  410.     }  
  411. #endif
  412.   }
  413.  
  414. /*
  415. ** remember where we are in the queue in case we have to back up.
  416. */
  417. setstage(before, start) int *before, *start; {
  418.   if((*before = snext) == 0)
  419.     snext = stage;
  420.   *start = snext;
  421.   }
  422.  
  423. /*
  424. ** generate code in staging buffer.
  425. */
  426. gen(pcode, value)
  427. int pcode, value;
  428.   {
  429.     int newcsp;
  430.     switch(pcode)
  431.       {
  432.         case GETb1pu:
  433.         case GETb1p:
  434.         case GETw1p:
  435.         case GETd1p:
  436.           gen(MOVE21, 0);
  437.           break;
  438.         case SUB12:
  439.         case MOD12:
  440.         case MOD12u:
  441.         case DIV12:
  442.         case DIV12u:
  443.           gen(SWAP12, 0);
  444.           break;
  445.         case PUSH1:
  446. #ifdef INT32
  447.           csp -= BPD;
  448. #else
  449.           csp -= BPW;
  450. #endif
  451.           break;
  452.         case POP2:
  453. #ifdef INT32
  454.           csp += BPD;
  455. #else
  456.           csp += BPW;
  457. #endif
  458.           break;
  459.         case ADDSP:
  460.         case RETURN:
  461.           newcsp = value;
  462.           value -= csp;
  463.           csp = newcsp;
  464.       }
  465.     if(snext == 0)
  466.       {
  467.         outcode(pcode, value);
  468.         return;
  469.       }
  470.     if(snext >= slast)
  471.       {
  472.         error("staging buffer overflow");
  473.         return;
  474.       }
  475.     snext[0] = pcode;
  476.     snext[1] = value;
  477.     snext += 2;
  478.   }
  479.  
  480. /*
  481. ** dump the contents of the queue.
  482. ** If start = 0, throw away contents.
  483. ** If before != 0, don't dump queue yet.
  484. */
  485. clearstage(before, start)
  486. int *before, *start;
  487.   {
  488.     if(before)
  489.       {
  490.         snext = before;
  491.         return;
  492.       }
  493.     if(start)
  494.       dumpstage();
  495.     snext = 0;
  496.   }
  497.  
  498. /*
  499. ** dump the staging buffer
  500. */
  501. dumpstage()
  502.   {
  503.     int i;
  504.     stail = snext;
  505.     snext = stage;
  506.     while(snext < stail)
  507.       {
  508.         if(optimize)
  509.           {
  510. restart:
  511.             i = -1;
  512.             while(++i <= HIGH_SEQ)
  513.               if(peep(seq[i]))
  514.                 {
  515. #ifdef DISOPT
  516.                   if(isatty(output))
  517.                     fprintf(stderr, "                   optimized %2u\n", i);
  518. #endif
  519.                   goto restart;
  520.                 }
  521.           }
  522.         outcode(snext[0], snext[1]);
  523.         snext += 2;
  524.       }
  525.   }
  526.  
  527. /*
  528. ** change to a new segment
  529. ** may be called with NULL, CODESEG, or DATASEG
  530. ** With NASM the section names are case-sensitive
  531. */
  532. toseg(newseg)
  533. int newseg;
  534.   {
  535.     if(oldseg == newseg)
  536.       return;
  537. /*    if(oldseg == CODESEG)
  538.       outline("_TEXT ENDS");
  539.     else if(oldseg == DATASEG)
  540.       outline("_DATA ENDS");  <-- */
  541.  
  542. /* - FASM
  543.     if(newseg == CODESEG)
  544.       {
  545.         outline("SECTION .text");
  546.       }
  547.     else if(newseg == DATASEG)
  548.       outline("SECTION .data");
  549. */
  550.     oldseg = newseg;
  551.   }
  552.  
  553. /*
  554. ** declare entry point
  555. */
  556. public(ident) int ident;{
  557.   if(ident == FUNCTION)
  558.        toseg(CODESEG);
  559.   else toseg(DATASEG);
  560. /* - FASM
  561.   outstr("GLOBAL ");
  562.   outname(ssname);
  563. */
  564.   newline();
  565.   outname(ssname);
  566.   if(ident == FUNCTION) {
  567.     colon();
  568.     newline();
  569.     }
  570.   }
  571.  
  572. /*
  573. ** declare external reference
  574. */
  575. external(name, size, ident) char *name; int size, ident; {
  576.   if(ident == FUNCTION)
  577.        toseg(CODESEG);
  578.   else toseg(DATASEG);
  579. /* - FASM
  580.   outstr("EXTERN ");
  581.   outname(name);
  582. /#  colon();
  583.   outsize(size, ident); <-- #/
  584.   newline();
  585. */
  586.   }
  587.  
  588. /*
  589. ** output the size of the object pointed to.
  590. */
  591. outsize(size, ident) int size, ident;
  592.   {
  593.     /* why not size on FUNCTION and POINTER ? */
  594.     if (ident == FUNCTION)
  595.       outstr("NEAR");
  596.     else if (ident == POINTER)
  597.       outstr("DWORD");
  598.     else if(size == 1)
  599.       outstr("BYTE");
  600.     else if(size == 2)
  601.       outstr("WORD");
  602.     else
  603.       outstr("DWORD");
  604.   }
  605.  
  606. /*
  607. ** point to following object(s)
  608. */
  609. point() {
  610.   outline(" DW $+2");
  611.   }
  612.  
  613. /*
  614. ** dump the literal pool
  615. */
  616. dumplits(size) int size;
  617. {
  618.   int j, k;
  619.   k = 0;
  620.   while (k < litptr)
  621.     {
  622.       if(size == 1)
  623.         {
  624.           gen(BYTE_, NULL);
  625.         }
  626.       else if (size == 2)
  627.         {
  628.           gen(WORD_, NULL);
  629.         }
  630.       else
  631.         {
  632.           gen(DWORD_,NULL);
  633.         }
  634.       j = 10;
  635.       while(j--)
  636.         {
  637.           outdec(getint(litq + k, size));
  638.           k += size;
  639.           if(j == 0 || k >= litptr)
  640.             {
  641.               newline();
  642.               break;
  643.             }
  644.           fputc(',', output);
  645.         }
  646.     }
  647. }
  648.  
  649. /*
  650. ** dump zeroes for default initial values
  651. */
  652. dumpzero(size, count)
  653. int size, count;
  654. {
  655.   if(count > 0)
  656.     {
  657.       if(size == 1)
  658.         gen(BYTEr0, count);
  659.       else if (size == 2)
  660.         gen(WORDr0, count);
  661.       else
  662.         gen(DWORDr0, count);
  663.     }
  664.   }
  665.  
  666. /******************** optimizer functions ***********************/
  667.  
  668. /*
  669. ** Try to optimize sequence at snext in the staging buffer.
  670. */
  671. peep(seq) int *seq; {
  672.   int *next, *count, *pop, n, skip, tmp, reply;
  673.   char c;
  674.   next = snext;
  675.   count = seq++;
  676.   while(*seq) {
  677.     switch(*seq) {
  678.       case any:   if(next < stail)       break;      return (NO);
  679.       case pfree: if(isfree(PRI, next))  break;      return (NO);
  680.       case sfree: if(isfree(SEC, next))  break;      return (NO);
  681.       case comm:  if(*next & COMMUTES)   break;      return (NO);
  682.       case _pop:  if(pop = getpop(next)) break;      return (NO);
  683.       default:    if(next >= stail || *next != *seq) return (NO);
  684.       }
  685.     next += 2; ++seq;
  686.     }
  687.  
  688.   /****** have a match, now optimize it ******/
  689.  
  690.   *count += 1;
  691.   reply = skip = NO;
  692.   while(*(++seq) || skip) {
  693.     if(skip) {
  694.       if(*seq == 0) skip = NO;
  695.       continue;
  696.       }
  697.     if(*seq >= PCODES) {
  698.       c = *seq & 0xFF;            /* get low byte of command */
  699.       n = c;                      /* and sign extend into n */
  700.       switch(*seq & 0xFF00) {
  701.         case ife:   if(snext[1] != n) skip = YES;  break;
  702.         case ifl:   if(snext[1] >= n) skip = YES;  break;
  703.         case go:    snext += (n<<1);               break;
  704.         case gc:    snext[0] =  snext[(n<<1)];     goto done;
  705.         case gv:    snext[1] =  snext[(n<<1)+1];   goto done;
  706.         case sum:   snext[1] += snext[(n<<1)+1];   goto done;
  707.         case neg:   snext[1] = -snext[1];          goto done;
  708.         case topop: pop[0] = n; pop[1] = snext[1]; goto done;
  709.         case swv:   tmp = snext[1];
  710.                     snext[1] = snext[(n<<1)+1];
  711.                     snext[(n<<1)+1] = tmp;
  712.         done:       reply = YES;
  713.                     break;
  714.         }
  715.       }
  716.     else snext[0] = *seq;         /* set p-code */
  717.     }
  718.   return (reply);
  719.   }
  720.  
  721. /*
  722. ** Is the primary or secondary register free?
  723. ** Is it zapped or unused by the p-code at pp
  724. ** or a successor?  If the primary register is
  725. ** unused by it still may not be free if the
  726. ** context uses the value of the expression.
  727. */
  728. isfree(reg, pp) int reg, *pp; {
  729.   char *cp;
  730.   while(pp < stail) {
  731.     cp = code[*pp];
  732.     if(*cp & USES & reg) return (NO);
  733.     if(*cp & ZAPS & reg) return (YES);
  734.     pp += 2;
  735.     }
  736.   if(usexpr) return (reg & 001);   /* PRI => NO, SEC => YES at end */
  737.   else       return (YES);
  738.   }
  739.  
  740. /*
  741. ** Get place where the currently pushed value is popped?
  742. ** NOTE: Function arguments are not popped, they are
  743. ** wasted with an ADDSP.
  744. */
  745. getpop(next) int *next; {
  746.   char *cp;
  747.   int level;  level = 0;
  748.   while(YES) {
  749.     if(next >= stail)                     /* compiler error */
  750.       return 0;
  751.     if(*next == POP2)
  752.       if(level) --level;
  753.       else return next;                   /* have a matching POP2 */
  754.     else if(*next == ADDSP) {             /* after func call */
  755.       if((level -= (next[1]>>LBPW)) < 0)
  756.         return 0;
  757.       }
  758.     else {
  759.       cp = code[*next];                   /* code string ptr */
  760.       if(*cp & PUSHES) ++level;           /* must be a push */
  761.       }
  762.     next += 2;
  763.     }
  764.   }
  765.  
  766. /******************* output functions *********************/
  767.  
  768. colon() {
  769.   fputc(':', output);
  770.   }
  771.  
  772. newline() {
  773.   fputc('\15', output);
  774.   fputc(NEWLINE, output);
  775.   }
  776.  
  777. /*
  778. ** output assembly code.
  779. **
  780. */
  781. outcode(pcode, value)
  782. int pcode, value;
  783.   {
  784.     int part, skip, count;
  785.     int byte_opt;
  786.     char *cp, *back;
  787.     int loc_label;
  788.     part = back = 0;
  789.     skip = NO;
  790.     byte_opt = 0;
  791.    
  792.     cp = code[pcode] + 1;          /* skip 1st byte of code string */
  793.  
  794. #ifdef _MSC_VER
  795.  
  796.     switch (pcode)
  797.       {
  798.         case BYTE_:
  799.         case BYTEn:
  800.         case BYTEr0:
  801.         case WORD_:
  802.         case WORDn:
  803.         case WORDr0:
  804.         case DWORD_:
  805.         case DWORDn:
  806.         case DWORDr0:
  807.         case REFm:
  808.         case COMMAn:
  809.         case PLUSn:
  810.           break;
  811.  
  812.         default:
  813.  
  814.           dump_debug (pcode, value);
  815.           outtab ();
  816.     }
  817. #endif
  818.  
  819.     if (pcode == ADD1n)
  820.       {
  821.         if (value < 0)
  822.           {
  823.             pcode = SUB1n;
  824.             value = -value;
  825.           }
  826.         if (value < 128)
  827.           {
  828.             byte_opt = 1;
  829.           }
  830.       }
  831.    
  832.     while(*cp)
  833.       {
  834.         if(*cp == '<')
  835.           {
  836.             ++cp;                      /* skip to action code */
  837.             if(skip == NO)
  838.               switch(*cp)
  839.                 {
  840.                   case 'm':
  841.                     outname(value+NAME);
  842.                     break; /* mem ref by label */
  843.                   case 'n':
  844.                     if (byte_opt)
  845.                       {
  846.                         outstr ("BYTE ");
  847.                       }
  848.                     outdec(value);
  849.                     break; /* numeric constant */
  850.                   case 'o':
  851.                     offset(value);
  852.                     break; /* numeric constant */
  853.                   case 'l':
  854.                     outdec(litlab);
  855.                     break; /* current literal label */
  856.                   case 'g':     /* generate local label */
  857.                     loc_label = getlabel ();
  858.                     break;
  859.                   case 'd':     /* dump local label */
  860.                     outdec(loc_label);
  861.                     break;
  862.                 }
  863.               cp += 2;                   /* skip past > */
  864.           }
  865.         else if(*cp == '?')        /* ?..if value...?...if not value...? */
  866.           {
  867.             switch(++part)
  868.               {
  869.                 case 1:
  870.                   if(value == 0)
  871.                     skip = YES;
  872.                   break;
  873.                 case 2:
  874.                   skip = !skip;
  875.                   break;
  876.                 case 3:
  877.                   part = 0;
  878.                   skip = NO;
  879.                   break;
  880.               }
  881.             ++cp;                      /* skip past ? */
  882.           }
  883.         else if(*cp == '#')
  884.           {        /* repeat #...# value times */
  885.             ++cp;
  886.             if(back == 0)
  887.               {
  888.                 if((count = value) < 1)
  889.                   {
  890.                     while(*cp && *cp++ != '#')
  891.                       ;
  892.                     continue;
  893.                   }
  894.                 back = cp;
  895.                 continue;
  896.               }
  897.             if(--count > 0)
  898.               cp = back;
  899.             else
  900.               back = 0;
  901.           }
  902.         else if(skip == NO)
  903.           fputc(*cp++, output);
  904.         else
  905.           ++cp;
  906.       }
  907.   }
  908.  
  909. outdec(number)  int number; {
  910.   int k, zs;
  911.   char c, *q, *r;
  912.   zs = 0;
  913.   k = 1000000000;
  914.  
  915. #ifdef _MSC_VER
  916. //  fprintf(output, "/* %d */", number);
  917. #endif
  918.  
  919.   if(number < 0) {
  920.     number = -number;
  921.     fputc('-', output);
  922.     }
  923.  
  924.   while (k >= 1) {
  925.     q = 0;
  926.     r = number;
  927.     while(r >= k) {++q; r = r - k;}
  928.     c = q + '0';
  929.     if(c != '0' || k == 1 || zs) {
  930.       zs = 1;
  931.       fputc(c, output);
  932.       }
  933.     number = r;
  934.     k /= 10;
  935.     }
  936.   }
  937.  
  938. offset(number)
  939. int number;
  940. {
  941.   int k, zs;
  942.   char c, *q, *r;
  943.   zs = 0;
  944.   k = 1000000000;
  945.   if(number < 0) {
  946.     number = -number;
  947.     fputc('-', output);
  948.     }
  949.   else
  950.     {
  951.       fputc('+',output);
  952.     }
  953.  
  954.   while (k >= 1) {
  955.     q = 0;
  956.     r = number;
  957.     while(r >= k) {++q; r = r - k;}
  958.     c = q + '0';
  959.     if(c != '0' || k == 1 || zs) {
  960.       zs = 1;
  961.       fputc(c, output);
  962.       }
  963.     number = r;
  964.     k /= 10;
  965.     }
  966.   }
  967.  
  968. outline(ptr)  char ptr[];  {
  969.   outstr(ptr);
  970.   newline();
  971.   }
  972.  
  973. outname(ptr) char ptr[]; {
  974.   outstr("_");
  975.   while(*ptr >= ' ') fputc(*ptr++, output);
  976.   }
  977.  
  978. outstr(ptr) char ptr[]; {
  979.   while(*ptr == '\t' || *ptr >= ' ') fputc(*ptr++, output);
  980.   }
  981.  
  982. outtab ()
  983.   {
  984.     fputc ('\t', output);
  985.   }