From 8a0511d297819771546f47da5a6ff9df2d54261a Mon Sep 17 00:00:00 2001 From: MerryMage Date: Fri, 8 Jul 2016 17:43:28 +0800 Subject: [PATCH] Implement thumb1_AND_reg --- src/backend_x64/emit_x64.cpp | 9 +++++++++ src/backend_x64/emit_x64.h | 1 + src/frontend/decoder/thumb1.h | 4 ++-- src/frontend/disassembler_thumb.cpp | 4 ++++ src/frontend/ir/opcodes.inc | 1 + src/frontend/ir_emitter.cpp | 4 ++++ src/frontend/ir_emitter.h | 1 + src/frontend/translate_thumb.cpp | 10 ++++++++++ tests/arm/fuzz_thumb.cpp | 2 +- 9 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 20228bb9..52e549dc 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -436,6 +436,15 @@ void EmitX64::EmitAddWithCarry(IR::Value* value_) { } } +void EmitX64::EmitAnd(IR::Value* value_) { + auto value = reinterpret_cast(value_); + + X64Reg andend = reg_alloc.UseRegister(value->GetArg(1).get()); + X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value); + + code->AND(32, R(result), R(andend)); +} + void EmitX64::EmitAddCycles(size_t cycles) { ASSERT(cycles < std::numeric_limits::max()); code->SUB(64, MDisp(R15, offsetof(JitState, cycles_remaining)), Imm32(static_cast(cycles))); diff --git a/src/backend_x64/emit_x64.h b/src/backend_x64/emit_x64.h index ba802c29..1730e675 100644 --- a/src/backend_x64/emit_x64.h +++ b/src/backend_x64/emit_x64.h @@ -53,6 +53,7 @@ public: void EmitLogicalShiftRight(IR::Value* value); void EmitArithmeticShiftRight(IR::Value* value); void EmitAddWithCarry(IR::Value* value); + void EmitAnd(IR::Value* value); void EmitAddCycles(size_t cycles); diff --git a/src/frontend/decoder/thumb1.h b/src/frontend/decoder/thumb1.h index cb6972e2..0d93097d 100644 --- a/src/frontend/decoder/thumb1.h +++ b/src/frontend/decoder/thumb1.h @@ -56,7 +56,7 @@ private: }; template -static const std::array, 9> g_thumb1_instruction_table {{ +static const std::array, 10> g_thumb1_instruction_table {{ #define INST(fn, name, bitstring) detail::detail::GetMatcher(name, bitstring) @@ -74,7 +74,7 @@ static const std::array, 9> g_thumb1_instruction_table {{ //{ INST(&V::thumb1_SUB_ri, "SUB (ri)", "00111dddvvvvvvvv") }, // Data-processing instructions -// { INST(&V::thumb1_AND_reg, "AND (reg)", "0100000000mmmddd") }, + { INST(&V::thumb1_AND_reg, "AND (reg)", "0100000000mmmddd") }, // { INST(&V::thumb1_EOR_reg, "EOR (reg)", "0100000001mmmddd") }, { INST(&V::thumb1_LSL_reg, "LSL (reg)", "0100000010mmmddd") }, { INST(&V::thumb1_LSR_reg, "LSR (reg)", "0100000011mmmddd") }, diff --git a/src/frontend/disassembler_thumb.cpp b/src/frontend/disassembler_thumb.cpp index 22d7481f..076a6d37 100644 --- a/src/frontend/disassembler_thumb.cpp +++ b/src/frontend/disassembler_thumb.cpp @@ -118,6 +118,10 @@ public: return Common::StringFromFormat("adds %s, %s, %s", RegStr(d), RegStr(n), RegStr(m)); } + std::string thumb1_AND_reg(Reg m, Reg d_n) { + return Common::StringFromFormat("ands %s, %s", RegStr(d_n), RegStr(m)); + } + std::string thumb1_LSL_reg(Reg m, Reg d_n) { return Common::StringFromFormat("lsls %s, %s", RegStr(d_n), RegStr(m)); } diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index bf042336..79c5a685 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -30,3 +30,4 @@ OPCODE(LogicalShiftLeft, T::U32, T::U32, T::U8, OPCODE(LogicalShiftRight, T::U32, T::U32, T::U8, T::U1 ) OPCODE(ArithmeticShiftRight, T::U32, T::U32, T::U8, T::U1 ) OPCODE(AddWithCarry, T::U32, T::U32, T::U32, T::U1 ) +OPCODE(And, T::U32, T::U32, T::U32 ) diff --git a/src/frontend/ir_emitter.cpp b/src/frontend/ir_emitter.cpp index 277c0e8a..8d0ee16a 100644 --- a/src/frontend/ir_emitter.cpp +++ b/src/frontend/ir_emitter.cpp @@ -106,6 +106,10 @@ IREmitter::ResultAndCarryAndOverflow IREmitter::AddWithCarry(IR::ValuePtr a, IR: return {result, carry_out, overflow}; } +IR::ValuePtr IREmitter::And(IR::ValuePtr a, IR::ValuePtr b) { + return Inst(IR::Opcode::And, {a, b}); +} + void IREmitter::SetTerm(const IR::Terminal& terminal) { ASSERT_MSG(block.terminal.which() == 0, "Terminal has already been set."); block.terminal = terminal; diff --git a/src/frontend/ir_emitter.h b/src/frontend/ir_emitter.h index ea9081f7..0cac8b55 100644 --- a/src/frontend/ir_emitter.h +++ b/src/frontend/ir_emitter.h @@ -56,6 +56,7 @@ public: ResultAndCarry LogicalShiftRight(IR::ValuePtr value_in, IR::ValuePtr shift_amount, IR::ValuePtr carry_in); ResultAndCarry ArithmeticShiftRight(IR::ValuePtr value_in, IR::ValuePtr shift_amount, IR::ValuePtr carry_in); ResultAndCarryAndOverflow AddWithCarry(IR::ValuePtr a, IR::ValuePtr b, IR::ValuePtr carry_in); + IR::ValuePtr And(IR::ValuePtr a, IR::ValuePtr b); void SetTerm(const IR::Terminal& terminal); diff --git a/src/frontend/translate_thumb.cpp b/src/frontend/translate_thumb.cpp index 14b95b2e..83635380 100644 --- a/src/frontend/translate_thumb.cpp +++ b/src/frontend/translate_thumb.cpp @@ -76,6 +76,16 @@ struct TranslatorVisitor final { return true; } + bool thumb1_AND_reg(Reg m, Reg d_n) { + const Reg d = d_n, n = d_n; + // ANDS , + // Note that it is not possible to encode Rdn == R15. + auto result = ir.And(ir.GetRegister(n), ir.GetRegister(m)); + ir.SetRegister(d, result); + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + return true; + } bool thumb1_LSL_reg(Reg m, Reg d_n) { const Reg d = d_n, n = d_n; // LSLS , diff --git a/tests/arm/fuzz_thumb.cpp b/tests/arm/fuzz_thumb.cpp index 1ed562e1..6e0dd87d 100644 --- a/tests/arm/fuzz_thumb.cpp +++ b/tests/arm/fuzz_thumb.cpp @@ -210,7 +210,7 @@ TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") { }; SECTION("short blocks") { - FuzzJitThumb(5, 6, 100, instruction_select); + FuzzJitThumb(5, 6, 300, instruction_select); } SECTION("long blocks") {