use of org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand in project JikesRVM by JikesRVM.
the class CallingConvention method expandParametersToCall.
/**
* Explicitly copy parameters to a call into the appropriate physical
* registers as defined by the calling convention.<p>
*
* Note: Assumes that ESP points to the word before the slot where the
* first parameter should be stored.
*
* @param call the call instruction
* @param ir the IR that contains the call
* @return number of bytes necessary to hold the parameters
*/
private static int expandParametersToCall(Instruction call, IR ir) {
int nGPRParams = 0;
int nFPRParams = 0;
PhysicalRegisterSet phys = (PhysicalRegisterSet) ir.regpool.getPhysicalRegisterSet();
// count the number FPR parameters in a pre-pass
int FPRRegisterParams = countFPRParams(call);
FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfFPRParams());
// offset, in bytes, from the SP, for the next parameter slot on the
// stack
int parameterBytes = 0;
// Require ESP to be at bottom of frame before a call,
call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(0)));
// walk over each parameter
// must count then before we start nulling them out!
int numParams = MIR_Call.getNumberOfParams(call);
int nParamsInRegisters = 0;
for (int i = 0; i < numParams; i++) {
Operand param = MIR_Call.getClearParam(call, i);
MIR_Call.setParam(call, i, null);
TypeReference paramType = param.getType();
if (paramType.isFloatingPointType()) {
nFPRParams++;
int size;
if (paramType.isFloatType()) {
size = BYTES_IN_FLOAT;
parameterBytes -= WORDSIZE;
} else {
size = BYTES_IN_DOUBLE;
parameterBytes -= 2 * WORDSIZE;
}
if (nFPRParams > PhysicalRegisterSet.getNumberOfFPRParams()) {
// pass the FP parameter on the stack
Operand M = new StackLocationOperand(false, parameterBytes, size);
if (SSE2_FULL) {
if (paramType.isFloatType()) {
call.insertBefore(MIR_Move.create(IA32_MOVSS, M, param));
} else {
call.insertBefore(MIR_Move.create(IA32_MOVSD, M, param));
}
} else {
call.insertBefore(MIR_Move.create(IA32_FMOV, M, param));
}
} else {
// Pass the parameter in a register.
RegisterOperand real;
if (SSE2_FULL) {
real = new RegisterOperand(phys.getFPRParam(nFPRParams - 1), paramType);
if (paramType.isFloatType()) {
call.insertBefore(MIR_Move.create(IA32_MOVSS, real, param));
} else {
call.insertBefore(MIR_Move.create(IA32_MOVSD, real, param));
}
} else {
// Note that if k FPRs are passed in registers,
// the 1st goes in F(k-1),
// the 2nd goes in F(k-2), etc...
real = new RegisterOperand(phys.getFPRParam(FPRRegisterParams - nFPRParams), paramType);
call.insertBefore(MIR_Move.create(IA32_FMOV, real, param));
}
// Record that the call now has a use of the real register.
MIR_Call.setParam(call, nParamsInRegisters++, real.copy());
}
} else {
nGPRParams++;
parameterBytes -= WORDSIZE;
if (paramIsNativeLongOn64Bit(param)) {
parameterBytes -= WORDSIZE;
}
if (nGPRParams > PhysicalRegisterSet.getNumberOfGPRParams()) {
// parameter into the appropriate stack frame location.
if (paramIsNativeLongOn64Bit(param)) {
call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes + WORDSIZE * 2)));
call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, IC(0)));
} else {
call.insertBefore(MIR_UnaryNoRes.create(REQUIRE_ESP, IC(parameterBytes + WORDSIZE)));
}
call.insertBefore(MIR_UnaryNoRes.create(IA32_PUSH, param));
} else {
// Pass the parameter in a register.
Register phy = phys.getGPRParam(nGPRParams - 1);
RegisterOperand real = new RegisterOperand(phy, paramType);
call.insertBefore(MIR_Move.create(IA32_MOV, real, param));
// Record that the call now has a use of the real register.
MIR_Call.setParam(call, nParamsInRegisters++, real.copy());
}
}
}
return parameterBytes;
}
use of org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand in project JikesRVM by JikesRVM.
the class CallingConvention method restoreNonvolatilesAfterSysCall.
/**
* Restore all nonvolatile registers after a syscall.
* We do this in case the sys call does not respect our
* register conventions.<p>
*
* We save/restore all nonvolatiles and the PR, whether
* or not this routine uses them. This may be a tad inefficient, but if
* you're making a system call, you probably don't care.
*
* @param call the sys call
* @param ir the IR that contains the call
*/
static void restoreNonvolatilesAfterSysCall(Instruction call, IR ir) {
GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
StackManager sm = (StackManager) ir.stackManager;
// get the offset into the stack frame of where to stash the first
// nonvolatile for this case.
int location = sm.getOffsetForSysCall();
// restore each non-volatile
for (Enumeration<Register> e = phys.enumerateNonvolatileGPRs(); e.hasMoreElements(); ) {
Register r = e.nextElement();
Operand M = new StackLocationOperand(true, -location, (byte) WORDSIZE);
call.insertAfter(MIR_Move.create(IA32_MOV, new RegisterOperand(r, wordType), M));
location += WORDSIZE;
}
// restore the thread register
Operand M = new StackLocationOperand(true, -location, (byte) WORDSIZE);
call.insertAfter(MIR_Move.create(IA32_MOV, ir.regpool.makeTROp(), M));
// restore the JTOC, if applicable
if (JTOC_REGISTER != null) {
location += WORDSIZE;
Operand jtocSave = new StackLocationOperand(true, -location, (byte) WORDSIZE);
call.insertAfter(MIR_Move.create(IA32_MOV, ir.regpool.makeTocOp(), jtocSave));
}
}
use of org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method SSE2_X87_REM.
/**
* Performs a long -> double/float conversion using x87 and
* marshalls between to XMMs.
*
* @param s instruction to modify for the conversion
*/
protected final void SSE2_X87_REM(Instruction s) {
Operand result = Binary.getClearResult(s);
RegisterOperand st0 = new RegisterOperand(getST0(), result.getType());
int offset = -burs.ir.stackManager.allocateSpaceForConversion();
StackLocationOperand sl = new StackLocationOperand(true, offset, SSE2_SIZE(result));
EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), sl, Binary.getClearVal2(s))));
EMIT(CPOS(s, MIR_Move.create(IA32_FLD, st0, sl.copy())));
EMIT(CPOS(s, MIR_Move.create(SSE2_MOVE(result), sl.copy(), Binary.getClearVal1(s))));
EMIT(CPOS(s, MIR_Move.create(IA32_FLD, st0.copy(), sl.copy())));
// The parameters to FPREM actually get ignored (implied ST0/ST1)
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_FPREM, st0.copy(), st0.copy())));
EMIT(CPOS(s, MIR_Move.create(IA32_FSTP, sl.copy(), st0.copy())));
EMIT(CPOS(s, MIR_Nullary.create(IA32_FFREE, st0.copy())));
EMIT(MIR_Move.mutate(s, SSE2_MOVE(result), result, sl.copy()));
}
use of org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method GET_EXCEPTION_OBJECT.
/*
* IA32-specific emit rules that are complex enough that we didn't want to
* write them in the LIR2MIR.rules file. However, all expansions in this file
* are called during BURS and thus are constrained to generate nonbranching
* code (ie they can't create new basic blocks and/or do branching).
*/
/**
* Emit code to get a caught exception object into a register
*
* @param s the instruction to expand
*/
protected final void GET_EXCEPTION_OBJECT(Instruction s) {
int offset = -burs.ir.stackManager.allocateSpaceForCaughtException();
StackLocationOperand sl = new StackLocationOperand(true, offset, DW);
EMIT(MIR_Move.mutate(s, IA32_MOV, Nullary.getResult(s), sl));
}
use of org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method GPR2FPR_64.
/**
* Emits code to move 64 bits from GPRs to FPRs.
*
* @param s instruction to modify for the move
*/
protected final void GPR2FPR_64(Instruction s) {
int offset = -burs.ir.stackManager.allocateSpaceForConversion();
StackLocationOperand sl = new StackLocationOperand(true, offset, QW);
StackLocationOperand sl1 = new StackLocationOperand(true, offset + 4, DW);
StackLocationOperand sl2 = new StackLocationOperand(true, offset, DW);
Operand i1, i2;
Operand val = Unary.getClearVal(s);
if (val instanceof RegisterOperand) {
RegisterOperand rval = (RegisterOperand) val;
i1 = val;
i2 = new RegisterOperand(regpool.getSecondReg(rval.getRegister()), TypeReference.Int);
} else {
LongConstantOperand rhs = (LongConstantOperand) val;
i1 = IC(rhs.upper32());
i2 = IC(rhs.lower32());
}
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl1, i1)));
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, sl2, i2)));
EMIT(MIR_Move.mutate(s, IA32_FMOV, Unary.getResult(s), sl));
}
Aggregations