Bug 1406999: [MIPS32] Cleanup floating point registers handling; r=nbp

This commit is contained in:
Dragan Mladjenovic 2017-12-20 14:30:56 +01:00
Родитель 6821480454
Коммит ebf5c48dc5
12 изменённых файлов: 211 добавлений и 215 удалений

Просмотреть файл

@ -2242,14 +2242,9 @@ MachineState::FromBailout(RegisterDump::GPRArray& regs, RegisterDump::FPUArray&
for (unsigned i = 0; i < FloatRegisters::TotalSingle; i++)
machine.setRegisterLocation(FloatRegister(i, FloatRegister::Single), (double*)&fbase[i]);
#elif defined(JS_CODEGEN_MIPS32)
float* fbase = (float*)&fpregs[0];
for (unsigned i = 0; i < FloatRegisters::TotalDouble; i++) {
machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Double),
&fpregs[i].d);
}
for (unsigned i = 0; i < FloatRegisters::TotalSingle; i++) {
machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Single),
(double*)&fbase[i]);
for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) {
machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Double), &fpregs[i]);
machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Single), &fpregs[i]);
}
#elif defined(JS_CODEGEN_MIPS64)
for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) {

Просмотреть файл

@ -1967,7 +1967,7 @@ MacroAssembler::convertValueToFloatingPoint(ValueOperand value, FloatRegister ou
jump(&done);
bind(&isDouble);
FloatRegister tmp = output;
FloatRegister tmp = output.asDouble();
if (outputType == MIRType::Float32 && hasMultiAlias())
tmp = ScratchDoubleReg;

Просмотреть файл

@ -423,6 +423,10 @@ struct FloatRegister
return false;
}
FloatRegister asSingle() const { return FloatRegister(code_, FloatRegisters::Single); }
FloatRegister asDouble() const { return FloatRegister(code_, FloatRegisters::Double); }
FloatRegister asSimd128() const { MOZ_CRASH(); }
static uint32_t FirstBit(SetType x) {
JS_STATIC_ASSERT(sizeof(SetType) == 8);
return mozilla::CountTrailingZeroes64(x);

Просмотреть файл

@ -266,7 +266,7 @@ class FloatRegistersMIPSShared
f31,
invalid_freg
};
typedef FPRegisterID Code;
typedef uint32_t Code;
typedef FPRegisterID Encoding;
// Content spilled during bailouts.
@ -274,7 +274,7 @@ class FloatRegistersMIPSShared
double d;
};
static const char* GetName(Code code) {
static const char* GetName(Encoding code) {
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",
@ -283,9 +283,13 @@ class FloatRegistersMIPSShared
return Names[code];
}
static const Code Invalid = invalid_freg;
static const Encoding Invalid = invalid_freg;
#if defined(JS_CODEGEN_MIPS32)
typedef uint32_t SetType;
#elif defined(JS_CODEGEN_MIPS64)
typedef uint64_t SetType;
#endif
};
template <typename T>
@ -298,16 +302,33 @@ class FloatRegisterMIPSShared
typedef FloatRegistersMIPSShared::SetType SetType;
#if defined(JS_CODEGEN_MIPS32)
static uint32_t SetSize(SetType x) {
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
return mozilla::CountPopulation32(x);
}
static uint32_t FirstBit(SetType x) {
static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
return mozilla::CountTrailingZeroes32(x);
}
static uint32_t LastBit(SetType x) {
static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
return 31 - mozilla::CountLeadingZeroes32(x);
}
#elif defined(JS_CODEGEN_MIPS64)
static uint32_t SetSize(SetType x) {
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
return mozilla::CountPopulation64(x);
}
static uint32_t FirstBit(SetType x) {
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
return mozilla::CountTrailingZeroes64(x);
}
static uint32_t LastBit(SetType x) {
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
return 63 - mozilla::CountLeadingZeroes64(x);
}
#endif
};
namespace mips_private {
@ -328,12 +349,12 @@ hasUnaliasedDouble() {
return false;
}
// On MIPS, fn-double aliases both fn-float32 and fn+1-float32, so if you need
// to convert a float32 to a double as a temporary, you need a temporary
// double register.
// MIPS64 doesn't support it and on MIPS32 we don't allocate odd single fp
// registers thus not exposing multi aliasing to the jit.
// See comments in Arhitecture-mips32.h.
inline bool
hasMultiAlias() {
return true;
return false;
}
} // namespace jit

