diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 305dacce..11042741 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -525,6 +525,15 @@ void EmitX64::EmitEor(IR::Value* value_) { code->XOR(32, R(result), R(eorend)); } +void EmitX64::EmitOr(IR::Value* value_) { + auto value = reinterpret_cast(value_); + + X64Reg orend = reg_alloc.UseRegister(value->GetArg(1).get()); + X64Reg result = reg_alloc.UseDefRegister(value->GetArg(0).get(), value); + + code->OR(32, R(result), R(orend)); +} + 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 beeef22c..8806f0ae 100644 --- a/src/backend_x64/emit_x64.h +++ b/src/backend_x64/emit_x64.h @@ -57,6 +57,7 @@ public: void EmitSubWithCarry(IR::Value* value); void EmitAnd(IR::Value* value); void EmitEor(IR::Value* value); + void EmitOr(IR::Value* value); void EmitAddCycles(size_t cycles); diff --git a/src/frontend/decoder/thumb1.h b/src/frontend/decoder/thumb1.h index 01057c87..8c956109 100644 --- a/src/frontend/decoder/thumb1.h +++ b/src/frontend/decoder/thumb1.h @@ -56,7 +56,7 @@ private: }; template -static const std::array, 25> g_thumb1_instruction_table {{ +static const std::array, 26> g_thumb1_instruction_table {{ #define INST(fn, name, bitstring) detail::detail::GetMatcher(name, bitstring) @@ -86,7 +86,7 @@ static const std::array, 25> g_thumb1_instruction_table {{ { INST(&V::thumb1_RSB_imm, "RSB (imm)", "0100001001nnnddd") }, { INST(&V::thumb1_CMP_reg, "CMP (reg)", "0100001010mmmnnn") }, { INST(&V::thumb1_CMN_reg, "CMN (reg)", "0100001011mmmnnn") }, - //{ INST(&V::thumb1_ORRS_rr, "ORRS (rr)", "0100001100mmmddd") }, + { 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_MVNS_rr, "MVNS (rr)", "0100001111mmmddd") }, diff --git a/src/frontend/disassembler_thumb.cpp b/src/frontend/disassembler_thumb.cpp index 325da510..194a1ad1 100644 --- a/src/frontend/disassembler_thumb.cpp +++ b/src/frontend/disassembler_thumb.cpp @@ -195,6 +195,10 @@ public: return Common::StringFromFormat("cmn %s, %s", RegStr(n), RegStr(m)); } + std::string thumb1_ORR_reg(Reg m, Reg d_n) { + return Common::StringFromFormat("orrs %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 1c67e942..01257f64 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -34,3 +34,4 @@ OPCODE(AddWithCarry, T::U32, T::U32, T::U32, OPCODE(SubWithCarry, T::U32, T::U32, T::U32, T::U1 ) OPCODE(And, T::U32, T::U32, T::U32 ) OPCODE(Eor, T::U32, T::U32, T::U32 ) +OPCODE(Or, T::U32, T::U32, T::U32 ) diff --git a/src/frontend/ir_emitter.cpp b/src/frontend/ir_emitter.cpp index ac08cca1..a4a76a26 100644 --- a/src/frontend/ir_emitter.cpp +++ b/src/frontend/ir_emitter.cpp @@ -128,6 +128,10 @@ IR::ValuePtr IREmitter::Eor(IR::ValuePtr a, IR::ValuePtr b) { return Inst(IR::Opcode::Eor, {a, b}); } +IR::ValuePtr IREmitter::Or(IR::ValuePtr a, IR::ValuePtr b) { + return Inst(IR::Opcode::Or, {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 f713dcb2..84909adb 100644 --- a/src/frontend/ir_emitter.h +++ b/src/frontend/ir_emitter.h @@ -60,6 +60,7 @@ public: ResultAndCarryAndOverflow SubWithCarry(IR::ValuePtr a, IR::ValuePtr b, IR::ValuePtr carry_in); 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); void SetTerm(const IR::Terminal& terminal); diff --git a/src/frontend/translate_thumb.cpp b/src/frontend/translate_thumb.cpp index 13ec616d..0bb4b59d 100644 --- a/src/frontend/translate_thumb.cpp +++ b/src/frontend/translate_thumb.cpp @@ -287,6 +287,16 @@ struct TranslatorVisitor final { ir.SetVFlag(result.overflow); return true; } + bool thumb1_ORR_reg(Reg m, Reg d_n) { + Reg d = d_n, n = d_n; + // ORRS , + // Rd cannot encode R15. + auto result = ir.Or(ir.GetRegister(m), ir.GetRegister(n)); + 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;