aboutsummaryrefslogtreecommitdiff
path: root/src/ARMJIT_x64
diff options
context:
space:
mode:
authorRSDuck <rsduck@users.noreply.github.com>2019-08-25 12:28:48 +0200
committerRSDuck <rsduck@users.noreply.github.com>2020-04-26 13:05:00 +0200
commit5ea91b8a039e0735ac5cb102e2375c26c4f7a150 (patch)
tree197761d920867febb0b6f7a5c1947fe6fc8e13b6 /src/ARMJIT_x64
parent03ab7f1645f5a5c8427bc53a12f417845a17c980 (diff)
optimise away unneeded flag sets
- especially useful for thumb code and larger max block sizes - can still be improved upon
Diffstat (limited to 'src/ARMJIT_x64')
-rw-r--r--src/ARMJIT_x64/ARMJIT_ALU.cpp64
-rw-r--r--src/ARMJIT_x64/ARMJIT_Compiler.cpp9
-rw-r--r--src/ARMJIT_x64/ARMJIT_Compiler.h6
3 files changed, 60 insertions, 19 deletions
diff --git a/src/ARMJIT_x64/ARMJIT_ALU.cpp b/src/ARMJIT_x64/ARMJIT_ALU.cpp
index f0bcf8e..6a7d711 100644
--- a/src/ARMJIT_x64/ARMJIT_ALU.cpp
+++ b/src/ARMJIT_x64/ARMJIT_ALU.cpp
@@ -111,6 +111,8 @@ OpArg Compiler::A_Comp_GetALUOp2(bool S, bool& carryUsed)
}
else
{
+ S = S && (CurInstr.SetFlags & 0x2);
+
int op = (CurInstr.Instr >> 5) & 0x3;
if (CurInstr.Instr & (1 << 4))
{
@@ -215,7 +217,8 @@ void Compiler::A_Comp_MovOp()
if (S)
{
- TEST(32, rd, rd);
+ if (FlagsNZRequired())
+ TEST(32, rd, rd);
Comp_RetriveFlags(false, false, carryUsed);
}
@@ -263,12 +266,14 @@ void Compiler::Comp_MulOp(bool S, bool add, Gen::OpArg rd, Gen::OpArg rm, Gen::O
{
IMUL(32, RSCRATCH, rs);
LEA(32, rd.GetSimpleReg(), MRegSum(RSCRATCH, rn.GetSimpleReg()));
- TEST(32, rd, rd);
+ if (S && FlagsNZRequired())
+ TEST(32, rd, rd);
}
else
{
IMUL(32, RSCRATCH, rs);
MOV(32, rd, R(RSCRATCH));
+ if (S && FlagsNZRequired())
TEST(32, R(RSCRATCH), R(RSCRATCH));
}
@@ -331,7 +336,7 @@ void Compiler::A_Comp_SMULL_SMLAL()
else
{
IMUL(64, RSCRATCH2, R(RSCRATCH3));
- if (S)
+ if (S && FlagsNZRequired())
TEST(64, R(RSCRATCH2), R(RSCRATCH2));
}
@@ -345,9 +350,20 @@ void Compiler::A_Comp_SMULL_SMLAL()
void Compiler::Comp_RetriveFlags(bool sign, bool retriveCV, bool carryUsed)
{
- CPSRDirty = true;
+ if (CurInstr.SetFlags == 0)
+ return;
+ if (retriveCV && !(CurInstr.SetFlags & 0x3))
+ retriveCV = false;
bool carryOnly = !retriveCV && carryUsed;
+ if (carryOnly && !(CurInstr.SetFlags & 0x2))
+ {
+ carryUsed = false;
+ carryOnly = false;
+ }
+
+ CPSRDirty = true;
+
if (retriveCV)
{
SETcc(CC_O, R(RSCRATCH));
@@ -355,19 +371,28 @@ void Compiler::Comp_RetriveFlags(bool sign, bool retriveCV, bool carryUsed)
LEA(32, RSCRATCH2, MComplex(RSCRATCH, RSCRATCH3, SCALE_2, 0));
}
- SETcc(CC_S, R(RSCRATCH));
- SETcc(CC_Z, R(RSCRATCH3));
- LEA(32, RSCRATCH, MComplex(RSCRATCH3, RSCRATCH, SCALE_2, 0));
- int shiftAmount = 30;
- if (retriveCV || carryUsed)
+ if (FlagsNZRequired())
{
- LEA(32, RSCRATCH, MComplex(RSCRATCH2, RSCRATCH, carryOnly ? SCALE_2 : SCALE_4, 0));
- shiftAmount = carryOnly ? 29 : 28;
- }
- SHL(32, R(RSCRATCH), Imm8(shiftAmount));
+ SETcc(CC_S, R(RSCRATCH));
+ SETcc(CC_Z, R(RSCRATCH3));
+ LEA(32, RSCRATCH, MComplex(RSCRATCH3, RSCRATCH, SCALE_2, 0));
+ int shiftAmount = 30;
+ if (retriveCV || carryUsed)
+ {
+ LEA(32, RSCRATCH, MComplex(RSCRATCH2, RSCRATCH, carryOnly ? SCALE_2 : SCALE_4, 0));
+ shiftAmount = carryOnly ? 29 : 28;
+ }
+ SHL(32, R(RSCRATCH), Imm8(shiftAmount));
- AND(32, R(RCPSR), Imm32(0x3FFFFFFF & ~(carryUsed << 29) & ~((retriveCV ? 3 : 0) << 28)));
- OR(32, R(RCPSR), R(RSCRATCH));
+ AND(32, R(RCPSR), Imm32(0x3FFFFFFF & ~(carryUsed << 29) & ~((retriveCV ? 3 : 0) << 28)));
+ OR(32, R(RCPSR), R(RSCRATCH));
+ }
+ else
+ {
+ SHL(32, R(RSCRATCH2), Imm8(carryOnly ? 29 : 28));
+ AND(32, R(RCPSR), Imm32(0xFFFFFFFF & ~(carryUsed << 29) & ~((retriveCV ? 3 : 0) << 28)));
+ OR(32, R(RCPSR), R(RSCRATCH2));
+ }
}
// always uses RSCRATCH, RSCRATCH2 only if S == true
@@ -523,7 +548,8 @@ void Compiler::T_Comp_ShiftImm()
if (shifted != rd)
MOV(32, rd, shifted);
- TEST(32, rd, rd);
+ if (FlagsNZRequired())
+ TEST(32, rd, rd);
Comp_RetriveFlags(false, false, carryUsed);
}
@@ -557,7 +583,8 @@ void Compiler::T_Comp_ALU_Imm8()
{
case 0x0:
MOV(32, rd, imm);
- TEST(32, rd, rd);
+ if (FlagsNZRequired())
+ TEST(32, rd, rd);
Comp_RetriveFlags(false, false, false);
return;
case 0x1:
@@ -607,7 +634,8 @@ void Compiler::T_Comp_ALU()
int shiftOp = op == 0x7 ? 3 : op - 0x2;
bool carryUsed;
OpArg shifted = Comp_RegShiftReg(shiftOp, rs, rd, true, carryUsed);
- TEST(32, shifted, shifted);
+ if (FlagsNZRequired())
+ TEST(32, shifted, shifted);
MOV(32, rd, shifted);
Comp_RetriveFlags(false, false, true);
}
diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.cpp b/src/ARMJIT_x64/ARMJIT_Compiler.cpp
index ab13cb6..6abb2bb 100644
--- a/src/ARMJIT_x64/ARMJIT_Compiler.cpp
+++ b/src/ARMJIT_x64/ARMJIT_Compiler.cpp
@@ -342,6 +342,11 @@ const Compiler::CompileFunc T_Comp[ARMInstrInfo::tk_Count] = {
};
#undef F
+bool Compiler::CanCompile(bool thumb, u16 kind)
+{
+ return (thumb ? T_Comp[kind] : A_Comp[kind]) != NULL;
+}
+
void Compiler::Reset()
{
memset(ResetStart, 0xcc, CodeMemSize);
@@ -380,11 +385,15 @@ CompiledBlock Compiler::CompileBlock(ARM* cpu, FetchedInstr instrs[], int instrs
// TODO: this is ugly as a whole, do better
RegCache = RegisterCache<Compiler, X64Reg>(this, instrs, instrsCount);
+ printf("block start %d\n", Thumb);
+
for (int i = 0; i < instrsCount; i++)
{
R15 += Thumb ? 2 : 4;
CurInstr = instrs[i];
+ printf("%x %d %d %d\n", CurInstr.Instr, CurInstr.SetFlags, CurInstr.Info.WriteFlags, CurInstr.Info.ReadFlags);
+
CompileFunc comp = Thumb
? T_Comp[CurInstr.Info.Kind]
: A_Comp[CurInstr.Info.Kind];
diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.h b/src/ARMJIT_x64/ARMJIT_Compiler.h
index 3151cbc..8861884 100644
--- a/src/ARMJIT_x64/ARMJIT_Compiler.h
+++ b/src/ARMJIT_x64/ARMJIT_Compiler.h
@@ -29,6 +29,8 @@ public:
void LoadReg(int reg, Gen::X64Reg nativeReg);
void SaveReg(int reg, Gen::X64Reg nativeReg);
+ bool CanCompile(bool thumb, u16 kind);
+
typedef void (Compiler::*CompileFunc)();
void Comp_JumpTo(Gen::X64Reg addr, bool restoreCPSR = false);
@@ -64,7 +66,6 @@ public:
void A_Comp_BranchImm();
void A_Comp_BranchXchangeReg();
-
void T_Comp_ShiftImm();
void T_Comp_AddSub_();
void T_Comp_ALU_Imm8();
@@ -121,6 +122,9 @@ public:
void LoadCPSR();
void SaveCPSR();
+ bool FlagsNZRequired()
+ { return CurInstr.SetFlags & 0xC; }
+
Gen::FixupBranch CheckCondition(u32 cond);
Gen::OpArg MapReg(int reg)