Bug 1184959 part 4 - MIPS MoveEmitter: Add support for pairs of registers. r=rankov

This commit is contained in:
Nicolas B. Pierron 2015-08-17 11:32:17 +02:00
parent a313c62745
commit eb2bcc5d0d
4 changed files with 56 additions and 39 deletions

View File

@ -534,6 +534,12 @@ hasMultiAlias() {
return true;
}
// In order to handle functions such as int(*)(int, double) where the first
// argument is a general purpose register, and the second argument is a floating
// point register, we have to store the double content into 2 general purpose
// registers, namely a2 and a3.
#define JS_CODEGEN_REGISTER_PAIR 1
// See the comments above AsmJSMappedSize in AsmJSValidate.h for more info.
// TODO: Implement this for MIPS. Note that it requires Codegen to respect the
// offset field of AsmJSHeapAccess.

View File

@ -23,18 +23,18 @@ using namespace js::jit;
ABIArgGenerator::ABIArgGenerator()
: usedArgSlots_(0),
firstArgFloat(false),
firstArgFloatSize_(0),
useGPRForFloats_(false),
current_()
{}
ABIArg
ABIArgGenerator::next(MIRType type)
{
FloatRegister::RegType regType;
Register destReg;
switch (type) {
case MIRType_Int32:
case MIRType_Pointer:
Register destReg;
if (GetIntArgReg(usedArgSlots_, &destReg))
current_ = ABIArg(destReg);
else
@ -42,19 +42,34 @@ ABIArgGenerator::next(MIRType type)
usedArgSlots_++;
break;
case MIRType_Float32:
case MIRType_Double:
regType = (type == MIRType_Double ? FloatRegister::Double : FloatRegister::Single);
if (!usedArgSlots_) {
current_ = ABIArg(FloatRegister(FloatRegisters::f12, regType));
usedArgSlots_ += 2;
firstArgFloat = true;
} else if (usedArgSlots_ <= 2) {
// NOTE: We will use f14 always. This is not compatible with
// system ABI. We will have to introduce some infrastructure
// changes if we have to use system ABI here.
current_ = ABIArg(FloatRegister(FloatRegisters::f14, regType));
current_ = ABIArg(f12.asSingle());
firstArgFloatSize_ = 1;
} else if (usedArgSlots_ == firstArgFloatSize_) {
current_ = ABIArg(f14.asSingle());
} else if (useGPRForFloats_ && GetIntArgReg(usedArgSlots_, &destReg)) {
current_ = ABIArg(destReg);
} else {
if (usedArgSlots_ < NumIntArgRegs)
usedArgSlots_ = NumIntArgRegs;
current_ = ABIArg(usedArgSlots_ * sizeof(intptr_t));
}
usedArgSlots_++;
break;
case MIRType_Double:
if (!usedArgSlots_) {
current_ = ABIArg(f12);
usedArgSlots_ = 2;
firstArgFloatSize_ = 2;
} else if (usedArgSlots_ == firstArgFloatSize_) {
current_ = ABIArg(f14);
usedArgSlots_ = 4;
} else if (useGPRForFloats_ && usedArgSlots_ <= 2) {
current_ = ABIArg(a2, a3);
usedArgSlots_ = 4;
} else {
if (usedArgSlots_ < NumIntArgRegs)
usedArgSlots_ = NumIntArgRegs;
usedArgSlots_ += usedArgSlots_ % 2;
current_ = ABIArg(usedArgSlots_ * sizeof(intptr_t));
usedArgSlots_ += 2;
@ -64,8 +79,8 @@ ABIArgGenerator::next(MIRType type)
MOZ_CRASH("Unexpected argument type");
}
return current_;
}
const Register ABIArgGenerator::NonArgReturnReg0 = t0;
const Register ABIArgGenerator::NonArgReturnReg1 = t1;
const Register ABIArgGenerator::NonArg_VolatileReg = v0;

View File

@ -80,7 +80,10 @@ static const uint32_t NumCallTempNonArgRegs = mozilla::ArrayLength(CallTempNonAr
class ABIArgGenerator
{
unsigned usedArgSlots_;
bool firstArgFloat;
unsigned firstArgFloatSize_;
// Note: This is not compliant with the system ABI. The Lowering phase
// expects to lower an MAsmJSParameter to only one register.
bool useGPRForFloats_;
ABIArg current_;
public:
@ -88,6 +91,10 @@ class ABIArgGenerator
ABIArg next(MIRType argType);
ABIArg& current() { return current_; }
void enforceO32ABI() {
useGPRForFloats_ = true;
}
uint32_t stackBytesConsumedSoFar() const {
if (usedArgSlots_ <= 4)
return ShadowStackSpace;

View File

@ -255,16 +255,14 @@ MoveEmitterMIPS::emitDoubleMove(const MoveOperand& from, const MoveOperand& to)
if (from.isFloatReg()) {
if (to.isFloatReg()) {
masm.moveDouble(from.floatReg(), to.floatReg());
} else if (to.isGeneralReg()) {
} else if (to.isGeneralRegPair()) {
// Used for passing double parameter in a2,a3 register pair.
// Two moves are added for one double parameter by
// MacroAssemblerMIPSCompat::passABIArg
if(to.reg() == a2)
masm.moveFromDoubleLo(from.floatReg(), a2);
else if(to.reg() == a3)
masm.moveFromDoubleHi(from.floatReg(), a3);
else
MOZ_CRASH("Invalid emitDoubleMove arguments.");
// MacroAssembler::passABIArg
MOZ_ASSERT(to.evenReg() == a2 && to.oddReg() == a3,
"Invalid emitDoubleMove arguments.");
masm.moveFromDoubleLo(from.floatReg(), a2);
masm.moveFromDoubleHi(from.floatReg(), a3);
} else {
MOZ_ASSERT(to.isMemory());
masm.storeDouble(from.floatReg(), getAdjustedAddress(to));
@ -272,24 +270,15 @@ MoveEmitterMIPS::emitDoubleMove(const MoveOperand& from, const MoveOperand& to)
} else if (to.isFloatReg()) {
MOZ_ASSERT(from.isMemory());
masm.loadDouble(getAdjustedAddress(from), to.floatReg());
} else if (to.isGeneralReg()) {
} else if (to.isGeneralRegPair()) {
// Used for passing double parameter in a2,a3 register pair.
// Two moves are added for one double parameter by
// MacroAssemblerMIPSCompat::passABIArg
if (from.isMemory()) {
if(to.reg() == a2)
masm.loadPtr(getAdjustedAddress(from), a2);
else if(to.reg() == a3)
masm.loadPtr(Address(from.base(), getAdjustedOffset(from) + sizeof(uint32_t)), a3);
else
MOZ_CRASH("Invalid emitDoubleMove arguments.");
} else {
// Used for moving a double parameter from the same source. See Bug 1123874.
if(to.reg() == a2 || to.reg() == a3)
masm.ma_move(to.reg(), from.reg());
else
MOZ_CRASH("Invalid emitDoubleMove arguments.");
}
// MacroAssembler::passABIArg
MOZ_ASSERT(from.isMemory());
MOZ_ASSERT(to.evenReg() == a2 && to.oddReg() == a3,
"Invalid emitDoubleMove arguments.");
masm.loadPtr(getAdjustedAddress(from), a2);
masm.loadPtr(Address(from.base(), getAdjustedOffset(from) + sizeof(uint32_t)), a3);
} else {
MOZ_ASSERT(from.isMemory());
MOZ_ASSERT(to.isMemory());