mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 849489. Optimise use of vstm/vldm. r=mjrosenb
--HG-- extra : rebase_source : e5bbcc5fe569c0f81114587330ec80212fc9b560
This commit is contained in:
parent
3f9c051d47
commit
2d0baf56dd
@ -150,10 +150,11 @@ MacroAssembler::PushRegsInMask(RegisterSet set)
|
|||||||
}
|
}
|
||||||
JS_ASSERT(diffG == 0);
|
JS_ASSERT(diffG == 0);
|
||||||
|
|
||||||
reserveStack(diffF);
|
|
||||||
#ifdef JS_CPU_ARM
|
#ifdef JS_CPU_ARM
|
||||||
diffF -= transferMultipleByRuns(set.fpus(), IsStore, StackPointer, IA);
|
adjustFrame(diffF);
|
||||||
|
diffF += transferMultipleByRuns(set.fpus(), IsStore, StackPointer, DB);
|
||||||
#else
|
#else
|
||||||
|
reserveStack(diffF);
|
||||||
for (FloatRegisterIterator iter(set.fpus()); iter.more(); iter++) {
|
for (FloatRegisterIterator iter(set.fpus()); iter.more(); iter++) {
|
||||||
diffF -= sizeof(double);
|
diffF -= sizeof(double);
|
||||||
storeDouble(*iter, Address(StackPointer, diffF));
|
storeDouble(*iter, Address(StackPointer, diffF));
|
||||||
@ -175,6 +176,7 @@ MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
|
|||||||
// the registers we previously saved to the stack.
|
// the registers we previously saved to the stack.
|
||||||
if (ignore.empty(true)) {
|
if (ignore.empty(true)) {
|
||||||
diffF -= transferMultipleByRuns(set.fpus(), IsLoad, StackPointer, IA);
|
diffF -= transferMultipleByRuns(set.fpus(), IsLoad, StackPointer, IA);
|
||||||
|
adjustFrame(-reservedF);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -183,8 +185,8 @@ MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
|
|||||||
if (!ignore.has(*iter))
|
if (!ignore.has(*iter))
|
||||||
loadDouble(Address(StackPointer, diffF), *iter);
|
loadDouble(Address(StackPointer, diffF), *iter);
|
||||||
}
|
}
|
||||||
|
freeStack(reservedF);
|
||||||
}
|
}
|
||||||
freeStack(reservedF);
|
|
||||||
JS_ASSERT(diffF == 0);
|
JS_ASSERT(diffF == 0);
|
||||||
|
|
||||||
#ifdef JS_CPU_ARM
|
#ifdef JS_CPU_ARM
|
||||||
|
@ -1622,14 +1622,19 @@ class Assembler
|
|||||||
dtmCond = c;
|
dtmCond = c;
|
||||||
dtmLastReg = -1;
|
dtmLastReg = -1;
|
||||||
dtmMode = mode;
|
dtmMode = mode;
|
||||||
|
dtmDelta = 0;
|
||||||
}
|
}
|
||||||
void transferFloatReg(VFPRegister rn)
|
void transferFloatReg(VFPRegister rn)
|
||||||
{
|
{
|
||||||
if (dtmLastReg == -1) {
|
if (dtmLastReg == -1) {
|
||||||
vdtmFirstReg = rn;
|
vdtmFirstReg = rn.code();
|
||||||
} else {
|
} else {
|
||||||
|
if (dtmDelta == 0) {
|
||||||
|
dtmDelta = rn.code() - dtmLastReg;
|
||||||
|
JS_ASSERT(dtmDelta == 1 || dtmDelta == -1);
|
||||||
|
}
|
||||||
JS_ASSERT(dtmLastReg >= 0);
|
JS_ASSERT(dtmLastReg >= 0);
|
||||||
JS_ASSERT(rn.code() == unsigned(dtmLastReg) + 1);
|
JS_ASSERT(rn.code() == unsigned(dtmLastReg) + dtmDelta);
|
||||||
}
|
}
|
||||||
dtmLastReg = rn.code();
|
dtmLastReg = rn.code();
|
||||||
}
|
}
|
||||||
@ -1637,16 +1642,20 @@ class Assembler
|
|||||||
JS_ASSERT(dtmActive);
|
JS_ASSERT(dtmActive);
|
||||||
dtmActive = false;
|
dtmActive = false;
|
||||||
JS_ASSERT(dtmLastReg != -1);
|
JS_ASSERT(dtmLastReg != -1);
|
||||||
|
dtmDelta = dtmDelta ? dtmDelta : 1;
|
||||||
// fencepost problem.
|
// fencepost problem.
|
||||||
int len = dtmLastReg - vdtmFirstReg.code() + 1;
|
int len = dtmDelta * (dtmLastReg - vdtmFirstReg) + 1;
|
||||||
as_vdtm(dtmLoadStore, dtmBase, vdtmFirstReg, len, dtmCond);
|
as_vdtm(dtmLoadStore, dtmBase,
|
||||||
|
VFPRegister(FloatRegister::FromCode(Min(vdtmFirstReg, dtmLastReg))),
|
||||||
|
len, dtmCond);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int dtmRegBitField;
|
int dtmRegBitField;
|
||||||
|
int vdtmFirstReg;
|
||||||
int dtmLastReg;
|
int dtmLastReg;
|
||||||
|
int dtmDelta;
|
||||||
Register dtmBase;
|
Register dtmBase;
|
||||||
VFPRegister vdtmFirstReg;
|
|
||||||
DTMWriteBack dtmUpdate;
|
DTMWriteBack dtmUpdate;
|
||||||
DTMMode dtmMode;
|
DTMMode dtmMode;
|
||||||
LoadStore dtmLoadStore;
|
LoadStore dtmLoadStore;
|
||||||
|
@ -1386,37 +1386,6 @@ MacroAssemblerARM::ma_vstr(VFPRegister src, Register base, Register index, int32
|
|||||||
ma_vstr(src, Operand(ScratchRegister, 0), cc);
|
ma_vstr(src, Operand(ScratchRegister, 0), cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32_t
|
|
||||||
MacroAssemblerARM::transferMultipleByRuns(FloatRegisterSet set, LoadStore ls,
|
|
||||||
Register rm, DTMMode mode)
|
|
||||||
{
|
|
||||||
int32_t delta;
|
|
||||||
if (mode == IA) {
|
|
||||||
delta = sizeof(double);
|
|
||||||
} else if (mode == DB) {
|
|
||||||
delta = -sizeof(double);
|
|
||||||
} else {
|
|
||||||
JS_NOT_REACHED("Invalid data transfer addressing mode");
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t offset = 0;
|
|
||||||
FloatRegisterForwardIterator iter(set);
|
|
||||||
while (iter.more()) {
|
|
||||||
startFloatTransferM(ls, rm, mode, WriteBack);
|
|
||||||
int32_t reg = (*iter).code_;
|
|
||||||
do {
|
|
||||||
offset += delta;
|
|
||||||
transferFloatReg(*iter);
|
|
||||||
} while ((++iter).more() && (*iter).code_ == ++reg);
|
|
||||||
finishFloatTransfer();
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_ASSERT(offset == set.size() * sizeof(double) * (mode == DB ? -1 : 1));
|
|
||||||
ma_sub(Imm32(offset), rm);
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MacroAssemblerARMCompat::buildFakeExitFrame(const Register &scratch, uint32_t *offset)
|
MacroAssemblerARMCompat::buildFakeExitFrame(const Register &scratch, uint32_t *offset)
|
||||||
{
|
{
|
||||||
|
@ -334,10 +334,48 @@ class MacroAssemblerARM : public Assembler
|
|||||||
// Float registers can only be loaded/stored in continuous runs
|
// Float registers can only be loaded/stored in continuous runs
|
||||||
// when using vstm/vldm.
|
// when using vstm/vldm.
|
||||||
// This function breaks set into continuous runs and loads/stores
|
// This function breaks set into continuous runs and loads/stores
|
||||||
// them at [rm]. rm will be modified, but returned to its initial value.
|
// them at [rm]. rm will be modified and left in a state logically
|
||||||
|
// suitable for the next load/store.
|
||||||
// Returns the offset from [dm] for the logical next load/store.
|
// Returns the offset from [dm] for the logical next load/store.
|
||||||
int32_t transferMultipleByRuns(FloatRegisterSet set, LoadStore ls,
|
int32_t transferMultipleByRuns(FloatRegisterSet set, LoadStore ls,
|
||||||
Register rm, DTMMode mode);
|
Register rm, DTMMode mode)
|
||||||
|
{
|
||||||
|
if (mode == IA) {
|
||||||
|
return transferMultipleByRunsImpl
|
||||||
|
<FloatRegisterForwardIterator>(set, ls, rm, mode, 1);
|
||||||
|
}
|
||||||
|
if (mode == DB) {
|
||||||
|
return transferMultipleByRunsImpl
|
||||||
|
<FloatRegisterIterator>(set, ls, rm, mode, -1);
|
||||||
|
}
|
||||||
|
JS_NOT_REACHED("Invalid data transfer addressing mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Implementation for transferMultipleByRuns so we can use different
|
||||||
|
// iterators for forward/backward traversals.
|
||||||
|
// The sign argument should be 1 if we traverse forwards, -1 if we
|
||||||
|
// traverse backwards.
|
||||||
|
template<typename RegisterIterator> int32_t
|
||||||
|
transferMultipleByRunsImpl(FloatRegisterSet set, LoadStore ls,
|
||||||
|
Register rm, DTMMode mode, int32_t sign)
|
||||||
|
{
|
||||||
|
int32_t delta = sign * sizeof(double);
|
||||||
|
int32_t offset = 0;
|
||||||
|
RegisterIterator iter(set);
|
||||||
|
while (iter.more()) {
|
||||||
|
startFloatTransferM(ls, rm, mode, WriteBack);
|
||||||
|
int32_t reg = (*iter).code_;
|
||||||
|
do {
|
||||||
|
offset += delta;
|
||||||
|
transferFloatReg(*iter);
|
||||||
|
} while ((++iter).more() && (*iter).code_ == (reg += sign));
|
||||||
|
finishFloatTransfer();
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_ASSERT(offset == set.size() * sizeof(double) * sign);
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroAssemblerARMCompat : public MacroAssemblerARM
|
class MacroAssemblerARMCompat : public MacroAssemblerARM
|
||||||
|
Loading…
Reference in New Issue
Block a user