Implement data processing instructions
ADC, ADD, AND, BIC, CMN, CMP, EOR, MOV, MVN, ORR, RSB, RSC, SBC, SUB, TEQ, TST The code could use some serious deduplication...
This commit is contained in:
parent
fe71cc9d78
commit
30a90295b9
4 changed files with 870 additions and 92 deletions
|
@ -89,53 +89,53 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
||||||
|
|
||||||
// Data Processing instructions
|
// Data Processing instructions
|
||||||
INST(&V::arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_ADC_imm, "ADC (imm)", "cccc0010101Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_ADC_reg, "ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_ADC_reg, "ADC (reg)", "cccc0000101Snnnnddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_ADC_rsr, "ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm"), // all
|
INST(&V::arm_ADC_rsr, "ADC (rsr)", "cccc0000101Snnnnddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_ADD_imm, "ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_ADD_imm, "ADD (imm)", "cccc0010100Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_ADD_reg, "ADD (reg)", "cccc0000100Snnnnddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_ADD_reg, "ADD (reg)", "cccc0000100Snnnnddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_ADD_rsr, "ADD (rsr)", "cccc0000100Snnnnddddssss0rr1mmmm"), // all
|
INST(&V::arm_ADD_rsr, "ADD (rsr)", "cccc0000100Snnnnddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_AND_imm, "AND (imm)", "cccc0010000Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_AND_imm, "AND (imm)", "cccc0010000Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_AND_reg, "AND (reg)", "cccc0000000Snnnnddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_AND_reg, "AND (reg)", "cccc0000000Snnnnddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_AND_rsr, "AND (rsr)", "cccc0000000Snnnnddddssss0rr1mmmm"), // all
|
INST(&V::arm_AND_rsr, "AND (rsr)", "cccc0000000Snnnnddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_BIC_imm, "BIC (imm)", "cccc0011110Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_BIC_imm, "BIC (imm)", "cccc0011110Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_BIC_reg, "BIC (reg)", "cccc0001110Snnnnddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_BIC_reg, "BIC (reg)", "cccc0001110Snnnnddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_BIC_rsr, "BIC (rsr)", "cccc0001110Snnnnddddssss0rr1mmmm"), // all
|
INST(&V::arm_BIC_rsr, "BIC (rsr)", "cccc0001110Snnnnddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_CMN_imm, "CMN (imm)", "cccc00110111nnnn0000rrrrvvvvvvvv"), // all
|
INST(&V::arm_CMN_imm, "CMN (imm)", "cccc00110111nnnn0000rrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_CMN_reg, "CMN (reg)", "cccc00010111nnnn0000vvvvvrr0mmmm"), // all
|
INST(&V::arm_CMN_reg, "CMN (reg)", "cccc00010111nnnn0000vvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_CMN_rsr, "CMN (rsr)", "cccc00010111nnnn0000ssss0rr1mmmm"), // all
|
INST(&V::arm_CMN_rsr, "CMN (rsr)", "cccc00010111nnnn0000ssss0rr1mmmm"), // all
|
||||||
INST(&V::arm_CMP_imm, "CMP (imm)", "cccc00110101nnnn0000rrrrvvvvvvvv"), // all
|
INST(&V::arm_CMP_imm, "CMP (imm)", "cccc00110101nnnn0000rrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_CMP_reg, "CMP (reg)", "cccc00010101nnnn0000vvvvvrr0mmmm"), // all
|
INST(&V::arm_CMP_reg, "CMP (reg)", "cccc00010101nnnn0000vvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_CMP_rsr, "CMP (rsr)", "cccc00010101nnnn0000ssss0rr1mmmm"), // all
|
INST(&V::arm_CMP_rsr, "CMP (rsr)", "cccc00010101nnnn0000ssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_EOR_imm, "EOR (imm)", "cccc0010001Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_EOR_imm, "EOR (imm)", "cccc0010001Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_EOR_reg, "EOR (reg)", "cccc0000001Snnnnddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_EOR_reg, "EOR (reg)", "cccc0000001Snnnnddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_EOR_rsr, "EOR (rsr)", "cccc0000001Snnnnddddssss0rr1mmmm"), // all
|
INST(&V::arm_EOR_rsr, "EOR (rsr)", "cccc0000001Snnnnddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_MOV_imm, "MOV (imm)", "cccc0011101S0000ddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_MOV_imm, "MOV (imm)", "cccc0011101S0000ddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_MOV_reg, "MOV (reg)", "cccc0001101S0000ddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_MOV_reg, "MOV (reg)", "cccc0001101S0000ddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_MOV_rsr, "MOV (rsr)", "cccc0001101S0000ddddssss0rr1mmmm"), // all
|
INST(&V::arm_MOV_rsr, "MOV (rsr)", "cccc0001101S0000ddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_MVN_imm, "MVN (imm)", "cccc0011111S0000ddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_MVN_imm, "MVN (imm)", "cccc0011111S0000ddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_MVN_reg, "MVN (reg)", "cccc0001111S0000ddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_MVN_reg, "MVN (reg)", "cccc0001111S0000ddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_MVN_rsr, "MVN (rsr)", "cccc0001111S0000ddddssss0rr1mmmm"), // all
|
INST(&V::arm_MVN_rsr, "MVN (rsr)", "cccc0001111S0000ddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_ORR_imm, "ORR (imm)", "cccc0011100Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_ORR_imm, "ORR (imm)", "cccc0011100Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_ORR_reg, "ORR (reg)", "cccc0001100Snnnnddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_ORR_reg, "ORR (reg)", "cccc0001100Snnnnddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_ORR_rsr, "ORR (rsr)", "cccc0001100Snnnnddddssss0rr1mmmm"), // all
|
INST(&V::arm_ORR_rsr, "ORR (rsr)", "cccc0001100Snnnnddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_RSB_imm, "RSB (imm)", "cccc0010011Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_RSB_imm, "RSB (imm)", "cccc0010011Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_RSB_reg, "RSB (reg)", "cccc0000011Snnnnddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_RSB_reg, "RSB (reg)", "cccc0000011Snnnnddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_RSB_rsr, "RSB (rsr)", "cccc0000011Snnnnddddssss0rr1mmmm"), // all
|
INST(&V::arm_RSB_rsr, "RSB (rsr)", "cccc0000011Snnnnddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_RSC_imm, "RSC (imm)", "cccc0010111Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_RSC_imm, "RSC (imm)", "cccc0010111Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_RSC_reg, "RSC (reg)", "cccc0000111Snnnnddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_RSC_reg, "RSC (reg)", "cccc0000111Snnnnddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_RSC_rsr, "RSC (rsr)", "cccc0000111Snnnnddddssss0rr1mmmm"), // all
|
INST(&V::arm_RSC_rsr, "RSC (rsr)", "cccc0000111Snnnnddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_SBC_imm, "SBC (imm)", "cccc0010110Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_SBC_imm, "SBC (imm)", "cccc0010110Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_SBC_reg, "SBC (reg)", "cccc0000110Snnnnddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_SBC_reg, "SBC (reg)", "cccc0000110Snnnnddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_SBC_rsr, "SBC (rsr)", "cccc0000110Snnnnddddssss0rr1mmmm"), // all
|
INST(&V::arm_SBC_rsr, "SBC (rsr)", "cccc0000110Snnnnddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_SUB_imm, "SUB (imm)", "cccc0010010Snnnnddddrrrrvvvvvvvv"), // all
|
INST(&V::arm_SUB_imm, "SUB (imm)", "cccc0010010Snnnnddddrrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_SUB_reg, "SUB (reg)", "cccc0000010Snnnnddddvvvvvrr0mmmm"), // all
|
INST(&V::arm_SUB_reg, "SUB (reg)", "cccc0000010Snnnnddddvvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_SUB_rsr, "SUB (rsr)", "cccc0000010Snnnnddddssss0rr1mmmm"), // all
|
INST(&V::arm_SUB_rsr, "SUB (rsr)", "cccc0000010Snnnnddddssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_TEQ_imm, "TEQ (imm)", "cccc00110011nnnn0000rrrrvvvvvvvv"), // all
|
INST(&V::arm_TEQ_imm, "TEQ (imm)", "cccc00110011nnnn0000rrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_TEQ_reg, "TEQ (reg)", "cccc00010011nnnn0000vvvvvrr0mmmm"), // all
|
INST(&V::arm_TEQ_reg, "TEQ (reg)", "cccc00010011nnnn0000vvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_TEQ_rsr, "TEQ (rsr)", "cccc00010011nnnn0000ssss0rr1mmmm"), // all
|
INST(&V::arm_TEQ_rsr, "TEQ (rsr)", "cccc00010011nnnn0000ssss0rr1mmmm"), // all
|
||||||
//INST(&V::arm_TST_imm, "TST (imm)", "cccc00110001nnnn0000rrrrvvvvvvvv"), // all
|
INST(&V::arm_TST_imm, "TST (imm)", "cccc00110001nnnn0000rrrrvvvvvvvv"), // all
|
||||||
//INST(&V::arm_TST_reg, "TST (reg)", "cccc00010001nnnn0000vvvvvrr0mmmm"), // all
|
INST(&V::arm_TST_reg, "TST (reg)", "cccc00010001nnnn0000vvvvvrr0mmmm"), // all
|
||||||
//INST(&V::arm_TST_rsr, "TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm"), // all
|
INST(&V::arm_TST_rsr, "TST (rsr)", "cccc00010001nnnn0000ssss0rr1mmmm"), // all
|
||||||
|
|
||||||
// Exception Generating instructions
|
// Exception Generating instructions
|
||||||
//INST(&V::arm_BKPT, "BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv"), // v5
|
//INST(&V::arm_BKPT, "BKPT", "cccc00010010vvvvvvvvvvvv0111vvvv"), // v5
|
||||||
|
|
|
@ -93,5 +93,50 @@ bool ArmTranslatorVisitor::LinkToNextInstruction() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IREmitter::ResultAndCarry ArmTranslatorVisitor::EmitImmShift(IR::Value value, ShiftType type, Imm5 imm5, IR::Value carry_in) {
|
||||||
|
IREmitter::ResultAndCarry result_and_carry;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ShiftType::LSL:
|
||||||
|
result_and_carry = ir.LogicalShiftLeft(value, ir.Imm8(imm5), carry_in);
|
||||||
|
break;
|
||||||
|
case ShiftType::LSR:
|
||||||
|
imm5 = imm5 ? imm5 : 32;
|
||||||
|
result_and_carry = ir.LogicalShiftRight(value, ir.Imm8(imm5), carry_in);
|
||||||
|
break;
|
||||||
|
case ShiftType::ASR:
|
||||||
|
imm5 = imm5 ? imm5 : 32;
|
||||||
|
result_and_carry = ir.ArithmeticShiftRight(value, ir.Imm8(imm5), carry_in);
|
||||||
|
break;
|
||||||
|
case ShiftType::ROR:
|
||||||
|
if (imm5)
|
||||||
|
result_and_carry = ir.RotateRight(value, ir.Imm8(imm5), carry_in);
|
||||||
|
else
|
||||||
|
result_and_carry = ir.RotateRightExtended(value, carry_in);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result_and_carry;
|
||||||
|
}
|
||||||
|
|
||||||
|
IREmitter::ResultAndCarry ArmTranslatorVisitor::EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in) {
|
||||||
|
IREmitter::ResultAndCarry result_and_carry;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ShiftType::LSL:
|
||||||
|
result_and_carry = ir.LogicalShiftLeft(value, amount, carry_in);
|
||||||
|
break;
|
||||||
|
case ShiftType::LSR:
|
||||||
|
result_and_carry = ir.LogicalShiftRight(value, amount, carry_in);
|
||||||
|
break;
|
||||||
|
case ShiftType::ASR:
|
||||||
|
result_and_carry = ir.ArithmeticShiftRight(value, amount, carry_in);
|
||||||
|
break;
|
||||||
|
case ShiftType::ROR:
|
||||||
|
result_and_carry = ir.RotateRight(value, amount, carry_in);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result_and_carry;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Arm
|
} // namespace Arm
|
||||||
} // namespace Dynarmic
|
} // namespace Dynarmic
|
||||||
|
|
|
@ -10,9 +10,9 @@ namespace Dynarmic {
|
||||||
namespace Arm {
|
namespace Arm {
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
u32 imm32 = ArmExpandImm(rotate, imm8);
|
|
||||||
// ADC{S}<c> <Rd>, <Rn>, #<imm>
|
// ADC{S}<c> <Rd>, <Rn>, #<imm>
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
|
u32 imm32 = ArmExpandImm(rotate, imm8);
|
||||||
auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.GetCFlag());
|
auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.GetCFlag());
|
||||||
|
|
||||||
if (d == Reg::PC) {
|
if (d == Reg::PC) {
|
||||||
|
@ -34,52 +34,290 @@ bool ArmTranslatorVisitor::arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rota
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.GetCFlag());
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_ADC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.GetCFlag());
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_ADD_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
u32 imm32 = ArmExpandImm(rotate, imm8);
|
||||||
|
auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_ADD_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_ADD_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_AND_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
|
||||||
|
auto result = ir.And(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(imm_carry.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_AND_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
|
||||||
|
auto result = ir.And(ir.GetRegister(n), shifted.result);
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_AND_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.And(ir.GetRegister(n), shifted.result);
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_BIC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
|
||||||
|
auto result = ir.And(ir.GetRegister(n), ir.Not(ir.Imm32(imm_carry.imm32)));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(imm_carry.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_BIC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
|
||||||
|
auto result = ir.And(ir.GetRegister(n), ir.Not(shifted.result));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_BIC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.And(ir.GetRegister(n), ir.Not(shifted.result));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_CMN_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
u32 imm32 = ArmExpandImm(rotate, imm8);
|
||||||
|
auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_CMN_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0));
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_CMN_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.AddWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(0));
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
||||||
u32 imm32 = ArmExpandImm(rotate, imm8);
|
|
||||||
// CMP<c> <Rn>, #<imm>
|
// CMP<c> <Rn>, #<imm>
|
||||||
if (ConditionPassed(cond)) {
|
if (ConditionPassed(cond)) {
|
||||||
|
u32 imm32 = ArmExpandImm(rotate, imm8);
|
||||||
auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
||||||
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
ir.SetZFlag(ir.IsZero(result.result));
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
@ -90,101 +328,578 @@ bool ArmTranslatorVisitor::arm_CMP_imm(Cond cond, Reg n, int rotate, Imm8 imm8)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_CMP_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(1));
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_CMP_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(1));
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_EOR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
|
||||||
|
auto result = ir.Eor(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(imm_carry.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_EOR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
|
||||||
|
auto result = ir.Eor(ir.GetRegister(n), shifted.result);
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_EOR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.Eor(ir.GetRegister(n), shifted.result);
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_MOV_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
|
||||||
|
auto result = ir.Imm32(imm_carry.imm32);
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(imm_carry.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_MOV_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
|
||||||
|
auto result = shifted.result;
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_MOV_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = shifted.result;
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_MVN_imm(Cond cond, bool S, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
|
||||||
|
auto result = ir.Not(ir.Imm32(imm_carry.imm32));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(imm_carry.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_MVN_reg(Cond cond, bool S, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
|
||||||
|
auto result = ir.Not(shifted.result);
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_MVN_rsr(Cond cond, bool S, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.Not(shifted.result);
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_ORR_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
|
||||||
|
auto result = ir.Or(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(imm_carry.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_ORR_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
|
||||||
|
auto result = ir.Or(ir.GetRegister(n), shifted.result);
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_ORR_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.Or(ir.GetRegister(n), shifted.result);
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_RSB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
return InterpretThisInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_RSB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
return InterpretThisInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_RSB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
return InterpretThisInstruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_RSC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
u32 imm32 = ArmExpandImm(rotate, imm8);
|
||||||
|
auto result = ir.SubWithCarry(ir.Imm32(imm32), ir.GetRegister(n), ir.GetCFlag());
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_RSC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
auto result = ir.SubWithCarry(shifted.result, ir.GetRegister(n), ir.GetCFlag());
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_RSC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.SubWithCarry(shifted.result, ir.GetRegister(n), ir.GetCFlag());
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_SBC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
u32 imm32 = ArmExpandImm(rotate, imm8);
|
||||||
|
auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.GetCFlag());
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_SBC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.GetCFlag());
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_SBC_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.GetCFlag());
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_SUB_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
u32 imm32 = ArmExpandImm(rotate, imm8);
|
||||||
|
auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_SUB_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, ir.GetCFlag());
|
||||||
|
auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(1));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_SUB_rsr(Cond cond, bool S, Reg n, Reg d, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.SubWithCarry(ir.GetRegister(n), shifted.result, ir.Imm1(1));
|
||||||
|
if (d == Reg::PC) {
|
||||||
|
ASSERT(!S);
|
||||||
|
ir.ALUWritePC(result.result);
|
||||||
|
ir.SetTerm(IR::Term::ReturnToDispatch{});
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
ir.SetRegister(d, result.result);
|
||||||
|
if (S) {
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result.result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result.result));
|
||||||
|
ir.SetCFlag(result.carry);
|
||||||
|
ir.SetVFlag(result.overflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_TEQ_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
|
||||||
|
auto result = ir.Eor(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(imm_carry.carry);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_TEQ_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
|
||||||
|
auto result = ir.Eor(ir.GetRegister(n), shifted.result);
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_TEQ_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.Eor(ir.GetRegister(n), shifted.result);
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
bool ArmTranslatorVisitor::arm_TST_imm(Cond cond, Reg n, int rotate, Imm8 imm8) {
|
||||||
//auto result = ArmExpandImm_C(rotate, imm8);
|
if (ConditionPassed(cond)) {
|
||||||
return InterpretThisInstruction();
|
auto imm_carry = ArmExpandImm_C(rotate, imm8, ir.GetCFlag());
|
||||||
|
auto result = ir.And(ir.GetRegister(n), ir.Imm32(imm_carry.imm32));
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(imm_carry.carry);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_TST_reg(Cond cond, Reg n, Imm5 imm5, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (ConditionPassed(cond)) {
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitImmShift(ir.GetRegister(m), shift, imm5, carry_in);
|
||||||
|
auto result = ir.And(ir.GetRegister(n), shifted.result);
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArmTranslatorVisitor::arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
bool ArmTranslatorVisitor::arm_TST_rsr(Cond cond, Reg n, Reg s, ShiftType shift, Reg m) {
|
||||||
return InterpretThisInstruction();
|
if (n == Reg::PC || m == Reg::PC || s == Reg::PC)
|
||||||
|
return UnpredictableInstruction();
|
||||||
|
if (ConditionPassed(cond)) {
|
||||||
|
auto shift_n = ir.LeastSignificantByte(ir.GetRegister(s));
|
||||||
|
auto carry_in = ir.GetCFlag();
|
||||||
|
auto shifted = EmitRegShift(ir.GetRegister(m), shift, shift_n, carry_in);
|
||||||
|
auto result = ir.And(ir.GetRegister(n), shifted.result);
|
||||||
|
ir.SetNFlag(ir.MostSignificantBit(result));
|
||||||
|
ir.SetZFlag(ir.IsZero(result));
|
||||||
|
ir.SetCFlag(shifted.carry);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Arm
|
} // namespace Arm
|
||||||
|
|
|
@ -43,6 +43,24 @@ struct ArmTranslatorVisitor final {
|
||||||
return rotr(static_cast<u32>(imm8), rotate*2);
|
return rotr(static_cast<u32>(imm8), rotate*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ImmAndCarry {
|
||||||
|
u32 imm32;
|
||||||
|
IR::Value carry;
|
||||||
|
};
|
||||||
|
|
||||||
|
ImmAndCarry ArmExpandImm_C(int rotate, u32 imm8, IR::Value carry_in) {
|
||||||
|
u32 imm32 = imm8;
|
||||||
|
auto carry_out = carry_in;
|
||||||
|
if (rotate) {
|
||||||
|
imm32 = rotr(imm8, rotate * 2);
|
||||||
|
carry_out = ir.Imm1(imm32 >> 31 == 1);
|
||||||
|
}
|
||||||
|
return {imm32, carry_out};
|
||||||
|
}
|
||||||
|
|
||||||
|
IREmitter::ResultAndCarry EmitImmShift(IR::Value value, ShiftType type, Imm5 imm5, IR::Value carry_in);
|
||||||
|
IREmitter::ResultAndCarry EmitRegShift(IR::Value value, ShiftType type, IR::Value amount, IR::Value carry_in);
|
||||||
|
|
||||||
// Data processing instructions
|
// Data processing instructions
|
||||||
bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
||||||
bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
bool arm_ADC_reg(Cond cond, bool S, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m);
|
||||||
|
|
Loading…
Reference in a new issue