use of org.jikesrvm.compilers.common.assembler.ia32.Assembler in project JikesRVM by JikesRVM.
the class OutOfLineMachineCode method generatePcThunkInstructions.
/**
* Machine code to get the address of the instruction after the call to this
* method
*/
private static void generatePcThunkInstructions() {
Assembler asm = new Assembler(0);
asm.emitMOV_Reg_RegInd(EAX, SP);
asm.emitRET();
pcThunkEAXInstructions = asm.getMachineCodes();
pcThunkInstructionsField[EAX.value()] = EntrypointHelper.getField(OutOfLineMachineCode.class, "pcThunkEAXInstructions", CodeArray.class);
asm = new Assembler(0);
asm.emitMOV_Reg_RegInd(EBX, SP);
asm.emitRET();
pcThunkEBXInstructions = asm.getMachineCodes();
pcThunkInstructionsField[EBX.value()] = EntrypointHelper.getField(OutOfLineMachineCode.class, "pcThunkEBXInstructions", CodeArray.class);
asm = new Assembler(0);
asm.emitMOV_Reg_RegInd(ECX, SP);
asm.emitRET();
pcThunkECXInstructions = asm.getMachineCodes();
pcThunkInstructionsField[ECX.value()] = EntrypointHelper.getField(OutOfLineMachineCode.class, "pcThunkECXInstructions", CodeArray.class);
asm = new Assembler(0);
asm.emitMOV_Reg_RegInd(EDX, SP);
asm.emitRET();
pcThunkEDXInstructions = asm.getMachineCodes();
pcThunkInstructionsField[EDX.value()] = EntrypointHelper.getField(OutOfLineMachineCode.class, "pcThunkEDXInstructions", CodeArray.class);
// NB a PC thunk into ESP isn't allowed
asm = new Assembler(0);
asm.emitMOV_Reg_RegInd(EBP, SP);
asm.emitRET();
pcThunkEBPInstructions = asm.getMachineCodes();
pcThunkInstructionsField[EBP.value()] = EntrypointHelper.getField(OutOfLineMachineCode.class, "pcThunkEBPInstructions", CodeArray.class);
asm = new Assembler(0);
asm.emitMOV_Reg_RegInd(ESI, SP);
asm.emitRET();
pcThunkESIInstructions = asm.getMachineCodes();
pcThunkInstructionsField[ESI.value()] = EntrypointHelper.getField(OutOfLineMachineCode.class, "pcThunkESIInstructions", CodeArray.class);
asm = new Assembler(0);
asm.emitMOV_Reg_RegInd(EDI, SP);
asm.emitRET();
pcThunkEDIInstructions = asm.getMachineCodes();
pcThunkInstructionsField[EDI.value()] = EntrypointHelper.getField(OutOfLineMachineCode.class, "pcThunkEDIInstructions", CodeArray.class);
}
use of org.jikesrvm.compilers.common.assembler.ia32.Assembler in project JikesRVM by JikesRVM.
the class OutOfLineMachineCode method generateStackTrampolineBridgeInstructions.
/**
* Machine code to perform a stack trampoline bridge for
* implementing a return barrier.
* <p>
* This code is used to hijack a return and bridge to some
* other method (which implements the return barrier) before
* falling back to the intended return address.
* <p>
* The key here is to preserve register and stack state so that
* the caller is oblivious of the detour that occurred during
* the return.
*
* @return instructions for the stack trampoline bridge
*/
private static CodeArray generateStackTrampolineBridgeInstructions() {
if (VM.VerifyAssertions) {
// assuming no NV FPRs (otherwise would have to save them here)
VM._assert(NUM_NONVOLATILE_FPRS == 0);
}
Assembler asm = new Assembler(0);
/* push the hijacked return address (which is held in thread-local state) */
asm.emitPUSH_RegDisp(TR, ArchEntrypoints.hijackedReturnAddressField.getOffset());
/* push the GPRs and fp */
for (int i = 0; i < NUM_GPRS; i++) {
asm.emitPUSH_Reg(ALL_GPRS[i]);
}
asm.emitPUSH_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset());
/* call the handler */
asm.generateJTOCcall(Entrypoints.returnBarrierMethod.getOffset());
/* pop the fp and GPRs */
asm.emitPOP_RegDisp(TR, ArchEntrypoints.framePointerField.getOffset());
for (int i = NUM_GPRS - 1; i >= 0; i--) {
asm.emitPOP_Reg(ALL_GPRS[i]);
}
/* pop the hijacked return address and return */
asm.emitRET();
return asm.getMachineCodes();
}
use of org.jikesrvm.compilers.common.assembler.ia32.Assembler in project JikesRVM by JikesRVM.
the class OutOfLineMachineCode method generateRestoreHardwareExceptionStateInstructions.
/**
* Machine code to implement "Magic.restoreHardwareExceptionState()".
* <pre>
* Registers taken at runtime:
* T0 == address of Registers object
*
* Registers returned at runtime:
* none
*
* Side effects at runtime:
* all registers are restored except THREAD_REGISTER and EFLAGS;
* execution resumes at "registers.ip"
* </pre>
*
* @return instructions to restore the hardware exception state
*/
private static CodeArray generateRestoreHardwareExceptionStateInstructions() {
Assembler asm = new Assembler(0);
// Set TR.framePointer to be registers.fp
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, T0, ArchEntrypoints.registersFPField.getOffset());
asm.emitMOV_RegDisp_Reg(THREAD_REGISTER, ArchEntrypoints.framePointerField.getOffset(), S0);
} else {
asm.emitMOV_Reg_RegDisp_Quad(S0, T0, ArchEntrypoints.registersFPField.getOffset());
asm.emitMOV_RegDisp_Reg_Quad(THREAD_REGISTER, ArchEntrypoints.framePointerField.getOffset(), S0);
}
// Restore SP
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, T0, ArchEntrypoints.registersGPRsField.getOffset());
asm.emitMOV_Reg_RegDisp(SP, S0, Offset.fromIntZeroExtend(SP.value() << LG_WORDSIZE));
} else {
asm.emitMOV_Reg_RegDisp_Quad(S0, T0, ArchEntrypoints.registersGPRsField.getOffset());
asm.emitMOV_Reg_RegDisp_Quad(SP, S0, Offset.fromIntZeroExtend(SP.value() << LG_WORDSIZE));
}
// Push registers.ip to stack (now that SP has been restored)
asm.emitPUSH_RegDisp(T0, ArchEntrypoints.registersIPField.getOffset());
// Restore the GPRs except for S0, TR, SP and JTOC
// (restored above and then modified by pushing registers.ip!)
Offset off = Offset.zero();
for (byte i = 0; i < NUM_GPRS; i++, off = off.plus(WORDSIZE)) {
if (i != S0.value() && i != ESI.value() && i != SP.value() && (JTOC_REGISTER == null || i != JTOC_REGISTER.value())) {
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(GPR.lookup(i), S0, off);
} else {
asm.emitMOV_Reg_RegDisp_Quad(GPR.lookup(i), S0, off);
}
}
}
// Restore S0
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, S0, Offset.fromIntZeroExtend(S0.value() << LG_WORDSIZE));
} else {
asm.emitMOV_Reg_RegDisp_Quad(S0, S0, Offset.fromIntZeroExtend(S0.value() << LG_WORDSIZE));
}
// Return to registers.ip (popping stack)
asm.emitRET();
return asm.getMachineCodes();
}
use of org.jikesrvm.compilers.common.assembler.ia32.Assembler in project JikesRVM by JikesRVM.
the class OutOfLineMachineCode method generateReflectiveMethodInvokerInstructions.
/**
* Machine code for reflective method invocation.
* <pre>
* VM compiled with NUM_PARAMETERS_GPRS == 0
* Registers taken at runtime:
* none
* Stack taken at runtime:
* hi-mem
* address of method entrypoint to be called
* address of gpr registers to be loaded
* address of fpr registers to be loaded
* address of parameters area in calling frame
* return address
* low-mem
*
* VM compiled with NUM_PARAMETERS_GPRS == 1
* T0 == address of method entrypoint to be called
* Stack taken at runtime:
* hi-mem
* space ???
* address of gpr registers to be loaded
* address of fpr registers to be loaded
* address of parameters area in calling frame
* return address
* low-mem
*
* VM compiled with NUM_PARAMETERS_GPRS == 2
* T0 == address of method entrypoint to be called
* T1 == address of gpr registers to be loaded
* Stack taken at runtime:
* hi-mem
* space ???
* space ???
* address of fpr registers to be loaded
* address of parameters area in calling frame
* return address
* low-mem
*
* Registers returned at runtime:
* standard return value conventions used
*
* Side effects at runtime:
* artificial stackframe created and destroyed
* volatile, and scratch registers destroyed
* </pre>
*
* @return instructions for the reflective method invoker
*/
private static CodeArray generateReflectiveMethodInvokerInstructions() {
Assembler asm = new Assembler(100);
int gprs;
Offset fpOffset = ArchEntrypoints.framePointerField.getOffset();
GPR T = T0;
gprs = NUM_PARAMETER_GPRS;
// we have exactly 5 paramaters, offset 0 from SP is the return address the
// parameters are at offsets 5 to 1
Offset offset = Offset.fromIntZeroExtend(5 << LG_WORDSIZE);
// logically equivalent to ParamaterRegisterUnload in the compiler
if (gprs > 0) {
gprs--;
if (VM.BuildFor32Addr) {
asm.emitMOV_RegDisp_Reg(SP, offset, T);
} else {
asm.emitMOV_RegDisp_Reg_Quad(SP, offset, T);
}
T = T1;
offset = offset.minus(WORDSIZE);
}
if (gprs > 0) {
if (VM.BuildFor32Addr) {
asm.emitMOV_RegDisp_Reg(SP, offset, T);
} else {
asm.emitMOV_RegDisp_Reg_Quad(SP, offset, T);
}
}
/* available registers S0, T0, T1 */
/* push a new frame */
// link this frame with next
asm.emitPUSH_RegDisp(TR, fpOffset);
if (VM.BuildFor32Addr) {
// establish base of new frame
asm.emitMOV_RegDisp_Reg(THREAD_REGISTER, fpOffset, SP);
asm.emitPUSH_Imm(INVISIBLE_METHOD_ID);
asm.emitADD_Reg_Imm(SP, STACKFRAME_BODY_OFFSET.toInt());
} else {
// establish base of new frame
asm.emitMOV_RegDisp_Reg_Quad(THREAD_REGISTER, fpOffset, SP);
asm.emitPUSH_Imm(INVISIBLE_METHOD_ID);
asm.emitADD_Reg_Imm_Quad(SP, STACKFRAME_BODY_OFFSET.toInt());
}
/* write parameters on stack
* move data from memory addressed by Paramaters array, the fourth
* parameter to this, into the stack.
* SP target address
* S0 source address
* T1 length
* T0 scratch
*/
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, THREAD_REGISTER, fpOffset);
// S0 <- Parameters
asm.emitMOV_Reg_RegDisp(S0, S0, PARAMS_FP_OFFSET);
// T1 <- Parameters.length()
asm.emitMOV_Reg_RegDisp(T1, S0, ObjectModel.getArrayLengthOffset());
// length == 0 ?
asm.emitCMP_Reg_Imm(T1, 0);
} else {
asm.emitMOV_Reg_RegDisp_Quad(S0, THREAD_REGISTER, fpOffset);
// S0 <- Parameters
asm.emitMOV_Reg_RegDisp_Quad(S0, S0, PARAMS_FP_OFFSET);
if (ARRAY_LENGTH_BYTES == 4) {
// T1 <- Parameters.length()
asm.emitMOV_Reg_RegDisp(T1, S0, ObjectModel.getArrayLengthOffset());
// length == 0 ?
asm.emitCMP_Reg_Imm(T1, 0);
} else {
// T1 <- Parameters.length()
asm.emitMOV_Reg_RegDisp_Quad(T1, S0, ObjectModel.getArrayLengthOffset());
// length == 0 ?
asm.emitCMP_Reg_Imm_Quad(T1, 0);
}
}
int parameterLoopLabel = asm.getMachineCodeIndex();
// done? --> branch to end
ForwardReference fr1 = asm.forwardJcc(EQ);
if (VM.BuildFor32Addr) {
// T0 <- Paramaters[i]
asm.emitMOV_Reg_RegInd(T0, S0);
} else {
// T0 <- Paramaters[i]
asm.emitMOV_Reg_RegInd_Quad(T0, S0);
}
// mem[j++] <- Parameters[i]
asm.emitPUSH_Reg(T0);
if (VM.BuildFor32Addr) {
// i++
asm.emitADD_Reg_Imm(S0, WORDSIZE);
} else {
// i++
asm.emitADD_Reg_Imm_Quad(S0, WORDSIZE);
}
if (ARRAY_LENGTH_BYTES == 4) {
// length--
asm.emitADD_Reg_Imm(T1, -1);
} else {
// length--
asm.emitADD_Reg_Imm_Quad(T1, -1);
}
asm.emitJMP_Imm(parameterLoopLabel);
// end of the loop
fr1.resolve(asm);
if (SSE2_FULL) {
/* write fprs onto fprs registers */
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, THREAD_REGISTER, fpOffset);
// T0 <- FPRs
asm.emitMOV_Reg_RegDisp(T0, S0, FPRS_FP_OFFSET);
// T1 <- FPRs.length()
asm.emitMOV_Reg_RegDisp(T1, T0, ObjectModel.getArrayLengthOffset());
// S0 <- FPRmeta
asm.emitMOV_Reg_RegDisp(S0, S0, FPRMETA_FP_OFFSET);
} else {
asm.emitMOV_Reg_RegDisp_Quad(S0, THREAD_REGISTER, fpOffset);
// T0 <- FPRs
asm.emitMOV_Reg_RegDisp_Quad(T0, S0, FPRS_FP_OFFSET);
if (ARRAY_LENGTH_BYTES == 4) {
// T1 <- FPRs.length()
asm.emitMOV_Reg_RegDisp(T1, T0, ObjectModel.getArrayLengthOffset());
} else {
// T1 <- FPRs.length()
asm.emitMOV_Reg_RegDisp_Quad(T1, T0, ObjectModel.getArrayLengthOffset());
}
// S0 <- FPRmeta
asm.emitMOV_Reg_RegDisp_Quad(S0, S0, FPRMETA_FP_OFFSET);
}
if (VM.VerifyAssertions)
VM._assert(NUM_PARAMETER_FPRS <= 4);
ForwardReference fr_next;
// length == 0 ?
asm.emitCMP_Reg_Imm(T1, 0);
ForwardReference fpr_r1 = asm.forwardJcc(EQ);
asm.emitMOVSD_Reg_RegInd(XMM0, T0);
asm.emitCMP_RegInd_Imm_Byte(S0, 0);
fr_next = asm.forwardJcc(NE);
asm.emitCVTSD2SS_Reg_Reg(XMM0, XMM0);
fr_next.resolve(asm);
// length == 0 ?
asm.emitSUB_Reg_Imm(T1, 1);
ForwardReference fpr_r2 = asm.forwardJcc(EQ);
asm.emitMOVSD_Reg_RegDisp(XMM1, T0, Offset.fromIntZeroExtend(BYTES_IN_DOUBLE));
asm.emitCMP_RegDisp_Imm_Byte(S0, Offset.fromIntZeroExtend(1), 0);
fr_next = asm.forwardJcc(NE);
asm.emitCVTSD2SS_Reg_Reg(XMM1, XMM1);
fr_next.resolve(asm);
// length == 0 ?
asm.emitSUB_Reg_Imm(T1, 1);
ForwardReference fpr_r3 = asm.forwardJcc(EQ);
asm.emitMOVSD_Reg_RegDisp(XMM2, T0, Offset.fromIntZeroExtend(BYTES_IN_DOUBLE * 2));
asm.emitCMP_RegDisp_Imm_Byte(S0, Offset.fromIntZeroExtend(2), 0);
fr_next = asm.forwardJcc(NE);
asm.emitCVTSD2SS_Reg_Reg(XMM2, XMM2);
fr_next.resolve(asm);
// length == 0 ?
asm.emitSUB_Reg_Imm(T1, 1);
ForwardReference fpr_r4 = asm.forwardJcc(EQ);
asm.emitMOVSD_Reg_RegDisp(XMM3, T0, Offset.fromIntZeroExtend(BYTES_IN_DOUBLE * 3));
asm.emitCMP_RegDisp_Imm_Byte(S0, Offset.fromIntZeroExtend(3), 0);
fr_next = asm.forwardJcc(NE);
asm.emitCVTSD2SS_Reg_Reg(XMM3, XMM3);
fr_next.resolve(asm);
fpr_r1.resolve(asm);
fpr_r2.resolve(asm);
fpr_r3.resolve(asm);
fpr_r4.resolve(asm);
} else {
if (VM.VerifyAssertions)
VM._assert(VM.BuildFor32Addr);
/* write fprs onto fprs registers */
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, THREAD_REGISTER, fpOffset);
} else {
asm.emitMOV_Reg_RegDisp_Quad(S0, THREAD_REGISTER, fpOffset);
}
// S0 <- FPRs
asm.emitMOV_Reg_RegDisp(S0, S0, FPRS_FP_OFFSET);
// T1 <- FPRs.length()
asm.emitMOV_Reg_RegDisp(T1, S0, ObjectModel.getArrayLengthOffset());
// length in bytes
asm.emitSHL_Reg_Imm(T1, LG_WORDSIZE + 1);
// S0 <- last FPR + 8
asm.emitADD_Reg_Reg(S0, T1);
// length == 0 ?
asm.emitCMP_Reg_Imm(T1, 0);
int fprsLoopLabel = asm.getMachineCodeIndex();
// done? --> branch to end
ForwardReference fr2 = asm.forwardJcc(EQ);
// i--
asm.emitSUB_Reg_Imm(S0, 2 * WORDSIZE);
// frp[fpr_sp++] <-FPRs[i]
asm.emitFLD_Reg_RegInd_Quad(FP0, S0);
// length--
asm.emitSUB_Reg_Imm(T1, 2 * WORDSIZE);
asm.emitJMP_Imm(fprsLoopLabel);
// end of the loop
fr2.resolve(asm);
}
/* write gprs: S0 = Base address of GPRs[], T1 = GPRs.length */
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, THREAD_REGISTER, fpOffset);
// S0 <- GPRs
asm.emitMOV_Reg_RegDisp(S0, S0, GPRS_FP_OFFSET);
// T1 <- GPRs.length()
asm.emitMOV_Reg_RegDisp(T1, S0, ObjectModel.getArrayLengthOffset());
// length == 0 ?
asm.emitCMP_Reg_Imm(T1, 0);
} else {
asm.emitMOV_Reg_RegDisp_Quad(S0, THREAD_REGISTER, fpOffset);
// S0 <- GPRs
asm.emitMOV_Reg_RegDisp_Quad(S0, S0, GPRS_FP_OFFSET);
if (ARRAY_LENGTH_BYTES == 4) {
// T1 <- GPRs.length()
asm.emitMOV_Reg_RegDisp(T1, S0, ObjectModel.getArrayLengthOffset());
// length == 0 ?
asm.emitCMP_Reg_Imm(T1, 0);
} else {
// T1 <- GPRs.length()
asm.emitMOV_Reg_RegDisp_Quad(T1, S0, ObjectModel.getArrayLengthOffset());
// length == 0 ?
asm.emitCMP_Reg_Imm_Quad(T1, 0);
}
}
// result 0 --> branch to end
ForwardReference fr3 = asm.forwardJcc(EQ);
if (VM.BuildFor32Addr) {
// T0 <- GPRs[0]
asm.emitMOV_Reg_RegInd(T0, S0);
// S0 += WORDSIZE
asm.emitADD_Reg_Imm(S0, WORDSIZE);
// T1--
asm.emitADD_Reg_Imm(T1, -1);
} else {
// T0 <- GPRs[0]
asm.emitMOV_Reg_RegInd_Quad(T0, S0);
// S0 += WORDSIZE
asm.emitADD_Reg_Imm_Quad(S0, WORDSIZE);
// T1--
asm.emitADD_Reg_Imm_Quad(T1, -1);
}
// result 0 --> branch to end
ForwardReference fr4 = asm.forwardJcc(EQ);
if (VM.BuildFor32Addr) {
// T1 <- GPRs[1]
asm.emitMOV_Reg_RegInd(T1, S0);
} else {
// T1 <- GPRs[1]
asm.emitMOV_Reg_RegInd_Quad(T1, S0);
}
fr3.resolve(asm);
fr4.resolve(asm);
/* branch to method. On a good day we might even be back */
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_RegDisp(S0, THREAD_REGISTER, fpOffset);
// S0 <- code
asm.emitMOV_Reg_RegDisp(S0, S0, CODE_FP_OFFSET);
} else {
asm.emitMOV_Reg_RegDisp_Quad(S0, THREAD_REGISTER, fpOffset);
// S0 <- code
asm.emitMOV_Reg_RegDisp_Quad(S0, S0, CODE_FP_OFFSET);
}
// go there
asm.emitCALL_Reg(S0);
// add back in the initial SP to FP delta to get SP to be a framepointer again!
if (VM.BuildFor32Addr) {
asm.emitADD_Reg_Imm(SP, -STACKFRAME_BODY_OFFSET.toInt() + WORDSIZE);
} else {
asm.emitADD_Reg_Imm_Quad(SP, -STACKFRAME_BODY_OFFSET.toInt() + WORDSIZE);
}
asm.emitPOP_RegDisp(TR, fpOffset);
// again, exactly 5 parameters
asm.emitRET_Imm(5 << LG_WORDSIZE);
return asm.getMachineCodes();
}
Aggregations