|
|
|
@@ -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
|
|
|
|
|