Просмотреть файл

@ -58,6 +58,13 @@ js::jit::SA(uint32_t value)
return value << SAShift;
}
uint32_t
js::jit::FS(uint32_t value)
{
MOZ_ASSERT(value < 32);
return value << FSShift;
}
Register
js::jit::toRS(Instruction& i)
{
@ -1341,15 +1348,15 @@ AssemblerMIPSShared::as_movd(FloatRegister fd, FloatRegister fs)
BufferOffset
AssemblerMIPSShared::as_ctc1(Register rt, FPControl fc)
{
spew("ctc1 %3s,%3s", rt.name(), FloatRegister(fc).name());
return writeInst(InstReg(op_cop1, rs_ctc1, rt, FloatRegister(fc)).encode());
spew("ctc1 %3s,%d", rt.name(), fc);
return writeInst(InstReg(op_cop1, rs_ctc1, rt, (uint32_t)fc).encode());
}
BufferOffset
AssemblerMIPSShared::as_cfc1(Register rt, FPControl fc)
{
spew("cfc1 %3s,%3s", rt.name(), FloatRegister(fc).name());
return writeInst(InstReg(op_cop1, rs_cfc1, rt, FloatRegister(fc)).encode());
spew("cfc1 %3s,%d", rt.name(), fc);
return writeInst(InstReg(op_cop1, rs_cfc1, rt, (uint32_t)fc).encode());
}
BufferOffset

Просмотреть файл

@ -219,15 +219,14 @@ class InstJump;
uint32_t RS(Register r);
uint32_t RT(Register r);
uint32_t RT(uint32_t regCode);
uint32_t RT(FloatRegister r);
uint32_t RD(Register r);
uint32_t RD(FloatRegister r);
uint32_t RD(uint32_t regCode);
uint32_t RZ(Register r);
uint32_t RZ(FloatRegister r);
uint32_t SA(uint32_t value);
uint32_t SA(FloatRegister r);
uint32_t FS(uint32_t value);
Register toRS (Instruction& i);
Register toRT (Instruction& i);
@ -1422,6 +1421,9 @@ class InstReg : public Instruction
: Instruction(op | code | ff)
{ }
// for float point
InstReg(Opcode op, RSField rs, Register rt, uint32_t fs)
: Instruction(op | rs | RT(rt) | FS(fs))
{ }
InstReg(Opcode op, RSField rs, Register rt, FloatRegister rd)
: Instruction(op | rs | RT(rt) | RD(rd))
{ }

Просмотреть файл

@ -28,38 +28,33 @@ const Registers::SetType Registers::CallMask =
(1 << Registers::v0) |
(1 << Registers::v1); // used for double-size returns
FloatRegisters::Code
FloatRegisters::Encoding
FloatRegisters::FromName(const char* name)
{
for (size_t i = 0; i < Total; i++) {
for (size_t i = 0; i < RegisterIdLimit; i++) {
if (strcmp(GetName(i), name) == 0)
return Code(i);
return Encoding(i);
}
return Invalid;
}
FloatRegister
FloatRegister::doubleOverlay(unsigned int which) const
FloatRegister::doubleOverlay() const
{
MOZ_ASSERT(!isInvalid());
if (kind_ != Double)
return FloatRegister(code_ & ~1, Double);
MOZ_ASSERT(isNotOdd());
if (isSingle())
return FloatRegister(code_, Double);
return *this;
}
FloatRegister
FloatRegister::singleOverlay(unsigned int which) const
FloatRegister::singleOverlay() const
{
MOZ_ASSERT(!isInvalid());
if (kind_ == Double) {
// Only even registers are double
MOZ_ASSERT(code_ % 2 == 0);
MOZ_ASSERT(which < 2);
return FloatRegister(code_ + which, Single);
}
MOZ_ASSERT(which == 0);
return FloatRegister(code_, Single);
MOZ_ASSERT(isNotOdd());
if (isDouble())
return FloatRegister(code_, Single);
return *this;
}
FloatRegisterSet
@ -67,12 +62,8 @@ FloatRegister::ReduceSetForPush(const FloatRegisterSet& s)
{
LiveFloatRegisterSet mod;
for (FloatRegisterIterator iter(s); iter.more(); ++iter) {
if ((*iter).isSingle()) {
// Even for single size registers save complete double register.
mod.addUnchecked((*iter).doubleOverlay());
} else {
mod.addUnchecked(*iter);
}
// Even for single size registers save complete double register.
mod.addUnchecked((*iter).doubleOverlay());
}
return mod.set();
}
@ -83,18 +74,21 @@ FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s)
FloatRegisterSet ss = s.reduceSetForPush();
uint64_t bits = ss.bits();
// We are only pushing double registers.
MOZ_ASSERT((bits & 0xffffffff) == 0);
uint32_t ret = mozilla::CountPopulation32(bits >> 32) * sizeof(double);
MOZ_ASSERT((bits & 0xFFFF) == 0);
uint32_t ret = mozilla::CountPopulation32(bits) * sizeof(double);
// Additional space needed by MacroAssembler::PushRegsInMask to ensure
// correct alignment of double values.
if (ret)
ret += sizeof(double);
return ret;
}
uint32_t
FloatRegister::getRegisterDumpOffsetInBytes()
{
if (isSingle())
return id() * sizeof(float);
if (isDouble())
return id() * sizeof(double);
MOZ_CRASH();
MOZ_ASSERT(isNotOdd());
return id() * sizeof(float);
}
} // namespace ion

