%{ #define STACK_MACHINE #include "c.h" #define NODEPTR_TYPE Node #define OP_LABEL(p) ((p)->op) #define LEFT_CHILD(p) ((p)->kids[0]) #define RIGHT_CHILD(p) ((p)->kids[1]) #define STATE_LABEL(p) ((p)->x.state) static void address(Symbol, Symbol, long); static void defaddress(Symbol); static void defconst(int, int, Value); static void defstring(int, char *); static void defsymbol(Symbol); static void emit2(Node); static void export(Symbol); static void function(Symbol, Symbol [], Symbol [], int); static void global(Symbol); static void import(Symbol); static void local(Symbol); static void progbeg(int, char **); static void progend(void); static void segment(int); static void space(int); static void blockbeg(Env* env); static void blockend(Env* env); extern void stackemit(Node forest); extern Node stackgen(Node forest); extern void swtch(Symbol label); extern FILE* logfile; %} %start stmt %term STACKP=727 %term COPYP=759 %term CNSTF4=4113 %term CNSTF8=8209 %term CNSTI1=1045 %term CNSTI2=2069 %term CNSTI4=4117 %term CNSTI8=8213 %term CNSTP4=4119 %term CNSTU1=1046 %term CNSTU2=2070 %term CNSTU4=4118 %term CNSTU8=8214 %term ARGB=41 %term ARGF4=4129 %term ARGF8=8225 %term ARGI4=4133 %term ARGI8=8229 %term ARGP4=4135 %term ARGU4=4134 %term ARGU8=8230 %term ASGNB=57 %term ASGNF4=4145 %term ASGNF8=8241 %term ASGNI1=1077 %term ASGNI2=2101 %term ASGNI4=4149 %term ASGNI8=8245 %term ASGNP4=4151 %term ASGNU1=1078 %term ASGNU2=2102 %term ASGNU4=4150 %term ASGNU8=8246 %term INDIRB=73 %term INDIRF4=4161 %term INDIRF8=8257 %term INDIRI1=1093 %term INDIRI2=2117 %term INDIRI4=4165 %term INDIRI8=8261 %term INDIRP4=4167 %term INDIRU1=1094 %term INDIRU2=2118 %term INDIRU4=4166 %term INDIRU8=8262 %term CVFF4=4209 %term CVFF8=8305 %term CVFI4=4213 %term CVFI8=8309 %term CVIF4=4225 %term CVIF8=8321 %term CVII1=1157 %term CVII2=2181 %term CVII4=4229 %term CVII8=8325 %term CVIU1=1158 %term CVIU2=2182 %term CVIU4=4230 %term CVIU8=8326 %term CVPU4=4246 %term CVUI1=1205 %term CVUI2=2229 %term CVUI4=4277 %term CVUI8=8373 %term CVUP4=4279 %term CVUU1=1206 %term CVUU2=2230 %term CVUU4=4278 %term CVUU8=8374 %term NEGF4=4289 %term NEGF8=8385 %term NEGI4=4293 %term NEGI8=8389 %term CALLB=217 %term CALLF4=4305 %term CALLF8=8401 %term CALLI4=4309 %term CALLI8=8405 %term CALLP4=4311 %term CALLU4=4310 %term CALLU8=8406 %term CALLV=216 %term RETF4=4337 %term RETF8=8433 %term RETI4=4341 %term RETI8=8437 %term RETP4=4343 %term RETU4=4342 %term RETU8=8438 %term RETV=248 %term ADDRGP4=4359 %term ADDRFP4=4375 %term ADDRLP4=4391 %term ADDF4=4401 %term ADDF8=8497 %term ADDI4=4405 %term ADDI8=8501 %term ADDP4=4407 %term ADDU4=4406 %term ADDU8=8502 %term SUBF4=4417 %term SUBF8=8513 %term SUBI4=4421 %term SUBI8=8517 %term SUBP4=4423 %term SUBU4=4422 %term SUBU8=8518 %term LSHI4=4437 %term LSHI8=8533 %term LSHU4=4438 %term LSHU8=8534 %term MODI4=4453 %term MODI8=8549 %term MODU4=4454 %term MODU8=8550 %term RSHI4=4469 %term RSHI8=8565 %term RSHU4=4470 %term RSHU8=8566 %term BANDI4=4485 %term BANDI8=8581 %term BANDU4=4486 %term BANDU8=8582 %term BCOMI4=4501 %term BCOMI8=8597 %term BCOMU4=4502 %term BCOMU8=8598 %term BORI4=4517 %term BORI8=8613 %term BORU4=4518 %term BORU8=8614 %term BXORI4=4533 %term BXORI8=8629 %term BXORU4=4534 %term BXORU8=8630 %term DIVF4=4545 %term DIVF8=8641 %term DIVI4=4549 %term DIVI8=8645 %term DIVU4=4550 %term DIVU8=8646 %term MULF4=4561 %term MULF8=8657 %term MULI4=4565 %term MULI8=8661 %term MULU4=4566 %term MULU8=8662 %term EQF4=4577 %term EQF8=8673 %term EQI4=4581 %term EQI8=8677 %term EQU4=4582 %term EQU8=8678 %term GEF4=4593 %term GEF8=8689 %term GEI4=4597 %term GEI8=8693 %term GEU4=4598 %term GEU8=8694 %term GTF4=4609 %term GTF8=8705 %term GTI4=4613 %term GTI8=8709 %term GTU4=4614 %term GTU8=8710 %term LEF4=4625 %term LEF8=8721 %term LEI4=4629 %term LEI8=8725 %term LEU4=4630 %term LEU8=8726 %term LTF4=4641 %term LTF8=8737 %term LTI4=4645 %term LTI8=8741 %term LTU4=4646 %term LTU8=8742 %term NEF4=4657 %term NEF8=8753 %term NEI4=4661 %term NEI8=8757 %term NEU4=4662 %term NEU8=8758 %term JUMPV=584 %term LABELV=600 %term TUCKF4=4833 %term TUCKF8=8929 %term TUCKI1=1765 %term TUCKI2=2789 %term TUCKI4=4837 %term TUCKI8=8933 %term TUCKP4=4839 %term TUCKU1=1766 %term TUCKU2=2790 %term TUCKU4=4838 %term TUCKU8=8934 %term VREGP = 711 %term NOOP = 48 %% sread8: STACKP "\n" range(a, 1, 1) sread8: STACKP "rrot\n" range(a, 2, 2) sread8: STACKP "rot4\nrot4\n" range(a, 3, 3) sread: STACKP "\n" range(a, 1, 1) sread: STACKP "swap\n" range(a, 2, 2)+1 sread: STACKP "rot\n" range(a, 3, 3)+1 sread: STACKP "rot4\n" range(a, 4, 4)+1 sread: COPYP "copy%b\n" range(a, 1, 4)+1 sread: COPYP "any\n" range(a, 0, 0) drop: STACKP "drop%b\n" sread: VREGP "ERROR - FORGOTTEN VIRTUAL!\n" stmt: INDIRI1(drop) "\n" stmt: INDIRU1(drop) "\n" stmt: INDIRI2(drop) "\n" stmt: INDIRU2(drop) "\n" stmt: INDIRF4(drop) "\n" stmt: INDIRI4(drop) "\n" stmt: INDIRP4(drop) "\n" stmt: INDIRU4(drop) "\n" stk: INDIRI1(sread) "\n" stk: INDIRU1(sread) "\n" stk: INDIRI2(sread) "\n" stk: INDIRU2(sread) "\n" stk: INDIRF4(sread) "\n" stk: INDIRI4(sread) "\n" stk: INDIRP4(sread) "\n" stk: INDIRU4(sread) "\n" stk2: INDIRI8(sread8) "\n" stk2: INDIRF8(sread8) "\n" stk2: INDIRU8(sread8) "\n" tuck1: TUCKI1(stk) "\n" range(a, 1, 1) tuck1: TUCKU1(stk) "\n" range(a, 1, 1) tuck1: TUCKI2(stk) "\n" range(a, 1, 1) tuck1: TUCKU2(stk) "\n" range(a, 1, 1) tuck1: TUCKI4(stk) "\n" range(a, 1, 1) tuck1: TUCKU4(stk) "\n" range(a, 1, 1) tuck1: TUCKF4(stk) "\n" range(a, 1, 1) tuck1: TUCKP4(stk) "\n" range(a, 1, 1) tuck2: TUCKI1(stk) "\n" range(a, 2, 2) tuck2: TUCKU1(stk) "\n" range(a, 2, 2) tuck2: TUCKI2(stk) "\n" range(a, 2, 2) tuck2: TUCKU2(stk) "\n" range(a, 2, 2) tuck2: TUCKI4(stk) "\n" range(a, 2, 2) tuck2: TUCKU4(stk) "\n" range(a, 2, 2) tuck2: TUCKF4(stk) "\n" range(a, 2, 2) tuck2: TUCKP4(stk) "\n" range(a, 2, 2) tuck3: TUCKI1(stk) "\n" range(a, 3, 3) tuck3: TUCKU1(stk) "\n" range(a, 3, 3) tuck3: TUCKI2(stk) "\n" range(a, 3, 3) tuck3: TUCKU2(stk) "\n" range(a, 3, 3) tuck3: TUCKI4(stk) "\n" range(a, 3, 3) tuck3: TUCKU4(stk) "\n" range(a, 3, 3) tuck3: TUCKF4(stk) "\n" range(a, 3, 3) tuck3: TUCKP4(stk) "\n" range(a, 3, 3) tuck4: TUCKI1(stk) "\n" range(a, 4, 4) tuck4: TUCKU1(stk) "\n" range(a, 4, 4) tuck4: TUCKI2(stk) "\n" range(a, 4, 4) tuck4: TUCKU2(stk) "\n" range(a, 4, 4) tuck4: TUCKI4(stk) "\n" range(a, 4, 4) tuck4: TUCKU4(stk) "\n" range(a, 4, 4) tuck4: TUCKF4(stk) "\n" range(a, 4, 4) tuck4: TUCKP4(stk) "\n" range(a, 4, 4) stk: tuck1 "copy1\n" stk: tuck2 "tuck2\n" stk: tuck3 "tuck3\n" stk: tuck4 "tuck4\n" stmt: tuck1 "\n" stmt: tuck2 "swap\n" stmt: tuck3 "rrot\n" stmt: tuck4 "rrot4\n" stmt: ASGNI1(stk, var) "\n" stmt: ASGNU1(stk, var) "\n" stmt: ASGNI2(stk, var) "\n" stmt: ASGNU2(stk, var) "\n" stmt: ASGNF4(stk, var) "\n" stmt: ASGNI4(stk, var) "\n" stmt: ASGNP4(stk, var) "\n" stmt: ASGNU4(stk, var) "\n" var: STACKP "\n" range(a, 1, 1) var: STACKP "swap\n" range(a, 2, 2)+1 var: STACKP "rrot\n" range(a, 3, 3)+1 var: STACKP "rrot4\n" range(a, 4, 4)+1 cnst1: CNSTI1 "" range(a, 1, 1) cnst1: CNSTU1 "" range(a, 1, 1) cnst1: CNSTI2 "" range(a, 1, 1) cnst1: CNSTU2 "" range(a, 1, 1) cnst1: CNSTI4 "" range(a, 1, 1) cnst1: CNSTU4 "" range(a, 1, 1) cnst2: CNSTI1 "" range(a, 2, 2) cnst2: CNSTU1 "" range(a, 2, 2) cnst2: CNSTI2 "" range(a, 2, 2) cnst2: CNSTU2 "" range(a, 2, 2) cnst2: CNSTI4 "" range(a, 2, 2) cnst2: CNSTU4 "" range(a, 2, 2) cnst4: CNSTI1 "" range(a, 4, 4) cnst4: CNSTU1 "" range(a, 4, 4) cnst4: CNSTI2 "" range(a, 4, 4) cnst4: CNSTU2 "" range(a, 4, 4) cnst4: CNSTI4 "" range(a, 4, 4) cnst4: CNSTU4 "" range(a, 4, 4) cnst32: CNSTI4 "" range(a, 32, 32) con9: CNSTI1 "%a" con9: CNSTU1 "%a" con9: CNSTI2 "%a" range(a, -(1<<8)+1, (1<<8)-1) con9: CNSTU2 "%a" range(a, 0, (1<<8)-1) con9: CNSTU2 "%a" range(a, 0xffffff01, 0xffffffff) con9: CNSTI4 "%a" range(a, -(1<<8)+1, (1<<8)-1) con9: CNSTU4 "%a" range(a, 0, (1<<8)-1) con9: CNSTU4 "%a" range(a, 0xffffff01, 0xffffffff) con9: CNSTP4 "%a" range(a, 0, (1<<8)-1) ucon9: CNSTI1 "%a" range(a, 0, (1<<8)-1) ucon9: CNSTU1 "%a" ucon9: CNSTI2 "%a" range(a, 0, (1<<8)-1) ucon9: CNSTU2 "%a" range(a, 0, (1<<8)-1) ucon9: CNSTU2 "%a" range(a, 0, 0xffffffff) ucon9: CNSTI4 "%a" range(a, 0, (1<<8)-1) ucon9: CNSTU4 "%a" range(a, 0, (1<<8)-1) ucon9: CNSTP4 "%a" range(a, 0, (1<<8)-1) stk: cnst2 "lit2\n" 1 stk: cnst4 "lit4\n" 1 cnst: CNSTI1 "%a" 3 cnst: CNSTI2 "%a" 3 cnst: CNSTI4 "%a" 3 cnst: CNSTF4 "%a" 3 cnst: CNSTU1 "%a" 3 cnst: CNSTU2 "%a" 3 cnst: CNSTU4 "%a" 3 cnst: CNSTP4 "%a" 3 stk : cnst "lit %0\n" 3 stk2: CNSTI4 "lit %a\ntlz\ninv\nadd1\n" stk2: CNSTU4 "lit %a\nlit0\n" stmt: stk "drop1\n" 1 stmt: stk2 "drop1\ndrop1\n" 2 glob: ADDRGP4 "%a" local: ADDRLP4 "%a" local: ADDRFP4 "%a" stk: glob "lit %0\n" 2 stk: NOOP "dead\n" 0 stk: ADDRFP4 "Error - Address of parameter\n" LBURG_MAX stk: ADDRLP4 "#\n" 3 zero: CNSTI1 "" range(a, 0, 0) zero: CNSTI2 "" range(a, 0, 0) zero: CNSTI4 "" range(a, 0, 0) zero: CNSTU1 "" range(a, 0, 0) zero: CNSTU2 "" range(a, 0, 0) zero: CNSTU4 "" range(a, 0, 0) zero: CNSTP4 "" range(a, 0, 0) cnst_m1: CNSTI4 "" range(a, -1, -1) stmt: ASGNI1(stk, local) "#\n" 3 stmt: ASGNU1(stk, local) "#\n" 3 stmt: ASGNI2(stk, local) "#\n" 3 stmt: ASGNU2(stk, local) "#\n" 3 stmt: ASGNI4(stk, local) "#\n" 3 stmt: ASGNU4(stk, local) "#\n" 3 stmt: ASGNF4(stk, local) "#\n" 3 stmt: ASGNP4(stk, local) "#\n" 3 stmt: ASGNI8(stk2, local) "#\n" 3 stmt: ASGNU8(stk2, local) "#\n" 3 stmt: ASGNF8(stk2, local) "#\n" 3 stmt: ASGNI1(stk,stk) "stb\ndrop1\n" 4 stmt: ASGNU1(stk,stk) "stb\ndrop1\n" 4 stmt: ASGNI2(stk,stk) "stw\ndrop1\n" 4 stmt: ASGNU2(stk,stk) "stw\ndrop1\n" 4 stmt: ASGNI4(stk,stk) "stl\ndrop1\n" 4 stmt: ASGNU4(stk,stk) "stl\ndrop1\n" 4 stmt: ASGNP4(stk,stk) "stl\ndrop1\n" 4 stmt: ASGNF4(stk,stk) "stl\ndrop1\n" 4 stmt: ASGNI8(stk2, stk) "stli\nstl\ndrop1\n" 6 stmt: ASGNU8(stk2, stk) "stli\nstl\ndrop1\n" 6 stmt: ASGNF8(stk2, stk) "stli\nstl\ndrop1\n" 6 cpyst: COPYP "swap\nstl\n" range(a, 2, 2) + 3 cpyst: COPYP "rot\nstl\nswap\n" range(a, 3, 3) + 4 cpyst: COPYP "rot4\nstl\nrrot\n" range(a, 4, 4) + 4 cpystb: COPYP "swap\nstb\n" range(a, 2, 2) + 3 cpystb: COPYP "rot\nstb\nswap\n" range(a, 3, 3) + 4 cpystb: COPYP "rot4\nstb\nrrot\n" range(a, 4, 4) + 4 cpystw: COPYP "swap\nstw\n" range(a, 2, 2) + 3 cpystw: COPYP "rot\nstw\nswap\n" range(a, 3, 3) + 4 cpystw: COPYP "rot4\nstw\nrrot\n" range(a, 4, 4) + 4 stmt: ASGNU1(stk, INDIRP4(cpystb)) "\n" stmt: ASGNI1(stk, INDIRP4(cpystb)) "\n" stmt: ASGNU2(stk, INDIRP4(cpystw)) "\n" stmt: ASGNI2(stk, INDIRP4(cpystw)) "\n" stmt: ASGNI4(stk, INDIRP4(cpyst)) "\n" stmt: ASGNU4(stk, INDIRP4(cpyst)) "\n" stmt: ASGNF4(stk, INDIRP4(cpyst)) "\n" stmt: ASGNP4(stk, INDIRP4(cpyst)) "\n" tuckst: TUCKP4(stk) "stl\n" range(a, 2, 2) + 3 tuckst: TUCKP4(stk) "stl\nswap\n" range(a, 3, 3) + 4 tuckst: TUCKP4(stk) "stl\nsrrot\n" range(a, 4, 4) + 4 stmt: ASGNI4(stk, tuckst) "\n" stmt: ASGNU4(stk, tuckst) "\n" stmt: ASGNF4(stk, tuckst) "\n" stmt: ASGNP4(stk, tuckst) "\n" stk: INDIRI1(local) "#\n" 3 stk: INDIRU1(local) "#\n" 3 stk: INDIRI2(local) "#\n" 3 stk: INDIRU2(local) "#\n" 3 stk: INDIRP4(local) "#\n" 3 stk: INDIRI4(local) "#\n" 3 stk: INDIRU4(local) "#\n" 3 stk: INDIRF4(local) "#\n" 3 stk2: INDIRI8(local) "#\n" 5 stk2: INDIRU8(local) "#\n" 5 stk2: INDIRF8(local) "#\n" 5 stk: INDIRI1(stk) "ldb\nsxb\n" 3 stk: INDIRU1(stk) "ldb\n" 3 stk: INDIRI2(stk) "ldw\nsxw\n" 3 stk: INDIRU2(stk) "ldw\n" 3 stk: INDIRI4(stk) "ldl\n" 3 stk: INDIRU4(stk) "ldl\n" 3 stk: INDIRP4(stk) "ldl\n" 3 stk: INDIRF4(stk) "ldl\n" 3 stk2: INDIRI8(stk) "ldli\nswap\nldl\nswap\n" 7 stk2: INDIRU8(stk) "ldli\nswap\nldl\nswap\n" 7 stk2: INDIRF8(stk) "ldli\nswap\nldl\nswap\n" 7 stk: MODI4(stk,stk) "call __mod__\n" 20 stk: MODU4(stk,stk) "lit0\nswap\ndivmod64\ndrop2\n" 8 stk: MULI4(stk,stk) "mul32\ndrop1\n" 3 stk: MULU4(stk,stk) "mul32\ndrop1\n" 3 stk: DIVI4(stk,stk) "call __div__\n" 20 stk: DIVU4(stk,stk) "lit0\nswap\ndivmod64\ndrop1\n" 8 stk2: MODI8(stk2,stk2) "call __mod64__\n" 20 stk2: MODU8(stk2,stk2) "call __modu64__\n" 10 stk2: MULI8(stk2,stk2) "call __mul64__\n" 8 stk2: MULU8(stk2,stk2) "call __mul64__\n" 10 stk2: DIVI8(stk2,stk2) "call __div64__\n" 20 stk2: DIVU8(stk2,stk2) "call __divu64__\n" 20 stk: ADDI4(stk, cnst1) "add1\n" 1 stk: ADDP4(stk, cnst1) "add1\n" 1 stk: ADDU4(stk, cnst1) "add1\n" 1 stk: ADDI4(stk, cnst_m1) "sub1\n" 1 stk: ADDP4(stk, cnst_m1) "sub1\n" 1 stk: ADDU4(stk, cnst_m1) "sub1\n" 1 stk: ADDI4(stk, cnst2) "add2\n" 1 stk: ADDP4(stk, cnst2) "add2\n" 1 stk: ADDU4(stk, cnst2) "add2\n" 1 stk: ADDI4(stk, con9) "addl tos %1\n" 2 stk: ADDP4(stk, con9) "addl tos %1\n" 2 stk: ADDU4(stk, con9) "addl tos %1\n" 2 stk: ADDI4(stk, cnst4) "add4\n" 1 stk: ADDP4(stk, cnst4) "add4\n" 1 stk: ADDU4(stk, cnst4) "add4\n" 1 stk: ADDI4(stk, zero) "\n" stk: ADDP4(stk, zero) "\n" stk: ADDU4(stk, zero) "\n" stk: SUBI4(stk, cnst1) "sub1\n" 1 stk: SUBP4(stk, cnst1) "sub1\n" 1 stk: SUBU4(stk, cnst1) "sub1\n" 1 stk: SUBI4(stk, ucon9) "addl tos -%1\n" 2 stk: SUBP4(stk, ucon9) "addl tos -%1\n" 2 stk: SUBU4(stk, ucon9) "addl tos -%1\n" 2 stk: ADDI4(stk, stk) "add\n" 1 stk: ADDP4(stk, stk) "add\n" 1 stk: ADDU4(stk, stk) "add\n" 1 stk2: ADDI8(stk2, stk2) "swap\nrot4\nadd\nrrot\naddc\n" 5 /* msw goes tos */ stk2: ADDU8(stk2, stk2) "swap\nrot4\nadd\nrrot\naddc\n" 5 /* msw goes tos */ stk: BANDI4(stk, stk) "and\n" 1 stk: BORI4(stk, stk) "or\n" 1 stk: BXORI4(stk, stk) "xor\n" 1 stk: BANDU4(stk, stk) "and\n" 1 stk: BORU4(stk, stk) "or\n" 1 stk: BXORU4(stk, stk) "xor\n" 1 stk: SUBI4(stk, stk) "sub\n" 1 stk: SUBP4(stk, stk) "sub\n" 1 stk: SUBU4(stk, stk) "sub\n" 1 stk2: BANDI8(stk2, stk2) "swap\nrot4\nand\nrrot\nand\n" 5 /* msw goes tos */ stk2: BANDU8(stk2, stk2) "swap\nrot4\nand\nrrot\nand\n" 5 /* msw goes tos */ stk2: BORI8(stk2, stk2) "swap\nrot4\nor\nrrot\nor\n" 5 /* msw goes tos */ stk2: BORU8(stk2, stk2) "swap\nrot4\nor\nrrot\nor\n" 5 /* msw goes tos */ stk2: BXORI8(stk2, stk2) "swap\nrot4\nxor\nrrot\nxor\n" 5 /* msw goes tos */ stk2: BXORU8(stk2, stk2) "swap\nrot4\nxor\nrrot\nxor\n" 5 /* msw goes tos */ stk2: SUBI8(stk2, stk2) "swap\nrot4\nsub\nrrot\nsubc\n" 5 /* msw goes tos */ stk2: SUBU8(stk2, stk2) "swap\nrot4\nsub\nrrot\nsubc\n" 5 /* msw goes tos */ stk2: BCOMI8(stk2) "inv\nswap\ninv\nswap\n" 4 stk2: BCOMU8(stk2) "inv\nswap\ninv\nswap\n" 4 stk2: NEGI4(stk2) "swap\ninv\nadd1\nswap\ninv\ntcs\nadd\nadd1\n" 8 stk2: LSHI8(stk2, cnst1) "swap\nshl\nswap\nshlc\n" 6 stk2: LSHU8(stk2, cnst1) "swap\nshl\nswap\nshlc\n" 6 stk2: RSHI8(stk2, cnst1) "asr\nswap\nshrc\nswap\n" 6 stk2: RSHU8(stk2, cnst1) "shr\nswap\nshrc\nswap\n" 6 stk: LSHI4(stk, cnst) "#\n" 1 stk: LSHU4(stk, cnst) "#\n" 1 stk: RSHI4(stk,cnst) "#\n" 1 stk: RSHU4(stk,cnst) "#\n" 1 stk2: LSHI8(stk2,stk) "call __bshl64__\n" 10 stk2: LSHU8(stk2,stk) "call __bshl64__\n" 10 stk2: RSHI8(stk2,stk) "call __basr64__\n" 10 stk2: RSHU8(stk2,stk) "call __blsr64__\n" 10 stk: LSHI4(stk,stk) "call __bshl__\n" 10 stk: LSHU4(stk,stk) "call __bshl__\n" 10 stk: RSHI4(stk,stk) "call __basr__\n" 10 stk: RSHU4(stk,stk) "call __blsr__\n" 10 stk: BCOMI4(stk) "inv\n" 1 stk: BCOMU4(stk) "inv\n" 1 stk: NEGI4(stk) "inv\nadd1\n" 2 stk: ADDF4(stk,stk) "call _ufo_add_f32\n" 15 stk: DIVF4(stk,stk) "call _ufo_div_f32\n" 60 stk: MULF4(stk,stk) "call _ufo_mul_f32\n" 30 stk: SUBF4(stk,stk) "call _ufo_sub_f32\n" 15 stk: NEGF4(stk) "call _ufo_neg_f32\n" 6 stk2: ADDF8(stk2,stk2) "call _ufo_add_f64\n" 15 stk2: DIVF8(stk2,stk2) "call _ufo_div_f64\n" 60 stk2: MULF8(stk2,stk2) "call _ufo_mul_f64\n" 30 stk2: SUBF8(stk2,stk2) "call _ufo_sub_f64\n" 15 stk2: NEGF8(stk2) "call _ufo_neg_f64\n" 6 stk: CVII1(stk) "sxb\n" stk: CVII2(stk) "sxw\n" stk: CVII4(stk) "\n" stk: CVII4(stk2) "drop1\n" 1 stk: CVIU1(stk) "lit #ff\nand\n" stk: CVIU2(stk) "lit #ffff\nand\n" stk: CVIU4(stk) "\n" stk: CVIU4(stk2) "drop2\n" 1 stk: CVUI1(stk) "sxb\n" stk: CVUI2(stk) "sxw\n" stk: CVUI4(stk) "\n" stk: CVUI4(stk2) "drop1\n" 1 stk2: RSHI8(stk2, cnst32) "drop2\ncopy1\ntlz\ninv\nadd1\n" 5 stk2: RSHU8(stk2, cnst32) "drop2\nlit0\n" 3 stk: CVII4(RSHI8(stk2, cnst32)) "drop2\n" 1 stk: CVUU1(stk) "lit #ff\nand\n" stk: CVUU2(stk) "lit #ffff\nand\n" stk: CVUU4(stk) "\n" stk: CVUU4(stk2) "drop1\n" 1 stk2: CVIU8(stk) "lit0\n" 1 stk2: CVIU8(stk2) "\n" stk2: CVUI8(stk) "lit0\n" 1 stk2: CVUI8(stk2) "\n" stk2: CVII8(stk) "copy1\ntlz\ninv\nadd1\n" 4 stk2: CVUU8(stk) "lit0\n" 1 stk: CVFF4(stk2) "call _ufo_f64_to_f32\n" 6 stk: CVIF4(stk) "call _ufo_i32_to_f32\n" 10 stk: CVIF4(stk2) "call _ufo_i64_to_f32\n" 10 stk: CVFI4(stk) "call _ufo_f32_to_i32\n" 20 stk: CVFI4(stk2) "call _ufo_f64_to_i32\n" 20 stk2: CVFF8(stk) "call _ufo_f32_to_f64\n" 6 stk2: CVIF8(stk) "call _ufo_i32_to_f64\n" 10 stk2: CVIF8(stk2) "call _ufo_i64_to_f64\n" 10 stk2: CVFI8(stk) "call _ufo_f32_to_i64\n" 20 stk2: CVFI8(stk2) "call _ufo_f64_to_i64\n" 20 stk: CVPU4(stk) "\n" stk: CVUP4(stk) "\n" stmt: LABELV "%a:\n" stmt: JUMPV(glob) "br %0\n" 1 stmt: JUMPV(stk) "stpc\n" 3 stmt: EQI4(stk,stk) "ceq\nbrnz %a\n" 2 stmt: EQU4(stk,stk) "ceq\nbrnz %a\n" 2 stmt: NEI4(stk,stk) "cne\nbrnz %a\n" 2 stmt: NEU4(stk,stk) "cne\nbrnz %a\n" 2 stmt: GEI4(stk,stk) "clt\nbrz %a\n" 2 stmt: GTI4(stk,stk) "cgt\nbrnz %a\n" 2 stmt: LEI4(stk,stk) "cgt\nbrz %a\n" 2 stmt: LTI4(stk,stk) "clt\nbrnz %a\n" 2 stmt: GEU4(CVPU4(stk),stk) "clt\nbrz %a\n" 2 stmt: GTU4(CVPU4(stk),stk) "cgt\nbrnz %a\n" 2 stmt: LEU4(CVPU4(stk),stk) "cgt\nbrz %a\n" 2 stmt: LTU4(CVPU4(stk),stk) "clt\nbrnz %a\n" 2 stmt: GEU4(stk,CVPU4(stk)) "clt\nbrz %a\n" 2 stmt: GTU4(stk,CVPU4(stk)) "cgt\nbrnz %a\n" 2 stmt: LEU4(stk,CVPU4(stk)) "cgt\nbrz %a\n" 2 stmt: LTU4(stk,CVPU4(stk)) "clt\nbrnz %a\n" 2 stmt: GEU4(CVPU4(stk),CVPU4(stk)) "clt\nbrz %a\n" 2 stmt: GTU4(CVPU4(stk),CVPU4(stk)) "cgt\nbrnz %a\n" 2 stmt: LEU4(CVPU4(stk),CVPU4(stk)) "cgt\nbrz %a\n" 2 stmt: LTU4(CVPU4(stk),CVPU4(stk)) "clt\nbrnz %a\n" 2 stmt: EQI8(stk2,stk2) "rot\nceq\nrrot\nceq\nand\nbrnz %a\n" 6 stmt: EQU8(stk2,stk2) "rot\nceq\nrrot\nceq\nand\nbrnz %a\n" 6 stmt: NEI8(stk2,stk2) "rot\ncne\nrrot\ncne\nor\nbrnz %a\n" 6 stmt: NEU8(stk2,stk2) "rot\ncne\nrrot\ncne\nor\nbrnz %a\n" 6 stmt: GEI8(stk2,stk2) "call cmp_int64\ntlz\nbrz %a\n" 2 stmt: GTI8(stk2,stk2) "call cmp_int64\ntgz\nbrnz %a\n" 2 stmt: LEI8(stk2,stk2) "call cmp_int64\ntgz\nbrz %a\n" 2 stmt: LTI8(stk2,stk2) "call cmp_int64\ntlz\nbrnz %a\n" 2 stmt: GEU8(stk2,stk2) "call cmp_uint64\ntlz\nbrz %a\n" 2 stmt: GTU8(stk2,stk2) "call cmp_uint64\ntgz\nbrnz %a\n" 2 stmt: LEU8(stk2,stk2) "call cmp_uint64\ntgz\nbrz %a\n" 2 stmt: LTU8(stk2,stk2) "call cmp_uint64\ntlz\nbrnz %a\n" 2 stmt: GEI4(stk, zero) "tlz\nbrz %a\n" 2 stmt: GTI4(stk, zero) "tgz\nbrnz %a\n" 2 stmt: LEI4(stk, zero) "tgz\nbrz %a\n" 2 stmt: LTI4(stk, zero) "tlz\nbrnz %a\n" 2 stmt: EQI4(stk,zero) "brz %a\n" 1 stmt: EQU4(stk,zero) "brz %a\n" 1 stmt: NEI4(stk,zero) "brnz %a\n" 1 stmt: NEU4(stk,zero) "brnz %a\n" 1 stmt: GEU4(stk, stk) "lit1\nror\ntuck2\nxor\nrrot\nxor\ncgt\nbrz %a\n" 8 stmt: GTU4(stk, stk) "lit1\nror\ntuck2\nxor\nrrot\nxor\nclt\nbrnz %a\n" 8 stmt: LEU4(stk, stk) "lit1\nror\ntuck2\nxor\nrrot\nxor\nclt\nbrz %a\n" 8 stmt: LTU4(stk, stk) "lit1\nror\ntuck2\nxor\nrrot\nxor\ncgt\nbrnz %a\n" 8 stmt: EQF4(stk, stk) "call _ufo_f32_eq\nbrnz %a\n" 2 stmt: LEF4(stk, stk) "call _ufo_f32_le\nbrnz %a\n" 2 stmt: LTF4(stk, stk) "call _ufo_f32_lt\nbrnz %a\n" 2 stmt: GEF4(stk, stk) "call _ufo_f32_lt\nbrz %a\n" 2 stmt: GTF4(stk, stk) "call _ufo_f32_le\nbrz %a\n" 2 stmt: NEF4(stk, stk) "call _ufo_f32_eq\nbrz %a\n" 2 stmt: EQF8(stk2, stk2) "call _ufo_f64_eq\nbrnz %a\n" 2 stmt: LEF8(stk2, stk2) "call _ufo_f64_le\nbrnz %a\n" 2 stmt: LTF8(stk2, stk2) "call _ufo_f64_lt\nbrnz %a\n" 2 stmt: GEF8(stk2, stk2) "call _ufo_f64_lt\nbrz %a\n" 2 stmt: GTF8(stk2, stk2) "call _ufo_f64_le\nbrz %a\n" 2 stmt: NEF8(stk2, stk2) "call _ufo_f64_eq\nbrz %a\n" 2 addr: ADDRGP4 "%a" addr: CNSTP4 "%a" stk: CALLF4(addr) "#\n" 4 stk: CALLI4(addr) "#\n" 4 stk: CALLP4(addr) "#\n" 4 stk: CALLU4(addr) "#\n" 4 stk2: CALLF8(addr) "#\n" 4 stk2: CALLI8(addr) "#\n" 4 stk2: CALLU8(addr) "#\n" 4 stmt: CALLV(addr) "#\n" 4 stmt: CALLB(addr, stk) "#\n" 4 stk: CALLF4(stk) "#\n" 3 stk: CALLI4(stk) "#\n" 3 stk: CALLP4(stk) "#\n" 3 stk: CALLU4(stk) "#\n" 3 stk2: CALLF8(stk) "# ; 2\n" 3 stk2: CALLI8(stk) "# ; 2\n" 3 stk2: CALLU8(stk) "# ; 2\n" 3 stmt: CALLV(stk) "#\n" 3 stmt: CALLB(stk, stk) "#\n" 3 stmt: RETF8(stk2) "\n" 1 stmt: RETI8(stk2) "\n" 1 stmt: RETU8(stk2) "\n" 1 stmt: RETF4(stk) "\n" 1 stmt: RETI4(stk) "\n" 1 stmt: RETU4(stk) "\n" 1 stmt: RETP4(stk) "\n" 1 stmt: RETV "\n" 1 stmt: ARGF4(stk) "#\n" 0 stmt: ARGI4(stk) "#\n" 0 stmt: ARGP4(stk) "#\n" 0 stmt: ARGU4(stk) "#\n" 0 stmt: ARGF8(stk2) "#\n" 0 stmt: ARGI8(stk2) "#\n" 0 stmt: ARGU8(stk2) "#\n" 0 stmt: ASGNB(INDIRB(stk), stk) "#\n" 10 %% /** When ldt and sdt are sorted, will want to use this stmt: ASGNI4(stk, ADDP4(stk, con9)) "swap\nstt +%2\ndrop1\n" 4 stmt: ASGNU4(stk, ADDP4(stk, con9)) "swap\nstt +%2\ndrop1\n" 4 stmt: ASGNP4(stk, ADDP4(stk, con9)) "swap\nstt +%2\ndrop1\n" 4 stmt: ASGNF4(stk, ADDP4(stk, con9)) "swap\nstt +%2\ndrop1\n" 4 stk: INDIRI4(ADDP4(stk, con9)) "swap\nldt +%1\ndrop1\n" 4 stk: INDIRU4(ADDP4(stk,con9)) "swap\nldt +%1\ndrop1\n" 4 stk: INDIRP4(ADDP4(stk, con9)) "swap\nldt +%1\ndrop1\n" 4 stk: INDIRF4(ADDP4(stk, con9)) "swap\nldt +%1\ndrop1\n" 4 */ static void preamble(Symbol f, Symbol caller[], Symbol callee[], int ncalls); static void postamble(Symbol f, Symbol caller[], Symbol callee[], int ncalls); static int makeTemp(Symbol p) { if (!isscalar(p->type) || p->type->size == 8) { p->sclass = AUTO; return 0; } else if (p->sclass == AUTO) { if (p->addressed) { return 0; } else { makeTemporary(p); return 1; } } else if (p->sclass == REGISTER) { makeTemporary(p); return 1; } else { return 0; } } static void local(Symbol p) { if (!makeTemp(p)) { mkauto(p); } } static char* declare_type(Symbol p) { char arg_letter, ret_letter; Type rType; if (isfunc(p->type)) { if (variadic(p->type)) { arg_letter = 'V'; } else { if (p->type->u.f.oldstyle) { arg_letter = 'U'; } else { int arg_size = 0; Type* proto = p->type->u.f.proto; while (*proto) { if (*proto != voidtype) { arg_size += (*proto)->size > 4 ? 2 : 1; } proto++; } if (arg_size < 10) { arg_letter = '0' + arg_size; } else if (arg_size < 16) { arg_letter = 'A' - 10 + arg_size; } else { arg_letter = 'X'; } } } rType = freturn(p->type); if (rType == voidtype) { ret_letter = '0'; } else if (rType->size > 4) { ret_letter = '2'; } else { ret_letter = '1'; } print(".type %s F%c%c\n", p->x.name, arg_letter, ret_letter); } else { int tsize = isscalar(p->type) ? (p->type->size > 4 ? 2 : 1) : 1; print(".type %s _%d\n", p->x.name, tsize); } } static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { int i, size, varargs; Node params; write_log("Function %s\n", f->x.name); offset = local_variable_count = 0; varargs = variadic(f->type); params = stackParameters(caller, callee); gencode(caller, callee); optimise(); framesize = roundup(offset, 4); preamble(f, caller, callee, ncalls); stackemit(params); emitcode(); postamble(f, caller, callee, ncalls); } static Node recalcNode(Node temp, Node calc) { int op = specific(calc->op); if (op == CNST + I || op == CNST + U || op == CNST + P) { int lit = calc->syms[0]->u.c.v.i; if (lit >= -(1<<10) && lit < (1<<10)) { return calc; } else { return temp; } } else { int gop = generic(calc->op); if (gop == CVP) { if (generic(calc->kids[0]->op) == INDIR && calc->kids[0]->kids[0]->op == VREG + P) return calc; } else if (gop == INDIR && calc->kids[0]->op == VREG + P) return calc; return temp; } } static int arguments = 0; static void preamble(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { if (strcmp(f->x.name, "main") == 0) { print(".entry main\n"); } print("%s:\n", f->x.name); if (variadic(f->type)) { print("call _variadic_\n"); } if (framesize) { assert(framesize > 0); if (framesize < 256) { print("addl fp -%d\n", framesize); } else { print("lit -%d\nldfp\nadd\nstfp\n", framesize); } } } static void postamble(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { if (variadic(f->type)) { print("trs\nstfp\n"); } else { if (framesize) { assert(framesize > 0); if (framesize < 256) { print("addl fp %d\n", framesize); } else { print("lit %d\nldfp\nadd\nstfp\n", framesize); } } } print("exit\n\n"); } static void localAddress(int local) { int offset = framesize + local; if (offset) { if (offset < 256) print("ldfp\naddl tos %d\n", offset); else print("ldfp\nlit %d\nadd\n", offset); } else { print("ldfp\n"); } } static void accessLocal(int store, int size, int local, int sign) { char mem; int offset = framesize + local; if (size == 4 && offset < 16) { print("%sloc%d\n", store ? "st" : "ld", offset/4); return; } if (size == 8) { if (store) { accessLocal(1, 4, local, 0); accessLocal(1, 4, local + 4, 0); } else { accessLocal(0, 4, local + 4, 0); accessLocal(0, 4, local, 0); } return; } mem = size < 4 ? (size == 1 ? 'b' : 'w') : 'l' ; if (offset/size < 64) { print("%s%c fp+%d\n", store ? "st" : "ld", mem, offset); } else { if (offset < 256) print("ldfp\naddl tos %d\n", offset); else print("ldfp\nlit %d\nadd\n", offset); if (store) print("st%c\ndrop1\n", mem); else print("ld%c\n", mem); } if (size < 4 && sign && (!store)) { if (size == 1) print("sxb\n"); else print("sxw\n"); } } static int fixedParameters(Type ty) { int i, count = 0; for (i = 0; ty->u.f.proto[i+1]; i++) count += ty->u.f.proto[i]->size == 8 ? 2 : 1; return count; } static void emit2(Node p) { int op = generic(p->op); if (op == ADDRL) { /* Address of local */ localAddress(p->syms[0]->x.offset); } else if (op == INDIR) { assert(p->kids[0]->op != VREG + P); accessLocal(0, opsize(p->op), p->kids[0]->syms[0]->x.offset, optype(p->op) == I); } else if (op == ASGN) { if (p->op == ASGN + B) { int size = p->syms[0]->u.c.v.i; if (size == 4) print("\nswap\nldl\nswap\nstl\ndrop1\n"); else if (size == 8) print("swap\nldli\nrrot\nldl\nrrot\nstli\nstl\ndrop1\n"); else if (size % 4) print("lit %d\ncall __copy__\n", size); else print("lit %d\ncall __copyw__\n", size >> 2); } else { accessLocal(1, opsize(p->op), p->kids[1]->syms[0]->x.offset, optype(p->op) == I); } } else if (op == CALL) { if (variadic(p->syms[0]->type)) { print("lit %d\nstxp\n", arguments - fixedParameters(p->syms[0]->type)); } arguments = 0; if (generic(p->kids[0]->op) == ADDRG) { print("call %s\n", p->kids[0]->syms[0]->x.name); } else { print("icall\n"); } } else if (op == ARG) { if (opsize(p->op) == 8) arguments += 2; else arguments++; } else if (op == LSH) { int shift = p->kids[1]->syms[0]->u.c.v.i & 31; if (shift >= 11) { print("elit 0\n"); shift -= 11; } if (shift >= 11) { print("elit 0\n"); shift -= 11; } while (shift) { print("shl\n"); --shift; } } else if (op == RSH) { int shift = p->kids[1]->syms[0]->u.c.v.i & 31; if (specific(p->op) == I) { if (shift == 31) { print("tlz\ninv\nadd1\n"); } else if (shift == 24) { int i; for (i = 0; i < 8; i++) print("rol\n"); print("sxb\n"); } else { while(shift) { print("asr\n"); --shift; } } } else { if (shift == 31) { print("tlz\n"); } else if (shift > 18) { int mask = (1 << (32 - shift)) - 1; while(shift) { print("rol\n"); --shift; } print("lit %d\nand\n", mask); } else { while(shift) { print("shr\n"); --shift; } } } } else { assert(0); } } static void defconst(int suffix, int size, Value v) { if (suffix == F && size == 4) { float f = v.d; print(".word #%x\n", *(unsigned *)&f); } else if (suffix == F && size == 8) { double d = v.d; print("", d); // Need to refernce d here other wise we get junk in ((unsigned *)&d)[1] // Either a bug in GCC or a bug in the hardware... print(".word #%x\n", ((unsigned *)&d)[1]); print(".word #%x\n", *(unsigned *)&d); } else if (suffix == P) { print(".word #%x\n", (unsigned)v.p); } else if (size == 1) { print(".byte #%x\n", (unsigned)((unsigned char)(suffix == I ? v.i : v.u))); } else if (size == 2) { unsigned int value = (unsigned short)(suffix == I ? v.i : v.u); print(".byte #%x\n", (value >> 8)); print(".byte #%x\n", (value & 0xff)); } else if (size == 4) { print(".word #%x\n", (unsigned)(suffix == I ? v.i : v.u)); } else { print(".word #%x\n", (unsigned)(suffix == I ? v.i : v.u)); print(".word #%x\n", (unsigned)(suffix == I ? (&(v.i))[1] : (&(v.u))[1])); } } static void defaddress(Symbol p) { print(".addr %s\n", p->x.name); /* print(".addr %s\n", p->x.name); */ } static void defstring(int n, char *str) { int i; for (i = 0; i < n; i++) print(".byte %d\n", str[i]); } static void export(Symbol p) { print(".export %s\n", p->x.name); declare_type(p); } static void import(Symbol p) { declare_type(p); // if (!isfunc(p->type)) // print(".extern %s %d\n", p->name, p->type->size); } static void defsymbol(Symbol p) { if (p->scope == LABELS) { p->x.name = stringf("l(%s)", p->name); } else if (p->generated) { p->x.name = stringf("$%s", p->name); } else if (p->scope >= LOCAL && p->sclass == STATIC) { p->x.name = stringf("$%d", genlabel(1)); } else if (p->name[0] == '0' && p->name[1] == 'x') { p->x.name = stringf("#%s", p->name + 2); } else { p->x.name = p->name; } } static void address(Symbol q, Symbol p, long n) { if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN) { // Assembler cannot handle arbitary arithmetic, so have to check for offset. int i; char c; for (i = 0; c = p->x.name[i]; i++) { if (c == '+' || c == '-') { int offset = atoi(p->x.name + i + 1); if (c == '+') offset = -offset; p->x.name[i] = '\0'; n += offset; q->x.name = stringf("%s%s%D", p->x.name, n >= 0 ? "+" : "", n); p->x.name[i] = c; return; } } q->x.name = stringf("%s%s%D", p->x.name, n >= 0 ? "+" : "", n); } else { assert(n <= INT_MAX && n >= INT_MIN); q->x.offset = p->x.offset + n; q->x.name = stringd(q->x.offset); } } static void global(Symbol p) { if (p->type->align != 1) { print(".align %d\n", p->type->align); } print("%s:\n", p->x.name); } static void segment(int n) { switch (n) { case CODE: print(".text\n"); break; case LIT: print(".data\n"); break; case DATA: print(".data\n"); break; case BSS: print(".bss\n"); break; } } static void space(int n) { print(".skip %d\n", n); } static void stabinit(char *, int, char *[]); static void stabline(Coordinate *); static void stabsym(Symbol); static char *currentfile; /* stabinit - initialize stab output */ static void stabinit(char *file, int argc, char *argv[]) { if (file) { print(".file \"%s\"\n", file); currentfile = file; } } /* stabline - emit stab entry for source coordinate *cp */ static void stabline(Coordinate *cp) { if (cp->file && cp->file != currentfile) { print(".file %s\n", cp->file); currentfile = cp->file; } print(".line %d\n", cp->y); } /* stabsym - output a stab entry for symbol p */ static void stabsym(Symbol p) { // if (p == cfunc && IR->stabline) // (*IR->stabline)(&p->src); } static void progbeg(int argc, char *argv[]) { backendflags(argc, argv); print(".text\n"); } static void blockbeg(Env* env) { } static void blockend(Env* env) { } static void progend(void){ if (logfile) fclose(logfile); } Interface ufoIR = { { 1, 1, 0 }, /* char_metrics */ { 2, 2, 0 }, /* short_metrics */ { 4, 4, 0 }, /* int_metrics */ { 4, 4, 0 }, /* long_metrics */ { 8, 4, 1 }, /* long_long_metrics */ { 4, 4, 1 }, /* float_metrics */ { 8, 4, 1 }, /* double_metrics */ { 8, 4, 1 }, /* long_double_metrics */ { 4, 4, 0 }, /* word_metrics */ { 0, 4, 0 }, /* struct_metrics */ 0, /* little_endian */ 0, /* mulops_calls */ 0, /* wants_callb */ 0, /* wants_argb */ 1, /* left_to_right */ 0, /* wants_dag */ 1, /* unsigned_char */ address, blockbeg, blockend, defaddress, defconst, defstring, defsymbol, stackemit, export, function, stackgen, global, import, local, progbeg, progend, segment, space, 0, 0, 0, stabinit, stabline, stabsym, 0, swtch, { 1, /* max_unaligned_load */ 3, /* depth */ recalcNode, makeTemp, NULL, _label, _rule, _nts, _kids, _string, _templates, _isinstruction, _ntname, emit2, { 0, // sub 0, // lsh 0, // rsh 0, // mod 0, // div 0, // lt 0, // le 0, // gt 0 // ge } } };