From 1410221b4795faafe5cc73235f1cad3434810f53 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Mon, 11 Jul 2016 23:06:35 +0100 Subject: [PATCH] Implement thumb1_STR_reg, thumb1_STRH_reg, thumb1_STRB_reg --- src/backend_x64/emit_x64.cpp | 10 +++++++++- src/backend_x64/emit_x64.h | 1 + src/frontend/decoder/thumb1.h | 8 ++++---- src/frontend/disassembler_thumb.cpp | 12 ++++++++++++ src/frontend/ir/opcodes.inc | 1 + src/frontend/ir_emitter.cpp | 4 ++++ src/frontend/ir_emitter.h | 1 + src/frontend/translate_thumb.cpp | 27 +++++++++++++++++++++++++++ tests/arm/fuzz_thumb.cpp | 2 +- 9 files changed, 60 insertions(+), 6 deletions(-) diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 81e9b6c2..58ce9f19 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -223,10 +223,18 @@ void EmitX64::EmitGetOverflowFromOp(IR::Value*) { ASSERT_MSG(0, "should never happen"); } +void EmitX64::EmitLeastSignificantHalf(IR::Value* value_) { + auto value = reinterpret_cast(value_); + + // TODO: Optimize + + reg_alloc.UseDefRegister(value->GetArg(0).get(), value); +} + void EmitX64::EmitLeastSignificantByte(IR::Value* value_) { auto value = reinterpret_cast(value_); - // TODO: Flag optimization + // TODO: Optimize reg_alloc.UseDefRegister(value->GetArg(0).get(), value); } diff --git a/src/backend_x64/emit_x64.h b/src/backend_x64/emit_x64.h index 589e59ff..9caccea0 100644 --- a/src/backend_x64/emit_x64.h +++ b/src/backend_x64/emit_x64.h @@ -46,6 +46,7 @@ public: void EmitSetVFlag(IR::Value* value); void EmitGetCarryFromOp(IR::Value* value); void EmitGetOverflowFromOp(IR::Value* value); + void EmitLeastSignificantHalf(IR::Value* value); void EmitLeastSignificantByte(IR::Value* value); void EmitMostSignificantBit(IR::Value* value); void EmitIsZero(IR::Value* value); diff --git a/src/frontend/decoder/thumb1.h b/src/frontend/decoder/thumb1.h index bd2e56b4..7288fff9 100644 --- a/src/frontend/decoder/thumb1.h +++ b/src/frontend/decoder/thumb1.h @@ -56,7 +56,7 @@ private: }; template -static const std::array, 32> g_thumb1_instruction_table {{ +static const std::array, 35> g_thumb1_instruction_table {{ #define INST(fn, name, bitstring) detail::detail::GetMatcher(name, bitstring) @@ -98,9 +98,9 @@ static const std::array, 32> g_thumb1_instruction_table {{ // Store/Load single data item instructions { INST(&V::thumb1_LDR_literal, "LDR (literal)", "01001tttvvvvvvvv") }, - //{ INST(&V::thumb1_STR_rrr, "STR (rrr)", "0101000mmmnnnddd") }, - //{ INST(&V::thumb1_STRH_rrr, "STRH (rrr)", "0101001mmmnnnddd") }, - //{ INST(&V::thumb1_STRB_rrr, "STRB (rrr)", "0101010mmmnnnddd") }, + { INST(&V::thumb1_STR_reg, "STR (reg)", "0101000mmmnnnttt") }, + { INST(&V::thumb1_STRH_reg, "STRH (reg)", "0101001mmmnnnttt") }, + { INST(&V::thumb1_STRB_reg, "STRB (reg)", "0101010mmmnnnttt") }, //{ INST(&V::thumb1_LDRSB_rrr, "LDRSB (rrr)", "0101011mmmnnnddd") }, //{ INST(&V::thumb1_LDR_rrr, "LDR (rrr)", "0101100mmmnnnddd") }, //{ INST(&V::thumb1_LDRH_rrr, "LDRH (rrr)", "0101101mmmnnnddd") }, diff --git a/src/frontend/disassembler_thumb.cpp b/src/frontend/disassembler_thumb.cpp index 43fa5dc0..da34252f 100644 --- a/src/frontend/disassembler_thumb.cpp +++ b/src/frontend/disassembler_thumb.cpp @@ -227,6 +227,18 @@ public: return Common::StringFromFormat("ldr %s, [pc, #%u]", RegStr(t), imm32); } + std::string thumb1_STR_reg(Reg m, Reg n, Reg t) { + return Common::StringFromFormat("str %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m)); + } + + std::string thumb1_STRH_reg(Reg m, Reg n, Reg t) { + return Common::StringFromFormat("strh %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m)); + } + + std::string thumb1_STRB_reg(Reg m, Reg n, Reg t) { + return Common::StringFromFormat("strb %s, [%s, %s]", RegStr(t), RegStr(n), RegStr(m)); + } + std::string thumb1_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) { u32 imm32 = imm5 << 2; return Common::StringFromFormat("ldr %s, [%s, #%u]", RegStr(t), RegStr(n), imm32); diff --git a/src/frontend/ir/opcodes.inc b/src/frontend/ir/opcodes.inc index f4b65d7f..a8151718 100644 --- a/src/frontend/ir/opcodes.inc +++ b/src/frontend/ir/opcodes.inc @@ -23,6 +23,7 @@ OPCODE(GetCarryFromOp, T::U1, T::U32 OPCODE(GetOverflowFromOp, T::U1, T::U32 ) // Calculations +OPCODE(LeastSignificantHalf, T::U16, T::U32 ) OPCODE(LeastSignificantByte, T::U8, T::U32 ) OPCODE(MostSignificantBit, T::U1, T::U32 ) OPCODE(IsZero, T::U1, T::U32 ) diff --git a/src/frontend/ir_emitter.cpp b/src/frontend/ir_emitter.cpp index d5b6cd65..d88cd82b 100644 --- a/src/frontend/ir_emitter.cpp +++ b/src/frontend/ir_emitter.cpp @@ -79,6 +79,10 @@ void IREmitter::SetVFlag(IR::ValuePtr value) { Inst(IR::Opcode::SetVFlag, {value}); } +IR::ValuePtr IREmitter::LeastSignificantHalf(IR::ValuePtr value) { + return Inst(IR::Opcode::LeastSignificantHalf, {value}); +} + IR::ValuePtr IREmitter::LeastSignificantByte(IR::ValuePtr value) { return Inst(IR::Opcode::LeastSignificantByte, {value}); } diff --git a/src/frontend/ir_emitter.h b/src/frontend/ir_emitter.h index 19523920..54ef09e4 100644 --- a/src/frontend/ir_emitter.h +++ b/src/frontend/ir_emitter.h @@ -50,6 +50,7 @@ public: void SetCFlag(IR::ValuePtr value); void SetVFlag(IR::ValuePtr value); + IR::ValuePtr LeastSignificantHalf(IR::ValuePtr value); IR::ValuePtr LeastSignificantByte(IR::ValuePtr value); IR::ValuePtr MostSignificantBit(IR::ValuePtr value); IR::ValuePtr IsZero(IR::ValuePtr value); diff --git a/src/frontend/translate_thumb.cpp b/src/frontend/translate_thumb.cpp index 2c8116c6..c3073c6d 100644 --- a/src/frontend/translate_thumb.cpp +++ b/src/frontend/translate_thumb.cpp @@ -375,6 +375,33 @@ struct TranslatorVisitor final { return true; } + bool thumb1_STR_reg(Reg m, Reg n, Reg t) { + // STR , [, ] + // Rt cannot encode R15. + auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); + auto data = ir.GetRegister(t); + ir.WriteMemory32(address, data); + return true; + } + + bool thumb1_STRH_reg(Reg m, Reg n, Reg t) { + // STRH , [, ] + // Rt cannot encode R15. + auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); + auto data = ir.LeastSignificantHalf(ir.GetRegister(t)); + ir.WriteMemory16(address, data); + return true; + } + + bool thumb1_STRB_reg(Reg m, Reg n, Reg t) { + // STRB , [, ] + // Rt cannot encode R15. + auto address = ir.Add(ir.GetRegister(n), ir.GetRegister(m)); + auto data = ir.LeastSignificantByte(ir.GetRegister(t)); + ir.WriteMemory8(address, data); + return true; + } + bool thumb1_LDR_imm_t1(Imm5 imm5, Reg n, Reg t) { u32 imm32 = imm5 << 2; // LDR , [, #} diff --git a/tests/arm/fuzz_thumb.cpp b/tests/arm/fuzz_thumb.cpp index 33edd87d..f26473d6 100644 --- a/tests/arm/fuzz_thumb.cpp +++ b/tests/arm/fuzz_thumb.cpp @@ -267,7 +267,7 @@ TEST_CASE("Fuzz Thumb instructions set 1", "[JitX64][Thumb]") { SECTION("short blocks") { FuzzJitThumb(5, 6, 3000, instruction_select); } - + SECTION("long blocks") { FuzzJitThumb(1024, 1025, 25, instruction_select); }