Implement more instructions
SXTB, SXTH, SXTAB, SXTAH, UXTB, UXTH, UXTAB, UXTAH, REV16
This commit is contained in:
parent
30a90295b9
commit
fc33f1d374
5 changed files with 170 additions and 38 deletions
|
@ -143,18 +143,18 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
|||
INST(&V::arm_UDF, "UDF", "111001111111------------1111----"), // all
|
||||
|
||||
// Extension instructions
|
||||
//INST(&V::arm_SXTB, "SXTB", "cccc011010101111ddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_SXTB16, "SXTB16", "cccc011010001111ddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_SXTH, "SXTH", "cccc011010111111ddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_SXTAB, "SXTAB", "cccc01101010nnnnddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_SXTAB16, "SXTAB16", "cccc01101000nnnnddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_SXTAH, "SXTAH", "cccc01101011nnnnddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_UXTB, "UXTB", "cccc011011101111ddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_UXTB16, "UXTB16", "cccc011011001111ddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_UXTH, "UXTH", "cccc011011111111ddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_UXTAB, "UXTAB", "cccc01101110nnnnddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_UXTAB16, "UXTAB16", "cccc01101100nnnnddddrr000111mmmm"), // v6
|
||||
//INST(&V::arm_UXTAH, "UXTAH", "cccc01101111nnnnddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_SXTB, "SXTB", "cccc011010101111ddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_SXTB16, "SXTB16", "cccc011010001111ddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_SXTH, "SXTH", "cccc011010111111ddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_SXTAB, "SXTAB", "cccc01101010nnnnddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_SXTAB16, "SXTAB16", "cccc01101000nnnnddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_SXTAH, "SXTAH", "cccc01101011nnnnddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_UXTB, "UXTB", "cccc011011101111ddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_UXTB16, "UXTB16", "cccc011011001111ddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_UXTH, "UXTH", "cccc011011111111ddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_UXTAB, "UXTAB", "cccc01101110nnnnddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_UXTAB16, "UXTAB16", "cccc01101100nnnnddddrr000111mmmm"), // v6
|
||||
INST(&V::arm_UXTAH, "UXTAH", "cccc01101111nnnnddddrr000111mmmm"), // v6
|
||||
|
||||
// Hint instructions
|
||||
//INST(&V::arm_PLD, "PLD", "111101---101----1111------------"), // v5E
|
||||
|
@ -236,7 +236,7 @@ boost::optional<const ArmMatcher<V>&> DecodeArm(u32 instruction) {
|
|||
|
||||
// Reversal instructions
|
||||
INST(&V::arm_REV, "REV", "cccc011010111111dddd11110011mmmm"), // v6
|
||||
//INST(&V::arm_REV16, "REV16", "cccc011010111111dddd11111011mmmm"), // v6
|
||||
INST(&V::arm_REV16, "REV16", "cccc011010111111dddd11111011mmmm"), // v6
|
||||
INST(&V::arm_REVSH, "REVSH", "cccc011011111111dddd11111011mmmm"), // v6
|
||||
|
||||
// Saturation instructions
|
||||
|
|
|
@ -66,6 +66,21 @@ public:
|
|||
return "<internal error>";
|
||||
}
|
||||
|
||||
std::string RorStr(Reg m, SignExtendRotation rotate) {
|
||||
switch (rotate) {
|
||||
case SignExtendRotation::ROR_0:
|
||||
return RegToString(m);
|
||||
case SignExtendRotation::ROR_8:
|
||||
return Common::StringFromFormat("%s, ror #8", RegToString(m));
|
||||
case SignExtendRotation::ROR_16:
|
||||
return Common::StringFromFormat("%s, ror #16", RegToString(m));
|
||||
case SignExtendRotation::ROR_24:
|
||||
return Common::StringFromFormat("%s, ror #24", RegToString(m));
|
||||
}
|
||||
assert(false);
|
||||
return "<internal error>";
|
||||
}
|
||||
|
||||
// Branch instructions
|
||||
std::string arm_B(Cond cond, Imm24 imm24) {
|
||||
s32 offset = Common::SignExtend<26, s32>(imm24 << 2) + 8;
|
||||
|
@ -245,7 +260,9 @@ public:
|
|||
}
|
||||
|
||||
// Exception generation instructions
|
||||
std::string arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4) { return "ice"; }
|
||||
std::string arm_BKPT(Cond cond, Imm12 imm12, Imm4 imm4) {
|
||||
return Common::StringFromFormat("bkpt #%hu", imm12 << 4 | imm4);
|
||||
}
|
||||
std::string arm_SVC(Cond cond, Imm24 imm24) {
|
||||
return Common::StringFromFormat("svc%s #%u", CondToString(cond), imm24);
|
||||
}
|
||||
|
@ -254,18 +271,42 @@ public:
|
|||
}
|
||||
|
||||
// Extension functions
|
||||
std::string arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) { return "ice"; }
|
||||
std::string arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("sxtab%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("sxtab16%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("sxtah%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("sxtb%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("sxtb16%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("sxth%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("uxtab%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("uxtab16%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("uxtah%s %s, %s, %s", CondToString(cond), RegToString(d), RegToString(n), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("uxtb%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("uxtb16%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str());
|
||||
}
|
||||
std::string arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return Common::StringFromFormat("uxth%s %s, %s", CondToString(cond), RegToString(d), RorStr(m, rotate).c_str());
|
||||
}
|
||||
|
||||
// Hint instructions
|
||||
std::string arm_PLD() { return "<unimplemented>"; }
|
||||
|
@ -313,7 +354,7 @@ public:
|
|||
|
||||
// Miscellaneous instructions
|
||||
std::string arm_CLZ(Cond cond, Reg d, Reg m) { return "ice"; }
|
||||
std::string arm_NOP() { return "ice"; }
|
||||
std::string arm_NOP() { return "nop"; }
|
||||
std::string arm_SEL(Cond cond, Reg n, Reg d, Reg m) { return "ice"; }
|
||||
|
||||
// Unsigned sum of absolute difference functions
|
||||
|
|
|
@ -9,8 +9,34 @@
|
|||
namespace Dynarmic {
|
||||
namespace Arm {
|
||||
|
||||
IR::Value ArmTranslatorVisitor::SignZeroExtendRor(Reg m, SignExtendRotation rotate) {
|
||||
IR::Value rotated, reg_m = ir.GetRegister(m);
|
||||
switch (rotate) {
|
||||
case SignExtendRotation::ROR_0:
|
||||
rotated = reg_m;
|
||||
break;
|
||||
case SignExtendRotation::ROR_8:
|
||||
rotated = ir.RotateRight(reg_m, ir.Imm8(8), ir.Imm1(0)).result;
|
||||
break;
|
||||
case SignExtendRotation::ROR_16:
|
||||
rotated = ir.RotateRight(reg_m, ir.Imm8(16), ir.Imm1(0)).result;
|
||||
break;
|
||||
case SignExtendRotation::ROR_24:
|
||||
rotated = ir.RotateRight(reg_m, ir.Imm8(24), ir.Imm1(0)).result;
|
||||
}
|
||||
return rotated;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_SXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return InterpretThisInstruction();
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
if (ConditionPassed(cond)) {
|
||||
auto rotated = SignZeroExtendRor(m, rotate);
|
||||
auto reg_n = ir.GetRegister(n);
|
||||
auto result = ir.Add(reg_n, ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated)));
|
||||
ir.SetRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
|
@ -18,11 +44,26 @@ bool ArmTranslatorVisitor::arm_SXTAB16(Cond cond, Reg n, Reg d, SignExtendRotati
|
|||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_SXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return InterpretThisInstruction();
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
if (ConditionPassed(cond)) {
|
||||
auto rotated = SignZeroExtendRor(m, rotate);
|
||||
auto reg_n = ir.GetRegister(n);
|
||||
auto result = ir.Add(reg_n, ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated)));
|
||||
ir.SetRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_SXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return InterpretThisInstruction();
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
if (ConditionPassed(cond)) {
|
||||
auto rotated = SignZeroExtendRor(m, rotate);
|
||||
auto result = ir.SignExtendByteToWord(ir.LeastSignificantByte(rotated));
|
||||
ir.SetRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
|
@ -30,11 +71,26 @@ bool ArmTranslatorVisitor::arm_SXTB16(Cond cond, Reg d, SignExtendRotation rotat
|
|||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_SXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return InterpretThisInstruction();
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
if (ConditionPassed(cond)) {
|
||||
auto rotated = SignZeroExtendRor(m, rotate);
|
||||
auto result = ir.SignExtendHalfToWord(ir.LeastSignificantHalf(rotated));
|
||||
ir.SetRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_UXTAB(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return InterpretThisInstruction();
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
if (ConditionPassed(cond)) {
|
||||
auto rotated = SignZeroExtendRor(m, rotate);
|
||||
auto reg_n = ir.GetRegister(n);
|
||||
auto result = ir.Add(reg_n, ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated)));
|
||||
ir.SetRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
|
@ -42,11 +98,26 @@ bool ArmTranslatorVisitor::arm_UXTAB16(Cond cond, Reg n, Reg d, SignExtendRotati
|
|||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_UXTAH(Cond cond, Reg n, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return InterpretThisInstruction();
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
if (ConditionPassed(cond)) {
|
||||
auto rotated = SignZeroExtendRor(m, rotate);
|
||||
auto reg_n = ir.GetRegister(n);
|
||||
auto result = ir.Add(reg_n, ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated)));
|
||||
ir.SetRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_UXTB(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return InterpretThisInstruction();
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
if (ConditionPassed(cond)) {
|
||||
auto rotated = SignZeroExtendRor(m, rotate);
|
||||
auto result = ir.ZeroExtendByteToWord(ir.LeastSignificantByte(rotated));
|
||||
ir.SetRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
|
@ -54,7 +125,14 @@ bool ArmTranslatorVisitor::arm_UXTB16(Cond cond, Reg d, SignExtendRotation rotat
|
|||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_UXTH(Cond cond, Reg d, SignExtendRotation rotate, Reg m) {
|
||||
return InterpretThisInstruction();
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
if (ConditionPassed(cond)) {
|
||||
auto rotated = SignZeroExtendRor(m, rotate);
|
||||
auto result = ir.ZeroExtendHalfToWord(ir.LeastSignificantHalf(rotated));
|
||||
ir.SetRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Arm
|
||||
|
|
|
@ -11,7 +11,8 @@ namespace Arm {
|
|||
|
||||
bool ArmTranslatorVisitor::arm_REV(Cond cond, Reg d, Reg m) {
|
||||
// REV<c> <Rd>, <Rm>
|
||||
ASSERT(d != Reg::PC && m != Reg::PC);
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
|
||||
if (ConditionPassed(cond)) {
|
||||
auto result = ir.ByteReverseWord(ir.GetRegister(m));
|
||||
|
@ -21,12 +22,23 @@ bool ArmTranslatorVisitor::arm_REV(Cond cond, Reg d, Reg m) {
|
|||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_REV16(Cond cond, Reg d, Reg m) {
|
||||
return InterpretThisInstruction();
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
|
||||
if (ConditionPassed(cond)) {
|
||||
auto reg_m = ir.GetRegister(m);
|
||||
auto lo = ir.And(ir.LogicalShiftRight(reg_m, ir.Imm8(8), ir.Imm1(0)).result, ir.Imm32(0x00FF00FF));
|
||||
auto hi = ir.And(ir.LogicalShiftLeft(reg_m, ir.Imm8(8), ir.Imm1(0)).result, ir.Imm32(0xFF00FF00));
|
||||
auto result = ir.Or(lo, hi);
|
||||
ir.SetRegister(d, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArmTranslatorVisitor::arm_REVSH(Cond cond, Reg d, Reg m) {
|
||||
// REVSH<c> <Rd>, <Rm>
|
||||
ASSERT(d != Reg::PC && m != Reg::PC);
|
||||
if (d == Reg::PC || m == Reg::PC)
|
||||
return UnpredictableInstruction();
|
||||
|
||||
if (ConditionPassed(cond)) {
|
||||
auto rev_half = ir.ByteReverseHalf(ir.LeastSignificantHalf(ir.GetRegister(m)));
|
||||
|
|
|
@ -60,6 +60,7 @@ struct ArmTranslatorVisitor final {
|
|||
|
||||
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);
|
||||
IR::Value SignZeroExtendRor(Reg m, SignExtendRotation rotate);
|
||||
|
||||
// Data processing instructions
|
||||
bool arm_ADC_imm(Cond cond, bool S, Reg n, Reg d, int rotate, Imm8 imm8);
|
||||
|
|
Loading…
Reference in a new issue