mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 07:20:15 +00:00
JitX64: Data Processing: Implement shift-by-register (_rsr) instructions
This commit is contained in:
parent
fc1f126ec5
commit
ec7c34ec92
@ -148,13 +148,13 @@ static const std::array<Instruction, 27> thumb_instruction_table = { {
|
||||
v->EOR_reg(0xE, /*S=*/true, Rd_Rn, Rd_Rn, 0, 0, Rm_Rs);
|
||||
break;
|
||||
case 2: // LSL Rd, Rs
|
||||
v->MOV_rsr(0xE, /*S=*/true, Rd_Rn, Rm_Rs, 0b0001, Rd_Rn);
|
||||
v->MOV_rsr(0xE, /*S=*/true, Rd_Rn, Rm_Rs, 0b00, Rd_Rn);
|
||||
break;
|
||||
case 3: // LSR Rd, Rs
|
||||
v->MOV_rsr(0xE, /*S=*/true, Rd_Rn, Rm_Rs, 0b0011, Rd_Rn);
|
||||
v->MOV_rsr(0xE, /*S=*/true, Rd_Rn, Rm_Rs, 0b01, Rd_Rn);
|
||||
break;
|
||||
case 4: // ASR Rd, Rs
|
||||
v->MOV_rsr(0xE, /*S=*/true, Rd_Rn, Rm_Rs, 0b0101, Rd_Rn);
|
||||
v->MOV_rsr(0xE, /*S=*/true, Rd_Rn, Rm_Rs, 0b10, Rd_Rn);
|
||||
break;
|
||||
case 5: // ADC Rd, Rm
|
||||
v->ADC_reg(0xE, /*S=*/true, Rd_Rn, Rd_Rn, 0, 0, Rm_Rs);
|
||||
@ -163,7 +163,7 @@ static const std::array<Instruction, 27> thumb_instruction_table = { {
|
||||
v->SBC_reg(0xE, /*S=*/true, Rd_Rn, Rd_Rn, 0, 0, Rm_Rs);
|
||||
break;
|
||||
case 7: // ROR Rd, Rs
|
||||
v->MOV_rsr(0xE, /*S=*/true, Rd_Rn, Rm_Rs, 0b0111, Rd_Rn);
|
||||
v->MOV_rsr(0xE, /*S=*/true, Rd_Rn, Rm_Rs, 0b11, Rd_Rn);
|
||||
break;
|
||||
case 8: // TST Rm, Rn
|
||||
v->TST_reg(0xE, Rd_Rn, 0, 0, Rm_Rs);
|
||||
|
@ -62,7 +62,9 @@ void JitX64::CompileDataProcessingHelper_Reverse(ArmReg Rn_index, ArmReg Rd_inde
|
||||
}
|
||||
|
||||
X64Reg JitX64::CompileDataProcessingHelper_reg(ArmImm5 imm5, ShiftType shift, ArmReg Rm_index, bool do_shifter_carry_out) {
|
||||
// We directly put shifter_carry_out into MJitStateCFlag()
|
||||
// Caller must call reg_alloc.UnlockTemp on return value.
|
||||
// if do_shifter_carry_out,
|
||||
// we output code that calculates and puts shifter_carry_out into MJitStateCFlag().
|
||||
|
||||
X64Reg tmp = reg_alloc.AllocTemp();
|
||||
|
||||
@ -119,12 +121,14 @@ X64Reg JitX64::CompileDataProcessingHelper_reg(ArmImm5 imm5, ShiftType shift, Ar
|
||||
if (imm5 == 0) { //RRX
|
||||
code->BT(8, MJitStateCFlag(), Imm8(0));
|
||||
code->RCR(32, R(tmp), Imm8(1));
|
||||
if (do_shifter_carry_out)
|
||||
if (do_shifter_carry_out) {
|
||||
code->SETcc(CC_C, MJitStateCFlag());
|
||||
}
|
||||
} else {
|
||||
code->ROR(32, R(tmp), Imm8(imm5));
|
||||
if (do_shifter_carry_out)
|
||||
if (do_shifter_carry_out) {
|
||||
code->SETcc(CC_C, MJitStateCFlag());
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
@ -132,6 +136,176 @@ X64Reg JitX64::CompileDataProcessingHelper_reg(ArmImm5 imm5, ShiftType shift, Ar
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
X64Reg JitX64::CompileDataProcessingHelper_rsr(ArmReg Rs_index, ShiftType shift, ArmReg Rm_index, bool do_shifter_carry_out) {
|
||||
// Caller must call reg_alloc.UnlockTemp on return value.
|
||||
// if do_shifter_carry_out,
|
||||
// we output code that calculates and puts shifter_carry_out into MJitStateCFlag().
|
||||
|
||||
reg_alloc.FlushX64(RCX);
|
||||
reg_alloc.LockX64(RCX);
|
||||
|
||||
X64Reg tmp = reg_alloc.AllocTemp();
|
||||
|
||||
if (Rs_index != 15) {
|
||||
OpArg Rs = reg_alloc.LockArmForRead(Rs_index);
|
||||
code->MOV(32, R(RCX), Rs);
|
||||
code->AND(32, R(RCX), Imm32(0xFF));
|
||||
reg_alloc.UnlockArm(Rs_index);
|
||||
} else {
|
||||
code->MOV(32, R(RCX), Imm32(GetReg15Value() & 0xFF));
|
||||
}
|
||||
|
||||
if (Rm_index != 15) {
|
||||
OpArg Rm = reg_alloc.LockArmForRead(Rm_index);
|
||||
code->MOV(32, R(tmp), Rm);
|
||||
reg_alloc.UnlockArm(Rm_index);
|
||||
} else {
|
||||
code->MOV(32, R(tmp), Imm32(GetReg15Value()));
|
||||
}
|
||||
|
||||
switch (shift) {
|
||||
case 0b00: { // Logical shift left by register
|
||||
if (!do_shifter_carry_out) {
|
||||
code->SHL(32, R(tmp), R(CL));
|
||||
|
||||
code->CMP(32, R(RCX), Imm8(32));
|
||||
X64Reg zero = reg_alloc.AllocTemp();
|
||||
code->MOV(32, R(zero), Imm32(0));
|
||||
code->CMOVcc(32, tmp, R(zero), CC_NB);
|
||||
reg_alloc.UnlockTemp(zero);
|
||||
} else {
|
||||
code->CMP(32, R(RCX), Imm8(32));
|
||||
auto Rs_gt32 = code->J_CC(CC_A);
|
||||
auto Rs_eq32 = code->J_CC(CC_E);
|
||||
// if (Rs & 0xFF == 0) goto end;
|
||||
code->TEST(32, R(RCX), R(RCX));
|
||||
auto Rs_zero = code->J_CC(CC_Z);
|
||||
// if (Rs & 0xFF < 32) {
|
||||
code->SHL(32, R(tmp), R(CL));
|
||||
code->SETcc(CC_C, MJitStateCFlag());
|
||||
auto jmp_to_end_1 = code->J();
|
||||
// } else if (Rs & 0xFF > 32) {
|
||||
code->SetJumpTarget(Rs_gt32);
|
||||
code->MOV(32, R(tmp), Imm32(0));
|
||||
code->MOV(8, MJitStateCFlag(), Imm8(0));
|
||||
auto jmp_to_end_2 = code->J();
|
||||
// } else if (Rs & 0xFF == 32) {
|
||||
code->SetJumpTarget(Rs_eq32);
|
||||
code->BT(32, R(tmp), Imm8(0));
|
||||
code->SETcc(CC_C, MJitStateCFlag());
|
||||
code->MOV(32, R(tmp), Imm32(0));
|
||||
// }
|
||||
code->SetJumpTarget(jmp_to_end_1);
|
||||
code->SetJumpTarget(jmp_to_end_1);
|
||||
code->SetJumpTarget(Rs_zero);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0b01: { // Logical shift right by register
|
||||
if (!do_shifter_carry_out) {
|
||||
code->SHR(32, R(tmp), R(RCX));
|
||||
|
||||
code->CMP(32, R(RCX), Imm8(32));
|
||||
X64Reg zero = reg_alloc.AllocTemp();
|
||||
code->MOV(32, R(zero), Imm32(0));
|
||||
code->CMOVcc(32, tmp, R(zero), CC_NB);
|
||||
reg_alloc.UnlockTemp(zero);
|
||||
} else {
|
||||
code->CMP(32, R(RCX), Imm8(32));
|
||||
auto Rs_gt32 = code->J_CC(CC_A);
|
||||
auto Rs_eq32 = code->J_CC(CC_E);
|
||||
// if (Rs & 0xFF == 0) goto end;
|
||||
code->TEST(32, R(RCX), R(RCX));
|
||||
auto Rs_zero = code->J_CC(CC_Z);
|
||||
// if (Rs & 0xFF < 32) {
|
||||
code->SHR(32, R(tmp), R(RCX));
|
||||
code->SETcc(CC_C, MJitStateCFlag());
|
||||
auto jmp_to_end_1 = code->J();
|
||||
// } else if (Rs & 0xFF > 32) {
|
||||
code->SetJumpTarget(Rs_gt32);
|
||||
code->MOV(32, R(tmp), Imm32(0));
|
||||
code->MOV(8, MJitStateCFlag(), Imm8(0));
|
||||
auto jmp_to_end_2 = code->J();
|
||||
// } else if (Rs & 0xFF == 32) {
|
||||
code->SetJumpTarget(Rs_eq32);
|
||||
code->BT(32, R(tmp), Imm8(31));
|
||||
code->SETcc(CC_C, MJitStateCFlag());
|
||||
code->MOV(32, R(tmp), Imm32(0));
|
||||
// }
|
||||
code->SetJumpTarget(jmp_to_end_1);
|
||||
code->SetJumpTarget(jmp_to_end_2);
|
||||
code->SetJumpTarget(Rs_zero);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0b10: { // Arithmetic shift right by register
|
||||
if (!do_shifter_carry_out) {
|
||||
code->CMP(32, R(RCX), Imm8(31));
|
||||
auto Rs_gt31 = code->J_CC(CC_A);
|
||||
// if (Rs & 0xFF <= 31) {
|
||||
code->SAR(32, R(tmp), R(CL));
|
||||
auto jmp_to_end = code->J();
|
||||
// } else {
|
||||
code->SetJumpTarget(Rs_gt31);
|
||||
code->SAR(32, R(tmp), Imm8(31)); // Verified.
|
||||
// }
|
||||
code->SetJumpTarget(jmp_to_end);
|
||||
} else {
|
||||
code->CMP(32, R(RCX), Imm8(31));
|
||||
auto Rs_gt31 = code->J_CC(CC_A);
|
||||
// if (Rs & 0xFF == 0) goto end;
|
||||
code->TEST(32, R(RCX), R(RCX));
|
||||
auto Rs_zero = code->J_CC(CC_Z);
|
||||
// if (Rs & 0xFF <= 31) {
|
||||
code->SAR(32, R(tmp), R(CL));
|
||||
code->SETcc(CC_C, MJitStateCFlag());
|
||||
auto jmp_to_end = code->J();
|
||||
// } else if (Rs & 0xFF > 31) {
|
||||
code->SetJumpTarget(Rs_gt31);
|
||||
code->SAR(32, R(tmp), Imm8(31)); // Verified.
|
||||
code->BT(32, R(tmp), Imm8(31));
|
||||
code->SETcc(CC_C, MJitStateCFlag());
|
||||
// }
|
||||
code->SetJumpTarget(jmp_to_end);
|
||||
code->SetJumpTarget(Rs_zero);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0b11: { // Rotate right by register
|
||||
if (!do_shifter_carry_out) {
|
||||
code->AND(32, R(RCX), Imm32(0x1F));
|
||||
code->ROR(32, R(tmp), R(CL));
|
||||
} else {
|
||||
// if (Rs & 0xFF == 0) goto end;
|
||||
code->TEST(32, R(RCX), R(RCX));
|
||||
auto Rs_zero = code->J_CC(CC_Z);
|
||||
|
||||
code->AND(32, R(RCX), Imm32(0x1F));
|
||||
auto zero_1F = code->J_CC(CC_Z);
|
||||
// if (Rs & 0x1F != 0) {
|
||||
code->ROR(32, R(tmp), R(CL));
|
||||
code->SETcc(CC_C, MJitStateCFlag());
|
||||
auto jmp_to_end = code->J();
|
||||
// } else {
|
||||
code->SetJumpTarget(zero_1F);
|
||||
code->BT(32, R(tmp), Imm8(31));
|
||||
code->SETcc(CC_C, MJitStateCFlag());
|
||||
// }
|
||||
code->SetJumpTarget(jmp_to_end);
|
||||
code->SetJumpTarget(Rs_zero);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
} // switch (shift)
|
||||
|
||||
reg_alloc.UnlockX64(RCX);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void JitX64::ADC_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -174,6 +348,28 @@ void JitX64::ADC_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::ADC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, false);
|
||||
|
||||
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||
code->BT(32, MJitStateCFlag(), Imm8(0));
|
||||
code->ADC(32, R(Rd), R(tmp));
|
||||
});
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZVCN();
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::ADD_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -214,6 +410,27 @@ void JitX64::ADD_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::ADD_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, false);
|
||||
|
||||
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||
code->ADD(32, R(Rd), R(tmp));
|
||||
});
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZVCN();
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::AND_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -249,6 +466,29 @@ void JitX64::AND_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZN();
|
||||
// C updated by CompileDataProcessingHelper_reg
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::AND_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, S);
|
||||
|
||||
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||
code->AND(32, R(Rd), R(tmp));
|
||||
});
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZN();
|
||||
// C updated by CompileDataProcessingHelper_reg
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
@ -302,6 +542,29 @@ void JitX64::BIC_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::BIC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, S);
|
||||
|
||||
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||
// TODO: Use ANDN instead.
|
||||
code->NOT(32, R(tmp));
|
||||
code->AND(32, R(Rd), R(tmp));
|
||||
});
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZN();
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::CMN_imm(Cond cond, ArmReg Rn_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -345,6 +608,26 @@ void JitX64::CMN_reg(Cond cond, ArmReg Rn_index, ArmImm5 imm5, ShiftType shift,
|
||||
current.arm_pc += GetInstSize();
|
||||
}
|
||||
|
||||
void JitX64::CMN_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, false);
|
||||
|
||||
if (Rn_index != 15) {
|
||||
OpArg Rn = reg_alloc.LockArmForRead(Rn_index);
|
||||
code->ADD(32, R(tmp), Rn);
|
||||
reg_alloc.UnlockArm(Rn_index);
|
||||
} else {
|
||||
code->ADD(32, R(tmp), Imm32(GetReg15Value()));
|
||||
}
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
UpdateFlagsZVCN();
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
}
|
||||
|
||||
void JitX64::CMP_imm(Cond cond, ArmReg Rn_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -393,6 +676,31 @@ void JitX64::CMP_reg(Cond cond, ArmReg Rn_index, ArmImm5 imm5, ShiftType shift,
|
||||
current.arm_pc += GetInstSize();
|
||||
}
|
||||
|
||||
void JitX64::CMP_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, false);
|
||||
|
||||
if (Rn_index != 15) {
|
||||
OpArg Rn = reg_alloc.LockArmForRead(Rn_index);
|
||||
code->CMP(32, Rn, R(tmp));
|
||||
reg_alloc.UnlockArm(Rn_index);
|
||||
} else {
|
||||
// TODO: Optimize this
|
||||
X64Reg tmp2 = reg_alloc.AllocTemp();
|
||||
code->MOV(32, R(tmp2), Imm32(GetReg15Value()));
|
||||
code->CMP(32, R(tmp2), R(tmp));
|
||||
reg_alloc.UnlockTemp(tmp2);
|
||||
}
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
UpdateFlagsC_complement();
|
||||
UpdateFlagsZVN();
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
}
|
||||
|
||||
void JitX64::EOR_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -436,6 +744,27 @@ void JitX64::EOR_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::EOR_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, S);
|
||||
|
||||
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||
code->XOR(32, R(Rd), R(tmp));
|
||||
});
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZN();
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::MOV_imm(Cond cond, bool S, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -483,6 +812,28 @@ void JitX64::MOV_reg(Cond cond, bool S, ArmReg Rd_index, ArmImm5 imm5, ShiftType
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::MOV_rsr(Cond cond, bool S, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, S);
|
||||
|
||||
Gen::OpArg Rd = reg_alloc.LockArmForWrite(Rd_index);
|
||||
code->MOV(32, Rd, R(tmp));
|
||||
reg_alloc.UnlockArm(Rd_index);
|
||||
|
||||
if (S) {
|
||||
code->CMP(32, R(tmp), Imm32(0));
|
||||
UpdateFlagsZN();
|
||||
}
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::MVN_imm(Cond cond, bool S, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -531,6 +882,29 @@ void JitX64::MVN_reg(Cond cond, bool S, ArmReg Rd_index, ArmImm5 imm5, ShiftType
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::MVN_rsr(Cond cond, bool S, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, S);
|
||||
code->NOT(32, R(tmp));
|
||||
|
||||
Gen::OpArg Rd = reg_alloc.LockArmForWrite(Rd_index);
|
||||
code->MOV(32, Rd, R(tmp));
|
||||
reg_alloc.UnlockArm(Rd_index);
|
||||
|
||||
if (S) {
|
||||
code->CMP(32, R(tmp), Imm32(0));
|
||||
UpdateFlagsZN();
|
||||
}
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::ORR_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -574,6 +948,27 @@ void JitX64::ORR_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::ORR_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, S);
|
||||
|
||||
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||
code->OR(32, R(Rd), R(tmp));
|
||||
});
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZN();
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::RSB_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -632,6 +1027,36 @@ void JitX64::RSB_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::RSB_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, false);
|
||||
|
||||
CompileDataProcessingHelper_Reverse(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||
code->MOV(32, R(Rd), R(tmp));
|
||||
|
||||
if (Rn_index == 15) {
|
||||
code->SUB(32, R(Rd), Imm32(GetReg15Value()));
|
||||
} else {
|
||||
Gen::OpArg Rn = reg_alloc.LockArmForRead(Rn_index);
|
||||
code->SUB(32, R(Rd), Rn);
|
||||
reg_alloc.UnlockArm(Rn_index);
|
||||
}
|
||||
});
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZVN();
|
||||
UpdateFlagsC_complement();
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::RSC_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -696,6 +1121,39 @@ void JitX64::RSC_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::RSC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, false);
|
||||
|
||||
CompileDataProcessingHelper_Reverse(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||
code->MOV(32, R(Rd), R(tmp));
|
||||
|
||||
code->BT(32, MJitStateCFlag(), Imm8(0));
|
||||
code->CMC();
|
||||
|
||||
if (Rn_index == 15) {
|
||||
code->SBB(32, R(Rd), Imm32(GetReg15Value()));
|
||||
} else {
|
||||
Gen::OpArg Rn = reg_alloc.LockArmForRead(Rn_index);
|
||||
code->SBB(32, R(Rd), Rn);
|
||||
reg_alloc.UnlockArm(Rn_index);
|
||||
}
|
||||
});
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZVN();
|
||||
UpdateFlagsC_complement();
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::SBC_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -742,6 +1200,30 @@ void JitX64::SBC_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::SBC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, false);
|
||||
|
||||
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||
code->BT(32, MJitStateCFlag(), Imm8(0));
|
||||
code->CMC();
|
||||
code->SBB(32, R(Rd), R(tmp));
|
||||
});
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZVN();
|
||||
UpdateFlagsC_complement();
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::SUB_imm(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -784,6 +1266,29 @@ void JitX64::SUB_reg(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmImm
|
||||
}
|
||||
}
|
||||
|
||||
void JitX64::SUB_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, false);
|
||||
|
||||
CompileDataProcessingHelper(Rn_index, Rd_index, [&](X64Reg Rd) {
|
||||
code->SUB(32, R(Rd), R(tmp));
|
||||
});
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
if (S) {
|
||||
UpdateFlagsZVN();
|
||||
UpdateFlagsC_complement();
|
||||
}
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
if (Rd_index == 15) {
|
||||
CompileReturnToDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JitX64::TEQ_imm(Cond cond, ArmReg Rn_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -831,6 +1336,26 @@ void JitX64::TEQ_reg(Cond cond, ArmReg Rn_index, ArmImm5 imm5, ShiftType shift,
|
||||
current.arm_pc += GetInstSize();
|
||||
}
|
||||
|
||||
void JitX64::TEQ_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, true);
|
||||
|
||||
if (Rn_index == 15) {
|
||||
code->XOR(32, R(tmp), Imm32(GetReg15Value()));
|
||||
} else {
|
||||
Gen::OpArg Rn = reg_alloc.LockArmForRead(Rn_index);
|
||||
code->XOR(32, R(tmp), Rn);
|
||||
reg_alloc.UnlockArm(Rn_index);
|
||||
}
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
UpdateFlagsZN();
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
}
|
||||
|
||||
void JitX64::TST_imm(Cond cond, ArmReg Rn_index, int rotate, ArmImm8 imm8) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
@ -881,21 +1406,24 @@ void JitX64::TST_reg(Cond cond, ArmReg Rn_index, ArmImm5 imm5, ShiftType shift,
|
||||
current.arm_pc += GetInstSize();
|
||||
}
|
||||
|
||||
void JitX64::ADC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::ADD_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::AND_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::BIC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::CMN_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::CMP_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::EOR_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::MOV_rsr(Cond cond, bool S, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::MVN_rsr(Cond cond, bool S, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::ORR_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::RSB_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::RSC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::SBC_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::SUB_rsr(Cond cond, bool S, ArmReg Rn_index, ArmReg Rd_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::TEQ_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::TST_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) { CompileInterpretInstruction(); }
|
||||
void JitX64::TST_rsr(Cond cond, ArmReg Rn_index, ArmReg Rs_index, ShiftType shift, ArmReg Rm_index) {
|
||||
cond_manager.CompileCond((ConditionCode)cond);
|
||||
|
||||
Gen::X64Reg tmp = CompileDataProcessingHelper_rsr(Rs_index, shift, Rm_index, true);
|
||||
|
||||
if (Rn_index == 15) {
|
||||
code->TEST(32, R(tmp), Imm32(GetReg15Value()));
|
||||
} else {
|
||||
OpArg Rn = reg_alloc.LockArmForRead(Rn_index);
|
||||
code->TEST(32, R(tmp), Rn);
|
||||
reg_alloc.UnlockArm(Rn_index);
|
||||
}
|
||||
|
||||
reg_alloc.UnlockTemp(tmp);
|
||||
|
||||
UpdateFlagsZN();
|
||||
|
||||
current.arm_pc += GetInstSize();
|
||||
}
|
||||
|
||||
} // namespace JitX64
|
||||
|
@ -161,7 +161,7 @@ private:
|
||||
void CompileDataProcessingHelper(ArmReg Rn_index, ArmReg Rd_index, std::function<void(Gen::X64Reg)> body);
|
||||
void CompileDataProcessingHelper_Reverse(ArmReg Rn_index, ArmReg Rd_index, std::function<void(Gen::X64Reg)> body);
|
||||
Gen::X64Reg CompileDataProcessingHelper_reg(ArmImm5 imm5, ShiftType shift, ArmReg Rm, bool do_shifter_carry_out);
|
||||
Gen::X64Reg CompileDataProcessingHelper_rsr(ArmReg Rs, ShiftType shift, ArmReg Rm);
|
||||
Gen::X64Reg CompileDataProcessingHelper_rsr(ArmReg Rs, ShiftType shift, ArmReg Rm, bool do_shifter_carry_out);
|
||||
void ADC_imm(Cond cond, bool S, ArmReg Rn, ArmReg Rd, int rotate, ArmImm8 imm8) override;
|
||||
void ADC_reg(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmImm5 imm5, ShiftType shift, ArmReg Rm) override;
|
||||
void ADC_rsr(Cond cond, bool S, ArmReg Rn, ArmReg Rd, ArmReg Rs, ShiftType shift, ArmReg Rm) override;
|
||||
|
@ -87,7 +87,7 @@ TEST_CASE("Fuzz ARM data processing instructions", "[JitX64]") {
|
||||
}
|
||||
|
||||
SECTION("long blocks") {
|
||||
FuzzJit(1024, 1025, 50, instruction_select_without_R15);
|
||||
FuzzJit(1024, 1025, 200, instruction_select_without_R15);
|
||||
}
|
||||
|
||||
auto instruction_select_only_R15 = [&]() -> u32 {
|
||||
|
Loading…
Reference in New Issue
Block a user