/* Generate code for arithmetic expression, return a register number */ int genarith(TOKEN code) { int num, reg; if (DEBUGGEN) { printf("genarith\n"); dbugprinttok(code); }; switch ( code->tokentype ) { case NUMBERTOK: switch (code->datatype) { case INTEGER: num = code->intval; reg = getreg(WORD); if ( num >= MINIMMEDIATE && num <= MAXIMMEDIATE ) asmimmed(MOVL, num, reg); break; case REAL: /* ***** fix this ***** */ break; } break; case IDENTIFIERTOK: /* ***** fix this ***** */ break; case OPERATOR: /* ***** fix this ***** */ break; }; return reg; }
/* Generate code for arithmetic expression, return a register number */ int genarith(TOKEN code) { if (DEBUGGEN) { printf("In genarith()\n"); dbugprinttok(code); } int num, reg_num, lhs_reg, rhs_reg; if (code->tokentype == NUMBERTOK) { if (code->datatype == INTEGER) { num = code->intval; reg_num = getreg(INTEGER); if (num >= MINIMMEDIATE && num <= MAXIMMEDIATE) { asmimmed(MOVL, num, reg_num); } else { /* Generate literal for the value of the constant, then load the literal into a register. */ } } else { /* Generate literal for the value of the constant, then load the literal into a register. */ num = code->intval; reg_num = getreg(REAL); } } else if (code->tokentype == IDENTIFIERTOK) { } else if (code->tokentype == OPERATOR) { reg_num = lhs_reg; } return reg_num; }
/* Generate code for arithmetic expression, return a register number */ int genarith(TOKEN code) { int num, reg; float fnum; TOKEN lhs, rhs; int reg1, reg2, freg; int offs; if (DEBUGGEN) { printf("genarith\n"); dbugprinttok(code); }; //printf("tokentype: %i\n", code->tokentype); switch ( code->tokentype ) { case NUMBERTOK: switch (code->datatype) { case INTEGER: num = code->intval; reg = getreg(WORD); if ( num >= MINIMMEDIATE && num <= MAXIMMEDIATE ) asmimmed(MOVL, num, reg); break; case REAL: fnum = code->realval; reg = getreg(FLOAT); makeflit(fnum, nextlabel); asmldflit(MOVSD, nextlabel, reg); nextlabel++; break; case POINTER: num = 0; reg = getreg(WORD); asmimmed(MOVQ, num, reg); break; } break; case IDENTIFIERTOK: offs = code->symentry->offset - stkframesize; /* net offset of the var */ switch(code->datatype) { case INTEGER: reg = getreg(WORD); //printf("kind: %i\n", code->symtype->datatype->kind); if(code->symtype == NULL || code->symtype->kind == BASICTYPE) asmld(MOVL, offs, reg, code->stringval); else asmld(MOVQ, offs, reg, code->stringval); break; case REAL: reg = getreg(FLOAT); asmld(MOVSD, offs, reg, code->stringval); break; } break; case OPERATOR: if(code->whichval != FUNCALLOP && code->whichval != AREFOP) { lhs = code->operands; rhs = lhs->link; if(code->datatype == REAL) { reg1 = genarith( lhs ); if(rhs != NULL) { if(rhs->tokentype == OPERATOR && rhs->whichval == FUNCALLOP) { asmsttemp(reg1); reg_map[reg1] = 0; reg2 = genarith( rhs ); reg1 = getreg(FLOAT); asmldtemp(reg1); } else { reg2 = genarith( rhs ); } } } else { reg1 = genarith( lhs ); if(rhs != NULL) reg2 = genarith( rhs ); } } switch(code->whichval) { case PLUSOP: if(code->datatype == INTEGER) asmrr(ADDL, reg2, reg1); else asmrr(ADDSD, reg2, reg1); reg = reg1; break; case MINUSOP: if(rhs != NULL) { if(code->datatype == INTEGER) asmrr(SUBL, reg2, reg1); else asmrr(SUBSD, reg2, reg1); } else { reg2 = getreg(FLOAT); asmfneg(reg1, reg2); reg_map[reg2] = 0; } reg = reg1; break; case TIMESOP: if(code->datatype == INTEGER) asmrr(IMULL, reg2, reg1); else asmrr(MULSD, reg2, reg1); reg = reg1; break; case DIVIDEOP: if(code->datatype == INTEGER) asmrr(DIVL, reg2, reg1); else asmrr(DIVSD, reg2, reg1); reg = reg1; break; case EQOP: case NEOP: case LTOP: case LEOP: case GEOP: case GTOP: asmrr(CMPL, reg2, reg1); reg = reg1; break; case FLOATOP: freg = getreg(FLOAT); asmfloat(reg1, freg); reg_map[reg1] = 0; reg = freg; break; case FIXOP: reg2 = getreg(WORD); asmfix(reg1, reg2); reg_map[freg] = 0; reg = reg2; break; case FUNCALLOP: reg = genfun(code); break; case AREFOP: reg = genaref(code, FBASE); break; } break; case STRINGTOK: makeblit(code->stringval, nextlabel); return nextlabel++; break; }; return reg; }
/* Generate code for arithmetic expression, return a register number */ int genarith(TOKEN code) { int num1, num2, reg1, reg2, offs; TOKEN tok, lhs, rhs; SYMBOL sym, lsym, rsym; if (DEBUGGEN) { printf("genarith\n"); dbugprinttok(code); }; // This switch determines how to handle the token based on its type switch ( code->tokentype ) { case NUMBERTOK: switch (code->datatype) { case INTEGER: num1 = code->intval; reg1 = getreg(WORD); if (code->symtype != NULL) { if(code->symtype->kind == POINTERSYM) asmimmed(MOVQ, num1, reg1); } else if ( num1 >= MINIMMEDIATE && num1 <= MAXIMMEDIATE ) asmimmed(MOVL, num1, reg1); break; case REAL: reg1 = getreg(FLOAT); makeflit(code->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg1); break; } break; case IDENTIFIERTOK: reg1 = getreg(WORD); sym = code->symentry; offs = sym->offset - stkframesize; asmld(MOVQ, offs, reg1, code->stringval); break; case OPERATOR: switch(code->whichval) { case PLUSOP: lhs = code->operands; rhs = lhs->link; lsym = lhs->symentry; rsym = rhs->symentry; if(lsym != NULL & lhs->tokentype != NUMBERTOK) { switch(lsym->basicdt) { case INTEGER: reg1 = getreg(WORD); break; case REAL: reg1 = getreg(FLOAT); break; } asmldr(MOVL, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); } else { if(lhs->tokentype == OPERATOR) reg1 = genarith(lhs); else switch(lhs->datatype) { case INTEGER: reg1 = getreg(WORD); asmimmed(MOVL, lhs->intval, reg1); break; case REAL: reg1 = getreg(FLOAT); makeflit(lhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg1); break; } } if(rsym != NULL & rhs->tokentype != NUMBERTOK) { switch(rsym->basicdt) { case INTEGER: reg2 = getreg(WORD); break; case REAL: reg2 = getreg(FLOAT); break; } asmldr(MOVL, rsym->offset - stkframesize, RBP, reg2, rsym->namestring); } else { if(rhs->tokentype == OPERATOR) reg2 = genarith(rhs); else switch(rhs->datatype) { case INTEGER: reg2 = getreg(WORD); asmimmed(MOVL, rhs->intval, reg2); break; case REAL: reg2 = getreg(FLOAT); makeflit(rhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg2); break; } } if(reg1 < 8 & reg2 < 8) asmrr(ADDL, reg2, reg1); else asmrr(ADDSD, reg2, reg1); unused(reg2); break; case MINUSOP: lhs = code->operands; lsym = lhs->symentry; rhs = lhs->link; if(rhs == NULL) //if this is just a negation { if(lsym != NULL & lhs->tokentype != NUMBERTOK) { switch(lsym->basicdt) { case INTEGER: reg1 = getreg(WORD); asmldr(MOVL, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); break; case REAL: reg1 = getreg(FLOAT); reg2 = getreg(FLOAT); asmldr(MOVSD, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); asmfneg(reg1, reg2); unused(reg2); break; } } else { if(lhs->tokentype == OPERATOR) reg1 = genarith(lhs); else switch(lhs->datatype) { case INTEGER: reg1 = getreg(WORD); asmimmed(MOVL, lhs->intval, reg1); break; case REAL: reg1 = getreg(FLOAT); reg2 = getreg(FLOAT); asmldflit(MOVSD, nextlabel++, reg1); asmfneg(reg1, reg2); unused(reg2); break; } } return reg1; } rsym = rhs->symentry; if(lsym != NULL & lhs->tokentype != NUMBERTOK) { switch(lsym->basicdt) { case INTEGER: reg1 = getreg(WORD); asmldr(MOVL, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); break; case REAL: reg1 = getreg(FLOAT); asmldr(MOVSD, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); break; } } else { if(lhs->tokentype == OPERATOR) reg1 = genarith(lhs); else switch(lhs->datatype) { case INTEGER: reg1 = getreg(WORD); asmimmed(MOVL, lhs->intval, reg1); break; case REAL: reg1 = getreg(FLOAT); makeflit(lhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg1); break; } } if(rsym != NULL & rhs->tokentype != NUMBERTOK) { switch(rsym->basicdt) { case INTEGER: reg2 = getreg(WORD); asmldr(MOVL, rsym->offset - stkframesize, RBP, reg2, rsym->namestring); break; case REAL: reg2 = getreg(FLOAT); asmldr(MOVSD, rsym->offset - stkframesize, RBP, reg2, rsym->namestring); break; } } else { if(rhs->tokentype == OPERATOR) reg2 = genarith(rhs); else switch(rhs->datatype) { case INTEGER: reg2 = getreg(WORD); asmimmed(MOVL, rhs->intval, reg2); break; case REAL: reg2 = getreg(FLOAT); makeflit(rhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg2); break; } } if(reg1 < 8 & reg2 < 8) asmrr(SUBL, reg2, reg1); else asmrr(SUBSD, reg2, reg1); unused(reg2); break; case TIMESOP: lhs = code->operands; rhs = lhs->link; lsym = lhs->symentry; rsym = rhs->symentry; if(lsym != NULL & lhs->tokentype != NUMBERTOK) { switch(lsym->basicdt) { case INTEGER: reg1 = getreg(WORD); asmldr(MOVL, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); break; case REAL: reg1 = getreg(FLOAT); asmldr(MOVSD, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); break; } } else { if(lhs->tokentype == OPERATOR) { reg1 = genarith(lhs); if(lhs->whichval == FUNCALLOP & rhs->whichval == FUNCALLOP) { asmsttemp(reg1); unused(reg1); } } else switch(lhs->datatype) { case INTEGER: reg1 = getreg(WORD); asmimmed(MOVL, lhs->intval, reg1); break; case REAL: reg1 = getreg(FLOAT); makeflit(lhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg1); break; } } if(rsym != NULL & rhs->tokentype != NUMBERTOK) { switch(rsym->basicdt) { case INTEGER: reg2 = getreg(WORD); asmldr(MOVL, rsym->offset - stkframesize, RBP, reg2, rsym->namestring); break; case REAL: reg2 = getreg(FLOAT); asmldr(MOVSD, rsym->offset - stkframesize, RBP, reg2, rsym->namestring); break; } } else { if(rhs->tokentype == OPERATOR) { reg2 = genarith(rhs); if(lhs->whichval == FUNCALLOP & rhs->whichval == FUNCALLOP) { switch(lhs->datatype) { case INTEGER: reg1 = getreg(WORD); break; case REAL: reg1 = getreg(FLOAT); break; } asmldtemp(reg1); } } else switch(rhs->datatype) { case INTEGER: reg2 = getreg(WORD); asmimmed(MOVL, rhs->intval, reg2); break; case REAL: reg2 = getreg(FLOAT); makeflit(rhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg2); break; } } if(reg1 < 8 & reg2 < 8) asmrr(IMULL, reg2, reg1); else asmrr(MULSD, reg2, reg1); unused(reg2); break; case FLOATOP: lhs = code->operands; lsym = lhs->symentry; reg1 = getreg(FLOAT); reg2 = getreg(WORD); asmldr(MOVL, lsym->offset - stkframesize, RBP, reg2, lsym->namestring); asmfloat(reg2, reg1); unused(reg2); break; case FUNCALLOP: tok = code->operands; if(tok->link != NULL) { switch(tok->link->tokentype) { case STRINGTOK: asmlitarg(nextlabel++, EDI); makeblit(tok->link->stringval, nextlabel-1); asmcall(tok->stringval); break; case OPERATOR: reg1 = genarith(tok->link); break; case NUMBERTOK: switch(tok->link->datatype) { case INTEGER: reg1 = getreg(WORD); asmimmed(MOVL,tok->link->intval,reg1); asmrr(MOVL, reg1, EDI); break; case REAL: reg1 = getreg(FLOAT); asmimmed(MOVSD,tok->link->realval,reg1); asmrr(MOVSD, reg1, EDI); break; } } } asmcall(tok->stringval); break; case FIXOP: reg1 = getreg(WORD); reg2 = genarith(code->operands); asmfix(reg2,reg1); break; case POINTEROP: lhs = code->operands; if(lhs->tokentype == OPERATOR & lhs->whichval == AREFOP) { reg1 = genarith(lhs); } else { reg1 = getreg(WORD); lsym = code->operands->symentry; asmld(MOVQ, lsym->offset - stkframesize, reg1, code->operands->stringval); } break; case AREFOP: lhs = code->operands; rhs = lhs->link; if(lhs->tokentype == OPERATOR & lhs->whichval == POINTEROP) { reg2 = genarith(lhs->operands); if(lhs->symtype != NULL) { if(lhs->symtype->basicdt == REAL) { reg1 = getreg(FLOAT); asmldr(MOVSD, rhs->intval, reg2, reg1, "^. "); unused(reg2); break; } } reg1 = getreg(WORD); asmldr(MOVQ, rhs->intval, reg2, reg1, "^. "); } unused(reg2); break; } break; }; return reg1; }
/* Generate code for a Statement from an intermediate-code form */ void genc(TOKEN code) { TOKEN tok, lhs, rhs; int reg, reg2, offs, jmpval, loop1, loop2; SYMBOL sym, lsym, rsym; if (DEBUGGEN) { printf("genc\n"); dbugprinttok(code); }; if ( code->tokentype != OPERATOR ) { printf("Bad code token"); dbugprinttok(code); }; // This switch statement will determine how to handle the token based on its operator value switch ( code->whichval ) { case PROGNOP: tok = code->operands; while ( tok != NULL ) { genc(tok); tok = tok->link; }; break; case ASSIGNOP: /* Trivial version: handles I := e */ lhs = code->operands; rhs = lhs->link; reg = genarith(rhs); /* generate rhs into a register */ if(rhs != NULL) rsym = rhs->symentry; if(lhs->tokentype == OPERATOR & lhs->whichval == AREFOP) { if(lhs->operands->tokentype != OPERATOR & lhs->operands->whichval != POINTEROP) { if(lhs->operands->link->tokentype == NUMBERTOK) { lsym = lhs->operands->symentry; reg2 = getreg(WORD); asmimmed(MOVL, lhs->operands->link->intval, reg2); asmop(CLTQ); if(reg < 8 & reg2 < 8) { asmstrr(MOVL, reg, lsym->offset - stkframesize, reg2, lhs->operands->stringval); } else { asmstrr(MOVSD, reg, lsym->offset - stkframesize, reg2, lhs->operands->stringval); } break; } else { reg2 = genarith(lhs->operands->link); asmop(CLTQ); lsym = lhs->operands->symentry; if(reg < 8 & reg2 < 8) { asmstrr(MOVL, reg, lsym->offset - stkframesize, reg2, lhs->operands->stringval); } else { asmstrr(MOVSD, reg, lsym->offset - stkframesize, reg2, lhs->operands->stringval); } break; } } reg2 = genarith(lhs->operands); offs = lhs->operands->link->intval; if(rsym != NULL) { if(rsym->datatype->kind == POINTERSYM) asmstr(MOVQ, reg, offs, reg2, "^. "); else { if (reg < 8 & reg2 < 8) asmstr(MOVL, reg, offs, reg2, "^. "); else asmstr(MOVSD, reg, offs, reg2, "^. "); } } else { if (reg < 8 & reg2 < 8) asmstr(MOVL, reg, offs, reg2, "^. "); else asmstr(MOVSD, reg, offs, reg2, "^. "); } unused(reg); break; } else { lsym = lhs->symentry; /* assumes lhs is a simple var */ offs = lsym->offset - stkframesize; /* net offset of the var */ } if(lsym->datatype->kind == POINTERSYM) { asmst(MOVQ, reg, offs, lhs->stringval); } else { switch (code->datatype) /* store value into lhs */ { case INTEGER: asmst(MOVL, reg, offs, lhs->stringval); break; case REAL: asmst(MOVSD, reg, offs, lhs->stringval); break; } } unused(reg); break; case PLUSOP: lhs = code->operands; rhs = lhs->link; lsym = lhs->symentry; rsym = rhs->symentry; if(lsym != NULL & lhs->tokentype != NUMBERTOK) asmldr(MOVL, lsym->offset - stkframesize, RBP, EAX, lsym->namestring); else asmimmed(MOVL, lhs->intval, EAX); if(rsym != NULL & rhs->tokentype != NUMBERTOK) asmldr(MOVL, rsym->offset - stkframesize, RBP, ECX, rsym->namestring); else asmimmed(MOVL, rhs->intval, ECX); asmrr(ADDL, ECX, EAX); break; case LABELOP: lhs = code->operands; asmlabel(lhs->intval); break; case IFOP: tok = code->operands; lhs = tok->operands; rhs = lhs->link; lsym = lhs->symentry; rsym = rhs->symentry; loop1 = nextlabel++; loop2 = nextlabel++; if(rhs->symtype != NULL) { if (rhs->symtype->kind == POINTERSYM) { if(lsym != NULL & lhs->tokentype != NUMBERTOK) asmldr(MOVQ, lsym->offset - stkframesize, RBP, EAX, lsym->namestring); else asmimmed(MOVQ, lhs->intval, EAX); if(rsym != NULL & rhs->tokentype != NUMBERTOK) asmldr(MOVQ, rsym->offset - stkframesize, RBP, ECX, rsym->namestring); else asmimmed(MOVQ, rhs->intval, ECX); asmrr(CMPQ, ECX, EAX); } else { if(lsym != NULL & lhs->tokentype != NUMBERTOK) asmldr(MOVL, lsym->offset - stkframesize, RBP, EAX, lsym->namestring); else asmimmed(MOVL, lhs->intval, EAX); if(rsym != NULL & rhs->tokentype != NUMBERTOK) asmldr(MOVL, rsym->offset - stkframesize, RBP, ECX, rsym->namestring); else asmimmed(MOVL, rhs->intval, ECX); asmrr(CMPL, ECX, EAX); } } else { if(lsym != NULL & lhs->tokentype != NUMBERTOK) asmldr(MOVL, lsym->offset - stkframesize, RBP, EAX, lsym->namestring); else asmimmed(MOVL, lhs->intval, EAX); if(rsym != NULL & rhs->tokentype != NUMBERTOK) asmldr(MOVL, rsym->offset - stkframesize, RBP, ECX, rsym->namestring); else asmimmed(MOVL, rhs->intval, ECX); asmrr(CMPL, ECX, EAX); } switch(tok->whichval) { case EQOP: jmpval = JE; break; case NEOP: jmpval = JNE; break; case LTOP: jmpval = JL; break; case LEOP: jmpval = JLE; break; case GEOP: jmpval = JGE; break; case GTOP: jmpval = JG; break; } asmjump(jmpval, loop1); tok = tok->link; //else part if(tok->link != NULL) genc(tok->link); asmjump(JMP, loop2); //if part asmlabel(loop1); genc(tok); asmlabel(loop2); break; case GOTOOP: lhs = code->operands; asmjump(JMP, lhs->intval); break; case FUNCALLOP: tok = code->operands; rhs = tok->link; if(rhs != NULL) { switch(rhs->tokentype) { case STRINGTOK: asmlitarg(nextlabel++, EDI); makeblit(rhs->stringval, nextlabel-1); asmcall(tok->stringval); break; case IDENTIFIERTOK: rsym = rhs->symentry; reg = getreg(WORD); asmld(MOVL, rsym->offset - stkframesize, reg, rhs->stringval); asmrr(MOVL, reg, EDI); asmcall(tok->stringval); break; case OPERATOR: rsym = rhs->symentry; reg = getreg(FLOAT); asmld(MOVL, -1000, EAX, rhs->operands->operands->stringval); asmldr(MOVSD, rhs->operands->link->intval, EAX, XMM0, "^. "); asmcall(tok->stringval); break; } } break; }; clearreg(); }