use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emit_d2l.
@Override
protected void emit_d2l() {
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_Quad(FP0, SP);
// Setup maxlong into FP0
asm.emitFLD_Reg_Abs_Quad(FP0, Magic.getTocPointer().plus(Entrypoints.maxlongField.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
// [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_RegDisp_Imm(SP, ONE_SLOT, 0x7FFFFFFF);
asm.emitMOV_RegInd_Imm(SP, -1);
ForwardReference fr4 = asm.forwardJMP();
fr3.resolve(asm);
asm.emitMOV_RegDisp_Imm(SP, ONE_SLOT, 0);
asm.emitMOV_RegInd_Imm(SP, 0);
fr2.resolve(asm);
fr4.resolve(asm);
} else {
// Set up value in XMM0
asm.emitMOVSD_Reg_RegInd(XMM0, SP);
// adjust = 0
asm.emitXOR_Reg_Reg(T1, T1);
// result = 0
asm.emitXOR_Reg_Reg(T0, T0);
// value cmp maxlong
asm.generateJTOCcmpDouble(XMM0, Entrypoints.maxlongField.getOffset());
// if NaN goto fr1
ForwardReference fr1 = asm.forwardJcc(PE);
// T1 = (value >= maxlong) ? 1 : 0;
asm.emitSET_Cond_Reg_Byte(LGE, T1);
// T0 = (int)value, or 0x80...00 if value > maxlong
asm.emitCVTTSD2SIQ_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.emitMOV_RegInd_Reg_Quad(SP, T0);
}
}
use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method genStackOverflowCheck.
private void genStackOverflowCheck() {
/*
* Generate stacklimit check.
*
* NOTE: The stack overflow check MUST happen before the frame is created.
* If the check were to happen after frame creation, the stack pointer
* could already be well below the stack limit. This would be a problem
* because the IA32 stack overflow handling code imposes a bound on the
* difference between the stack pointer and the stack limit.
*
* NOTE: Frame sizes for the baseline compiler can get very large because
* each non-parameter local slot and each slot for the operand stack
* requires one machine word.
*
* The Java Virtual Machine Specification has an overview of the limits for
* the local words and operand words in section 4.11,
* "Limitations of the Java Virtual Machine".
*/
if (isInterruptible) {
int frameSize = calculateRequiredSpaceForFrame(method);
// S0<-limit
if (VM.BuildFor32Addr) {
asm.emitMOV_Reg_Reg(S0, ESP);
asm.emitSUB_Reg_Imm(S0, frameSize);
asm.emitCMP_Reg_RegDisp(S0, TR, Entrypoints.stackLimitField.getOffset());
} else {
asm.emitMOV_Reg_Reg_Quad(S0, ESP);
asm.emitSUB_Reg_Imm_Quad(S0, frameSize);
asm.emitCMP_Reg_RegDisp_Quad(S0, TR, Entrypoints.stackLimitField.getOffset());
}
asm.emitBranchLikelyNextInstruction();
// Jmp around trap if OK
ForwardReference fr = asm.forwardJcc(LGT);
// trap
asm.emitINT_Imm(RuntimeEntrypoints.TRAP_STACK_OVERFLOW + RVM_TRAP_BASE);
fr.resolve(asm);
} else {
// TODO!! make sure stackframe of uninterruptible method doesn't overflow guard page
}
}
use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emit_lookupswitch.
/**
* Emit code to implement the lookupswitch bytecode.
* Uses linear search, one could use a binary search tree instead,
* but this is the baseline compiler, so don't worry about it.
*
* @param defaultval bcIndex of the default target
* @param npairs number of pairs in the lookup switch
*/
@Override
protected void emit_lookupswitch(int defaultval, int npairs) {
asm.emitPOP_Reg(T0);
for (int i = 0; i < npairs; i++) {
int match = bcodes.getLookupSwitchValue(i);
asm.emitCMP_Reg_Imm(T0, match);
int offset = bcodes.getLookupSwitchOffset(i);
int bTarget = biStart + offset;
int mTarget = bytecodeMap[bTarget];
if (!VM.runningTool && ((BaselineCompiledMethod) compiledMethod).hasCounterArray()) {
// Flip conditions so we can jump over the increment of the taken counter.
ForwardReference fr = asm.forwardJcc(NE);
incEdgeCounter(S0, null, edgeCounterIdx++);
asm.emitJMP_ImmOrLabel(mTarget, bTarget);
fr.resolve(asm);
} else {
asm.emitJCC_Cond_ImmOrLabel(EQ, mTarget, bTarget);
}
}
bcodes.skipLookupSwitchPairs(npairs);
int bTarget = biStart + defaultval;
int mTarget = bytecodeMap[bTarget];
if (!VM.runningTool && ((BaselineCompiledMethod) compiledMethod).hasCounterArray()) {
// increment default counter
incEdgeCounter(S0, null, edgeCounterIdx++);
}
asm.emitJMP_ImmOrLabel(mTarget, bTarget);
}
use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emit_lshl.
@Override
protected void emit_lshl() {
if (VM.BuildFor32Addr) {
if (SSE2_BASE) {
// shift amount (6 bits)
asm.emitPOP_Reg(T0);
// XMM1 <- [SP]
asm.emitMOVQ_Reg_RegInd(XMM1, SP);
// mask to 6bits
asm.emitAND_Reg_Imm(T0, 0x3F);
// XMM0 <- T0
asm.emitMOVD_Reg_Reg(XMM0, T0);
// XMM1 <<= XMM0
asm.emitPSLLQ_Reg_Reg(XMM1, XMM0);
// [SP] <- XMM1
asm.emitMOVQ_RegInd_Reg(SP, XMM1);
} else {
// ECX is constrained to be the shift count
if (VM.VerifyAssertions)
VM._assert(ECX != T0);
if (VM.VerifyAssertions)
VM._assert(ECX != T1);
// shift amount (6 bits)
asm.emitPOP_Reg(ECX);
// pop low half
asm.emitPOP_Reg(T0);
// pop high half
asm.emitPOP_Reg(T1);
asm.emitAND_Reg_Imm(ECX, 0x3F);
asm.emitCMP_Reg_Imm(ECX, 32);
ForwardReference fr1 = asm.forwardJcc(LT);
// high half = low half
asm.emitMOV_Reg_Reg(T1, T0);
// low half = 0
asm.emitXOR_Reg_Reg(T0, T0);
fr1.resolve(asm);
// shift high half, filling from low
asm.emitSHLD_Reg_Reg_Reg(T1, T0, ECX);
// shift low half
asm.emitSHL_Reg_Reg(T0, ECX);
// push high half
asm.emitPUSH_Reg(T1);
// push low half
asm.emitPUSH_Reg(T0);
}
} else {
asm.emitPOP_Reg(ECX);
asm.emitSHL_RegInd_Reg_Quad(SP, ECX);
}
}
use of org.jikesrvm.compilers.common.assembler.ForwardReference in project JikesRVM by JikesRVM.
the class BaselineCompilerImpl method emit_d2i.
@Override
protected void emit_d2i() {
if (SSE2_BASE) {
// Set up value in XMM0
asm.emitMOVSD_Reg_RegInd(XMM0, SP);
// throw away slots
adjustStack(2 * WORDSIZE, true);
// adjust = 0
asm.emitXOR_Reg_Reg(T1, T1);
// result = 0
asm.emitXOR_Reg_Reg(T0, T0);
// value cmp maxint
asm.generateJTOCcmpDouble(XMM0, Entrypoints.maxintField.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.emitCVTTSD2SI_Reg_Reg(T0, XMM0);
// T0 = T0 - T1, ie fix max int case
asm.emitSUB_Reg_Reg(T0, T1);
fr1.resolve(asm);
// push result
asm.emitPUSH_Reg(T0);
} else {
// TODO: use x87 operations to do this conversion inline taking care of
// the boundary cases that differ between x87 and Java
// (1) 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]);
}
// (2) Push args to C function (reversed)
asm.emitPUSH_RegDisp(SP, off.plus(4));
asm.emitPUSH_RegDisp(SP, off.plus(4));
// (3) invoke C function through bootrecord
asm.emitMOV_Reg_Abs(S0, Magic.getTocPointer().plus(Entrypoints.the_boot_recordField.getOffset()));
asm.emitCALL_RegDisp(S0, Entrypoints.sysDoubleToIntIPField.getOffset());
// (4) pop arguments
asm.emitPOP_Reg(S0);
asm.emitPOP_Reg(S0);
// (5) restore RVM nonvolatiles
for (int i = numNonVols - 1; i >= 0; i--) {
asm.emitPOP_Reg(NONVOLATILE_GPRS[i]);
}
// (6) put result on expression stack
// throw away slot
adjustStack(WORDSIZE, true);
asm.emitMOV_RegInd_Reg(SP, T0);
}
}
Aggregations