%{ #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); static int getLocal(Symbol s); static int isCurrentFun(Node); static int isNotCurrentFun(Node); static int isDefinedFun(Node); static int isNotDefinedFun(Node); static int isDefinedVar(Node); static int isNotDefinedVar(Node); static int isAligned(Node); static int isNotAligned(Node); extern void stackemit(Node forest); extern Node stackgen(Node forest); extern void swtch(Symbol label); static int initedVars = 0; // if 1 lcc defined BSS, where not initialized variables are placed static int arguments = 0; static int iElems = 0; // the number of elements in an array static long pendingBits = 0; // the number of elements in an array static int hasPendingBits = 0; // the number of elements in an array static Symbol curFun; #define USR_FUN 1 #define D 0 #define D_ENTER(p) if(D) enterDebug(p); #define D_LEAVE(p) if(D) exitDebug(p); #define D_POINT(p) if(D) traceDebug(p); int intend = 0; static void enterDebug(char* f){ int i; for(i = 0; i < intend;i++){ print("\t"); } intend++; print("enter: %s\n", f); } static void exitDebug(char* f){ int i; intend--; for(i = 0; i < intend;i++){ print("\t"); } print("leave: %s\n", f); } static void traceDebug(char* f){ int i; for(i = 0; i < intend;i++){ print("\t"); } print("trace: %s\n", f); } //Are their 3 Byte Operations? for 24 Bit #define WITH_MULT (0) //Not yet fully flexible in this param #define DATA_WIDTH (32) #define DATA_ADDR_WIDTH (12) #define DATA_BYTES (DATA_WIDTH/8) /* This is log(DATA_BYTES) <-- zweier log) */ #define BYTE_ADDR_BITS (2) #define COPY_BLOCK_SIZE (12) #define MULT_COST (((WITH_MULT^1)*(DATA_WIDTH+3))+1) %} %start stmt %term INDIRP1=1095 %term ADDI1=1333 %term ADDU1=1334 %term ADDP1=1335 %term SUBI1=1349 %term SUBU1=1350 %term SUBP1=1351 %term LOADI1=1253 %term LOADU1=1254 %term LOADP1=1255 %term BANDI1=1413 %term BANDU1=1414 %term BORI1=1445 %term BORU1=1446 %term BXORI1=1461 %term BXORU1=1462 %term LSHI1=1365 %term LSHU1=1366 %term MODI1=1381 %term MODU1=1382 %term RSHI1=1397 %term RSHU1=1398 %term DIVI1=1477 %term DIVU1=1478 %term MULI1=1493 %term MULU1=1494 %term EQI1=1509 %term EQU1=1510 %term GEI1=1525 %term GEU1=1526 %term GTI1=1541 %term GTU1=1542 %term LEI1=1557 %term LEU1=1558 %term LTI1=1573 %term LTU1=1574 %term NEI1=1589 %term NEU1=1590 %term CALLI1=1237 %term CALLU1=1238 %term CALLP1=1239 %term RETI1=1269 %term RETU1=1270 %term RETP1=1271 %term ADDRLP1=1319 %term ADDRGP1=1287 %term ARGI1=1061 %term ARGU1=1062 %term VREGP=711 %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=437 %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 NOOP = 48 %% 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) 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) cnst3: CNSTI4 "" range(a, 3, 3) 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) cnstn: CNSTU4 "%a\n" 2 cnstn: CNSTI4 "%a\n" 2 stk: CNSTI1 "%a\n" 1 stk: CNSTU1 "%a\n" 1 stk: CNSTI2 "%a\n" 1 stk: CNSTU2 "%a\n" 1 stk: CNSTI4 "%a\n" 1 stk: CNSTU4 "%a\n" 1 addr: CNSTP4 "#\n" 1 addr4: CNSTP4 "#\n" ((a->syms[0]->u.c.v.u & 3) ? LBURG_MAX : 1) addr4: CNSTI4 "#\n" ((a->syms[0]->u.c.v.i & 3) ? LBURG_MAX : 1) addr4: CNSTU4 "#\n" ((a->syms[0]->u.c.v.u & 3) ? LBURG_MAX : 1) stmt: stk "drop\n" 1 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: COPYP "dup\n" range(a, 1, 1)+1 sread: COPYP "over\n" range(a, 2, 2)+1 sread: COPYP "2over\nnip\n" range(a, 3, 3)+2 sread: COPYP "any\n" range(a, 0, 0)+1 swrite: STACKP "\n" range(a, 1, 1) swrite: STACKP "swap\n" range(a, 2, 2)+1 swrite: STACKP "-rot\n" range(a, 3, 3)+1 stk: INDIRI1(sread) "\n" 0 stk: INDIRU1(sread) "\n" 0 stk: INDIRI2(sread) "\n" 0 stk: INDIRU2(sread) "\n" 0 stk: INDIRI4(sread) "\n" 0 stk: INDIRU4(sread) "\n" 0 addr: INDIRP4(sread) "\n" 0 stmt: ASGNI1(stk, swrite) "\n" 0 stmt: ASGNU1(stk, swrite) "\n" 0 stmt: ASGNI2(stk, swrite) "\n" 0 stmt: ASGNU2(stk, swrite) "\n" 0 stmt: ASGNI4(stk, swrite) "\n" 0 stmt: ASGNU4(stk, swrite) "\n" 0 stmt: ASGNP4(addr, swrite) "\n" 0 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) addr: TUCKP4(addr) "dup\n" range(a, 1, 1)+1 stmt: TUCKP4(addr) "\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) addr: TUCKP4(addr) "tuck\n" range(a, 2, 2)+1 stmt: TUCKP4(addr) "swap\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) addr: TUCKP4(addr) "-rot\n2over\nnip\n" range(a, 3, 3)+3 stmt: TUCKP4(addr) "-rot\n" range(a, 3, 3) stk: tuck1 "dup\n" 1 stk: tuck2 "tuck\n" 1 stk: tuck3 "-rot\n2over\nnip\n" 3 stmt: tuck1 "\n" 0 stmt: tuck2 "swap\n" 1 stmt: tuck3 "-rot\n" 1 stk: NOOP "nop\n" 1 lAddr: ADDRLP4 "%a" 1 /*No \n so must be printed by assig/indir*/ jAddr: ADDRGP4 "%a" 1 /*No \n so must be printed by Jump*/ addr: ADDRGP4 "ADDR %a\n" 1+isNotDefinedVar(a) addr: ADDRGP4 "%a\n" 1+isDefinedVar(a) addr4: ADDRLP4 "#\n" 4+isAligned(a) /*increased by one to prefer local loads/stores*/ addr: ADDRLP4 "#\n" 4+isNotAligned(a) /*increased by one to prefer local loads/stores*/ addr: addr4 "\n" 0 stmt: ASGNI4(stk, lAddr) "#\n" 2 stmt: ASGNU4(stk, lAddr) "#\n" 2 stmt: ASGNP4(addr, lAddr) "#\n" 2 stmt: ASGNI1(stk, lAddr) "#\n" 7+isAligned(a) stmt: ASGNU1(stk, lAddr) "#\n" 7+isAligned(a) stmt: ASGNI2(stk, lAddr) "#\n" 7+isAligned(a) stmt: ASGNU2(stk, lAddr) "#\n" 7+isAligned(a) stmt: ASGNI1(stk, lAddr) "#\n" 30+isNotAligned(a) stmt: ASGNU1(stk, lAddr) "#\n" 30+isNotAligned(a) stmt: ASGNI2(stk, lAddr) "#\n" 30+isNotAligned(a) stmt: ASGNU2(stk, lAddr) "#\n" 30+isNotAligned(a) stmt: ASGNI1(stk, addr4) "__SAB__\n" 11 stmt: ASGNU1(stk, addr4) "__SAB__\n" 11 stmt: ASGNI2(stk, addr4) "__SAS__\n" 11 stmt: ASGNU2(stk, addr4) "__SAS__\n" 11 stmt: ASGNI1(stk, addr) "__SB__\n" 30 /* Candidate for Hardware Fun if pos */ stmt: ASGNU1(stk, addr) "__SB__\n" 30 stmt: ASGNI2(stk, addr) "__SS__\n" 30 stmt: ASGNU2(stk, addr) "__SS__\n" 30 stmt: ASGNI4(stk, addr) "!\n" 1 stmt: ASGNU4(stk, addr) "!\n" 1 stmt: ASGNP4(addr,addr) "!\n" 1 stk: INDIRI4(lAddr) "#\n" 2 stk: INDIRU4(lAddr) "#\n" 2 addr: INDIRP4(lAddr) "#\n" 2 stk: INDIRI1(lAddr) "#\n" 4+isAligned(a) stk: INDIRU1(lAddr) "#\n" 4+isAligned(a) stk: INDIRI2(lAddr) "#\n" 4+isAligned(a) stk: INDIRU2(lAddr) "#\n" 4+isAligned(a) stk: INDIRI1(lAddr) "#\n" 25+isNotAligned(a) stk: INDIRU1(lAddr) "#\n" 25+isNotAligned(a) stk: INDIRI2(lAddr) "#\n" 25+isNotAligned(a) stk: INDIRU2(lAddr) "#\n" 25+isNotAligned(a) stk: INDIRI1(addr4) "__RAB__\n" 6 stk: INDIRU1(addr4) "__RAB__\n" 6 stk: INDIRI2(addr4) "__RAS__\n" 6 stk: INDIRU2(addr4) "__RAS__\n" 6 stk: INDIRI1(addr) "__RB__\n" 25 /* Candidate for Hardware Fun if pos */ stk: INDIRU1(addr) "__RB__\n" 25 stk: INDIRI2(addr) "__RS__\n" 25 stk: INDIRU2(addr) "__RS__\n" 25 stk: INDIRI4(addr) "@\n" 1 stk: INDIRU4(addr) "@\n" 1 addr: INDIRP4(addr) "@\n" 1 addr4: MULU4(addr4, stk) "*\n" MULT_COST+1 addr4: MULU4(stk, addr4) "*\n" MULT_COST+1 addr4: MULI4(addr4, stk) "*\n" MULT_COST+1 addr4: MULI4(stk, addr4) "*\n" MULT_COST+1 addr4: ADDP4(addr4, zero) "\n" 0 addr4: ADDP4(addr4, cnst4) "1+\n" 1 addr4: ADDP4(addr4, addr4) "+\n" 1 addr4: ADDU4(addr4, addr4) "+\n" 1 addr: ADDP4(addr, addr4) "+\n" 1 addr: ADDU4(addr, addr4) "+\n" 1 addr: ADDP4(addr4, addr) "+\n" 1 addr: ADDU4(addr4, addr) "+\n" 1 addr: ADDP4(addr, zero) "\n" 0 addr: ADDP4(addr, stk) "swap\n__ROL__\n__ROL__\n+\n__ROR__\n__ROR__\n" 6 addr: ADDP4(stk, addr) "__ROL__\n__ROL__\n+\n__ROR__\n__ROR__\n" 5 addr: ADDP4(addr, cnst1) "__ROL__\n__ROL__\n1+\n__ROR__\n__ROR__\n" 5 addr: ADDP4(addr, cnst2) "__ROL__\n1+\n__ROR__\n" 3 addr: ADDP4(addr, cnst4) "1+\n" 1 addr: ADDP4(addr, cnstn) "__ROL__\n__ROL__\n%1\n+\n__ROR__\n__ROR__\n" 6 addr4: SUBP4(addr4, addr4) "-\n" 1 addr: SUBP4(addr, stk) "swap\n__ROL__\n__ROL__\n-\n__ROR__\n__ROR__\n" 6 addr: SUBP4(stk, addr) "__ROL__\n__ROL__\n-\n__ROR__\n__ROR__\n" 5 addr: SUBP4(addr, zero) "\n" 0 addr: SUBP4(addr, cnst1) "__ROL__\n__ROL__\n1-\n__ROR__\n__ROR__\n" 5 addr: SUBP4(addr, cnst2) "__ROL__\n1-\n__ROR__\n" 3 addr: SUBP4(addr, cnst4) "1-\n" 1 addr: SUBP4(addr, cnstn) "__ROL__\n__ROL__\n%1\n-\n__ROR__\n__ROR__\n" 6 addr4: LSHI4(stk, cnst2) "\n" 0 addr4: LSHU4(stk, cnst2) "\n" 0 addr4: LSHI4(stk, cnst3) "1\nshift\n" 2 addr4: LSHU4(stk, cnst3) "1\nshift\n" 2 addr4: LSHI4(stk, cnst4) "2\nshift\n" 3 addr4: LSHU4(stk, cnst4) "2\nshift\n" 3 addr4: CVPU4(addr4) "\n" 0 addr: CVPU4(addr) "\n" 0 stk: addr "__ROL__\n__ROL__\n" 2 addr: stk "__ROR__\n__ROR__\n" 2 stk: CVII1(stk) "\n" 0 stk: CVUU1(stk) "255\nand\n" 2 stk: CVII2(stk) "\n" 0 stk: CVUU2(stk) "65535\nand\n" 2 stk: CVII4(stk) "\n" 0 stk: CVUI4(stk) "\n" 0 stk: CVIU4(stk) "\n" 0 stk: CVUU4(stk) "\n" 0 stk: CVUP4(stk) "\n" 0 stk: ADDI4(stk, stk) "+\n" 1 /*Integerarithmetic: add two values*/ stk: ADDU4(stk, stk) "+\n" 1 /*Unsignedarithmetic: add two values*/ stk: ADDI4(cnst1, stk) "1+\n" 1 /*Integerarithmetic: add two values*/ stk: ADDU4(cnst1, stk) "1+\n" 1 /*Unsignedarithmetic: add two values*/ stk: ADDI4(stk, cnst1) "1+\n" 1 /*Integerarithmetic: add two values*/ stk: ADDU4(stk, cnst1) "1+\n" 1 /*Unsignedarithmetic: add two values*/ stk: SUBI4(stk, stk) "-\n" 1 /*Integerarithmetic: subtract two values*/ stk: SUBU4(stk, stk) "-\n" 1 /*Unsignedarithmetic: subtract two values*/ stk: SUBI4(stk, cnst1) "1-\n" 1 /*Integerarithmetic: subtract two values*/ stk: SUBU4(stk, cnst1) "1-\n" 1 /*Unsignedarithmetic: subtract two values*/ stk: BCOMI4(stk) "invert\n" 1 /*invert a integer*/ stk: BCOMU4(stk) "invert\n" 1 /*invert a unsigned integer*/ stk: NEGI4(stk) "negate\n" 1 /*negate a integer*/ stk: BANDI4(stk, stk) "and\n" 1 /*Logische operation: bitwise and of 2 values*/ stk: BORI4(stk, stk) "or\n" 1 /*Logische operation: bitwise or of 2 values*/ stk: BXORI4(stk, stk) "xor\n" 1 /*Logische operation: bitwise xor of 2 values*/ stk: BANDU4(stk, stk) "and\n" 1 /*Logische operation: bitwise and of 2 values */ stk: BORU4(stk, stk) "or\n" 1 /*Logische operation: bitwise or of 2 values */ stk: BXORU4(stk, stk) "xor\n" 1 /*Logische operation: bitwise xor of 2 values */ stk: DIVI4(stk, stk) "/\n" DATA_WIDTH+3 /*Integerarithmetic: divide by a value (cost depends on uForth Compiler, we assume he chose most performant variant)*/ stk: LSHI4(stk, stk) "shift\n" 1+(DATA_WIDTH+1)/2 /*Integerarithmetic: lshift by a value (cost depends on uForth Compiler, we assume a streight forward variant)*/ stk: MODI4(stk, stk) "mod\n" DATA_WIDTH+4 /*Integerarithmetic: mod a value (cost depends on uForth Compiler, we assume he chose most performant variant)*/ stk: MULI4(stk, stk) "*\n" MULT_COST+1 /*Integerarithmetic: multiply 2 values (cost may depend on uForth Compiler, we assume he chose most performant variant)*/ stk: RSHI4(stk, stk) "negate\nashift\n" 2+(DATA_WIDTH+1)/2 /*Integerarithmetic: rshift by a value (cost depends on uForth Compiler, we assume a streight forward variant)*/ stk: DIVU4(stk, stk) "u/\n" DATA_WIDTH+3 /*Unsignedarithmetic: divide by a value (cost depends on uForth Compiler, we assume he chose most performant variant)*/ stk: LSHU4(stk, stk) "shift\n" 1+(DATA_WIDTH+1)/2 /*Unsignedarithmetic: lshift by a value (cost depends on uForth Compiler, we assume a streight forward variant) (hardware fun candidate) */ stk: MODU4(stk, stk) "umod\n" DATA_WIDTH+4 /*Unsignedarithmetic: mod a value (cost depends on uForth Compiler, we assume he chose most performant variant)*/ stk: MULU4(stk, stk) "*\n" MULT_COST+1 /*Unsignedarithmetic: multiply 2 values (cost may depend on uForth Compiler, we assume most performant variant)*/ stk: RSHU4(stk, stk) "negate\nshift\n" 2+(DATA_WIDTH+1)/2 /*Unsignedarithmetic: rshift by a value (cost depends on uForth Compiler, we assume a streight forward variant)*/ stmt: EQI4(stk, stk) "-\n0=\n?GOTO %a ( jump if equal )\n" 3 /*Branchoperation: Branch if equal*/ stmt: EQU4(stk, stk) "-\n0=\n?GOTO %a ( jump if equal )\n" 3 /*Branchoperation: Branch if equal (DO WE NEED THIS)*/ stmt: GEI4(stk, stk) "<\n0=\n?GOTO %a ( jump if greater or equal )\n" 3 /*Branchoperation: Branch if greater or equal*/ /* check this in asm impl*/ stmt: GEU4(stk, stk) "u<\n0=\n?GOTO %a ( jump if greater or equal )\n" 5 /*Branchoperation: Branch if greater or equal*/ /* check this in asm impl*/ stmt: GTI4(stk, stk) ">\n?GOTO %a ( jump if greater )\n" 3 /*Branchoperation: Branch if greater*/ /* check this in asm impl*/ stmt: GTU4(stk, stk) "u>\n?GOTO %a ( jump if greater )\n" 5 /*Branchoperation: Branch if greater*/ /* check this in asm impl*/ stmt: LEI4(stk, stk) ">\n0=\n?GOTO %a ( jump if less or equal )\n" 3 /*Branchoperation: Branch if less or equal*/ stmt: LEU4(stk, stk) "u>\n0=\n?GOTO %a ( jump if less or equal )\n" 5 /*Branchoperation: Branch if less or equal*/ stmt: LTI4(stk, stk) "<\n?GOTO %a ( jump if less )\n" 3 /*Branchoperation: Branch if less*/ stmt: LTU4(stk, stk) "u<\n?GOTO %a ( jump if less )\n" 5 /*Branchoperation: Branch if less*/ stmt: NEI4(stk, stk) "-\n?GOTO %a ( jump if not equal )\n" 3 /*Branchoperation: Branch if not equal*/ stmt: NEU4(stk, stk) "-\n?GOTO %a ( jump if not equal )\n" 3 /*Branchoperation: Branch if not equal (DO WE NEED THIS)*/ stmt: CALLV(jAddr) "%0\n" 1+isNotCurrentFun(a)+isDefinedFun(a) stk: CALLI4(jAddr) "%0\n" 1+isNotCurrentFun(a)+isDefinedFun(a) stk: CALLU4(jAddr) "%0\n" 1+isNotCurrentFun(a)+isDefinedFun(a) addr: CALLP4(jAddr) "%0\n" 1+isNotCurrentFun(a)+isDefinedFun(a) stmt: CALLV(jAddr) "RECURSE ( recursive call to function )\n" 1+isCurrentFun(a) stk: CALLI4(jAddr) "RECURSE ( recursive call to function )\n" 1+isCurrentFun(a) stk: CALLU4(jAddr) "RECURSE ( recursive call to function )\n" 1+isCurrentFun(a) addr: CALLP4(jAddr) "RECURSE ( recursive call to function )\n" 1+isCurrentFun(a) stmt: CALLV(jAddr) "CALL %0 ( call to function )\n" 1+isNotCurrentFun(a)+isNotDefinedFun(a) stk: CALLI4(jAddr) "CALL %0 ( call to function )\n" 1+isNotCurrentFun(a)+isNotDefinedFun(a) stk: CALLU4(jAddr) "CALL %0 ( call to function )\n" 1+isNotCurrentFun(a)+isNotDefinedFun(a) addr: CALLP4(jAddr) "CALL %0 ( call to function )\n" 1+isNotCurrentFun(a)+isNotDefinedFun(a) stmt: CALLV(addr) "EXECUTE ( call to function pointer )\n" 1 stk: CALLI4(addr) "EXECUTE ( call to function pointer )\n" 1 stk: CALLU4(addr) "EXECUTE ( call to function pointer )\n" 1 addr: CALLP4(addr) "EXECUTE ( call to function pointer )\n" 1 stmt: RETI4(stk) "( return int )\n" 0 /*Return Int (is already on Datastack, because we have evaluated it there)*/ stmt: RETU4(stk) "( return uint )\n" 0 /*Return unsigned Int (is already on Datastack, because we have evaluated it there)*/ stmt: RETP4(addr) "( return addr )\n" 0 /*Return unsigned Int (is already on Datastack, because we have evaluated it there)*/ stmt: RETV "" 0 stmt: ARGI4(stk) "#\n" 0 /*Push int parameter for function call*/ stmt: ARGU4(stk) "#\n" 0 /*Push unsigned parameter for function call*/ stmt: ARGP4(addr) "#\n" 0 /*Push unsigned parameter for function call*/ stmt: JUMPV(jAddr) "GOTO %0\n" 1 /*Branchoperation: unconditional branch*/ stmt: JUMPV(addr) "branch\n" 1 /*Branchoperation: unconditional branch (to pointer)*/ stmt: LABELV "Label %a\n" 0 /*Define a Label at current position*/ stmt: ASGNB(INDIRB(addr),addr)"#\n" 20 /*Make Fun which does loo @ iTermSize and def costs*/ %% /* * function for increased cost, when a function call not points to the current function * We do not use LBURG Max, because we want to be able to use it with a + after alla */ static int isCurrentFun(Node call){ D_ENTER("isCurrentFun") int op = specific(call->op); if(op == CALL+I || op == CALL+P || op == CALL+V || op == CALL+U){ //second is needed because call to pointer has no sym (because is just a pointer) if(curFun != NULL && call->kids[0]->syms[0] && strcmp(call->kids[0]->syms[0]->x.name, curFun->x.name) == 0){ D_LEAVE("isCurrentFun") return 0; } else { D_LEAVE("isCurrentFun") return LBURG_MAX; } } D_LEAVE("isCurrentFun") return LBURG_MAX; } /* * function for increased cost, when a function call points to the current function * We do not use LBURG Max, because we want to be able to use it with a + after alla */ static int isNotCurrentFun(Node call){ D_ENTER("isNotCurrentFun") int op = specific(call->op); if(op == CALL+I || op == CALL+P || op == CALL+V || op == CALL+U){ //second is needed because call to pointer has no sym (because is just a pointer) if(curFun != NULL && call->kids[0]->syms[0] && strcmp(call->kids[0]->syms[0]->x.name, curFun->x.name) == 0){ D_LEAVE("isNotCurrentFun") return LBURG_MAX; } else { D_LEAVE("isNotCurrentFun") return 0; } } D_LEAVE("isNotCurrentFun") return 0; } /* * function for increased cost, when a Function Symbol is not already defined * We do not use LBURG Max, because we want to be able to use it with a + after alla */ static int isDefinedFun(Node n){ D_ENTER("isDefinedFun") int op = specific(n->op); if(op == CALL+I || op == CALL+P || op == CALL+V){ //first is needed because call to pointer has no sym (because is just a pointer) if(n->kids[0]->syms[0] && (n->kids[0]->syms[0]->x.offset == 1 || n->kids[0]->syms[0]->x.name[0] != '_')){ D_LEAVE("isDefinedFun") return 0; } else { D_LEAVE("isDefinedFun") return LBURG_MAX; } } D_LEAVE("isDefinedFun") return LBURG_MAX; } /* * function for increased cost, when a Function Symbol is already defined * We do not use LBURG Max, because we want to be able to use it with a + after alla */ static int isNotDefinedFun(Node n){ D_ENTER("isNotDefinedFun") int op = specific(n->op); if(op == CALL+I || op == CALL+P || op == CALL+V){ //first is needed because call to pointer has no sym (because is just a pointer) if(n->kids[0]->syms[0] && (n->kids[0]->syms[0]->x.offset == 1 || n->kids[0]->syms[0]->x.name[0] != '_')){ D_LEAVE("isNotDefinedFun") return LBURG_MAX; } else { D_LEAVE("isNotDefinedFun") return 0; } } D_LEAVE("isNotDefinedFun") return 0; } /* * function for increased cost, when a Function Symbol is not already defined * We do not use LBURG Max, because we want to be able to use it with a + after alla */ static int isDefinedVar(Node n){ D_ENTER("isDefinedVar") int op = specific(n->op); if(op == ADDRG+P || op == ADDRG+B){ if(n->syms[0]->x.offset == 2){ D_LEAVE("isDefinedVar") return 0; } else { D_LEAVE("isDefinedVar") return LBURG_MAX; } } D_LEAVE("isDefinedVar") return LBURG_MAX; } /* * function for increased cost, when a Function Symbol is already defined * We do not use LBURG Max, because we want to be able to use it with a + after alla */ static int isNotDefinedVar(Node n){ D_ENTER("isNotDefinedVar") int op = specific(n->op); if(op == ADDRG+P || op == ADDRG+B){ if(n->syms[0]->x.offset == 2){ D_LEAVE("isNotDefinedVar") return LBURG_MAX; } else { D_LEAVE("isNotDefinedVar") return 0; } } D_LEAVE("isNotDefinedVar") return 0; } static int isAligned(Node n){ D_ENTER("isAligned") int op = specific(n->op); if (op == ADDRL + P) { //calculates the global adress in byte format int index = getLocal(n->syms[0]); //we do not need the offset if ((index & ((1 << BYTE_ADDR_BITS)-1) << (DATA_WIDTH - BYTE_ADDR_BITS)) == 0){ D_LEAVE("isAligned") return 0; } else { D_LEAVE("isAligned") return LBURG_MAX; } } else if (op == ASGN + I || op == ASGN + U || op == ASGN + P) { if(n->kids[1]->syms[0]){ int index = getLocal(n->kids[1]->syms[0]); if(index < (1 << (DATA_WIDTH-BYTE_ADDR_BITS))){ D_LEAVE("isAligned") return 0; } else { D_LEAVE("isAligned") return LBURG_MAX; } } } else if (op == INDIR + I || op == INDIR + U || op == INDIR + P) { if(n->kids[0]->syms[0]){ int index = getLocal(n->kids[0]->syms[0]); if(index < (1 << (DATA_WIDTH-BYTE_ADDR_BITS))){ D_LEAVE("isAligned") return 0; } else { D_LEAVE("isAligned") return LBURG_MAX; } } } D_LEAVE("isAligned") return LBURG_MAX; } static int isNotAligned(Node n){ D_ENTER("isNotAligned") int op = specific(n->op); if (op == ADDRL + P) { //calculates the global adress in byte format int index = getLocal(n->syms[0]); //we do not need the offset if ((index & ((1 << BYTE_ADDR_BITS)-1) << (DATA_WIDTH - BYTE_ADDR_BITS)) == 0){ D_LEAVE("isNotAligned") return LBURG_MAX; } else { D_LEAVE("isNotAligned") return 0; } } else if (op == ASGN + I || op == ASGN + U || op == ASGN + P) { if(n->kids[1]->syms[0]){ int index = getLocal(n->kids[1]->syms[0]); if(index < (1 << (DATA_WIDTH-BYTE_ADDR_BITS))){ D_LEAVE("isNotAligned") return LBURG_MAX; } else { D_LEAVE("isNotAligned") return 0; } } } else if (op == INDIR + I || op == INDIR + U || op == INDIR + P) { if(n->kids[0]->syms[0]){ int index = getLocal(n->kids[0]->syms[0]); if(index < (1 << (DATA_WIDTH-BYTE_ADDR_BITS))){ D_LEAVE("isNotAligned") return LBURG_MAX; } else { D_LEAVE("isNotAligned") return 0; } } } D_LEAVE("isNotAligned") return 0; } 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) { D_ENTER("makeTemp") if (!isscalar(p->type) || p->type->size == 8) { p->sclass = AUTO; D_LEAVE("makeTemp") return 0; } else if (p->sclass == AUTO) { if (p->addressed) { D_LEAVE("makeTemp") return 0; } else { makeTemporary(p); D_LEAVE("makeTemp") return 1; } } else if (p->sclass == REGISTER) { makeTemporary(p); D_LEAVE("makeTemp") return 1; } else { D_LEAVE("makeTemp") return 0; } D_LEAVE("makeTemp") } static void local(Symbol p) { D_ENTER("local") //Do align local Blocks so we do not have to do tons of unaligned block copies (which are compilcated and do slow down everything if(p->type->size > DATA_BYTES){ p->type->size = roundup(p->type->size, DATA_BYTES); } if (isfloat(p->type)) { error("No floating point types supported by MicroCore TM\n"); assert(0); } if (!makeTemp(p)) { mkauto(p); } D_LEAVE("local") } static void optimiseLocals(){ D_ENTER("optimiseLocals") //1. Find all active vars (have store & loads) //2. Sort by Size //3. Use Same Slot, if Same Size and do not Overlap //4. Identify Standalones (No Overlap @ All) which we can optimise (have no pointer too it, addressed == 0) //5. Mark Stanalones to Use >r r> //6. Adapt alignement on semi filled slots (use the whole slot, so we have effective store loads) //7. Update nodes to use ASSIG4 and INDIR4 for the adapted slots Symbol D_LEAVE("optimiseLocals") } static void function(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { D_ENTER("function") int i, size, varargs; Node params; if(f->x.offset == 1){ D_LEAVE("function") return; } if(USR_FUN && f->name[0] == '_' && f->name[strlen(f->name)-1] == '_'){ f->x.name = malloc((strlen(f->name)-1)*sizeof(char)); strncpy(f->x.name,f->name+1,strlen(f->name)-2); f->x.offset = 1; D_LEAVE("function") return; } f->x.name = stringf("_%s", f->name); //calcs the functions name f->x.offset = 1; //Mark as defined function (misuse offset == 1 for this) //Sill ok or is used for stack Stuff??? curFun = f; offset = local_variable_count = 0; varargs = variadic(f->type); params = stackParameters(caller, callee); gencode(caller, callee); optimise(); //Optimises Stack, generate Local Spillings optimiseLocals(); //Optimise Locals framesize = roundup(offset, DATA_BYTES); preamble(f, caller, callee, ncalls); stackemit(params); emitcode(); postamble(f, caller, callee, ncalls); D_LEAVE("function") } static Node recalcNode(Node temp, Node calc) { D_ENTER("recalcNode") int op = specific(calc->op); if (generic(calc->op) == CNST || op == ADDRG + P) { D_LEAVE("recalcNode") return calc; } else if (op == LSH + I) { if (specific(calc->kids[1]->op) == CNST + I && calc->kids[1]->syms[0]->u.c.v.i == 2) { int lhs_op = generic(calc->kids[0]->op); if (lhs_op == INDIR) { int addr_op = specific(calc->kids[0]->kids[0]->op); if (addr_op == ADDRL + P || addr_op == ADDRG + P || addr_op == VREG + P) { D_LEAVE("recalcNode") return calc; } } } } D_LEAVE("recalcNode") return temp; } static void preamble(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { int fSize; D_ENTER("preamble") Type retType = freturn(f->type); int params = 0; print(": %s\n", f->x.name); //define the uForth word while(caller[params]) params++; print("( %d parameters ) \n", params); if (variadic(f->type)) { error("Varadic Arguments not yet supported\n"); assert(0); } if (framesize) { if((framesize & ((1 << BYTE_ADDR_BITS)-1)) != 0){ error("Wrong Framesize Alignement\n"); assert(0); } fSize = framesize >> BYTE_ADDR_BITS; if (fSize == 1) { print("0\n>r\n0\n>r ( allocate 1 local variable )\n"); //try later if we can use TOR and do >R r> then } else { print("0\n>r\nrsp@\n%d\n-\nrsp! ( allocate %d local variables )\n", fSize, fSize); //try later if we can use TOR and do >R r> then } } D_LEAVE("preamble") } static void postamble(Symbol f, Symbol caller[], Symbol callee[], int ncalls) { int i; int fSize; D_ENTER("postamble") if (variadic(f->type)) { error("Varadic Arguments not yet supported\n"); assert(0); } else { if (framesize) { if((framesize & ((1 << BYTE_ADDR_BITS)-1)) != 0){ error("Wrong Framesize Alignement\n"); assert(0); } fSize = framesize >> BYTE_ADDR_BITS; if (fSize < 4) { for(i = 0; i < fSize+1;i++) print("rdrop\n"); //drop each local print("( deallocate %d local Variables )\n",fSize); } else { print("\nrsp@\n%d\n+\nrsp!\nrdrop ( deallocate %d local variables )\n",fSize, fSize); } } } if (strcmp(f->name, "isr")) { // if not a ISR exit normal print(";\n\n"); } else { // else exit with IRET and assert that there are no parameters if(callee[0] || caller[0]){ error("Illegal isr Function\n"); assert(0); } print("\tIRET\n;\n\n"); //Do interrupt return and word ending } D_LEAVE("postamble") } static int fixedParameters(Type ty) { int i; D_ENTER("fixedParameters") for (i = 2; ty->u.f.proto[i]; i++); D_LEAVE("fixedParameters") return i - 1; } static int getLocal(Symbol s) { int offset = s->x.offset + framesize; //we address locals by offset to rsp (but this is subtracted not added) (we still track negative offsets for global adress calculations) return ((offset >> BYTE_ADDR_BITS)+1) | ((offset & ((1 << BYTE_ADDR_BITS)-1)) << (DATA_WIDTH-BYTE_ADDR_BITS)); } static void printStoreLocal(Symbol local, int size) { int i; D_ENTER("printStoreLocal") unsigned int index = getLocal(local); if(size == 4) { print("%d\nl!\n", index); } else if(index < (1 << (DATA_WIDTH-BYTE_ADDR_BITS))){ print("%d\nl@\n", index); int mask = -1; for(i = 0; i < size; i++){ mask = (mask << 8); } print("%d\nand\nor\n", mask); print("%d\nl!\n", index); } else { print("%d\shift\n", (index >> (DATA_WIDTH-BYTE_ADDR_BITS))*8); print("%d\nl@\n", index & ~(3 << (DATA_WIDTH-BYTE_ADDR_BITS))); int mask = -1; for(i = 0; i < size; i++){ mask = (mask << 8); } for(i = 0; i < (index >> (DATA_WIDTH-BYTE_ADDR_BITS)); i++){ mask = (mask << 8) | 0xFF; } print("%d\nand\nor\n", mask); print("%d\nl!\n", index & ~(3 << (DATA_WIDTH-BYTE_ADDR_BITS))); } D_LEAVE("printStoreLocal") } static void printReadLocal(Symbol local, int size) { int i; D_ENTER("printReadLocal") unsigned int index = getLocal(local); if(size == 4) { print("%d\nl@\n", index); } else if(index < (1 << (DATA_WIDTH-BYTE_ADDR_BITS))){ print("%d\nl@\n", index); int mask = 0; for(i = 0; i < size; i++){ mask = (mask << 8) | 0xFF; } print("%d\nand\n", mask); } else { print("%d\nl@\n", index & ~(3 << (DATA_WIDTH-BYTE_ADDR_BITS))); print("%d\shift\n", -((index >> (DATA_WIDTH-BYTE_ADDR_BITS))*8)); int mask = 0; for(i = 0; i < size; i++){ mask = (mask << 8) | 0xFF; } print("%d\nand\n", mask); } D_LEAVE("printReadLocal") } static void printbits(long i) { D_ENTER("printbits") if(i >= (1L << DATA_WIDTH)){ error("To Large Bitconstant %d\n",i); assert(0); } if(i >= (1L << (DATA_WIDTH-1))){ print("%d\n",(-1L << DATA_WIDTH) | i); } else { print("%d\n", i); } D_LEAVE("printbits") } static void structcopy(int iTermSize) { //assign Struct (need block copy) D_ENTER("structcopy") iTermSize = (roundup(iTermSize, DATA_BYTES) >> BYTE_ADDR_BITS); if (iTermSize <= COPY_BLOCK_SIZE) { //is their only one block to copy? print("%d\n+\n>r\n", iTermSize-1); //increment destination address by term size and push it on return stack if(iTermSize == 1){ print("@\n"); } else if(iTermSize == 2){ print("ld\n1+\n@\n"); } else { print("%d\nFOR\nld\n1+\nNEXT\n@\n", iTermSize-2); } print("r>\n"); if(iTermSize == 1){ print("!\n"); } else if(iTermSize == 2){ print("st\n1-\n!\n"); } else { print("%d\nFOR\nst\n1-\nNEXT\n!\n", iTermSize-2); } } else { //is their more than one block to copy? print(" MULTI BLOCK COPY NOT YET DONE "); //increment destination address by block size and push it on return stack } D_LEAVE("structcopy") } static void emit2(Node p) { D_ENTER("emit2") int op = specific(p->op); int size = opsize(p->op); if (op == ADDRL + P) { //calculates the global adress in byte format int index = getLocal(p->syms[0])-1; //we do not need the offset if (index){ print("rsp@\n%d\n+\n", index); } else { print("rsp@\n"); } } else if (op == INDIR + I || op == INDIR + U || op == INDIR + P) { printReadLocal(p->kids[0]->syms[0], size); } else if (op == ASGN + I || op == ASGN + U || op == ASGN + P) { printStoreLocal(p->kids[1]->syms[0], size); } else if (op == ASGN+B){ structcopy(p->syms[0]->u.c.v.i); } else if(op == CALL+I || op == CALL+U || op == CALL+P || op == CALL+V){ if (variadic(p->syms[0]->type)) { print("%d\n", arguments - fixedParameters(p->syms[0]->type)); } arguments = 0; } else if (op == CNST + P || op == CNST + I || op == CNST + U) { //Constant usesd as Adress unsigned int bytes = p->syms[0]->u.c.v.i; long addr = bytes >> BYTE_ADDR_BITS; long offset = bytes & ((1 << BYTE_ADDR_BITS)-1); if (offset) { addr = addr | (offset << (DATA_WIDTH - BYTE_ADDR_BITS)); } printbits(addr); } else if (op == ARG + P || op == ARG + I || op == ARG + F || op == ARG + U) { arguments++; } else { print("Error unexpected op\n"); } D_LEAVE("emit2") } static void printPending(){ D_ENTER("printPending") if(hasPendingBits){ print(" "); printbits(pendingBits); print(" ,\n"); pendingBits = 0; hasPendingBits = 0; } D_LEAVE("printPending") } static void defconst(int suffix, int size, Value v) { D_ENTER("defconst") long valueBits = 0; int shift = ((iElems*size) % DATA_BYTES)*8; if(shift == 0){ printPending(); } if (suffix == P){ //differ between int and pointer, other field holds the value valueBits = v.p; }else if (suffix == I){ valueBits = v.i; }else if (suffix == U){ valueBits = v.u; }else { error("No floating point types supported by MicroCore TM\n"); assert(0); } hasPendingBits = 1; pendingBits = pendingBits | valueBits << shift; iElems++; D_LEAVE("defconst") } static void defaddress(Symbol p) { D_ENTER("defaddress") print("%s\n,", p->x.name); //print the address and a , to fill the field. use ADDR to be able to also Fetch forward references iElems++; //one element filled (for arrays, structs) IS THIS NEEDED??? D_LEAVE("defaddress") } static void defstring(int n, char *str) { D_ENTER("defstring") int i = 0; //needed as counter for multi char Strings int shift = 0; while(i < n){ //print each char shift = (i % DATA_BYTES)*8; if(shift == 0){ printPending(); } hasPendingBits = 1; pendingBits = pendingBits | (str[i++] << shift); } iElems++; //one element filled (for arrays, structs) IS THIS NEEDED??? D_LEAVE("defstring") } static void export(Symbol f) { D_ENTER("export") if(USR_FUN && f->x.offset != 1 && f->name[0] == '_' && f->name[strlen(f->name)-1] == '_'){ f->x.name = malloc((strlen(f->name)-1)*sizeof(char)); strncpy(f->x.name,f->name+1,strlen(f->name)-2); f->x.offset = 1; } D_LEAVE("export") } static void import(Symbol f) { D_ENTER("import") if(USR_FUN && f->x.offset != 1 && f->name[0] == '_' && f->name[strlen(f->name)-1] == '_'){ f->x.name = malloc((strlen(f->name)-1)*sizeof(char)); strncpy(f->x.name,f->name+1,strlen(f->name)-2); f->x.offset = 1; } D_LEAVE("import") } static void defsymbol(Symbol p) { D_ENTER("defsymbol") if (p->scope >= LOCAL && p->sclass == STATIC) { D_POINT("LOCAL_STATIC") p->x.name = stringf("a_%d", genlabel(1)); //generate a name } else if (p->scope == LABELS) { D_POINT("LABEL") p->x.name = stringf("lbl_%s", p->name); } else if (p->generated){ D_POINT("GENERATED") p->x.name = stringf("x_%s", p->name); } else if (p->temporary){ D_POINT("TEMPORARY") p->x.name = stringf("tmp_%s", p->name); } else if (p->scope == GLOBAL){ D_POINT("GLOBAL") if(USR_FUN && p->name[0] == '_' && p->name[strlen(p->name)-1] == '_'){ p->x.name = malloc((strlen(p->name)-1)*sizeof(char)); strncpy(p->x.name,p->name+1,strlen(p->name)-2); p->x.offset = 1; } else { p->x.name = stringf("_%s", p->name); } } else { D_POINT("ELSE") if(!(p->scope != CONSTANTS || isint(p->type) || isptr(p->type))){ error("Unsupported Symbol definition\n"); assert(0); } p->x.name = p->name; } D_LEAVE("defsymbol") } static void address(Symbol q, Symbol p, long n) { // The problem of accessing global, static or extern variables has to be solved by uFortH int bOffset; int wOffset; int offset; D_ENTER("address") int neg = 0; if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN){ q->x.offset = p->x.offset; //take over the global offset, because we use it as marker flag in globals if(n < 0){ neg = 1; n = n*-1; } if(n % 4 == 0){ if(neg){ q->x.name = stringf("%s\n%D\n-", p->x.name, n >> BYTE_ADDR_BITS); } else { q->x.name = stringf("%s\n%D\n+", p->x.name, n >> BYTE_ADDR_BITS); } } else if(n % 2 == 0){ if(neg){ q->x.name = stringf("%s\n__ROL__\n%D\n-\n__ROR__", p->x.name, n >> 1); } else { q->x.name = stringf("%s\n__ROL__\n%D\n+\n__ROR__", p->x.name, n >> 1); } } else { if(neg){ q->x.name = stringf("%s\n__ROL__\n__ROL__\n%D\n-\n__ROR__\n__ROR__", p->x.name, n); } else { q->x.name = stringf("%s\n__ROL__\n__ROL__\n%D\n+\n__ROR__\n__ROR__", p->x.name, n); } } } else { //In case of local variables we need to calculate the offset of the variable on the return stack assert(n <= INT_MAX); //check that we are still a int q->x.offset = p->x.offset + n; q->x.name = stringd(q->x.offset); //update the name } D_LEAVE("address") } /* * globalarray() handles global arrays declaration and initialisationaccording to their type */ static void globalarray(Type t, Symbol p) { D_ENTER("globalarray") switch(t->type->op) { //Some array types need special handling case CHAR: case INT: case SHORT: case LONG: case CONST: case POINTER: case ENUM: case STRUCT: //Standard case, direct number or pointer printPending(); print("\nCreate %s\n", p->x.name); //Print uForth variable creation code p->x.offset = 2; //Mark as defined Var (Missuse offset == 2 for this) if(initedVars == 0) print("%d\nalloc\n", roundup(t->size, DATA_BYTES) >> BYTE_ADDR_BITS); //if it is not inited instantly, reserve enougth space break; case ARRAY: //Nested array special handling globalarray(t->type, p); //recursivel cyll this function for nested type break; case FLOAT: case DOUBLE: //Unsupported floationgpoint array types error("No floating point types supported by MicroCore TM\n"); assert(0); break; case UNSIGNED: //CHANGE THIS //Unsupported unsigned arry types error("No unsigned types supported by MicroCore TM\n"); assert(0); break; default: //Everything else is not supported error("No specified type: %d\n ", t->type->op); assert(0); } D_LEAVE("globalarray") } /* * global() handles global variables, which basically means it formats the output * of those global variables */ static void global(Symbol p) { iElems = 0; D_ENTER("global") switch(p->type->op) { //different cases for different types case CHAR: case INT: case SHORT: case LONG: case CONST: case POINTER: case ENUM: case STRUCT: //Standard case, direct number or pointer printPending(); print("\nCreate %s\n", p->x.name); //Print uForth variable creation code p->x.offset = 2; //Mark as defined Var (Missuse offset == 2 for this) //Can we still do this or is this used for stack offsets???? if(initedVars == 0) print("%d\nalloc\n", roundup(p->type->size, DATA_BYTES) >> 2); //if it is not inited instantly, reserve enougth space break; case ARRAY: //Array special handling globalarray(p->type, p); //forward to array creation function break; case FLOAT: case DOUBLE: //Unsupported floationgpoint array types error("No floating point types are supported by MicroCore TM\n"); assert(0); break; case UNSIGNED: //Unsupported unsigned arry types //Make Supported error("No unsigned types are supported by MicroCore TM\n"); assert(0); break; default: //Everything else is not supported error("No specified type: %d\n ", p->type->op); assert(0); } D_LEAVE("global") } static void segment(int n) { //begin Initialisation Block if we need it and are not already in D_ENTER("segment") if ((n == DATA || n == LIT) && initedVars == 0){ print("\nINITIALISED\n"); //print uForth directive initedVars = 1; //mark that we are in init Block //end Initialisation Block if we don't it and are in it } else if ((n != DATA && n != LIT) && initedVars == 1){ printPending(); print("\nUNINITIALISED\n\n"); //print uForth directive initedVars = 0; //mark that we are not in init Block } D_LEAVE("segment") } static void space(int n) { //Is this ok or do we ned to do nops D_ENTER("space") print("\n"); D_LEAVE("space") } static void stabinit(char *, int, char *[]); static void stabline(Coordinate *); static void stabsym(Symbol); static char *currentfile; /* stabinit - initialize stab output */ //not passed currenty static void stabinit(char *file, int argc, char *argv[]) { if (file) { print(" ( file 2 , \" %s \" ) \n", file); currentfile = file; } } /* stabline - emit stab entry for source coordinate *cp */ //not passed currenty static void stabline(Coordinate *cp) { if (cp->file && cp->file != currentfile) { print(" ( file 2 , \" %s \" ) \n", cp->file); currentfile = cp->file; } print(" ( loc 2 , %d ) \n" , cp->y); } /* stabsym - output a stab entry for symbol p */ //not passed currenty static void stabsym(Symbol p) { if (p == cfunc && IR->stabline) (*IR->stabline)(&p->src); } static void progbeg(int argc, char *argv[]) { D_ENTER("progbeg") backendflags(argc, argv); print("( MicroCore TM uForth )\n"); print("decimal\n"); //switch to decimal, so we can share uCore compiler code and uForth compiler code and do not have to made tons of dec -> hex D_LEAVE("progbeg") } static void blockbeg(Env* env) { } static void blockend(Env* env) { } static void progend(void){ D_ENTER("progend") //end init Block if we are still in it if (initedVars == 1){ printPending(); print("\nUNINITIALISED\n"); //print uForth directive } D_LEAVE("progend") } //Express with DATA_WIDTH_BYTES Interface mcoreIR = { { 1, 1, 0 }, /* char_metrics */ { 2, 2, 0 }, /* short_metrics */ { 4, 4, 0 }, /* int_metrics */ { 4, 4, 0 }, /* long_metrics */ { 4, 4, 0 }, /* long_long_metrics */ { 4, 4, 1 }, /* float_metrics */ { 4, 4, 1 }, /* double_metrics */ { 4, 4, 1 }, /* long_double_metrics */ { 4, 4, 0 }, /* word_metrics */ { 0, 4, 0 }, /* struct_metrics */ 1, /* little_endian */ 0, /* mulops_calls */ 0, /* wants_callb */ 0, /* wants_argb */ 1, /* left_to_right */ 0, /* wants_dag */ 0, /* unsigned_char */ address, blockbeg, blockend, defaddress, defconst, defstring, defsymbol, stackemit, export, function, stackgen, global, import, local, progbeg, progend, segment, space, 0, 0, 0, 0, 0, 0, 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 } } };