mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1184959 part 2 - ARM ABIArgGenerator: Add support for soft-fp. r=h4writer
This commit is contained in:
parent
58c3e4a6fe
commit
a98bebcec7
@ -10987,6 +10987,11 @@ GenerateEntry(ModuleCompiler& m, unsigned exportIndex)
|
||||
case ABIArg::GPR:
|
||||
masm.load32(src, iter->gpr());
|
||||
break;
|
||||
#ifdef JS_CODEGEN_REGISTER_PAIR
|
||||
case ABIArg::GPR_PAIR:
|
||||
MOZ_CRASH("AsmJS uses hardfp for function calls.");
|
||||
break;
|
||||
#endif
|
||||
case ABIArg::FPU: {
|
||||
static_assert(sizeof(AsmJSModule::EntryArg) >= jit::Simd128DataSize,
|
||||
"EntryArg must be big enough to store SIMD values");
|
||||
@ -11099,6 +11104,11 @@ FillArgumentArray(ModuleCompiler& m, const VarTypeVector& argTypes,
|
||||
case ABIArg::GPR:
|
||||
masm.storeValue(JSVAL_TYPE_INT32, i->gpr(), dstAddr);
|
||||
break;
|
||||
#ifdef JS_CODEGEN_REGISTER_PAIR
|
||||
case ABIArg::GPR_PAIR:
|
||||
MOZ_CRASH("AsmJS uses hardfp for function calls.");
|
||||
break;
|
||||
#endif
|
||||
case ABIArg::FPU:
|
||||
masm.canonicalizeDouble(i->fpu());
|
||||
masm.storeDouble(i->fpu(), dstAddr);
|
||||
|
@ -1220,7 +1220,14 @@ class AnyRegisterIterator
|
||||
class ABIArg
|
||||
{
|
||||
public:
|
||||
enum Kind { GPR, FPU, Stack };
|
||||
enum Kind {
|
||||
GPR,
|
||||
#ifdef JS_CODEGEN_REGISTER_PAIR
|
||||
GPR_PAIR,
|
||||
#endif
|
||||
FPU,
|
||||
Stack
|
||||
};
|
||||
|
||||
private:
|
||||
Kind kind_;
|
||||
@ -1233,11 +1240,39 @@ class ABIArg
|
||||
public:
|
||||
ABIArg() : kind_(Kind(-1)) { u.offset_ = -1; }
|
||||
explicit ABIArg(Register gpr) : kind_(GPR) { u.gpr_ = gpr.code(); }
|
||||
explicit ABIArg(Register gprLow, Register gprHigh)
|
||||
{
|
||||
#if defined(JS_CODEGEN_REGISTER_PAIR)
|
||||
kind_ = GPR_PAIR;
|
||||
#else
|
||||
MOZ_CRASH("Unsupported type of ABI argument.");
|
||||
#endif
|
||||
u.gpr_ = gprLow.code();
|
||||
MOZ_ASSERT(u.gpr_ % 2 == 0);
|
||||
MOZ_ASSERT(u.gpr_ + 1 == gprHigh.code());
|
||||
}
|
||||
explicit ABIArg(FloatRegister fpu) : kind_(FPU) { u.fpu_ = fpu.code(); }
|
||||
explicit ABIArg(uint32_t offset) : kind_(Stack) { u.offset_ = offset; }
|
||||
|
||||
Kind kind() const { return kind_; }
|
||||
Register gpr() const { MOZ_ASSERT(kind() == GPR); return Register::FromCode(u.gpr_); }
|
||||
#ifdef JS_CODEGEN_REGISTER_PAIR
|
||||
bool isGeneralRegPair() const { return kind_ == GPR_PAIR; }
|
||||
#else
|
||||
bool isGeneralRegPair() const { return false; }
|
||||
#endif
|
||||
|
||||
Register gpr() const {
|
||||
MOZ_ASSERT(kind() == GPR);
|
||||
return Register::FromCode(u.gpr_);
|
||||
}
|
||||
Register evenGpr() const {
|
||||
MOZ_ASSERT(isGeneralRegPair());
|
||||
return Register::FromCode(u.gpr_);
|
||||
}
|
||||
Register oddGpr() const {
|
||||
MOZ_ASSERT(isGeneralRegPair());
|
||||
return Register::FromCode(u.gpr_ + 1);
|
||||
}
|
||||
FloatRegister fpu() const { MOZ_ASSERT(kind() == FPU); return FloatRegister::FromCode(u.fpu_); }
|
||||
uint32_t offsetFromArgBase() const { MOZ_ASSERT(kind() == Stack); return u.offset_; }
|
||||
|
||||
|
@ -639,6 +639,10 @@ static inline bool UseHardFpABI()
|
||||
}
|
||||
#endif
|
||||
|
||||
// In order to handle SoftFp ABI calls, we need to be able to express that we
|
||||
// have ABIArg which are represented by pair of general purpose registers.
|
||||
#define JS_CODEGEN_REGISTER_PAIR 1
|
||||
|
||||
// See the comments above AsmJSMappedSize in AsmJSValidate.h for more info.
|
||||
// TODO: Implement this for ARM. Note that it requires Codegen to respect the
|
||||
// offset field of AsmJSHeapAccess.
|
||||
|
@ -24,17 +24,67 @@ using mozilla::CountLeadingZeroes32;
|
||||
|
||||
void dbg_break() {}
|
||||
|
||||
// Note this is used for inter-AsmJS calls and may pass arguments and results in
|
||||
// floating point registers even if the system ABI does not.
|
||||
// The ABIArgGenerator is used for making system ABI calls and for inter-AsmJS
|
||||
// calls. The system ABI can either be SoftFp or HardFp, and inter-AsmJS calls
|
||||
// are always HardFp calls. The initialization defaults to HardFp, and the ABI
|
||||
// choice is made before any system ABI calls with the method "setUseHardFp".
|
||||
ABIArgGenerator::ABIArgGenerator()
|
||||
: intRegIndex_(0),
|
||||
floatRegIndex_(0),
|
||||
stackOffset_(0),
|
||||
current_()
|
||||
current_(),
|
||||
useHardFp_(true)
|
||||
{ }
|
||||
|
||||
// See the "Parameter Passing" section of the "Procedure Call Standard for the
|
||||
// ARM Architecture" documentation.
|
||||
ABIArg
|
||||
ABIArgGenerator::next(MIRType type)
|
||||
ABIArgGenerator::softNext(MIRType type)
|
||||
{
|
||||
switch (type) {
|
||||
case MIRType_Int32:
|
||||
case MIRType_Pointer:
|
||||
if (intRegIndex_ == NumIntArgRegs) {
|
||||
current_ = ABIArg(stackOffset_);
|
||||
stackOffset_ += sizeof(uint32_t);
|
||||
break;
|
||||
}
|
||||
current_ = ABIArg(Register::FromCode(intRegIndex_));
|
||||
intRegIndex_++;
|
||||
break;
|
||||
case MIRType_Float32:
|
||||
if (intRegIndex_ == NumIntArgRegs) {
|
||||
current_ = ABIArg(stackOffset_);
|
||||
stackOffset_ += sizeof(uint32_t);
|
||||
break;
|
||||
}
|
||||
current_ = ABIArg(Register::FromCode(intRegIndex_));
|
||||
intRegIndex_++;
|
||||
break;
|
||||
case MIRType_Double:
|
||||
// Make sure to use an even register index. Increase to next even number
|
||||
// when odd.
|
||||
intRegIndex_ = (intRegIndex_ + 1) & ~1;
|
||||
if (intRegIndex_ == NumIntArgRegs) {
|
||||
// Align the stack on 8 bytes.
|
||||
static const int align = sizeof(double) - 1;
|
||||
stackOffset_ = (stackOffset_ + align) & ~align;
|
||||
current_ = ABIArg(stackOffset_);
|
||||
stackOffset_ += sizeof(double);
|
||||
break;
|
||||
}
|
||||
current_ = ABIArg(Register::FromCode(intRegIndex_), Register::FromCode(intRegIndex_ + 1));
|
||||
intRegIndex_ += 2;
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected argument type");
|
||||
}
|
||||
|
||||
return current_;
|
||||
}
|
||||
|
||||
ABIArg
|
||||
ABIArgGenerator::hardNext(MIRType type)
|
||||
{
|
||||
switch (type) {
|
||||
case MIRType_Int32:
|
||||
@ -59,7 +109,9 @@ ABIArgGenerator::next(MIRType type)
|
||||
floatRegIndex_++;
|
||||
break;
|
||||
case MIRType_Double:
|
||||
// Bump the number of used registers up to the next multiple of two.
|
||||
// Double register are composed of 2 float registers, thus we have to
|
||||
// skip any float register which cannot be used in a pair of float
|
||||
// registers in which a double value can be stored.
|
||||
floatRegIndex_ = (floatRegIndex_ + 1) & ~1;
|
||||
if (floatRegIndex_ == NumFloatArgRegs) {
|
||||
static const int align = sizeof(double) - 1;
|
||||
@ -78,6 +130,14 @@ ABIArgGenerator::next(MIRType type)
|
||||
return current_;
|
||||
}
|
||||
|
||||
ABIArg
|
||||
ABIArgGenerator::next(MIRType type)
|
||||
{
|
||||
if (useHardFp_)
|
||||
return hardNext(type);
|
||||
return softNext(type);
|
||||
}
|
||||
|
||||
const Register ABIArgGenerator::NonArgReturnReg0 = r4;
|
||||
const Register ABIArgGenerator::NonArgReturnReg1 = r5;
|
||||
const Register ABIArgGenerator::NonReturn_VolatileReg0 = r2;
|
||||
|
@ -72,9 +72,23 @@ class ABIArgGenerator
|
||||
uint32_t stackOffset_;
|
||||
ABIArg current_;
|
||||
|
||||
// ARM can either use HardFp (use float registers for float arguments), or
|
||||
// SoftFp (use general registers for float arguments) ABI. We keep this
|
||||
// switch as a runtime switch because AsmJS always use the HardFp back-end
|
||||
// while the calls to native functions have to use the one provided by the
|
||||
// system.
|
||||
bool useHardFp_;
|
||||
|
||||
ABIArg softNext(MIRType argType);
|
||||
ABIArg hardNext(MIRType argType);
|
||||
|
||||
public:
|
||||
ABIArgGenerator();
|
||||
|
||||
void setUseHardFp(bool useHardFp) {
|
||||
MOZ_ASSERT(intRegIndex_ == 0 && floatRegIndex_ == 0);
|
||||
useHardFp_ = useHardFp;
|
||||
}
|
||||
ABIArg next(MIRType argType);
|
||||
ABIArg& current() { return current_; }
|
||||
uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
|
||||
|
Loading…
Reference in New Issue
Block a user