// EXPR1 && EXPR2 // DND void CodeGen::visitCAExprAnd(CAExprAnd *caexprand) { curExpr.push(maxExpr++); int reg1 = allocRegs(1); string andAfter = getLabel(curScope, "and", maxExpr, "after"); caexprand->conditionalandexpression_->accept(this); emitCmd("MOV", reg1, 0); emitCmd("MOV", 0, "#0"); emitCmd("CMP", reg1, 0); emitCmd("BEQ", andAfter); emitCmd("MOV", 0, "#1"); caexprand->equalityexpression_->accept(this); emitCmd("MOV", reg1, 0); emitCmd("MOV", 0, "#0"); emitCmd("CMP", reg1, 0); emitCmd("MOVNE", 0, "#1"); emitLabel(andAfter); curExpr.pop(); freeRegs(1); }
/* Make register r available by making the opdesc that uses it (if * any) use a different register. Call getFreeRegnum to get a new * register (which in turn may cause spilling of some other register). * If 'op' is the opdesc that uses r, we need to MODIFY op since it is * still being used. Note that op could be a regop, dispop, or * indexop (in which case r could be either op->reg or op->reg2), but * in all cases we want to output "movl r, newreg" and update op to * use newreg instead of r. */ void makeAvailable(regnum r, int line) { opdesc *op = regTab[r].op; // if r is free, return, else: if (op == NULL) return; outputDebugS("making reg %s available", regname[r]); assert(!regTab[r].locked); // lock the opdesc's register(s) while getting a new regnum lock(op); regnum newr = getFreeRegnum(); unlock(op); // output a movl instruction and the current opdesc outputCmd("movl", line); outputReg(r); // mark the opdesc's register(s) (r and perhaps another) as free freeRegs(op); // change the opdesc to the new register and output that if (op->reg == r) op->reg = newr; if (op->reg2 == r) op->reg2 = newr; outputReg(newr); // update regTab to reflect that the new register now belongs to the opdesc regTab[r].op = NULL; regTab[newr].op = op; }
/* Free op's register(s) by spilling it into a memtemp. Update op to reflect * the change. If op is a dispop or indexop, need to 'movl' it into the * register it occupies (parameter r) before spilling. * If availMemTemps is not NULL, reuse first available displacement, else * increase localsize to get a new displacement. */ void spill(opdesc *op, regnum r) { int disp; // first, compute the correct displacement, and output one of: if(availMemTemps == NULL){ currentfundesc->fun.localsize += INTSIZE; disp = LOCAL_OFFS - currentfundesc->fun.localsize; outputDebugN("creating new memtemp at disp %d", disp); } else { memTemp *memFree = availMemTemps; disp = availMemTemps->disp; if (availMemTemps->next == NULL) availMemTemps = NULL; else availMemTemps = availMemTemps->next; free(memFree); outputDebugN("reusing memtemp at disp %d", disp); } // if memory location (dispop or indexop), need to move it into reg first: // output movl instruction and op, then mark op's register(s) as free, // then change op into register r and output that if (isMemloc(op)) { outputCmd("movl", 0); outputOp(op); freeRegs(op); op->type = regop; op->reg = r; op->isTemp = 0; outputOp(op); } // now we are ready for the actual spilling: // output movl instruction and op, then mark op's register as free // then use makeDispOp to change op into a temporary displacement off ebp // and output op assert(op->type == regop); outputCmd("movl", 0); outputOp(op); freeRegs(op); makeDispOp(op, disp, TRUE); op->reg = ebp; outputOp(op); }
//EXPR1 - EXPR2 // DND void CodeGen::visitAddExprSub(AddExprSub *addexprsub) { int reg1 = allocRegs(1); addexprsub->additiveexpression_->accept(this); emitCmd("MOV", reg1, 0); addexprsub->multiplicativeexpression_->accept(this); emitCmd("SUB", 0, reg1, 0); freeRegs(1); }
// EXPR1 + EXPR2 // DND void CodeGen::visitAddExprAdd(AddExprAdd *addexpradd) { int reg1 = allocRegs(1); addexpradd->additiveexpression_->accept(this); emitCmd("MOV", reg1, 0); addexpradd->multiplicativeexpression_->accept(this); emitCmd("ADD", 0, reg1, 0); freeRegs(1); }
// EXPR1 / EXPR2 // DND -- T18, T26, T31 // Uses *SIGNED* division void CodeGen::visitMulExprDiv(MulExprDiv *mulexprdiv) { int reg1 = allocRegs(1); mulexprdiv->multiplicativeexpression_->accept(this); emitCmd("MOV", reg1, 0); mulexprdiv->unaryexpression_->accept(this); emitCmd("SDIV", 0, reg1, 0); freeRegs(1); }
// EXPR1 * EXPR2 // DND void CodeGen::visitMulExprMul(MulExprMul *mulexprmul) { int reg1 = allocRegs(1); mulexprmul->multiplicativeexpression_->accept(this); emitCmd("MOV", reg1, 0); mulexprmul->unaryexpression_->accept(this); emitCmd("MUL", 0, reg1, 0); freeRegs(1); }
// !EXPR // DND void CodeGen::visitUnExprNeg(UnExprNeg *unexprneg) { unexprneg->unaryexpression_->accept(this); int reg1 = allocRegs(1); // BOOKMARK emitCmd("MOV", reg1, 0); emitCmd("MOV", 0, "#0"); emitCmd("CMP", reg1, 0); emitCmd("MOVNE", 0, "#1"); freeRegs(1); }
/* compute the address of a memory location */ opdesc *computeAddress(opdesc *op, int line) { // similar to forceToReg, except uses "leal" instead of "movl" freeRegs(op); /* free regs used by op so we can reuse them */ opdesc *newop = newRegOp(getFreeRegnum()); outputCmd("leal", line); outputOp(op); outputOp(newop); freeMemtemp(op); free(op); return newop; }
// EXPR1 != EXPR2 // DND void CodeGen::visitEqExprNE(EqExprNE *eqexprne) { curExpr.push(maxExpr++); int reg1 = allocRegs(1); eqexprne->equalityexpression_->accept(this); emitCmd("MOV", reg1, 0); eqexprne->relationalexpression_->accept(this); emitCmd("CMP", reg1, 0); emitCmd("MOVNE", 0, "#1"); emitCmd("MOVEQ", 0, "#0"); curExpr.pop(); freeRegs(1); }
// EXPR1 >= EXPR2 // DND void CodeGen::visitRelExprGE(RelExprGE *relexprge) { curExpr.push(maxExpr++); int reg1 = allocRegs(1); relexprge->relationalexpression_->accept(this); emitCmd("MOV", reg1, 0); relexprge->additiveexpression_->accept(this); emitCmd("CMP", reg1, 0); emitCmd("MOVGE", 0, "#1"); emitCmd("MOVLT", 0, "#0"); curExpr.pop(); freeRegs(1); }
/* Force an operand to a register. If it is a register already, just * return it. Otherwise, allocate a new register, output code to move * the operand to the register, free the old operand, and return the * new register. In order to allow the operand's register(s) to be * reused, call freeRegs(op) before allocating a new register, but * don't call freeOp(op) until the end. */ opdesc *forceToReg(opdesc *op, int line) { // use getFreeRegnum and newRegOp if (op->type == regop) return op; freeRegs(op); /* free regs used by op so we can reuse them */ opdesc *newop = newRegOp(getFreeRegnum()); outputCmd("movl", line); outputOp(op); outputOp(newop); freeMemtemp(op); free(op); return newop; }
// EXPR1 % EXPR2 // TODO -- LONGFILES AND T26 void CodeGen::visitMulExprMod(MulExprMod *mulexprmod) { int reg1 = allocRegs(1); int reg2 = allocRegs(1); mulexprmod->multiplicativeexpression_->accept(this); emitCmd("MOV", reg1, 0); // A is in reg1 mulexprmod->unaryexpression_->accept(this); emitCmd("MOV", reg2, 0); // B is in reg2 emitCmd("SDIV", 0, reg1, 0); // q(a,b) is in r0 emitCmd("MUL", 0, reg2, 0); emitCmd("SUB", 0, reg1, 0); freeRegs(2); }
// EXPR1 || EXPR2 // DND void CodeGen::visitCOExprOr(COExprOr *coexpror) { curExpr.push(maxExpr++); int reg1 = allocRegs(1); coexpror->conditionalorexpression_->accept(this); emitCmd("MOV", reg1, 0); coexpror->conditionalandexpression_->accept(this); // result of this add can only be 0, 1, or 2. emitCmd("ADD", 0, reg1, 0); emitCmd("CMP", 0, "#0"); // if it's not 0, move 1 in there just in case it's 2. emitCmd("MOVGT", 0, "#1"); curExpr.pop(); freeRegs(1); }
void freeOp(opdesc *op) { freeRegs(op); freeMemtemp(op); free(op); }