use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class StackManager method insertExceptionalPrologue.
/**
* prologue for the exceptional case.
* (1) R0 is the only available scratch register.
* (2) stack overflow check has to come first.
*/
void insertExceptionalPrologue() {
if (VM.VerifyAssertions) {
VM._assert((frameSize & (STACKFRAME_ALIGNMENT - 1)) == 0, "Stack frame alignment error");
}
if (frameSize >= 0x7ff0) {
throw new OptimizingCompilerException("Stackframe size exceeded!");
}
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
Register FP = phys.getFP();
Register TR = phys.getTR();
Register TSR = phys.getTSR();
Register R0 = phys.getTemp();
Register S1 = phys.getGPR(LAST_SCRATCH_GPR);
boolean interruptible = ir.method.isInterruptible();
boolean stackOverflow = interruptible;
boolean yp = hasPrologueYieldpoint();
Instruction ptr = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
if (VM.VerifyAssertions)
VM._assert(ptr.getOpcode() == IR_PROLOGUE_opcode);
// Stack overflow check
if (stackOverflow) {
// R0 is fairly useless (can't be operand 1 of an addi or the base ptr
// of a load) so, free up S1 for use by briefly saving its contents in the
// return address slot of my caller's frame
ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(S1), A(FP), IC(STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
Offset offset = Entrypoints.stackLimitField.getOffset();
if (VM.VerifyAssertions)
VM._assert(fits(offset, 16));
ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S1), A(phys.getTR()), IC(PPCMaskLower16(offset))));
ptr.insertBefore(MIR_Binary.create(PPC_ADDI, A(R0), A(S1), IC(frameSize)));
ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S1), A(FP), IC(STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
// Mutate the Prologue holder instruction into the trap
MIR_Trap.mutate(ptr, PPC_TAddr, PowerPCTrapOperand.LESS(), A(FP), A(R0), TrapCodeOperand.StackOverflow());
// advance ptr because we want the remaining instructions to come after
// the trap
ptr = ptr.nextInstructionInCodeOrder();
} else {
// no stack overflow test, so we must remove the IR_Prologue instruction
Instruction next = ptr.nextInstructionInCodeOrder();
ptr.remove();
ptr = next;
}
// Buy stack frame, save LR, caller's FP
ptr.insertBefore(MIR_Move.create(PPC_MFSPR, A(R0), A(phys.getLR())));
ptr.insertBefore(MIR_StoreUpdate.create(PPC_STAddrU, A(FP), A(FP), IC(-frameSize)));
ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(R0), A(FP), IC(frameSize + STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
// Store cmid
int cmid = ir.compiledMethod.getId();
if (cmid <= 0x7fff) {
ptr.insertBefore(MIR_Unary.create(PPC_LDI, I(R0), IC(cmid)));
} else {
ptr.insertBefore(MIR_Unary.create(PPC_LDIS, I(R0), IC(cmid >>> 16)));
ptr.insertBefore(MIR_Binary.create(PPC_ORI, I(R0), I(R0), IC(cmid & 0xffff)));
}
ptr.insertBefore(MIR_Store.create(PPC_STW, I(R0), A(FP), IC(STACKFRAME_METHOD_ID_OFFSET.toInt())));
// Now save the volatile/nonvolatile registers
if (ir.compiledMethod.isSaveVolatile()) {
saveVolatiles(ptr);
}
saveNonVolatiles(ptr);
// Threadswitch
if (yp) {
Offset offset = Entrypoints.takeYieldpointField.getOffset();
if (VM.VerifyAssertions)
VM._assert(fits(offset, 16));
ptr.insertBefore(MIR_Load.create(PPC_LInt, I(R0), A(TR), IC(PPCMaskLower16(offset))));
ptr.insertBefore(MIR_Binary.create(PPC_CMPI, I(TSR), I(R0), IC(0)));
}
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class StackManager method restoreScratchRegistersBefore.
/**
* Walk over the currently available scratch registers.
*
* <p>For any scratch register r which is def'ed by instruction s,
* spill r before s and remove r from the pool of available scratch
* registers.
*
* <p>For any scratch register r which is used by instruction s,
* restore r before s and remove r from the pool of available scratch
* registers.
*
* <p>For any scratch register r which has current contents symb, and
* symb is spilled to location M, and s defs M: the old value of symb is
* dead. Mark this.
*
* <p>Invalidate any scratch register assignments that are illegal in s.
*/
@Override
public void restoreScratchRegistersBefore(Instruction s) {
for (Iterator<ScratchRegister> i = scratchInUse.iterator(); i.hasNext(); ) {
ScratchRegister scratch = i.next();
if (scratch.getCurrentContents() == null)
continue;
if (VERBOSE_DEBUG) {
System.out.println("RESTORE: consider " + scratch);
}
boolean removed = false;
boolean unloaded = false;
if (definedIn(scratch.scratch, s) || (s.isCall() && s.operator() != CALL_SAVE_VOLATILE && scratch.scratch.isVolatile())) {
// are killed.
if (VERBOSE_DEBUG) {
System.out.println("RESTORE : unload because defined " + scratch);
}
unloadScratchRegisterBefore(s, scratch);
// update mapping information
if (VERBOSE_DEBUG) {
System.out.println("RSRB: End scratch interval " + scratch.scratch + " " + s);
}
scratchMap.endScratchInterval(scratch.scratch, s);
Register scratchContents = scratch.getCurrentContents();
if (scratchContents != null) {
if (VERBOSE_DEBUG) {
System.out.println("RSRB: End symbolic interval " + scratch.getCurrentContents() + " " + s);
}
scratchMap.endSymbolicInterval(scratch.getCurrentContents(), s);
}
i.remove();
removed = true;
unloaded = true;
}
if (usedIn(scratch.scratch, s) || !isLegal(scratch.getCurrentContents(), scratch.scratch, s)) {
// memory
if (!unloaded) {
if (VERBOSE_DEBUG) {
System.out.println("RESTORE : unload because used " + scratch);
}
unloadScratchRegisterBefore(s, scratch);
// update mapping information
if (VERBOSE_DEBUG) {
System.out.println("RSRB2: End scratch interval " + scratch.scratch + " " + s);
}
scratchMap.endScratchInterval(scratch.scratch, s);
Register scratchContents = scratch.getCurrentContents();
if (scratchContents != null) {
if (VERBOSE_DEBUG) {
System.out.println("RSRB2: End symbolic interval " + scratch.getCurrentContents() + " " + s);
}
scratchMap.endSymbolicInterval(scratch.getCurrentContents(), s);
}
}
// so restore the correct contents.
if (VERBOSE_DEBUG) {
System.out.println("RESTORE : reload because used " + scratch);
}
reloadScratchRegisterBefore(s, scratch);
if (!removed) {
i.remove();
removed = true;
}
}
}
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class StackManager method saveVolatiles.
/**
* Insert code in the prologue to save the
* volatile registers.
*
* @param inst
*/
private void saveVolatiles(Instruction inst) {
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
// 1. save the volatile GPRs
Register FP = phys.getFP();
int i = 0;
for (Enumeration<Register> e = phys.enumerateVolatileGPRs(); e.hasMoreElements(); i++) {
Register r = e.nextElement();
int location = saveVolatileGPRLocation[i];
inst.insertBefore(MIR_Store.create(PPC_STAddr, A(r), A(FP), IC(location)));
}
// 2. save the volatile FPRs
i = 0;
for (Enumeration<Register> e = phys.enumerateVolatileFPRs(); e.hasMoreElements(); i++) {
Register r = e.nextElement();
int location = saveVolatileFPRLocation[i];
inst.insertBefore(MIR_Store.create(PPC_STFD, D(r), A(FP), IC(location)));
}
// 3. Save some special registers
Register temp = phys.getTemp();
inst.insertBefore(MIR_Move.create(PPC_MFSPR, I(temp), I(phys.getXER())));
inst.insertBefore(MIR_Store.create(PPC_STW, I(temp), A(FP), IC(saveXERLocation)));
inst.insertBefore(MIR_Move.create(PPC_MFSPR, A(temp), A(phys.getCTR())));
inst.insertBefore(MIR_Store.create(PPC_STAddr, A(temp), A(FP), IC(saveCTRLocation)));
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class StackManager method restoreVolatileRegisters.
/**
* Insert code before a return instruction to restore the
* volatile registers.
*
* @param inst the return instruction
*/
private void restoreVolatileRegisters(Instruction inst) {
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
// 1. restore the volatile GPRs
Register FP = phys.getFP();
int i = 0;
for (Enumeration<Register> e = phys.enumerateVolatileGPRs(); e.hasMoreElements(); i++) {
Register r = e.nextElement();
int location = saveVolatileGPRLocation[i];
inst.insertBefore(MIR_Load.create(PPC_LAddr, A(r), A(FP), IC(location)));
}
// 2. restore the volatile FPRs
i = 0;
for (Enumeration<Register> e = phys.enumerateVolatileFPRs(); e.hasMoreElements(); i++) {
Register r = e.nextElement();
int location = saveVolatileFPRLocation[i];
inst.insertBefore(MIR_Load.create(PPC_LFD, D(r), A(FP), IC(location)));
}
// 3. Restore some special registers
Register temp = phys.getTemp();
inst.insertBefore(MIR_Load.create(PPC_LInt, I(temp), A(FP), IC(saveXERLocation)));
inst.insertBefore(MIR_Move.create(PPC_MTSPR, I(phys.getXER()), I(temp)));
inst.insertBefore(MIR_Load.create(PPC_LAddr, A(temp), A(FP), IC(saveCTRLocation)));
inst.insertBefore(MIR_Move.create(PPC_MTSPR, A(phys.getCTR()), A(temp)));
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class StackManager method saveNonVolatiles.
/**
* Insert code into the prologue to save any used non-volatile
* registers.
*
* @param inst the first instruction after the prologue.
*/
private void saveNonVolatiles(Instruction inst) {
GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
int nNonvolatileGPRS = ir.compiledMethod.getNumberOfNonvolatileGPRs();
if (ir.compiledMethod.isSaveVolatile()) {
// pretend we use all non-volatiles
nNonvolatileGPRS = PhysicalRegisterSet.getNumberOfNonvolatileGPRs();
}
// 1. save the nonvolatile GPRs
int n = nNonvolatileGPRS - 1;
Register FP = phys.getFP();
if (VM.BuildFor32Addr && n > MULTIPLE_CUTOFF) {
// use a stm
Register nv = null;
for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements() && n >= 0; n--) {
nv = e.nextElement();
}
n++;
RegisterOperand range = I(nv);
// YUCK!!! Why is this crap in register operand??
int offset = getNonvolatileGPROffset(n);
inst.insertBefore(MIR_Store.create(PPC_STMW, range, A(FP), IC(offset)));
} else {
// use a sequence of load instructions
for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements() && n >= 0; n--) {
Register nv = e.nextElement();
int offset = getNonvolatileGPROffset(n);
inst.insertBefore(MIR_Store.create(PPC_STAddr, A(nv), A(FP), IC(offset)));
}
}
// 1. save the nonvolatile FPRs
if (ir.compiledMethod.isSaveVolatile()) {
// DANGER: as an optimization, we assume that a SaveVolatile method
// will never use nonvolatile FPRs.
// this invariant is not checked!!!!!
// TODO: We really need some way to verify that this is true.
} else {
int nNonvolatileFPRS = ir.compiledMethod.getNumberOfNonvolatileFPRs();
n = nNonvolatileFPRS - 1;
// use a sequence of load instructions
for (Enumeration<Register> e = phys.enumerateNonvolatileFPRsBackwards(); e.hasMoreElements() && n >= 0; n--) {
Register nv = e.nextElement();
int offset = getNonvolatileFPROffset(n);
inst.insertBefore(MIR_Store.create(PPC_STFD, D(nv), A(FP), IC(offset)));
}
}
}
Aggregations