From d11df9067d70305a5db3a9e08536830d5f9c49e4 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 10 Jul 2016 10:44:45 +0800 Subject: [PATCH] Implement thumb1_BIC_reg --- src/backend_x64/emit_x64.cpp | 8 ++++++++ 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 ++++++++++ 8 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 11042741..5c3a1fcd 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -534,6 +534,14 @@ void EmitX64::EmitOr(IR::Value* value_) { code->OR(32, R(result), R(orend)); } +void EmitX64::EmitNot(IR::Value* value_) { + auto value = reinterpret_cast(value_); + + X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value); + + code->NOT(32, R(result)); +} + 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 8806f0ae..90432223 100644 --- a/src/backend_x64/emit_x64.h +++ b/src/backend_x64/emit_x64.h @@ -58,6 +58,7 @@ public: void EmitAnd(IR::Value* value); void EmitEor(IR::Value* value); void EmitOr(IR::Value* value); + void EmitNot(IR::Value* value); void EmitAddCycles(size_t cycles); diff --git a/src/frontend/decoder/thumb1.h b/src/frontend/decoder/thumb1.h index 8c956109..d4f1b4e5 100644 --- a/src/frontend/decoder/thumb1.h +++ b/src/frontend/decoder/thumb1.h @@ -56,7 +56,7 @@ private: }; template -static const std::array, 26> g_thumb1_instruction_table {{ +static const std::array, 27> g_thumb1_instruction_table {{ #define INST(fn, name, bitstring) detail::detail::GetMatcher(name, bitstring) @@ -88,7 +88,7 @@ static const std::array, 26> g_thumb1_instruction_table {{ { INST(&V::thumb1_CMN_reg, "CMN (reg)", "0100001011mmmnnn") }, { INST(&V::thumb1_ORR_reg, "ORR (reg)", "0100001100mmmddd") }, //{ INST(&V::thumb1_MULS_rr, "MULS (rr)", "0100001101mmmddd") }, - //{ INST(&V::thumb1_BICS_rr, "BICS (rr)", "0100001110mmmddd") }, + { INST(&V::thumb1_BIC_reg, "BIC (reg)", "0100001110mmmddd") }, //{ INST(&V::thumb1_MVNS_rr, "MVNS (rr)", "0100001111mmmddd") }, // Special data instructions diff --git a/src/frontend/disassembler_thumb.cpp b/src/frontend/disassembler_thumb.cpp index 194a1ad1..d7bfaac3 100644 --- a/src/frontend/disassembler_thumb.cpp +++ b/src/frontend/disassembler_thumb.cpp @@ -199,6 +199,10 @@ public: return Common::StringFromFormat("orrs %s, %s", RegStr(d_n), RegStr(m)); } + std::string thumb1_BIC_reg(Reg m, Reg d_n) { + return Common::StringFromFormat("bics %s, %s", RegStr(d_n), RegStr(m)); + } + std::string thumb1_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) { Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo; return Common::StringFromFormat("add %s, %s", RegStr(d_n), RegStr(m)); diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index 01257f64..94479f2a 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -35,3 +35,4 @@ OPCODE(SubWithCarry, T::U32, T::U32, T::U32, OPCODE(And, T::U32, T::U32, T::U32 ) OPCODE(Eor, T::U32, T::U32, T::U32 ) OPCODE(Or, T::U32, T::U32, T::U32 ) +OPCODE(Not, T::U32, T::U32 ) diff --git a/src/frontend/ir_emitter.cpp b/src/frontend/ir_emitter.cpp index a4a76a26..e907b965 100644 --- a/src/frontend/ir_emitter.cpp +++ b/src/frontend/ir_emitter.cpp @@ -132,6 +132,10 @@ IR::ValuePtr IREmitter::Or(IR::ValuePtr a, IR::ValuePtr b) { return Inst(IR::Opcode::Or, {a, b}); } +IR::ValuePtr IREmitter::Not(IR::ValuePtr a) { + return Inst(IR::Opcode::Not, {a}); +} + 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 84909adb..80cc8b0d 100644 --- a/src/frontend/ir_emitter.h +++ b/src/frontend/ir_emitter.h @@ -61,6 +61,7 @@ public: IR::ValuePtr And(IR::ValuePtr a, IR::ValuePtr b); IR::ValuePtr Eor(IR::ValuePtr a, IR::ValuePtr b); IR::ValuePtr Or(IR::ValuePtr a, IR::ValuePtr b); + IR::ValuePtr Not(IR::ValuePtr a); void SetTerm(const IR::Terminal& terminal); diff --git a/src/frontend/translate_thumb.cpp b/src/frontend/translate_thumb.cpp index 0bb4b59d..72e02084 100644 --- a/src/frontend/translate_thumb.cpp +++ b/src/frontend/translate_thumb.cpp @@ -297,6 +297,16 @@ struct TranslatorVisitor final { ir.SetZFlag(ir.IsZero(result)); return true; } + bool thumb1_BIC_reg(Reg m, Reg d_n) { + Reg d = d_n, n = d_n; + // BICS , + // Rd cannot encode R15. + auto result = ir.And(ir.GetRegister(n), ir.Not(ir.GetRegister(m))); + ir.SetRegister(d, result); + ir.SetNFlag(ir.MostSignificantBit(result)); + ir.SetZFlag(ir.IsZero(result)); + return true; + } bool thumb1_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) { Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo;