Merge in latest changes to ArmEmitter from the PPSSPP crew. Should fix the dumb random crashes I had from IOS icache clearing not initializing a value.
This commit is contained in:
parent
2c722bb04f
commit
6d9c0c8863
|
@ -83,6 +83,40 @@ bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Operand2 AssumeMakeOperand2(u32 imm) {
|
||||||
|
Operand2 op2;
|
||||||
|
bool result = TryMakeOperand2(imm, op2);
|
||||||
|
_dbg_assert_msg_(JIT, result, "Could not make assumed Operand2.");
|
||||||
|
return op2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ARMXEmitter::TrySetValue_TwoOp(ARMReg reg, u32 val)
|
||||||
|
{
|
||||||
|
int ops = 0;
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if ((val >> (i*2)) & 0x3)
|
||||||
|
{
|
||||||
|
ops++;
|
||||||
|
i+=3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ops > 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
for (int i = 0; i < 16; i++, val >>=2) {
|
||||||
|
if (val & 0x3) {
|
||||||
|
first ? MOV(reg, Operand2((u8)val, (u8)((16-i) & 0xF)))
|
||||||
|
: ORR(reg, reg, Operand2((u8)val, (u8)((16-i) & 0xF)));
|
||||||
|
first = false;
|
||||||
|
i+=3;
|
||||||
|
val >>= 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void ARMXEmitter::MOVI2F(ARMReg dest, float val, ARMReg tempReg)
|
void ARMXEmitter::MOVI2F(ARMReg dest, float val, ARMReg tempReg)
|
||||||
{
|
{
|
||||||
union {float f; u32 u;} conv;
|
union {float f; u32 u;} conv;
|
||||||
|
@ -93,6 +127,21 @@ void ARMXEmitter::MOVI2F(ARMReg dest, float val, ARMReg tempReg)
|
||||||
// Otherwise, use a literal pool and VLDR directly (+- 1020)
|
// Otherwise, use a literal pool and VLDR directly (+- 1020)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ARMXEmitter::ADDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
|
||||||
|
{
|
||||||
|
Operand2 op2;
|
||||||
|
bool negated;
|
||||||
|
if (TryMakeOperand2_AllowNegation(val, op2, &negated)) {
|
||||||
|
if (!negated)
|
||||||
|
ADD(rd, rs, op2);
|
||||||
|
else
|
||||||
|
SUB(rd, rs, op2);
|
||||||
|
} else {
|
||||||
|
MOVI2R(scratch, val);
|
||||||
|
ADD(rd, rs, scratch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ARMXEmitter::ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
|
void ARMXEmitter::ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
|
||||||
{
|
{
|
||||||
Operand2 op2;
|
Operand2 op2;
|
||||||
|
@ -109,6 +158,21 @@ void ARMXEmitter::ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ARMXEmitter::CMPI2R(ARMReg rs, u32 val, ARMReg scratch)
|
||||||
|
{
|
||||||
|
Operand2 op2;
|
||||||
|
bool negated;
|
||||||
|
if (TryMakeOperand2_AllowNegation(val, op2, &negated)) {
|
||||||
|
if (!negated)
|
||||||
|
CMP(rs, op2);
|
||||||
|
else
|
||||||
|
CMN(rs, op2);
|
||||||
|
} else {
|
||||||
|
MOVI2R(scratch, val);
|
||||||
|
CMP(rs, scratch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ARMXEmitter::ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
|
void ARMXEmitter::ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch)
|
||||||
{
|
{
|
||||||
Operand2 op2;
|
Operand2 op2;
|
||||||
|
@ -173,7 +237,7 @@ void ARMXEmitter::MOVI2R(ARMReg reg, u32 val, bool optimize)
|
||||||
MOVW(reg, val & 0xFFFF);
|
MOVW(reg, val & 0xFFFF);
|
||||||
if(val & 0xFFFF0000)
|
if(val & 0xFFFF0000)
|
||||||
MOVT(reg, val, true);
|
MOVT(reg, val, true);
|
||||||
} else {
|
} else if (!TrySetValue_TwoOp(reg,val)) {
|
||||||
// Use literal pool for ARMv6.
|
// Use literal pool for ARMv6.
|
||||||
AddNewLit(val);
|
AddNewLit(val);
|
||||||
LDR(reg, _PC); // To be backpatched later
|
LDR(reg, _PC); // To be backpatched later
|
||||||
|
@ -190,9 +254,7 @@ void ARMXEmitter::SetCodePtr(u8 *ptr)
|
||||||
{
|
{
|
||||||
code = ptr;
|
code = ptr;
|
||||||
startcode = code;
|
startcode = code;
|
||||||
#ifdef IOS
|
|
||||||
lastCacheFlushEnd = ptr;
|
lastCacheFlushEnd = ptr;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8 *ARMXEmitter::GetCodePtr() const
|
const u8 *ARMXEmitter::GetCodePtr() const
|
||||||
|
@ -236,12 +298,9 @@ void ARMXEmitter::FlushIcacheSection(u8 *start, u8 *end)
|
||||||
#elif defined(BLACKBERRY)
|
#elif defined(BLACKBERRY)
|
||||||
msync(start, end - start, MS_SYNC | MS_INVALIDATE_ICACHE);
|
msync(start, end - start, MS_SYNC | MS_INVALIDATE_ICACHE);
|
||||||
#elif defined(IOS)
|
#elif defined(IOS)
|
||||||
if (start != NULL)
|
// Header file says this is equivalent to: sys_icache_invalidate(start, end - start);
|
||||||
sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start);
|
sys_cache_control(kCacheFunctionPrepareForExecution, start, end - start);
|
||||||
#elif !defined(_WIN32)
|
#elif !defined(_WIN32)
|
||||||
#ifndef ANDROID
|
|
||||||
start = startcode; // Should be Linux Only
|
|
||||||
#endif
|
|
||||||
__builtin___clear_cache(start, end);
|
__builtin___clear_cache(start, end);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -628,7 +687,8 @@ void ARMXEmitter::SVC(Operand2 op)
|
||||||
|
|
||||||
// IMM, REG, IMMSREG, RSR
|
// IMM, REG, IMMSREG, RSR
|
||||||
// -1 for invalid if the instruction doesn't support that
|
// -1 for invalid if the instruction doesn't support that
|
||||||
const s32 LoadStoreOps[][4] = { {0x40, 0x60, 0x60, -1}, // STR
|
const s32 LoadStoreOps[][4] = {
|
||||||
|
{0x40, 0x60, 0x60, -1}, // STR
|
||||||
{0x41, 0x61, 0x61, -1}, // LDR
|
{0x41, 0x61, 0x61, -1}, // LDR
|
||||||
{0x44, 0x64, 0x64, -1}, // STRB
|
{0x44, 0x64, 0x64, -1}, // STRB
|
||||||
{0x45, 0x65, 0x65, -1}, // LDRB
|
{0x45, 0x65, 0x65, -1}, // LDRB
|
||||||
|
@ -638,7 +698,8 @@ const s32 LoadStoreOps[][4] = { {0x40, 0x60, 0x60, -1}, // STR
|
||||||
{ 0x5, 0x1, -1, -1}, // LDRSB
|
{ 0x5, 0x1, -1, -1}, // LDRSB
|
||||||
{ 0x5, 0x1, -1, -1}, // LDRSH
|
{ 0x5, 0x1, -1, -1}, // LDRSH
|
||||||
};
|
};
|
||||||
const char *LoadStoreNames[] = { "STR",
|
const char *LoadStoreNames[] = {
|
||||||
|
"STR",
|
||||||
"LDR",
|
"LDR",
|
||||||
"STRB",
|
"STRB",
|
||||||
"LDRB",
|
"LDRB",
|
||||||
|
@ -659,7 +720,7 @@ void ARMXEmitter::WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 Rm, bool R
|
||||||
bool Index = true;
|
bool Index = true;
|
||||||
bool Add = false;
|
bool Add = false;
|
||||||
|
|
||||||
// Special Encoding
|
// Special Encoding (misc addressing mode)
|
||||||
bool SpecialOp = false;
|
bool SpecialOp = false;
|
||||||
bool Half = false;
|
bool Half = false;
|
||||||
bool SignedLoad = false;
|
bool SignedLoad = false;
|
||||||
|
@ -703,6 +764,9 @@ void ARMXEmitter::WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 Rm, bool R
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TYPE_REG:
|
case TYPE_REG:
|
||||||
|
Data = Rm.GetData();
|
||||||
|
Add = RegAdd;
|
||||||
|
break;
|
||||||
case TYPE_IMMSREG:
|
case TYPE_IMMSREG:
|
||||||
if (!SpecialOp)
|
if (!SpecialOp)
|
||||||
{
|
{
|
||||||
|
@ -710,6 +774,7 @@ void ARMXEmitter::WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 Rm, bool R
|
||||||
Add = RegAdd;
|
Add = RegAdd;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Intentional fallthrough: TYPE_IMMSREG not supported for misc addressing.
|
||||||
default:
|
default:
|
||||||
// RSR not supported for any of these
|
// RSR not supported for any of these
|
||||||
// We already have the warning above
|
// We already have the warning above
|
||||||
|
@ -720,7 +785,7 @@ void ARMXEmitter::WriteStoreOp(u32 Op, ARMReg Rt, ARMReg Rn, Operand2 Rm, bool R
|
||||||
if (SpecialOp)
|
if (SpecialOp)
|
||||||
{
|
{
|
||||||
// Add SpecialOp things
|
// Add SpecialOp things
|
||||||
Data = (0x5 << 4) | (SignedLoad << 6) | (Half << 5) | Data;
|
Data = (0x9 << 4) | (SignedLoad << 6) | (Half << 5) | Data;
|
||||||
}
|
}
|
||||||
Write32(condition | (op << 20) | (Index << 24) | (Add << 23) | (Rn << 16) | (Rt << 12) | Data);
|
Write32(condition | (op << 20) | (Index << 24) | (Add << 23) | (Rn << 16) | (Rt << 12) | Data);
|
||||||
}
|
}
|
||||||
|
@ -947,7 +1012,6 @@ void ARMXEmitter::VLDR(ARMReg Dest, ARMReg Base, s16 offset)
|
||||||
{
|
{
|
||||||
Write32(condition | (0xD << 24) | (Add << 23) | ((Dest & 0x1) << 22) | (1 << 20) | (Base << 16) \
|
Write32(condition | (0xD << 24) | (Add << 23) | ((Dest & 0x1) << 22) | (1 << 20) | (Base << 16) \
|
||||||
| ((Dest & 0x1E) << 11) | (10 << 8) | (imm >> 2));
|
| ((Dest & 0x1E) << 11) | (10 << 8) | (imm >> 2));
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -320,6 +320,9 @@ bool TryMakeOperand2(u32 imm, Operand2 &op2);
|
||||||
bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse);
|
bool TryMakeOperand2_AllowInverse(u32 imm, Operand2 &op2, bool *inverse);
|
||||||
bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated);
|
bool TryMakeOperand2_AllowNegation(s32 imm, Operand2 &op2, bool *negated);
|
||||||
|
|
||||||
|
// Use this only when you know imm can be made into an Operand2.
|
||||||
|
Operand2 AssumeMakeOperand2(u32 imm);
|
||||||
|
|
||||||
inline Operand2 R(ARMReg Reg) { return Operand2(Reg, TYPE_REG); }
|
inline Operand2 R(ARMReg Reg) { return Operand2(Reg, TYPE_REG); }
|
||||||
inline Operand2 IMM(u32 Imm) { return Operand2(Imm, TYPE_IMM); }
|
inline Operand2 IMM(u32 Imm) { return Operand2(Imm, TYPE_IMM); }
|
||||||
inline Operand2 Mem(void *ptr) { return Operand2((u32)ptr, TYPE_IMM); }
|
inline Operand2 Mem(void *ptr) { return Operand2((u32)ptr, TYPE_IMM); }
|
||||||
|
@ -394,6 +397,7 @@ public:
|
||||||
|
|
||||||
void FlushLitPool();
|
void FlushLitPool();
|
||||||
void AddNewLit(u32 val);
|
void AddNewLit(u32 val);
|
||||||
|
bool TrySetValue_TwoOp(ARMReg reg, u32 val);
|
||||||
|
|
||||||
CCFlags GetCC() { return CCFlags(condition >> 28); }
|
CCFlags GetCC() { return CCFlags(condition >> 28); }
|
||||||
void SetCC(CCFlags cond = CC_AL);
|
void SetCC(CCFlags cond = CC_AL);
|
||||||
|
@ -562,7 +566,9 @@ public:
|
||||||
void MOVI2R(ARMReg reg, u32 val, bool optimize = true);
|
void MOVI2R(ARMReg reg, u32 val, bool optimize = true);
|
||||||
void MOVI2F(ARMReg dest, float val, ARMReg tempReg);
|
void MOVI2F(ARMReg dest, float val, ARMReg tempReg);
|
||||||
|
|
||||||
|
void ADDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
||||||
void ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
void ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
||||||
|
void CMPI2R(ARMReg rs, u32 val, ARMReg scratch);
|
||||||
void ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
void ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue