Implement more instructions

SXTB, SXTH, SXTAB, SXTAH, UXTB, UXTH, UXTAB, UXTAH, REV16
This commit is contained in:
Tillmann Karras 2016-08-02 10:16:30 +01:00
parent 30a90295b9
commit fc33f1d374
5 changed files with 170 additions and 38 deletions

View file

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

View file

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

View file

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

View file

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

View file

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