aboutsummaryrefslogtreecommitdiff
path: root/src/ARMJIT_x64/ARMJIT_ALU.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ARMJIT_x64/ARMJIT_ALU.cpp')
-rw-r--r--src/ARMJIT_x64/ARMJIT_ALU.cpp322
1 files changed, 181 insertions, 141 deletions
diff --git a/src/ARMJIT_x64/ARMJIT_ALU.cpp b/src/ARMJIT_x64/ARMJIT_ALU.cpp
index 6294e1d..c22751e 100644
--- a/src/ARMJIT_x64/ARMJIT_ALU.cpp
+++ b/src/ARMJIT_x64/ARMJIT_ALU.cpp
@@ -71,30 +71,30 @@ void Compiler::Comp_CmpOp(int op, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed)
{
switch (op)
{
- case 0: // TST
- if (rn.IsImm())
- {
- MOV(32, R(RSCRATCH3), rn);
- rn = R(RSCRATCH3);
- }
- TEST(32, rn, op2);
- break;
- case 1: // TEQ
+ case 0: // TST
+ if (rn.IsImm())
+ {
MOV(32, R(RSCRATCH3), rn);
- XOR(32, R(RSCRATCH3), op2);
- break;
- case 2: // CMP
- if (rn.IsImm())
- {
- MOV(32, R(RSCRATCH3), rn);
- rn = R(RSCRATCH3);
- }
- CMP(32, rn, op2);
- break;
- case 3: // CMN
+ rn = R(RSCRATCH3);
+ }
+ TEST(32, rn, op2);
+ break;
+ case 1: // TEQ
+ MOV(32, R(RSCRATCH3), rn);
+ XOR(32, R(RSCRATCH3), op2);
+ break;
+ case 2: // CMP
+ if (rn.IsImm())
+ {
MOV(32, R(RSCRATCH3), rn);
- ADD(32, R(RSCRATCH3), op2);
- break;
+ rn = R(RSCRATCH3);
+ }
+ CMP(32, rn, op2);
+ break;
+ case 3: // CMN
+ MOV(32, R(RSCRATCH3), rn);
+ ADD(32, R(RSCRATCH3), op2);
+ break;
}
Comp_RetriveFlags(op == 2, op >= 2, carryUsed);
@@ -103,38 +103,38 @@ void Compiler::Comp_CmpOp(int op, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed)
// also calculates cycles
OpArg Compiler::A_Comp_GetALUOp2(bool S, bool& carryUsed)
{
- if (CurrentInstr.Instr & (1 << 25))
+ if (CurInstr.Instr & (1 << 25))
{
Comp_AddCycles_C();
carryUsed = false;
- return Imm32(ROR(CurrentInstr.Instr & 0xFF, (CurrentInstr.Instr >> 7) & 0x1E));
+ return Imm32(ROR(CurInstr.Instr & 0xFF, (CurInstr.Instr >> 7) & 0x1E));
}
else
{
- int op = (CurrentInstr.Instr >> 5) & 0x3;
- if (CurrentInstr.Instr & (1 << 4))
+ int op = (CurInstr.Instr >> 5) & 0x3;
+ if (CurInstr.Instr & (1 << 4))
{
Comp_AddCycles_CI(1);
- OpArg rm = MapReg(CurrentInstr.A_Reg(0));
- if (rm.IsImm() && CurrentInstr.A_Reg(0) == 15)
+ OpArg rm = MapReg(CurInstr.A_Reg(0));
+ if (rm.IsImm() && CurInstr.A_Reg(0) == 15)
rm = Imm32(rm.Imm32() + 4);
- return Comp_RegShiftReg(op, MapReg(CurrentInstr.A_Reg(8)), rm, S, carryUsed);
+ return Comp_RegShiftReg(op, MapReg(CurInstr.A_Reg(8)), rm, S, carryUsed);
}
else
{
Comp_AddCycles_C();
- return Comp_RegShiftImm(op, (CurrentInstr.Instr >> 7) & 0x1F,
- MapReg(CurrentInstr.A_Reg(0)), S, carryUsed);
+ return Comp_RegShiftImm(op, (CurInstr.Instr >> 7) & 0x1F,
+ MapReg(CurInstr.A_Reg(0)), S, carryUsed);
}
}
}
void Compiler::A_Comp_CmpOp()
{
- u32 op = (CurrentInstr.Instr >> 21) & 0xF;
+ u32 op = (CurInstr.Instr >> 21) & 0xF;
bool carryUsed;
- OpArg rn = MapReg(CurrentInstr.A_Reg(16));
+ OpArg rn = MapReg(CurInstr.A_Reg(16));
OpArg op2 = A_Comp_GetALUOp2((1 << op) & 0xF303, carryUsed);
Comp_CmpOp(op - 0x8, rn, op2, carryUsed);
@@ -142,12 +142,12 @@ void Compiler::A_Comp_CmpOp()
void Compiler::A_Comp_Arith()
{
- bool S = CurrentInstr.Instr & (1 << 20);
- u32 op = (CurrentInstr.Instr >> 21) & 0xF;
+ bool S = CurInstr.Instr & (1 << 20);
+ u32 op = (CurInstr.Instr >> 21) & 0xF;
bool carryUsed;
- OpArg rn = MapReg(CurrentInstr.A_Reg(16));
- OpArg rd = MapReg(CurrentInstr.A_Reg(12));
+ OpArg rn = MapReg(CurInstr.A_Reg(16));
+ OpArg rd = MapReg(CurInstr.A_Reg(12));
OpArg op2 = A_Comp_GetALUOp2(S && (1 << op) & 0xF303, carryUsed);
u32 sFlag = S ? opSetsFlags : 0;
@@ -155,13 +155,13 @@ void Compiler::A_Comp_Arith()
{
case 0x0: // AND
Comp_ArithTriOp(AND, rd, rn, op2, carryUsed, opSymmetric|sFlag);
- return;
+ break;
case 0x1: // EOR
Comp_ArithTriOp(XOR, rd, rn, op2, carryUsed, opSymmetric|sFlag);
- return;
+ break;
case 0x2: // SUB
Comp_ArithTriOp(SUB, rd, rn, op2, carryUsed, sFlag|opRetriveCV|opInvertCarry);
- return;
+ break;
case 0x3: // RSB
if (op2.IsZero())
{
@@ -173,41 +173,44 @@ void Compiler::A_Comp_Arith()
}
else
Comp_ArithTriOpReverse(SUB, rd, rn, op2, carryUsed, sFlag|opRetriveCV|opInvertCarry);
- return;
+ break;
case 0x4: // ADD
Comp_ArithTriOp(ADD, rd, rn, op2, carryUsed, opSymmetric|sFlag|opRetriveCV);
- return;
+ break;
case 0x5: // ADC
Comp_ArithTriOp(ADC, rd, rn, op2, carryUsed, opSymmetric|sFlag|opRetriveCV|opSyncCarry);
- return;
+ break;
case 0x6: // SBC
Comp_ArithTriOp(SBB, rd, rn, op2, carryUsed, opSymmetric|sFlag|opRetriveCV|opSyncCarry|opInvertCarry);
- return;
+ break;
case 0x7: // RSC
Comp_ArithTriOpReverse(SBB, rd, rn, op2, carryUsed, sFlag|opRetriveCV|opInvertCarry|opSyncCarry);
- return;
+ break;
case 0xC: // ORR
Comp_ArithTriOp(OR, rd, rn, op2, carryUsed, opSymmetric|sFlag);
- return;
+ break;
case 0xE: // BIC
Comp_ArithTriOp(AND, rd, rn, op2, carryUsed, sFlag|opSymmetric|opInvertOp2);
- return;
+ break;
default:
assert("unimplemented");
}
+
+ if (CurInstr.A_Reg(12) == 15)
+ Comp_JumpTo(rd.GetSimpleReg(), S);
}
void Compiler::A_Comp_MovOp()
{
bool carryUsed;
- bool S = CurrentInstr.Instr & (1 << 20);
+ bool S = CurInstr.Instr & (1 << 20);
OpArg op2 = A_Comp_GetALUOp2(S, carryUsed);
- OpArg rd = MapReg(CurrentInstr.A_Reg(12));
+ OpArg rd = MapReg(CurInstr.A_Reg(12));
if (rd != op2)
MOV(32, rd, op2);
- if (((CurrentInstr.Instr >> 21) & 0xF) == 0xF)
+ if (((CurInstr.Instr >> 21) & 0xF) == 0xF)
NOT(32, rd);
if (S)
@@ -215,6 +218,9 @@ void Compiler::A_Comp_MovOp()
TEST(32, rd, rd);
Comp_RetriveFlags(false, false, carryUsed);
}
+
+ if (CurInstr.A_Reg(12) == 15)
+ Comp_JumpTo(rd.GetSimpleReg(), S);
}
void Compiler::Comp_RetriveFlags(bool sign, bool retriveCV, bool carryUsed)
@@ -230,7 +236,7 @@ void Compiler::Comp_RetriveFlags(bool sign, bool retriveCV, bool carryUsed)
}
if (carryUsed == 983298)
- printf("etwas ist faul im lande daenemark %x\n", CurrentInstr.Instr);
+ printf("etwas ist faul im lande daenemark %x\n", CurInstr.Instr);
SETcc(CC_S, R(RSCRATCH));
SETcc(CC_Z, R(RSCRATCH3));
@@ -324,61 +330,61 @@ OpArg Compiler::Comp_RegShiftImm(int op, int amount, OpArg rm, bool S, bool& car
switch (op)
{
- case 0: // LSL
- if (amount > 0)
- {
- MOV(32, R(RSCRATCH), rm);
- SHL(32, R(RSCRATCH), Imm8(amount));
- if (S)
- SETcc(CC_C, R(RSCRATCH2));
-
- return R(RSCRATCH);
- }
- else
- {
- carryUsed = false;
- return rm;
- }
- case 1: // LSR
- if (amount > 0)
- {
- MOV(32, R(RSCRATCH), rm);
- SHR(32, R(RSCRATCH), Imm8(amount));
- if (S)
- SETcc(CC_C, R(RSCRATCH2));
- return R(RSCRATCH);
- }
- else
- {
- if (S)
- {
- MOV(32, R(RSCRATCH2), rm);
- SHR(32, R(RSCRATCH2), Imm8(31));
- }
- return Imm32(0);
- }
- case 2: // ASR
+ case 0: // LSL
+ if (amount > 0)
+ {
MOV(32, R(RSCRATCH), rm);
- SAR(32, R(RSCRATCH), Imm8(amount ? amount : 31));
+ SHL(32, R(RSCRATCH), Imm8(amount));
if (S)
- {
- if (amount == 0)
- BT(32, rm, Imm8(31));
SETcc(CC_C, R(RSCRATCH2));
- }
+
return R(RSCRATCH);
- case 3: // ROR
+ }
+ else
+ {
+ carryUsed = false;
+ return rm;
+ }
+ case 1: // LSR
+ if (amount > 0)
+ {
MOV(32, R(RSCRATCH), rm);
- if (amount > 0)
- ROR_(32, R(RSCRATCH), Imm8(amount));
- else
- {
- BT(32, R(RCPSR), Imm8(29));
- RCR(32, R(RSCRATCH), Imm8(1));
- }
+ SHR(32, R(RSCRATCH), Imm8(amount));
if (S)
SETcc(CC_C, R(RSCRATCH2));
return R(RSCRATCH);
+ }
+ else
+ {
+ if (S)
+ {
+ MOV(32, R(RSCRATCH2), rm);
+ SHR(32, R(RSCRATCH2), Imm8(31));
+ }
+ return Imm32(0);
+ }
+ case 2: // ASR
+ MOV(32, R(RSCRATCH), rm);
+ SAR(32, R(RSCRATCH), Imm8(amount ? amount : 31));
+ if (S)
+ {
+ if (amount == 0)
+ BT(32, rm, Imm8(31));
+ SETcc(CC_C, R(RSCRATCH2));
+ }
+ return R(RSCRATCH);
+ case 3: // ROR
+ MOV(32, R(RSCRATCH), rm);
+ if (amount > 0)
+ ROR_(32, R(RSCRATCH), Imm8(amount));
+ else
+ {
+ BT(32, R(RCPSR), Imm8(29));
+ RCR(32, R(RSCRATCH), Imm8(1));
+ }
+ if (S)
+ SETcc(CC_C, R(RSCRATCH2));
+ return R(RSCRATCH);
}
assert(false);
@@ -386,11 +392,11 @@ OpArg Compiler::Comp_RegShiftImm(int op, int amount, OpArg rm, bool S, bool& car
void Compiler::T_Comp_ShiftImm()
{
- OpArg rd = MapReg(CurrentInstr.T_Reg(0));
- OpArg rs = MapReg(CurrentInstr.T_Reg(3));
+ OpArg rd = MapReg(CurInstr.T_Reg(0));
+ OpArg rs = MapReg(CurInstr.T_Reg(3));
- int op = (CurrentInstr.Instr >> 11) & 0x3;
- int amount = (CurrentInstr.Instr >> 6) & 0x1F;
+ int op = (CurInstr.Instr >> 11) & 0x3;
+ int amount = (CurInstr.Instr >> 6) & 0x1F;
Comp_AddCycles_C();
@@ -406,12 +412,12 @@ void Compiler::T_Comp_ShiftImm()
void Compiler::T_Comp_AddSub_()
{
- OpArg rd = MapReg(CurrentInstr.T_Reg(0));
- OpArg rs = MapReg(CurrentInstr.T_Reg(3));
+ OpArg rd = MapReg(CurInstr.T_Reg(0));
+ OpArg rs = MapReg(CurInstr.T_Reg(3));
- int op = (CurrentInstr.Instr >> 9) & 0x3;
+ int op = (CurInstr.Instr >> 9) & 0x3;
- OpArg rn = op >= 2 ? Imm32((CurrentInstr.Instr >> 6) & 0x7) : MapReg(CurrentInstr.T_Reg(6));
+ OpArg rn = op >= 2 ? Imm32((CurInstr.Instr >> 6) & 0x7) : MapReg(CurInstr.T_Reg(6));
Comp_AddCycles_C();
@@ -423,38 +429,38 @@ void Compiler::T_Comp_AddSub_()
void Compiler::T_Comp_ALU_Imm8()
{
- OpArg rd = MapReg(CurrentInstr.T_Reg(8));
+ OpArg rd = MapReg(CurInstr.T_Reg(8));
- u32 op = (CurrentInstr.Instr >> 11) & 0x3;
- OpArg imm = Imm32(CurrentInstr.Instr & 0xFF);
+ u32 op = (CurInstr.Instr >> 11) & 0x3;
+ OpArg imm = Imm32(CurInstr.Instr & 0xFF);
Comp_AddCycles_C();
switch (op)
{
- case 0x0:
- MOV(32, rd, imm);
- TEST(32, rd, rd);
- Comp_RetriveFlags(false, false, false);
- return;
- case 0x1:
- Comp_CmpOp(2, rd, imm, false);
- return;
- case 0x2:
- Comp_ArithTriOp(ADD, rd, rd, imm, false, opSetsFlags|opSymmetric|opRetriveCV);
- return;
- case 0x3:
- Comp_ArithTriOp(SUB, rd, rd, imm, false, opSetsFlags|opInvertCarry|opRetriveCV);
- return;
+ case 0x0:
+ MOV(32, rd, imm);
+ TEST(32, rd, rd);
+ Comp_RetriveFlags(false, false, false);
+ return;
+ case 0x1:
+ Comp_CmpOp(2, rd, imm, false);
+ return;
+ case 0x2:
+ Comp_ArithTriOp(ADD, rd, rd, imm, false, opSetsFlags|opSymmetric|opRetriveCV);
+ return;
+ case 0x3:
+ Comp_ArithTriOp(SUB, rd, rd, imm, false, opSetsFlags|opInvertCarry|opRetriveCV);
+ return;
}
}
void Compiler::T_Comp_ALU()
{
- OpArg rd = MapReg(CurrentInstr.T_Reg(0));
- OpArg rs = MapReg(CurrentInstr.T_Reg(3));
+ OpArg rd = MapReg(CurInstr.T_Reg(0));
+ OpArg rs = MapReg(CurInstr.T_Reg(3));
- u32 op = (CurrentInstr.Instr >> 6) & 0xF;
+ u32 op = (CurInstr.Instr >> 6) & 0xF;
if ((op >= 0x2 && op < 0x4) || op == 0x7)
Comp_AddCycles_CI(1);
@@ -522,28 +528,62 @@ void Compiler::T_Comp_ALU()
void Compiler::T_Comp_ALU_HiReg()
{
- OpArg rd = MapReg(((CurrentInstr.Instr & 0x7) | ((CurrentInstr.Instr >> 4) & 0x8)));
- OpArg rs = MapReg((CurrentInstr.Instr >> 3) & 0xF);
+ u32 rd = ((CurInstr.Instr & 0x7) | ((CurInstr.Instr >> 4) & 0x8));
+ OpArg rdMapped = MapReg(rd);
+ OpArg rs = MapReg((CurInstr.Instr >> 3) & 0xF);
- u32 op = (CurrentInstr.Instr >> 8) & 0x3;
+ u32 op = (CurInstr.Instr >> 8) & 0x3;
Comp_AddCycles_C();
switch (op)
{
- case 0x0: // ADD
- Comp_ArithTriOp(ADD, rd, rd, rs, false, opSymmetric|opRetriveCV);
- return;
- case 0x1: // CMP
- Comp_CmpOp(2, rd, rs, false);
- return;
- case 0x2: // MOV
- if (rd != rs)
- MOV(32, rd, rs);
- TEST(32, rd, rd);
- Comp_RetriveFlags(false, false, false);
- return;
+ case 0x0: // ADD
+ Comp_ArithTriOp(ADD, rdMapped, rdMapped, rs, false, opSymmetric|opRetriveCV);
+ break;
+ case 0x1: // CMP
+ Comp_CmpOp(2, rdMapped, rs, false);
+ return; // this is on purpose
+ case 0x2: // MOV
+ if (rdMapped != rs)
+ MOV(32, rdMapped, rs);
+ TEST(32, rdMapped, rdMapped);
+ Comp_RetriveFlags(false, false, false);
+ break;
+ }
+
+ if (rd == 15)
+ {
+ OR(32, rdMapped, Imm8(1));
+ Comp_JumpTo(rdMapped.GetSimpleReg());
}
}
+void Compiler::T_Comp_AddSP()
+{
+ Comp_AddCycles_C();
+
+ OpArg sp = MapReg(13);
+ OpArg offset = Imm32((CurInstr.Instr & 0x7F) << 2);
+ if (CurInstr.Instr & (1 << 7))
+ SUB(32, sp, offset);
+ else
+ ADD(32, sp, offset);
+}
+
+void Compiler::T_Comp_RelAddr()
+{
+ Comp_AddCycles_C();
+
+ OpArg rd = MapReg(CurInstr.T_Reg(8));
+ u32 offset = (CurInstr.Instr & 0xFF) << 2;
+ if (CurInstr.Instr & (1 << 11))
+ {
+ OpArg sp = MapReg(13);
+ LEA(32, rd.GetSimpleReg(), MDisp(sp.GetSimpleReg(), offset));
+ }
+ else
+ MOV(32, rd, Imm32((R15 & ~2) + offset));
+}
+
} \ No newline at end of file