use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emitDynamicLinkingSequence.
/**
* Emit dynamic linking sequence placing the offset of the given member in reg
* @param asm assembler to generate code into
* @param reg register to hold offset to method
* @param ref method reference to be resolved
* @param couldBeZero could the value in the offsets table require resolving
*/
static void emitDynamicLinkingSequence(Assembler asm, GPR reg, MemberReference ref, boolean couldBeZero) {
int memberId = ref.getId();
Offset memberOffset = Offset.fromIntZeroExtend(memberId << 2);
Offset tableOffset = Entrypoints.memberOffsetsField.getOffset();
if (couldBeZero) {
// branch here after dynamic class loading
int retryLabel = asm.getMachineCodeIndex();
// reg is offsets table
asm.generateJTOCloadWord(reg, tableOffset);
if (VM.BuildFor32Addr) {
// reg is offset of member, or 0 if member's class isn't loaded
asm.emitMOV_Reg_RegDisp(reg, reg, memberOffset);
} else {
// reg is offset of member, or 0 if member's class isn't loaded
asm.emitMOVSXDQ_Reg_RegDisp(reg, reg, memberOffset);
}
if (NEEDS_DYNAMIC_LINK == 0) {
// reg ?= NEEDS_DYNAMIC_LINK, is field's class loaded?
asm.emitTEST_Reg_Reg(reg, reg);
} else {
// reg ?= NEEDS_DYNAMIC_LINK, is field's class loaded?
asm.emitCMP_Reg_Imm(reg, NEEDS_DYNAMIC_LINK);
}
// if so, skip call instructions
ForwardReference fr = asm.forwardJcc(NE);
// pass member's dictId
asm.emitPUSH_Imm(memberId);
// pass 1 parameter word
genParameterRegisterLoad(asm, 1);
Offset resolverOffset = Entrypoints.resolveMemberMethod.getOffset();
// does class loading as sideffect
asm.generateJTOCcall(resolverOffset);
// reload reg with valid value
asm.emitJMP_Imm(retryLabel);
// come from Jcc above.
fr.resolve(asm);
} else {
// reg is offsets table
asm.generateJTOCloadWord(reg, tableOffset);
if (VM.BuildFor32Addr) {
// reg is offset of member
asm.emitMOV_Reg_RegDisp(reg, reg, memberOffset);
} else {
// reg is offset of member
asm.emitMOVSXDQ_Reg_RegDisp(reg, reg, memberOffset);
}
}
}
use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emit_f2l.
@Override
protected void emit_f2l() {
if (VM.BuildFor32Addr) {
// TODO: SSE3 has a FISTTP instruction that stores the value with truncation
// meaning the FPSCW can be left alone
// Setup value into FP1
asm.emitFLD_Reg_RegInd(FP0, SP);
// Setup maxlong into FP0
asm.emitFLD_Reg_Abs(FP0, Magic.getTocPointer().plus(Entrypoints.maxlongFloatField.getOffset()));
// if value > maxlong or NaN goto fr1; FP0 = value
asm.emitFUCOMIP_Reg_Reg(FP0, FP1);
ForwardReference fr1 = asm.forwardJcc(LLE);
// Normally the status and control word rounds numbers, but for conversion
// to an integer/long value we want truncation. We therefore save the FPSCW,
// set it to truncation perform operation then restore
// Grow the stack
adjustStack(-WORDSIZE, true);
// [SP-4] = fpscw
asm.emitFNSTCW_RegDisp(SP, MINUS_ONE_SLOT);
// EAX = fpscw
asm.emitMOVZX_Reg_RegDisp_Word(T0, SP, MINUS_ONE_SLOT);
// EAX = FPSCW in truncate mode
asm.emitOR_Reg_Imm(T0, 0xC00);
// [SP] = new fpscw value
asm.emitMOV_RegInd_Reg(SP, T0);
// Set FPSCW
asm.emitFLDCW_RegInd(SP);
// Store 64bit long
asm.emitFISTP_RegInd_Reg_Quad(SP, FP0);
// Restore FPSCW
asm.emitFLDCW_RegDisp(SP, MINUS_ONE_SLOT);
ForwardReference fr2 = asm.forwardJMP();
fr1.resolve(asm);
// pop FPU*1
asm.emitFSTP_Reg_Reg(FP0, FP0);
// if value == NaN goto fr3
ForwardReference fr3 = asm.forwardJcc(PE);
asm.emitMOV_RegInd_Imm(SP, 0x7FFFFFFF);
asm.emitPUSH_Imm(-1);
ForwardReference fr4 = asm.forwardJMP();
fr3.resolve(asm);
asm.emitMOV_RegInd_Imm(SP, 0);
asm.emitPUSH_Imm(0);
fr2.resolve(asm);
fr4.resolve(asm);
} else {
// Set up value in XMM0
asm.emitMOVSS_Reg_RegInd(XMM0, SP);
// adjust = 0
asm.emitXOR_Reg_Reg(T1, T1);
// result = 0
asm.emitXOR_Reg_Reg(T0, T0);
// value cmp maxlong
asm.generateJTOCcmpFloat(XMM0, Entrypoints.maxlongFloatField.getOffset());
// if NaN goto fr1
ForwardReference fr1 = asm.forwardJcc(PE);
// T1 = (value >= maxint) ? 1 : 0;
asm.emitSET_Cond_Reg_Byte(LGE, T1);
// T0 = (int)value, or 0x80000000 if value > maxint
asm.emitCVTTSS2SI_Reg_Reg_Quad(T0, XMM0);
// T0 = T0 - T1, ie fix max long case
asm.emitSUB_Reg_Reg_Quad(T0, T1);
fr1.resolve(asm);
// push result
asm.emitPUSH_Reg(T0);
}
}
use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emit_checkcast_final.
@Override
protected void emit_checkcast_final(RVMType type) {
if (VM.BuildFor32Addr) {
// load object from stack
asm.emitMOV_Reg_RegInd(ECX, SP);
} else {
// load object from stack
asm.emitMOV_Reg_RegInd_Quad(ECX, SP);
}
// jump forward if ECX == 0
ForwardReference isNull = asm.forwardJECXZ();
// TIB of object
asm.baselineEmitLoadTIB(S0, ECX);
asm.generateJTOCcmpWord(S0, type.getTibOffset());
asm.emitBranchLikelyNextInstruction();
ForwardReference fr = asm.forwardJcc(EQ);
asm.emitINT_Imm(RuntimeEntrypoints.TRAP_CHECKCAST + RVM_TRAP_BASE);
fr.resolve(asm);
isNull.resolve(asm);
}
use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emit_lrem.
@Override
protected void emit_lrem() {
if (VM.BuildFor64Addr) {
// ECX is divisor; NOTE: can't use symbolic registers because of intel hardware requirements
asm.emitPOP_Reg(ECX);
// throw away slot
asm.emitPOP_Reg(EAX);
// EAX is dividend
asm.emitPOP_Reg(EAX);
// sign extend EAX into EDX
asm.emitCDO();
asm.emitIDIV_Reg_Reg_Quad(EAX, ECX);
// push result
asm.emitPUSH_Reg(EDX);
} else {
// (1) zero check
asm.emitMOV_Reg_RegInd(T0, SP);
asm.emitOR_Reg_RegDisp(T0, SP, ONE_SLOT);
asm.emitBranchLikelyNextInstruction();
ForwardReference fr1 = asm.forwardJcc(NE);
// trap if divisor is 0
asm.emitINT_Imm(RuntimeEntrypoints.TRAP_DIVIDE_BY_ZERO + RVM_TRAP_BASE);
fr1.resolve(asm);
// (2) save RVM nonvolatiles
int numNonVols = NONVOLATILE_GPRS.length;
Offset off = Offset.fromIntSignExtend(numNonVols * WORDSIZE);
for (int i = 0; i < numNonVols; i++) {
asm.emitPUSH_Reg(NONVOLATILE_GPRS[i]);
}
// (3) Push args to C function (reversed)
asm.emitPUSH_RegDisp(SP, off.plus(4));
asm.emitPUSH_RegDisp(SP, off.plus(4));
asm.emitPUSH_RegDisp(SP, off.plus(20));
asm.emitPUSH_RegDisp(SP, off.plus(20));
// (4) invoke C function through bootrecord
asm.emitMOV_Reg_Abs(S0, Magic.getTocPointer().plus(Entrypoints.the_boot_recordField.getOffset()));
asm.emitCALL_RegDisp(S0, Entrypoints.sysLongRemainderIPField.getOffset());
// (5) pop space for arguments
adjustStack(4 * WORDSIZE, true);
// (6) restore RVM nonvolatiles
for (int i = numNonVols - 1; i >= 0; i--) {
asm.emitPOP_Reg(NONVOLATILE_GPRS[i]);
}
// (7) pop expression stack
adjustStack(WORDSIZE * 4, true);
// (8) push results
asm.emitPUSH_Reg(T1);
asm.emitPUSH_Reg(T0);
}
}
use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emit_ldiv.
@Override
protected void emit_ldiv() {
if (VM.BuildFor64Addr) {
// ECX is divisor; NOTE: can't use symbolic registers because of intel hardware requirements
asm.emitPOP_Reg(ECX);
// throw away slot
asm.emitPOP_Reg(EAX);
// EAX is dividend
asm.emitPOP_Reg(EAX);
// sign extend EAX into EDX
asm.emitCDO();
asm.emitIDIV_Reg_Reg_Quad(EAX, ECX);
// push result
asm.emitPUSH_Reg(EAX);
} else {
// (1) zero check
asm.emitMOV_Reg_RegInd(T0, SP);
asm.emitOR_Reg_RegDisp(T0, SP, ONE_SLOT);
asm.emitBranchLikelyNextInstruction();
ForwardReference fr1 = asm.forwardJcc(NE);
// trap if divisor is 0
asm.emitINT_Imm(RuntimeEntrypoints.TRAP_DIVIDE_BY_ZERO + RVM_TRAP_BASE);
fr1.resolve(asm);
// (2) save RVM nonvolatiles
int numNonVols = NONVOLATILE_GPRS.length;
Offset off = Offset.fromIntSignExtend(numNonVols * WORDSIZE);
for (int i = 0; i < numNonVols; i++) {
asm.emitPUSH_Reg(NONVOLATILE_GPRS[i]);
}
// (3) Push args to C function (reversed)
asm.emitPUSH_RegDisp(SP, off.plus(4));
asm.emitPUSH_RegDisp(SP, off.plus(4));
asm.emitPUSH_RegDisp(SP, off.plus(20));
asm.emitPUSH_RegDisp(SP, off.plus(20));
// (4) invoke C function through bootrecord
asm.emitMOV_Reg_Abs(S0, Magic.getTocPointer().plus(Entrypoints.the_boot_recordField.getOffset()));
asm.emitCALL_RegDisp(S0, Entrypoints.sysLongDivideIPField.getOffset());
// (5) pop space for arguments
adjustStack(4 * WORDSIZE, true);
// (6) restore RVM nonvolatiles
for (int i = numNonVols - 1; i >= 0; i--) {
asm.emitPOP_Reg(NONVOLATILE_GPRS[i]);
}
// (7) pop expression stack
adjustStack(WORDSIZE * 4, true);
// (8) push results
asm.emitPUSH_Reg(T1);
asm.emitPUSH_Reg(T0);
}
}
Aggregations