Bug 972836 - IonMonkey MIPS: Add odd float registers to the enum, but don't allocate them yet. r=froydnj,nbp

This commit is contained in:
Branislav Rankov 2014-04-07 17:36:06 +02:00
parent 83e2568195
commit 20985e40e8
6 changed files with 191 additions and 108 deletions

View File

@ -113,7 +113,7 @@ class Registers
return Names[code];
}
static const char *GetName(uint32_t i) {
MOZ_ASSERT(i < Total);
JS_ASSERT(i < Total);
return GetName(Code(i));
}
@ -191,38 +191,62 @@ class Registers
typedef uint32_t PackedRegisterMask;
// MIPS32 uses pairs of even and odd float registers as double precision
// registers. Example: f0 (double) is composed of f0 and f1 (single).
// This port only uses even registers to avoid allocation problems.
// MIPS32 can have two types of floating-point coprocessors:
// - 32 bit floating-point coprocessor - In this case, there are 32 single
// precision registers and pairs of even and odd float registers are used as
// double precision registers. Example: f0 (double) is composed of
// f0 and f1 (single).
// - 64 bit floating-point coprocessor - In this case, there are 32 double
// precision register which can also be used as single precision registers.
// When using O32 ABI, floating-point coprocessor is 32 bit
// When using N32 ABI, floating-point coprocessor is 64 bit.
class FloatRegisters
{
public:
enum FPRegisterID {
f0 = 0, // f0, f2 - Return values
f0 = 0,
f1,
f2,
f4, // f4 - f10, f16, f18 - Temporaries
f3,
f4,
f5,
f6,
f7,
f8,
f9,
f10,
f12, // f12, f14 - Arguments
f11,
f12,
f13,
f14,
f15,
f16,
f17,
f18,
f20, // f20 - f30 - Saved registers
f19,
f20,
f21,
f22,
f23,
f24,
f25,
f26,
f27,
f28,
f29,
f30,
f31,
invalid_freg
};
typedef FPRegisterID Code;
static const char *GetName(Code code) {
static const char * const Names[] = { "f0", "f2", "f4", "f6",
"f8", "f10", "f12", "f14",
"f16", "f18", "f20", "f22",
"f24", "f26", "f28", "f30"};
static const char * const Names[] = { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13",
"f14", "f15", "f16", "f17", "f18", "f19",
"f20", "f21", "f22", "f23", "f24", "f25",
"f26", "f27", "f28", "f29", "f30", "f31"};
return Names[code];
}
static const char *GetName(uint32_t i) {
@ -234,10 +258,12 @@ class FloatRegisters
static const Code Invalid = invalid_freg;
static const uint32_t Total = 16;
static const uint32_t Total = 32;
// :TODO: (Bug 972836) // Fix this once odd regs can be used as float32
// only. For now we don't allocate odd regs for O32 ABI.
static const uint32_t Allocatable = 14;
static const uint32_t AllMask = 0xffff;
static const uint32_t AllMask = 0xffffffff;
static const uint32_t VolatileMask =
(1 << FloatRegisters::f0) |
@ -260,10 +286,28 @@ class FloatRegisters
static const uint32_t WrapperMask = VolatileMask;
// f18 and f16 are MIPS scratch float registers.
// :TODO: (Bug 972836) // Fix this once odd regs can be used as float32
// only. For now we don't allocate odd regs for O32 ABI.
static const uint32_t NonAllocatableMask =
(1 << f16) |
(1 << f18);
(1 << FloatRegisters::f1) |
(1 << FloatRegisters::f3) |
(1 << FloatRegisters::f5) |
(1 << FloatRegisters::f7) |
(1 << FloatRegisters::f9) |
(1 << FloatRegisters::f11) |
(1 << FloatRegisters::f13) |
(1 << FloatRegisters::f15) |
(1 << FloatRegisters::f17) |
(1 << FloatRegisters::f19) |
(1 << FloatRegisters::f21) |
(1 << FloatRegisters::f23) |
(1 << FloatRegisters::f25) |
(1 << FloatRegisters::f27) |
(1 << FloatRegisters::f29) |
(1 << FloatRegisters::f31) |
// f18 and f16 are MIPS scratch float registers.
(1 << FloatRegisters::f16) |
(1 << FloatRegisters::f18);
// Registers that can be allocated without being saved, generally.
static const uint32_t TempMask = VolatileMask & ~NonAllocatableMask;

View File

@ -56,16 +56,7 @@ uint32_t
js::jit::RT(FloatRegister r)
{
JS_ASSERT(r.code() < FloatRegisters::Total);
return (2 * r.code()) << RTShift;
}
// Use to code odd float registers.
// :TODO: Bug 972836, It will be removed once we can use odd regs.
uint32_t
js::jit::RT(uint32_t regCode)
{
JS_ASSERT((regCode & ~RegMask) == 0);
return regCode << RTShift;
return r.code() << RTShift;
}
uint32_t
@ -79,16 +70,7 @@ uint32_t
js::jit::RD(FloatRegister r)
{
JS_ASSERT(r.code() < FloatRegisters::Total);
return (2 * r.code()) << RDShift;
}
// Use to code odd float registers.
// :TODO: Bug 972836, It will be removed once we can use odd regs.
uint32_t
js::jit::RD(uint32_t regCode)
{
JS_ASSERT((regCode & ~RegMask) == 0);
return regCode << RDShift;
return r.code() << RDShift;
}
uint32_t
@ -102,7 +84,7 @@ uint32_t
js::jit::SA(FloatRegister r)
{
JS_ASSERT(r.code() < FloatRegisters::Total);
return (2 * r.code()) << SAShift;
return r.code() << SAShift;
}
Register
@ -973,39 +955,6 @@ Assembler::as_mfc1(Register rt, FloatRegister fs)
return writeInst(InstReg(op_cop1, rs_mfc1, rt, fs).encode());
}
// :TODO: Bug 972836, Remove _Odd functions once we can use odd regs.
BufferOffset
Assembler::as_ls_Odd(FloatRegister fd, Register base, int32_t off)
{
JS_ASSERT(Imm16::isInSignedRange(off));
// Hardcoded because it will be removed once we can use odd regs.
return writeInst(op_lwc1 | RS(base) | RT(fd.code() * 2 + 1) | Imm16(off).encode());
}
BufferOffset
Assembler::as_ss_Odd(FloatRegister fd, Register base, int32_t off)
{
JS_ASSERT(Imm16::isInSignedRange(off));
// Hardcoded because it will be removed once we can use odd regs.
return writeInst(op_swc1 | RS(base) | RT(fd.code() * 2 + 1) | Imm16(off).encode());
}
BufferOffset
Assembler::as_mtc1_Odd(Register rt, FloatRegister fs)
{
// Hardcoded because it will be removed once we can use odd regs.
return writeInst(op_cop1 | rs_mtc1 | RT(rt) | RD(fs.code() * 2 + 1));
}
BufferOffset
Assembler::as_mfc1_Odd(Register rt, FloatRegister fs)
{
// Hardcoded because it will be removed once we can use odd regs.
return writeInst(op_cop1 | rs_mfc1 | RT(rt) | RD(fs.code() * 2 + 1));
}
// FP convert instructions
BufferOffset
Assembler::as_ceilws(FloatRegister fd, FloatRegister fs)

View File

@ -861,16 +861,14 @@ class Assembler
BufferOffset as_mfc1(Register rt, FloatRegister fs);
protected:
// These instructions should only be used to access the odd part of
// 64-bit register pair. Do not use odd registers as 32-bit registers.
// :TODO: Bug 972836, Remove _Odd functions once we can use odd regs.
BufferOffset as_ls_Odd(FloatRegister fd, Register base, int32_t off);
BufferOffset as_ss_Odd(FloatRegister fd, Register base, int32_t off);
BufferOffset as_mtc1_Odd(Register rt, FloatRegister fs);
public:
// Made public because CodeGenerator uses it to check for -0
BufferOffset as_mfc1_Odd(Register rt, FloatRegister fs);
// This is used to access the odd regiter form the pair of single
// precision registers that make one double register.
FloatRegister getOddPair(FloatRegister reg) {
JS_ASSERT(reg.code() % 2 == 0);
return FloatRegister::FromCode(reg.code() + 1);
}
public:
// FP convert instructions
BufferOffset as_ceilws(FloatRegister fd, FloatRegister fs);
BufferOffset as_floorws(FloatRegister fd, FloatRegister fs);

View File

@ -114,7 +114,7 @@ MacroAssemblerMIPS::convertDoubleToInt32(const FloatRegister &src, const Registe
// Test and bail for -0.0, when integer result is 0
// Move the top word of the double into the output reg, if it is
// non-zero, then the original value was -0.0
as_mfc1_Odd(dest, src);
moveFromDoubleHi(src, dest);
ma_b(dest, Imm32(INT32_MIN), fail, Assembler::Equal);
bind(&notZero);
}
@ -141,7 +141,7 @@ MacroAssemblerMIPS::convertFloat32ToInt32(const FloatRegister &src, const Regist
// Test and bail for -0.0, when integer result is 0
// Move the top word of the double into the output reg,
// if it is non-zero, then the original value was -0.0
as_mfc1_Odd(dest, src);
moveFromDoubleHi(src, dest);
ma_b(dest, Imm32(INT32_MIN), fail, Assembler::Equal);
bind(&notZero);
}
@ -1296,7 +1296,7 @@ MacroAssemblerMIPS::ma_lis(FloatRegister dest, float value)
Imm32 imm(mozilla::BitwiseCast<uint32_t>(value));
ma_li(ScratchRegister, imm);
as_mtc1(ScratchRegister, dest);
moveToFloat32(ScratchRegister, dest);
}
void
@ -1310,41 +1310,41 @@ MacroAssemblerMIPS::ma_lid(FloatRegister dest, double value)
// put hi part of 64 bit value into the odd register
if (intStruct.hi == 0) {
as_mtc1_Odd(zero, dest);
moveToDoubleHi(zero, dest);
} else {
ma_li(ScratchRegister, Imm32(intStruct.hi));
as_mtc1_Odd(ScratchRegister, dest);
moveToDoubleHi(ScratchRegister, dest);
}
// put low part of 64 bit value into the even register
if (intStruct.lo == 0) {
as_mtc1(zero, dest);
moveToDoubleLo(zero, dest);
} else {
ma_li(ScratchRegister, Imm32(intStruct.lo));
as_mtc1(ScratchRegister, dest);
moveToDoubleLo(ScratchRegister, dest);
}
}
void
MacroAssemblerMIPS::ma_liNegZero(FloatRegister dest)
{
as_mtc1(zero, dest);
moveToDoubleLo(zero, dest);
ma_li(ScratchRegister, Imm32(INT_MIN));
as_mtc1_Odd(ScratchRegister, dest);
moveToDoubleHi(ScratchRegister, dest);
}
void
MacroAssemblerMIPS::ma_mv(FloatRegister src, ValueOperand dest)
{
as_mfc1(dest.payloadReg(), src);
as_mfc1_Odd(dest.typeReg(), src);
moveFromDoubleLo(src, dest.payloadReg());
moveFromDoubleHi(src, dest.typeReg());
}
void
MacroAssemblerMIPS::ma_mv(ValueOperand src, FloatRegister dest)
{
as_mtc1(src.payloadReg(), dest);
as_mtc1_Odd(src.typeReg(), dest);
moveToDoubleLo(src.payloadReg(), dest);
moveToDoubleHi(src.typeReg(), dest);
}
void
@ -1369,12 +1369,12 @@ MacroAssemblerMIPS::ma_ld(FloatRegister ft, Address address)
int32_t off2 = address.offset + TAG_OFFSET;
if (Imm16::isInSignedRange(address.offset) && Imm16::isInSignedRange(off2)) {
as_ls(ft, address.base, Imm16(address.offset).encode());
as_ls_Odd(ft, address.base, Imm16(off2).encode());
as_ls(getOddPair(ft), address.base, Imm16(off2).encode());
} else {
ma_li(ScratchRegister, Imm32(address.offset));
as_addu(ScratchRegister, address.base, ScratchRegister);
as_ls(ft, ScratchRegister, PAYLOAD_OFFSET);
as_ls_Odd(ft, ScratchRegister, TAG_OFFSET);
as_ls(getOddPair(ft), ScratchRegister, TAG_OFFSET);
}
}
@ -1384,12 +1384,12 @@ MacroAssemblerMIPS::ma_sd(FloatRegister ft, Address address)
int32_t off2 = address.offset + TAG_OFFSET;
if (Imm16::isInSignedRange(address.offset) && Imm16::isInSignedRange(off2)) {
as_ss(ft, address.base, Imm16(address.offset).encode());
as_ss_Odd(ft, address.base, Imm16(off2).encode());
as_ss(getOddPair(ft), address.base, Imm16(off2).encode());
} else {
ma_li(ScratchRegister, Imm32(address.offset));
as_addu(ScratchRegister, address.base, ScratchRegister);
as_ss(ft, ScratchRegister, PAYLOAD_OFFSET);
as_ss_Odd(ft, ScratchRegister, TAG_OFFSET);
as_ss(getOddPair(ft), ScratchRegister, TAG_OFFSET);
}
}
@ -1540,6 +1540,72 @@ MacroAssemblerMIPSCompat::freeStack(Register amount)
as_addu(StackPointer, StackPointer, amount);
}
void
MacroAssembler::PushRegsInMask(RegisterSet set)
{
int32_t diffF = set.fpus().size() * sizeof(double);
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
reserveStack(diffG);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= sizeof(intptr_t);
storePtr(*iter, Address(StackPointer, diffG));
}
MOZ_ASSERT(diffG == 0);
// Double values have to be aligned. We reserve extra space so that we can
// start writing from the first aligned location.
// We reserve a whole extra double so that the buffer has even size.
ma_and(SecondScratchReg, sp, Imm32(~(StackAlignment - 1)));
reserveStack(diffF + sizeof(double));
for (FloatRegisterForwardIterator iter(set.fpus()); iter.more(); iter++) {
// Use assembly s.d because we have alligned the stack.
// :TODO: (Bug 972836) Fix this once odd regs can be used as
// float32 only. For now we skip saving odd regs for O32 ABI.
// :TODO: (Bug 985881) Make a switch for N32 ABI.
if ((*iter).code() % 2 == 0)
as_sd(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
}
MOZ_ASSERT(diffF == 0);
}
void
MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
{
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
int32_t diffF = set.fpus().size() * sizeof(double);
const int32_t reservedG = diffG;
const int32_t reservedF = diffF;
// Read the buffer form the first aligned location.
ma_addu(SecondScratchReg, sp, Imm32(reservedF + sizeof(double)));
ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(StackAlignment - 1)));
for (FloatRegisterForwardIterator iter(set.fpus()); iter.more(); iter++) {
// :TODO: (Bug 972836) Fix this once odd regs can be used as
// float32 only. For now we skip loading odd regs for O32 ABI.
// :TODO: (Bug 985881) Make a switch for N32 ABI.
if (!ignore.has(*iter) && ((*iter).code() % 2 == 0))
// Use assembly l.d because we have alligned the stack.
as_ld(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
}
freeStack(reservedF + sizeof(double));
MOZ_ASSERT(diffF == 0);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); iter++) {
diffG -= sizeof(intptr_t);
if (!ignore.has(*iter))
loadPtr(Address(StackPointer, diffG), *iter);
}
freeStack(reservedG);
MOZ_ASSERT(diffG == 0);
}
void
MacroAssemblerMIPSCompat::add32(Register src, Register dest)
{
@ -2324,17 +2390,17 @@ void
MacroAssemblerMIPSCompat::unboxDouble(const ValueOperand &operand, const FloatRegister &dest)
{
MOZ_ASSERT(dest != ScratchFloatReg);
as_mtc1(operand.payloadReg(), dest);
as_mtc1_Odd(operand.typeReg(), dest);
moveToDoubleLo(operand.payloadReg(), dest);
moveToDoubleHi(operand.typeReg(), dest);
}
void
MacroAssemblerMIPSCompat::unboxDouble(const Address &src, const FloatRegister &dest)
{
ma_lw(ScratchRegister, Address(src.base, src.offset + PAYLOAD_OFFSET));
as_mtc1(ScratchRegister, dest);
moveToDoubleLo(ScratchRegister, dest);
ma_lw(ScratchRegister, Address(src.base, src.offset + TAG_OFFSET));
as_mtc1_Odd(ScratchRegister, dest);
moveToDoubleHi(ScratchRegister, dest);
}
void
@ -2380,8 +2446,8 @@ MacroAssemblerMIPSCompat::unboxPrivate(const ValueOperand &src, Register dest)
void
MacroAssemblerMIPSCompat::boxDouble(const FloatRegister &src, const ValueOperand &dest)
{
as_mfc1(dest.payloadReg(), src);
as_mfc1_Odd(dest.typeReg(), src);
moveFromDoubleLo(src, dest.payloadReg());
moveFromDoubleHi(src, dest.typeReg());
}
void

View File

@ -234,6 +234,32 @@ class MacroAssemblerMIPS : public Assembler
void ma_bc1d(FloatRegister lhs, FloatRegister rhs, Label *label, DoubleCondition c,
JumpKind jumpKind = LongJump, FPConditionBit fcc = FCC0);
// These fuctions abstract the access to high part of the double precision
// float register. It is intended to work on both 32 bit and 64 bit
// floating point coprocessor.
// :TODO: (Bug 985881) Modify this for N32 ABI to use mthc1 and mfhc1
void moveToDoubleHi(Register src, FloatRegister dest) {
as_mtc1(src, getOddPair(dest));
}
void moveFromDoubleHi(FloatRegister src, Register dest) {
as_mfc1(dest, getOddPair(src));
}
void moveToDoubleLo(Register src, FloatRegister dest) {
as_mtc1(src, dest);
}
void moveFromDoubleLo(FloatRegister src, Register dest) {
as_mfc1(dest, src);
}
void moveToFloat32(Register src, FloatRegister dest) {
as_mtc1(src, dest);
}
void moveFromFloat32(FloatRegister src, Register dest) {
as_mfc1(dest, src);
}
protected:
void branchWithCode(InstImm code, Label *label, JumpKind jumpKind);
Condition ma_cmp(Register rd, Register lhs, Register rhs, Condition c);
@ -993,8 +1019,8 @@ public:
}
void zeroDouble(FloatRegister reg) {
as_mtc1(zero, reg);
as_mtc1_Odd(zero, reg);
moveToDoubleLo(zero, reg);
moveToDoubleHi(zero, reg);
}
void clampIntToUint8(Register reg) {

View File

@ -212,7 +212,7 @@ MoveEmitterMIPS::emitFloat32Move(const MoveOperand &from, const MoveOperand &to)
} else if (to.isGeneralReg()) {
// This should only be used when passing float parameter in a1,a2,a3
MOZ_ASSERT(to.reg() == a1 || to.reg() == a2 || to.reg() == a3);
masm.as_mfc1(to.reg(), from.floatReg());
masm.moveFromFloat32(from.floatReg(), to.reg());
} else {
MOZ_ASSERT(to.isMemory());
masm.storeFloat32(from.floatReg(), getAdjustedAddress(to));
@ -248,9 +248,9 @@ MoveEmitterMIPS::emitDoubleMove(const MoveOperand &from, const MoveOperand &to)
// Two moves are added for one double parameter by
// MacroAssemblerMIPSCompat::passABIArg
if(to.reg() == a2)
masm.as_mfc1(a2, from.floatReg());
masm.moveFromDoubleLo(from.floatReg(), a2);
else if(to.reg() == a3)
masm.as_mfc1_Odd(a3, from.floatReg());
masm.moveFromDoubleHi(from.floatReg(), a3);
else
MOZ_ASSUME_UNREACHABLE("Invalid emitDoubleMove arguments.");
} else {