Просмотреть файл

@ -19,7 +19,6 @@
namespace js {
namespace jit {
// Shadow stack space is not required on MIPS.
static const uint32_t ShadowStackSpace = 4 * sizeof(uintptr_t);
// These offsets are specific to nunboxing, and capture offsets into the
@ -32,88 +31,66 @@ static const int32_t NUNBOX32_PAYLOAD_OFFSET = 0;
// For MIPS this is 2 instructions relative call.
static const uint32_t BAILOUT_TABLE_ENTRY_SIZE = 2 * sizeof(void*);
// MIPS32 can have two types of floating-point coprocessors:
// - 32 bit floating-point coprocessor - In this case, there are 32 single
// MIPS32 can have two types of floating-point coprocessors modes:
// - FR=0 mode/ 32-bit FPRs - Historical default, 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.
// f0 and f1 (single). Loongson3A FPU running in this mode doesn't allow
// use of odd registers for single precision arithmetic.
// - FR=1 mode/ 64-bit FPRs - In this case, there are 32 double precision register
// which can also be used as single precision registers.
// More info https://dmz-portal.imgtec.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
// Currently we enable 16 even single precision registers which can be also can be used
// as double precision registers. It enables jit code to run even on Loongson3A.
// It does not support FR=1 mode because MacroAssembler threats odd single precision
// registers as high parts of even double precision registers.
#ifdef __mips_fpr
static_assert(__mips_fpr == 32, "MIPS32 jit only supports FR=0 fpu mode.");
#endif
// When using O32 ABI, floating-point coprocessor is 32 bit.
// When using N32 ABI, floating-point coprocessor is 64 bit.
class FloatRegisters : public FloatRegistersMIPSShared
{
public:
static const char* GetName(uint32_t i) {
MOZ_ASSERT(i < Total);
return FloatRegistersMIPSShared::GetName(Code(i % 32));
MOZ_ASSERT(i < RegisterIdLimit);
return FloatRegistersMIPSShared::GetName(Encoding(i % 32));
}
static Code FromName(const char* name);
static Encoding FromName(const char* name);
static const uint32_t Total = 64;
static const uint32_t Total = 32;
static const uint32_t TotalDouble = 16;
static const uint32_t RegisterIdLimit = 32;
// Workarounds: On Loongson CPU-s the odd FP registers behave differently
// in fp-32 mode than standard MIPS.
#if defined(_MIPS_ARCH_LOONGSON3A)
static const uint32_t TotalSingle = 16;
static const uint32_t Allocatable = 28;
static const SetType AllSingleMask = 0x55555555ULL;
#else
static const uint32_t TotalSingle = 32;
static const uint32_t Allocatable = 42;
static const SetType AllSingleMask = (1ULL << 32) - 1;
#endif
static const SetType AllSingleMask = (1ULL << TotalSingle) - 1;
static const SetType AllDoubleMask = ((1ULL << TotalDouble) - 1) << TotalSingle;
static const SetType AllMask = AllDoubleMask | AllSingleMask;
// When saving all registers we only need to do is save double registers.
static const uint32_t TotalPhys = 16;
static const uint32_t RegisterIdLimit = 32;
static_assert(sizeof(SetType) * 8 >= Total,
"SetType should be large enough to enumerate all registers.");
static const SetType AllDoubleMask = 0x55555555ULL << 32;
static const SetType AllMask = AllDoubleMask | AllSingleMask;
static const SetType NonVolatileDoubleMask =
((1ULL << FloatRegisters::f20) |
(1ULL << FloatRegisters::f22) |
(1ULL << FloatRegisters::f24) |
(1ULL << FloatRegisters::f26) |
(1ULL << FloatRegisters::f28) |
(1ULL << FloatRegisters::f30)) << 32;
// f20-single and f21-single alias f20-double ...
static const SetType NonVolatileMask =
NonVolatileDoubleMask |
(1ULL << FloatRegisters::f20) |
(1ULL << FloatRegisters::f21) |
(1ULL << FloatRegisters::f22) |
(1ULL << FloatRegisters::f23) |
(1ULL << FloatRegisters::f24) |
(1ULL << FloatRegisters::f25) |
(1ULL << FloatRegisters::f26) |
(1ULL << FloatRegisters::f27) |
(1ULL << FloatRegisters::f28) |
(1ULL << FloatRegisters::f29) |
(1ULL << FloatRegisters::f30) |
(1ULL << FloatRegisters::f31);
((SetType(1) << (FloatRegisters::f20 >> 1)) |
(SetType(1) << (FloatRegisters::f22 >> 1)) |
(SetType(1) << (FloatRegisters::f24 >> 1)) |
(SetType(1) << (FloatRegisters::f26 >> 1)) |
(SetType(1) << (FloatRegisters::f28 >> 1)) |
(SetType(1) << (FloatRegisters::f30 >> 1))) * ((1 << TotalSingle) + 1);
static const SetType VolatileMask = AllMask & ~NonVolatileMask;
static const SetType VolatileDoubleMask = AllDoubleMask & ~NonVolatileDoubleMask;
static const SetType WrapperMask = VolatileMask;
static const SetType NonAllocatableDoubleMask =
((1ULL << FloatRegisters::f16) |
(1ULL << FloatRegisters::f18)) << 32;
// f16-single and f17-single alias f16-double ...
static const SetType NonAllocatableMask =
NonAllocatableDoubleMask |
(1ULL << FloatRegisters::f16) |
(1ULL << FloatRegisters::f17) |
(1ULL << FloatRegisters::f18) |
(1ULL << FloatRegisters::f19);
((SetType(1) << (FloatRegisters::f16 >> 1)) |
(SetType(1) << (FloatRegisters::f18 >> 1))) * ((1 << TotalSingle) + 1);
// Registers that can be allocated without being saved, generally.
static const SetType TempMask = VolatileMask & ~NonAllocatableMask;
@ -133,16 +110,16 @@ class FloatRegister : public FloatRegisterMIPSShared
typedef Codes::Code Code;
typedef Codes::Encoding Encoding;
uint32_t code_ : 6;
Encoding code_ : 6;
protected:
RegType kind_ : 1;
public:
constexpr FloatRegister(uint32_t code, RegType kind = Double)
: code_ (Code(code)), kind_(kind)
: code_ (Encoding(code)), kind_(kind)
{ }
constexpr FloatRegister()
: code_(Code(FloatRegisters::invalid_freg)), kind_(Double)
: code_(FloatRegisters::invalid_freg), kind_(Double)
{ }
bool operator==(const FloatRegister& other) const {
@ -156,52 +133,43 @@ class FloatRegister : public FloatRegisterMIPSShared
return code_ == FloatRegisters::invalid_freg;
}
bool isNotOdd() const { return !isInvalid() && ((code_ & 1) == 0); }
bool isSingle() const { return kind_ == Single; }
bool isDouble() const { return kind_ == Double; }
FloatRegister doubleOverlay(unsigned int which = 0) const;
FloatRegister singleOverlay(unsigned int which = 0) const;
FloatRegister sintOverlay(unsigned int which = 0) const;
FloatRegister uintOverlay(unsigned int which = 0) const;
FloatRegister doubleOverlay() const;
FloatRegister singleOverlay() const;
FloatRegister asSingle() const { return singleOverlay(); }
FloatRegister asDouble() const { return doubleOverlay(); }
FloatRegister asSimd128() const { MOZ_CRASH("NYI"); }
Code code() const {
MOZ_ASSERT(!isInvalid());
return Code(code_ | (kind_ << 5));
MOZ_ASSERT(isNotOdd());
return Code((code_ >> 1) | (kind_ << 4));
}
Encoding encoding() const {
MOZ_ASSERT(!isInvalid());
return Encoding(code_);
return code_;
}
uint32_t id() const {
MOZ_ASSERT(!isInvalid());
return code_;
}
static FloatRegister FromCode(uint32_t i) {
uint32_t code = i & 31;
uint32_t kind = i >> 5;
return FloatRegister(code, RegType(kind));
uint32_t code = i & 15;
uint32_t kind = i >> 4;
return FloatRegister(Encoding(code << 1), RegType(kind));
}
// This is similar to FromCode except for double registers on O32.
static FloatRegister FromIndex(uint32_t index, RegType kind) {
#if defined(USES_O32_ABI)
// Only even FP registers are avaiable for Loongson on O32.
# if defined(_MIPS_ARCH_LOONGSON3A)
return FloatRegister(index * 2, kind);
# else
if (kind == Double)
return FloatRegister(index * 2, kind);
# endif
#endif
return FloatRegister(index, kind);
MOZ_ASSERT(index < 16);
return FloatRegister(Encoding(index << 1), kind);
}
bool volatile_() const {
if (isDouble())
return !!((1ULL << code_) & FloatRegisters::VolatileMask);
return !!((1ULL << (code_ & ~1)) & FloatRegisters::VolatileMask);
return !!((SetType(1) << code()) & FloatRegisters::VolatileMask);
}
const char* name() const {
return FloatRegisters::GetName(code_);
@ -210,61 +178,49 @@ class FloatRegister : public FloatRegisterMIPSShared
return other.kind_ != kind_ || code_ != other.code_;
}
bool aliases(const FloatRegister& other) {
if (kind_ == other.kind_)
return code_ == other.code_;
return doubleOverlay() == other.doubleOverlay();
MOZ_ASSERT(isNotOdd());
return code_ == other.code_;
}
uint32_t numAliased() const {
if (isDouble()) {
MOZ_ASSERT((code_ & 1) == 0);
return 3;
}
MOZ_ASSERT(isNotOdd());
return 2;
}
void aliased(uint32_t aliasIdx, FloatRegister* ret) {
MOZ_ASSERT(isNotOdd());
if (aliasIdx == 0) {
*ret = *this;
return;
}
if (isDouble()) {
MOZ_ASSERT((code_ & 1) == 0);
MOZ_ASSERT(aliasIdx <= 2);
*ret = singleOverlay(aliasIdx - 1);
return;
}
MOZ_ASSERT(aliasIdx == 1);
*ret = doubleOverlay(aliasIdx - 1);
if (isDouble()) {
*ret = singleOverlay();
} else {
*ret = doubleOverlay();
}
}
uint32_t numAlignedAliased() const {
if (isDouble()) {
MOZ_ASSERT((code_ & 1) == 0);
return 2;
}
// f1-float32 has 0 other aligned aliases, 1 total.
// f0-float32 has 1 other aligned alias, 2 total.
return 2 - (code_ & 1);
MOZ_ASSERT(isNotOdd());
return 2;
}
// | f0-double |
// | f0-float32 | f1-float32 |
// We only push double registers on MIPS. So, if we've stored f0-double
// we also want to f0-float32 is stored there.
void alignedAliased(uint32_t aliasIdx, FloatRegister* ret) {
MOZ_ASSERT(isDouble());
MOZ_ASSERT((code_ & 1) == 0);
MOZ_ASSERT(isNotOdd());
if (aliasIdx == 0) {
*ret = *this;
return;
}
MOZ_ASSERT(aliasIdx == 1);
*ret = singleOverlay(aliasIdx - 1);
if (isDouble()) {
*ret = singleOverlay();
} else {
*ret = doubleOverlay();
}
}
SetType alignedOrDominatedAliasedSet() const {
if (isSingle())
return SetType(1) << code_;
MOZ_ASSERT(isDouble());
return SetType(0b11) << code_;
MOZ_ASSERT(isNotOdd());
return (SetType(1) << (code_ >> 1)) * ((1 << FloatRegisters::TotalSingle) + 1);
}
static constexpr RegTypeName DefaultType = RegTypeName::Float64;
@ -306,6 +262,21 @@ FloatRegister::LiveAsIndexableSet<RegTypeName::Any>(SetType set)
return set;
}
template <> inline FloatRegister::SetType
FloatRegister::AllocatableAsIndexableSet<RegTypeName::Float32>(SetType set)
{
// Single registers are not dominating any smaller registers, thus masking
// is enough to convert an allocatable set into a set of register list all
// single register available.
return set & FloatRegisters::AllSingleMask;
}
template <> inline FloatRegister::SetType
FloatRegister::AllocatableAsIndexableSet<RegTypeName::Float64>(SetType set)
{
return set & FloatRegisters::AllDoubleMask;
}
// 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

Просмотреть файл

@ -157,7 +157,9 @@ class Assembler : public AssemblerMIPSShared
// precision registers that make one double register.
FloatRegister getOddPair(FloatRegister reg) {
MOZ_ASSERT(reg.isDouble());
return reg.singleOverlay(1);
MOZ_ASSERT(reg.id() % 2 == 0);
FloatRegister odd(reg.id() | 1, FloatRegister::Single);
return odd;
}
public:

Просмотреть файл

@ -826,6 +826,5 @@ CodeGeneratorMIPS::setReturnDoubleRegs(LiveRegisterSet* regs)
{
MOZ_ASSERT(ReturnFloat32Reg.code_ == ReturnDoubleReg.code_);
regs->add(ReturnFloat32Reg);
regs->add(ReturnDoubleReg.singleOverlay(1));
regs->add(ReturnDoubleReg);
}

Просмотреть файл

@ -751,7 +751,7 @@ MacroAssemblerMIPS::ma_ss(FloatRegister ft, Address address)
void
MacroAssemblerMIPS::ma_pop(FloatRegister fs)
{
ma_ld(fs.doubleOverlay(0), Address(StackPointer, 0));
ma_ld(fs.doubleOverlay(), Address(StackPointer, 0));
as_addiu(StackPointer, StackPointer, sizeof(double));
}
@ -759,7 +759,7 @@ void
MacroAssemblerMIPS::ma_push(FloatRegister fs)
{
as_addiu(StackPointer, StackPointer, -sizeof(double));
ma_sd(fs.doubleOverlay(0), Address(StackPointer, 0));
ma_sd(fs.doubleOverlay(), Address(StackPointer, 0));
}
bool
@ -2110,18 +2110,22 @@ MacroAssembler::PushRegsInMask(LiveRegisterSet set)
}
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(~(ABIStackAlignment - 1)));
reserveStack(diffF + sizeof(double));
if (diffF > 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(~(ABIStackAlignment - 1)));
reserveStack(diffF);
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) {
if ((*iter).code() % 2 == 0)
as_sd(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) {
as_sd(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
}
MOZ_ASSERT(diffF == 0);
}
MOZ_ASSERT(diffF == 0);
}
void
@ -2132,18 +2136,22 @@ MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
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(~(ABIStackAlignment - 1)));
if (reservedF > 0) {
// Read the buffer form the first aligned location.
ma_addu(SecondScratchReg, sp, Imm32(reservedF));
ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(ABIStackAlignment - 1)));
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) {
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);
LiveFloatRegisterSet fpignore(ignore.fpus().reduceSetForPush());
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) {
if (!ignore.has(*iter))
as_ld(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
}
freeStack(reservedF);
MOZ_ASSERT(diffF == 0);
}
freeStack(reservedF + sizeof(double));
MOZ_ASSERT(diffF == 0);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); ++iter) {
diffG -= sizeof(intptr_t);
@ -2155,14 +2163,13 @@ MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
}
void
MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register)
MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register scratch)
{
FloatRegisterSet fpuSet(set.fpus().reduceSetForPush());
unsigned numFpu = fpuSet.size();
int32_t diffF = fpuSet.getPushSizeInBytes();
int32_t diffF = set.fpus().getPushSizeInBytes();
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
MOZ_ASSERT(dest.offset >= diffG + diffF);
MOZ_ASSERT(dest.base == StackPointer);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); ++iter) {
diffG -= sizeof(intptr_t);
@ -2171,21 +2178,19 @@ MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register)
}
MOZ_ASSERT(diffG == 0);
for (FloatRegisterBackwardIterator iter(fpuSet); iter.more(); ++iter) {
FloatRegister reg = *iter;
diffF -= reg.size();
numFpu -= 1;
dest.offset -= reg.size();
if (reg.isDouble())
storeDouble(reg, dest);
else if (reg.isSingle())
storeFloat32(reg, dest);
else
MOZ_CRASH("Unknown register type.");
if (diffF > 0) {
computeEffectiveAddress(dest, scratch);
ma_and(scratch, scratch, Imm32(~(ABIStackAlignment - 1)));
diffF -= sizeof(double);
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) {
as_sd(*iter, scratch, -diffF);
diffF -= sizeof(double);
}
MOZ_ASSERT(diffF == 0);
}
MOZ_ASSERT(numFpu == 0);
diffF -= diffF % sizeof(uintptr_t);
MOZ_ASSERT(diffF == 0);
}
// ===============================================================
// ABI function calls.

Просмотреть файл

@ -239,11 +239,7 @@ static const LiveRegisterSet NonVolatileRegs =
FloatRegisterSet(FloatRegisters::NonVolatileMask));
#endif
#if defined(JS_CODEGEN_MIPS32)
static const unsigned NonVolatileRegsPushSize = NonVolatileRegs.gprs().size() * sizeof(intptr_t) +
NonVolatileRegs.fpus().getPushSizeInBytes() +
sizeof(double);
#elif defined(JS_CODEGEN_NONE)
#if defined(JS_CODEGEN_NONE)
static const unsigned NonVolatileRegsPushSize = 0;
#else
static const unsigned NonVolatileRegsPushSize = NonVolatileRegs.gprs().size() * sizeof(intptr_t) +