mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 965229 - ARM simulator: Scratch volatile registers across system ABI calls. r=nbp
This commit is contained in:
parent
4c5e3939e4
commit
0bdc2c1945
@ -2043,6 +2043,35 @@ typedef double (*Prototype_Double_IntDouble)(int32_t arg0, double arg1);
|
||||
typedef double (*Prototype_Double_DoubleDouble)(double arg0, double arg1);
|
||||
typedef int32_t (*Prototype_Int_IntDouble)(int32_t arg0, double arg1);
|
||||
|
||||
|
||||
// Fill the volatile registers with scratch values.
|
||||
//
|
||||
// Some of the ABI calls assume that the float registers are not scratched, even
|
||||
// though the ABI defines them as volatile - a performance optimization. These are
|
||||
// all calls passing operands in integer registers, so for now the simulator does not
|
||||
// scratch any float registers for these calls. Should try to narrow it further in
|
||||
// future.
|
||||
//
|
||||
void
|
||||
Simulator::scratchVolatileRegisters(bool scratchFloat)
|
||||
{
|
||||
int32_t scratch_value = 0xa5a5a5a5 ^ uint32_t(icount_);
|
||||
set_register(r0, scratch_value);
|
||||
set_register(r1, scratch_value);
|
||||
set_register(r2, scratch_value);
|
||||
set_register(r3, scratch_value);
|
||||
set_register(r12, scratch_value); // Intra-Procedure-call scratch register
|
||||
set_register(r14, scratch_value); // Link register
|
||||
|
||||
if (scratchFloat) {
|
||||
uint64_t scratch_value_d = 0x5a5a5a5a5a5a5a5aLU ^ uint64_t(icount_) ^ (uint64_t(icount_) << 30);
|
||||
for (uint32_t i = d0; i < d8; i++)
|
||||
set_d_register(i, &scratch_value_d);
|
||||
for (uint32_t i = d16; i < FloatRegisters::Total; i++)
|
||||
set_d_register(i, &scratch_value_d);
|
||||
}
|
||||
}
|
||||
|
||||
// Software interrupt instructions are used by the simulator to call into C++.
|
||||
void
|
||||
Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
@ -2072,42 +2101,53 @@ Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
case Args_General0: {
|
||||
Prototype_General0 target = reinterpret_cast<Prototype_General0>(external);
|
||||
int64_t result = target();
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General1: {
|
||||
Prototype_General1 target = reinterpret_cast<Prototype_General1>(external);
|
||||
int64_t result = target(arg0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General2: {
|
||||
Prototype_General2 target = reinterpret_cast<Prototype_General2>(external);
|
||||
int64_t result = target(arg0, arg1);
|
||||
// The ARM backend makes calls to __aeabi_idivmod and __aeabi_uidivmod assuming
|
||||
// that the float registers are non-volatile as a performance optimization, so the
|
||||
// float registers must not be scratch when calling these.
|
||||
bool scratchFloat = target != __aeabi_idivmod && target != __aeabi_uidivmod;
|
||||
scratchVolatileRegisters(/* scratchFloat = */ scratchFloat);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General3: {
|
||||
Prototype_General3 target = reinterpret_cast<Prototype_General3>(external);
|
||||
int64_t result = target(arg0, arg1, arg2);
|
||||
scratchVolatileRegisters(/* scratchFloat = true*/);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General4: {
|
||||
Prototype_General4 target = reinterpret_cast<Prototype_General4>(external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3);
|
||||
scratchVolatileRegisters(/* scratchFloat = true*/);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General5: {
|
||||
Prototype_General5 target = reinterpret_cast<Prototype_General5>(external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_General6: {
|
||||
Prototype_General6 target = reinterpret_cast<Prototype_General6>(external);
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
@ -2115,6 +2155,7 @@ Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
Prototype_General7 target = reinterpret_cast<Prototype_General7>(external);
|
||||
int32_t arg6 = stack_pointer[2];
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5, arg6);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
@ -2123,12 +2164,14 @@ Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
int32_t arg6 = stack_pointer[2];
|
||||
int32_t arg7 = stack_pointer[3];
|
||||
int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResult(result);
|
||||
break;
|
||||
}
|
||||
case Args_Double_None: {
|
||||
Prototype_Double_None target = reinterpret_cast<Prototype_Double_None>(external);
|
||||
double dresult = target();
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
@ -2138,6 +2181,7 @@ Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
Prototype_Int_Double target = reinterpret_cast<Prototype_Int_Double>(external);
|
||||
int32_t res = target(dval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
set_register(r0, res);
|
||||
break;
|
||||
}
|
||||
@ -2147,6 +2191,7 @@ Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
Prototype_Double_Double target = reinterpret_cast<Prototype_Double_Double>(external);
|
||||
double dresult = target(dval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
@ -2154,12 +2199,14 @@ Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
float fval0 = mozilla::BitwiseCast<float>(arg0);
|
||||
Prototype_Float32_Float32 target = reinterpret_cast<Prototype_Float32_Float32>(external);
|
||||
float fresult = target(fval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultFloat(fresult);
|
||||
break;
|
||||
}
|
||||
case Args_Double_Int: {
|
||||
Prototype_Double_Int target = reinterpret_cast<Prototype_Double_Int>(external);
|
||||
double dresult = target(arg0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
@ -2169,6 +2216,7 @@ Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
Prototype_DoubleInt target = reinterpret_cast<Prototype_DoubleInt>(external);
|
||||
double dresult = target(dval0, ival);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
@ -2178,6 +2226,7 @@ Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
getFpArgs(&dval0, &dval1, &ival);
|
||||
Prototype_Double_DoubleDouble target = reinterpret_cast<Prototype_Double_DoubleDouble>(external);
|
||||
double dresult = target(dval0, dval1);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
@ -2187,6 +2236,7 @@ Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
double dval0 = get_double_from_register_pair(2);
|
||||
Prototype_Double_IntDouble target = reinterpret_cast<Prototype_Double_IntDouble>(external);
|
||||
double dresult = target(ival, dval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
setCallResultDouble(dresult);
|
||||
break;
|
||||
}
|
||||
@ -2196,6 +2246,7 @@ Simulator::softwareInterrupt(SimInstruction *instr)
|
||||
double dval0 = get_double_from_register_pair(2);
|
||||
Prototype_Int_IntDouble target = reinterpret_cast<Prototype_Int_IntDouble>(external);
|
||||
int32_t result = target(ival, dval0);
|
||||
scratchVolatileRegisters(/* scratchFloat = true */);
|
||||
set_register(r0, result);
|
||||
break;
|
||||
}
|
||||
|
@ -281,6 +281,7 @@ class Simulator
|
||||
void setCallResultDouble(double result);
|
||||
void setCallResultFloat(float result);
|
||||
void setCallResult(int64_t res);
|
||||
void scratchVolatileRegisters(bool scratchFloat = true);
|
||||
|
||||
template<class ReturnType, int register_size>
|
||||
ReturnType getFromVFPRegister(int reg_index);
|
||||
|
Loading…
Reference in New Issue
Block a user