void GenIncDecIndirect(int regDst, int regSrc, int opSz, int tok) { int instr = MipsInstrAddU; if (tok != tokInc) instr = MipsInstrSubU; GenReadIndirect(regDst, regSrc, opSz); GenPrintInstr3Operands(instr, 0, regDst, 0, regDst, 0, MipsOpConst, 1); GenWriteIndirect(regSrc, regDst, opSz); GenExtendRegIfNeeded(regDst, opSz); }
void GenIncDecLocal(int regDst, int opSz, int ofs, int tok) { int instr = MipsInstrAddU; if (tok != tokInc) instr = MipsInstrSubU; GenReadLocal(regDst, opSz, ofs); GenPrintInstr3Operands(instr, 0, regDst, 0, regDst, 0, MipsOpConst, 1); GenWriteLocal(regDst, opSz, ofs); GenExtendRegIfNeeded(regDst, opSz); }
STATIC void GenIncDecIdent(int regDst, int opSz, int label, int tok) { int instr = Tr32InstrAdd; if (tok != tokInc) instr = Tr32InstrSub; GenReadIdent(regDst, opSz, label); GenPrintInstr3Operands(instr, 0, regDst, 0, regDst, 0, Tr32OpConst, 1); GenWriteIdent(regDst, opSz, label); GenExtendRegIfNeeded(regDst, opSz); }
void GenPostIncDecIdent(int regDst, int opSz, int label, int tok) { int instr = MipsInstrAddU; if (tok != tokPostInc) instr = MipsInstrSubU; GenReadIdent(regDst, opSz, label); GenPrintInstr3Operands(instr, 0, regDst, 0, regDst, 0, MipsOpConst, 1); GenWriteIdent(regDst, opSz, label); GenPrintInstr3Operands(instr, 0, regDst, 0, regDst, 0, MipsOpConst, -1); GenExtendRegIfNeeded(regDst, opSz); }
STATIC void GenPostIncDecIndirect(int regDst, int regSrc, int opSz, int tok) { int instr = Tr32InstrAdd; if (tok != tokPostInc) instr = Tr32InstrSub; GenReadIndirect(regDst, regSrc, opSz); GenPrintInstr3Operands(instr, 0, regDst, 0, regDst, 0, Tr32OpConst, 1); GenWriteIndirect(regSrc, regDst, opSz); GenPrintInstr3Operands(instr, 0, regDst, 0, regDst, 0, Tr32OpConst, -1); GenExtendRegIfNeeded(regDst, opSz); }
STATIC void GenPostIncDecLocal(int regDst, int opSz, int ofs, int tok) { int instr = Tr32InstrAdd; if (tok != tokPostInc) instr = Tr32InstrSub; GenReadLocal(regDst, opSz, ofs); GenPrintInstr3Operands(instr, 0, regDst, 0, regDst, 0, Tr32OpConst, 1); GenWriteLocal(regDst, opSz, ofs); GenPrintInstr3Operands(instr, 0, regDst, 0, regDst, 0, Tr32OpConst, -1); GenExtendRegIfNeeded(regDst, opSz); }
// Original, primitive stack-based code generator // DONE: test 32-bit code generation void GenExpr0(void) { int i; int gotUnary = 0; int maxCallDepth = 0; int callDepth = 0; int paramOfs = 0; for (i = 0; i < sp; i++) if (stack[i][0] == '(') { if (++callDepth > maxCallDepth) maxCallDepth = callDepth; } else if (stack[i][0] == ')') { callDepth--; } CanUseTempRegs = maxCallDepth == 0; TempsUsed = 0; for (i = 0; i < sp; i++) { int tok = stack[i][0]; int v = stack[i][1]; #ifndef NO_ANNOTATIONS switch (tok) { case tokNumInt: printf2(" # %d\n", truncInt(v)); break; case tokNumUint: printf2(" # %uu\n", truncUint(v)); break; case tokIdent: printf2(" # %s\n", IdentTable + v); break; case tokLocalOfs: printf2(" # local ofs\n"); break; case ')': printf2(" # ) fxn call\n"); break; case tokUnaryStar: printf2(" # * (read dereference)\n"); break; case '=': printf2(" # = (write dereference)\n"); break; case tokShortCirc: printf2(" # short-circuit "); break; case tokGoto: printf2(" # sh-circ-goto "); break; case tokLogAnd: printf2(" # short-circuit && target\n"); break; case tokLogOr: printf2(" # short-circuit || target\n"); break; case tokIf: case tokIfNot: break; default: printf2(" # %s\n", GetTokenName(tok)); break; } #endif switch (tok) { case tokNumInt: case tokNumUint: if (!(i + 1 < sp && (strchr("+-&^|", stack[i + 1][0]) || stack[i + 1][0] == tokLShift || stack[i + 1][0] == tokRShift || stack[i + 1][0] == tokURShift))) { if (gotUnary) GenPushReg(MipsOpRegV0); GenPrintInstr2Operands(MipsInstrLI, 0, MipsOpRegV0, 0, MipsOpConst, v); } gotUnary = 1; break; case tokIdent: if (gotUnary) GenPushReg(MipsOpRegV0); if (!(i + 1 < sp && (stack[i + 1][0] == ')' || stack[i + 1][0] == tokUnaryStar || stack[i + 1][0] == tokInc || stack[i + 1][0] == tokDec || stack[i + 1][0] == tokPostInc || stack[i + 1][0] == tokPostDec))) { GenPrintInstr2Operands(MipsInstrLA, 0, MipsOpRegV0, 0, MipsOpLabel, v); } gotUnary = 1; break; case tokLocalOfs: if (gotUnary) GenPushReg(MipsOpRegV0); if (!(i + 1 < sp && (stack[i + 1][0] == tokUnaryStar || stack[i + 1][0] == tokInc || stack[i + 1][0] == tokDec || stack[i + 1][0] == tokPostInc || stack[i + 1][0] == tokPostDec))) { GenPrintInstr3Operands(MipsInstrAddU, 0, MipsOpRegV0, 0, MipsOpRegFp, 0, MipsOpConst, v); } gotUnary = 1; break; case '(': if (gotUnary) GenPushReg(MipsOpRegV0); gotUnary = 0; if (v < 16) GenLocalAlloc(16 - v); paramOfs = v - 4; break; case ',': if (maxCallDepth == 1) { if (paramOfs == 16) { GenPushReg(MipsOpRegV0); gotUnary = 0; } if (paramOfs >= 0 && paramOfs <= 12) { GenPrintInstr2Operands(MipsInstrMov, 0, MipsOpRegA0 + paramOfs / 4, 0, MipsOpRegV0, 0); gotUnary = 0; } paramOfs -= 4; } break; case ')': if (maxCallDepth != 1) { if (v >= 4) GenPrintInstr2Operands(MipsInstrLW, 0, MipsOpRegA0, 0, MipsOpIndRegSp, 0); if (v >= 8) GenPrintInstr2Operands(MipsInstrLW, 0, MipsOpRegA1, 0, MipsOpIndRegSp, 4); if (v >= 12) GenPrintInstr2Operands(MipsInstrLW, 0, MipsOpRegA2, 0, MipsOpIndRegSp, 8); if (v >= 16) GenPrintInstr2Operands(MipsInstrLW, 0, MipsOpRegA3, 0, MipsOpIndRegSp, 12); } else { int vv = v; if (vv > 16) vv = 16; if (vv) GenLocalAlloc(vv); } if (stack[i - 1][0] == tokIdent) { GenPrintInstr1Operand(MipsInstrJAL, 0, MipsOpLabel, stack[i - 1][1]); } else { GenPrintInstr1Operand(MipsInstrJAL, 0, MipsOpRegV0, 0); } if (v < 16) v = 16; GenLocalAlloc(-v); break; case tokUnaryStar: if (stack[i - 1][0] == tokIdent) GenReadIdent(MipsOpRegV0, v, stack[i - 1][1]); else if (stack[i - 1][0] == tokLocalOfs) GenReadLocal(MipsOpRegV0, v, stack[i - 1][1]); else GenReadIndirect(MipsOpRegV0, MipsOpRegV0, v); break; case tokUnaryPlus: break; case '~': GenPrintInstr3Operands(MipsInstrNor, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpRegV0, 0); break; case tokUnaryMinus: GenPrintInstr3Operands(MipsInstrSubU, 0, MipsOpRegV0, 0, MipsOpRegZero, 0, MipsOpRegV0, 0); break; case '+': case '-': case '*': case '&': case '^': case '|': case tokLShift: case tokRShift: case tokURShift: if ((stack[i - 1][0] == tokNumInt || stack[i - 1][0] == tokNumUint) && tok != '*') { int instr = GenGetBinaryOperatorInstr(tok); GenPrintInstr3Operands(instr, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, stack[i - 1][1]); } else { int instr = GenGetBinaryOperatorInstr(tok); int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(instr, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); } break; case '/': case tokUDiv: case '%': case tokUMod: { int reg = GenPopReg(MipsOpRegT0); if (tok == '/' || tok == '%') GenPrintInstr2Operands(MipsInstrDiv, 0, reg, 0, MipsOpRegV0, 0); else GenPrintInstr2Operands(MipsInstrDivU, 0, reg, 0, MipsOpRegV0, 0); if (tok == '%' || tok == tokUMod) GenPrintInstr1Operand(MipsInstrMfHi, 0, MipsOpRegV0, 0); else GenPrintInstr1Operand(MipsInstrMfLo, 0, MipsOpRegV0, 0); } break; case tokInc: case tokDec: if (stack[i - 1][0] == tokIdent) { GenIncDecIdent(MipsOpRegV0, v, stack[i - 1][1], tok); } else if (stack[i - 1][0] == tokLocalOfs) { GenIncDecLocal(MipsOpRegV0, v, stack[i - 1][1], tok); } else { GenPrintInstr2Operands(MipsInstrMov, 0, MipsOpRegT0, 0, MipsOpRegV0, 0); GenIncDecIndirect(MipsOpRegV0, MipsOpRegT0, v, tok); } break; case tokPostInc: case tokPostDec: if (stack[i - 1][0] == tokIdent) { GenPostIncDecIdent(MipsOpRegV0, v, stack[i - 1][1], tok); } else if (stack[i - 1][0] == tokLocalOfs) { GenPostIncDecLocal(MipsOpRegV0, v, stack[i - 1][1], tok); } else { GenPrintInstr2Operands(MipsInstrMov, 0, MipsOpRegT0, 0, MipsOpRegV0, 0); GenPostIncDecIndirect(MipsOpRegV0, MipsOpRegT0, v, tok); } break; case tokPostAdd: case tokPostSub: { int instr = GenGetBinaryOperatorInstr(tok); int reg = GenPopReg(MipsOpRegT0); GenPrintInstr2Operands(MipsInstrMov, 0, MipsOpRegT1, 0, MipsOpRegV0, 0); GenReadIndirect(MipsOpRegV0, reg, v); GenPrintInstr3Operands(instr, 0, MipsOpRegT1, 0, MipsOpRegT1, 0, MipsOpRegV0, 0); GenWriteIndirect(reg, MipsOpRegT1, v); } break; case tokAssignAdd: case tokAssignSub: case tokAssignMul: case tokAssignAnd: case tokAssignXor: case tokAssignOr: case tokAssignLSh: case tokAssignRSh: case tokAssignURSh: { int instr = GenGetBinaryOperatorInstr(tok); int reg = GenPopReg(MipsOpRegT0); GenPrintInstr2Operands(MipsInstrMov, 0, MipsOpRegT1, 0, MipsOpRegV0, 0); GenReadIndirect(MipsOpRegV0, reg, v); GenPrintInstr3Operands(instr, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpRegT1, 0); GenWriteIndirect(reg, MipsOpRegV0, v); GenExtendRegIfNeeded(MipsOpRegV0, v); } break; case tokAssignDiv: case tokAssignUDiv: case tokAssignMod: case tokAssignUMod: { int reg = GenPopReg(MipsOpRegT0); GenReadIndirect(MipsOpRegT1, reg, v); if (tok == tokAssignDiv || tok == tokAssignMod) GenPrintInstr2Operands(MipsInstrDiv, 0, MipsOpRegT1, 0, MipsOpRegV0, 0); else GenPrintInstr2Operands(MipsInstrDivU, 0, MipsOpRegT1, 0, MipsOpRegV0, 0); if (tok == tokAssignMod || tok == tokAssignUMod) GenPrintInstr1Operand(MipsInstrMfHi, 0, MipsOpRegV0, 0); else GenPrintInstr1Operand(MipsInstrMfLo, 0, MipsOpRegV0, 0); GenWriteIndirect(reg, MipsOpRegV0, v); GenExtendRegIfNeeded(MipsOpRegV0, v); } break; case '=': { int reg = GenPopReg(MipsOpRegT0); GenWriteIndirect(reg, MipsOpRegV0, v); GenExtendRegIfNeeded(MipsOpRegV0, v); } break; /* i = il < ir; // i = slt(il, ir); i = il <= ir; // i = slt(ir, il) ^ 1; i = il > ir; // i = slt(ir, il); i = il >= ir; // i = slt(il, ir) ^ 1; i = il == ir; // i = sltu(il ^ ir, 1); i = il != ir; // i = sltu(0, il ^ ir); */ case '<': { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLT, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); } break; case tokULess: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); } break; case '>': { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLT, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, reg, 0); } break; case tokUGreater: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, reg, 0); } break; case tokLEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLT, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, reg, 0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 1); } break; case tokULEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, reg, 0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 1); } break; case tokGEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLT, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 1); } break; case tokUGEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 1); } break; case tokEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 1); } break; case tokNEQ: { int reg = GenPopReg(MipsOpRegT0); GenPrintInstr3Operands(MipsInstrXor, 0, MipsOpRegV0, 0, reg, 0, MipsOpRegV0, 0); GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, MipsOpRegZero, 0, MipsOpRegV0, 0); } break; case tok_Bool: GenPrintInstr3Operands(MipsInstrSLTU, 0, MipsOpRegV0, 0, MipsOpRegZero, 0, MipsOpRegV0, 0); break; case tokSChar: GenPrintInstr3Operands(MipsInstrSLL, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 24); GenPrintInstr3Operands(MipsInstrSRA, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 24); break; case tokUChar: GenPrintInstr3Operands(MipsInstrAnd, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 0xFF); break; case tokShort: GenPrintInstr3Operands(MipsInstrSLL, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 16); GenPrintInstr3Operands(MipsInstrSRA, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 16); break; case tokUShort: GenPrintInstr3Operands(MipsInstrAnd, 0, MipsOpRegV0, 0, MipsOpRegV0, 0, MipsOpConst, 0xFFFF); break; case tokShortCirc: #ifndef NO_ANNOTATIONS if (v >= 0) printf2("&&\n"); else printf2("||\n"); #endif if (v >= 0) GenJumpIfZero(v); // && else GenJumpIfNotZero(-v); // || gotUnary = 0; break; case tokGoto: #ifndef NO_ANNOTATIONS printf2("goto\n"); #endif GenJumpUncond(v); gotUnary = 0; break; case tokLogAnd: case tokLogOr: GenNumLabel(v); break; case tokVoid: gotUnary = 0; break; case tokComma: break; case tokIf: GenJumpIfNotZero(stack[i][1]); break; case tokIfNot: GenJumpIfZero(stack[i][1]); break; default: //error("Error: Internal Error: GenExpr0(): unexpected token %s\n", GetTokenName(tok)); errorInternal(102); break; } } }