A32: Implement ARM-mode RBIT
This commit is contained in:
parent
b2f7a0e7ba
commit
7305d13221
5 changed files with 39 additions and 3 deletions
|
@ -177,6 +177,7 @@ INST(arm_PKHBT, "PKHBT", "cccc01101000nnnnddddvvvvv001mmmm
|
|||
INST(arm_PKHTB, "PKHTB", "cccc01101000nnnnddddvvvvv101mmmm") // v6K
|
||||
|
||||
// Reversal instructions
|
||||
INST(arm_RBIT, "RBIT", "cccc011011111111dddd11110011mmmm") // v6T2
|
||||
INST(arm_REV, "REV", "cccc011010111111dddd11110011mmmm") // v6
|
||||
INST(arm_REV16, "REV16", "cccc011010111111dddd11111011mmmm") // v6
|
||||
INST(arm_REVSH, "REVSH", "cccc011011111111dddd11111011mmmm") // v6
|
||||
|
|
|
@ -589,6 +589,9 @@ public:
|
|||
std::string arm_NOP() {
|
||||
return "nop";
|
||||
}
|
||||
std::string arm_RBIT(Cond cond, Reg d, Reg m) {
|
||||
return fmt::format("rbit{} {}, {}", CondToString(cond), d, m);
|
||||
}
|
||||
std::string arm_SEL(Cond cond, Reg n, Reg d, Reg m) {
|
||||
return fmt::format("sel{} {}, {}, {}", CondToString(cond), d, n, m);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,36 @@
|
|||
|
||||
namespace Dynarmic::A32 {
|
||||
|
||||
// RBIT<c> <Rd>, <Rm>
|
||||
bool ArmTranslatorVisitor::arm_RBIT(Cond cond, Reg d, Reg m) {
|
||||
if (d == Reg::PC || m == Reg::PC) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
if (!ConditionPassed(cond)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const IR::U32 swapped = ir.ByteReverseWord(ir.GetRegister(m));
|
||||
|
||||
// ((x & 0xF0F0F0F0) >> 4) | ((x & 0x0F0F0F0F) << 4)
|
||||
const IR::U32 first_lsr = ir.LogicalShiftRight(ir.And(swapped, ir.Imm32(0xF0F0F0F0)), ir.Imm8(4));
|
||||
const IR::U32 first_lsl = ir.LogicalShiftLeft(ir.And(swapped, ir.Imm32(0x0F0F0F0F)), ir.Imm8(4));
|
||||
const IR::U32 corrected = ir.Or(first_lsl, first_lsr);
|
||||
|
||||
// ((x & 0x88888888) >> 3) | ((x & 0x44444444) >> 1) |
|
||||
// ((x & 0x22222222) << 1) | ((x & 0x11111111) << 3)
|
||||
const IR::U32 second_lsr = ir.LogicalShiftRight(ir.And(corrected, ir.Imm32(0x88888888)), ir.Imm8(3));
|
||||
const IR::U32 third_lsr = ir.LogicalShiftRight(ir.And(corrected, ir.Imm32(0x44444444)), ir.Imm8(1));
|
||||
const IR::U32 second_lsl = ir.LogicalShiftLeft(ir.And(corrected, ir.Imm32(0x22222222)), ir.Imm8(1));
|
||||
const IR::U32 third_lsl = ir.LogicalShiftLeft(ir.And(corrected, ir.Imm32(0x11111111)), ir.Imm8(3));
|
||||
|
||||
const IR::U32 result = ir.Or(ir.Or(ir.Or(second_lsr, third_lsr), second_lsl), third_lsl);
|
||||
|
||||
ir.SetRegister(d, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
// REV<c> <Rd>, <Rm>
|
||||
bool ArmTranslatorVisitor::arm_REV(Cond cond, Reg d, Reg m) {
|
||||
if (d == Reg::PC || m == Reg::PC) {
|
||||
|
|
|
@ -209,6 +209,7 @@ struct ArmTranslatorVisitor final {
|
|||
// Miscellaneous instructions
|
||||
bool arm_CLZ(Cond cond, Reg d, Reg m);
|
||||
bool arm_NOP() { return true; }
|
||||
bool arm_RBIT(Cond cond, Reg d, Reg m);
|
||||
bool arm_SEL(Cond cond, Reg n, Reg d, Reg m);
|
||||
|
||||
// Unsigned sum of absolute difference functions
|
||||
|
|
|
@ -763,9 +763,10 @@ TEST_CASE("Fuzz ARM reversal instructions", "[JitX64][A32]") {
|
|||
};
|
||||
|
||||
const std::array rev_instructions = {
|
||||
InstructionGenerator("cccc011010111111dddd11110011mmmm", is_valid),
|
||||
InstructionGenerator("cccc011010111111dddd11111011mmmm", is_valid),
|
||||
InstructionGenerator("cccc011011111111dddd11111011mmmm", is_valid),
|
||||
InstructionGenerator("cccc011011111111dddd11110011mmmm", is_valid), // RBIT
|
||||
InstructionGenerator("cccc011010111111dddd11110011mmmm", is_valid), // REV
|
||||
InstructionGenerator("cccc011010111111dddd11111011mmmm", is_valid), // REV16
|
||||
InstructionGenerator("cccc011011111111dddd11111011mmmm", is_valid), // REVSH
|
||||
};
|
||||
|
||||
SECTION("Reverse tests") {
|
||||
|
|
Loading…
Reference in a new issue