diff --git a/src/frontend/arm_types.h b/src/frontend/arm_types.h index af5add76..3b397553 100644 --- a/src/frontend/arm_types.h +++ b/src/frontend/arm_types.h @@ -39,6 +39,7 @@ inline Reg operator+(Reg reg, int number) { using Imm3 = u32; using Imm4 = u32; using Imm5 = u32; +using Imm7 = u32; using Imm8 = u32; using Imm11 = u32; using Imm12 = u32; diff --git a/src/frontend/decoder/thumb16.h b/src/frontend/decoder/thumb16.h index 058c51fc..d457944f 100644 --- a/src/frontend/decoder/thumb16.h +++ b/src/frontend/decoder/thumb16.h @@ -113,13 +113,13 @@ boost::optional&> DecodeThumb16(u16 instruction) { //INST(&V::thumb16_STR_sp, "STR (SP)", "10010dddvvvvvvvv"), //INST(&V::thumb16_LDR_sp, "LDR (SP)", "10011dddvvvvvvvv"), - // Generate relative address instruction + // Generate relative address instructions INST(&V::thumb16_ADR, "ADR", "10100dddvvvvvvvv"), - //INST(&V::thumb16_ADD_sp, "ADD (relative to SP)", "10101dddvvvvvvvv"), + INST(&V::thumb16_ADD_sp_t1, "ADD (SP plus imm, T1)", "10101dddvvvvvvvv"), + INST(&V::thumb16_ADD_sp_t2, "ADD (SP plus imm, T2)", "101100000vvvvvvv"), // v4T + INST(&V::thumb16_SUB_sp, "SUB (SP minus imm)", "101100001vvvvvvv"), // v4T // Miscellaneous 16-bit instructions - //INST(&V::thumb16_ADD_spsp, "ADD (imm to SP)", "101100000vvvvvvv"), // v4T - //INST(&V::thumb16_SUB_spsp, "SUB (imm from SP)", "101100001vvvvvvv"), // v4T INST(&V::thumb16_SXTH, "SXTH", "1011001000mmmddd"), // v6 INST(&V::thumb16_SXTB, "SXTB", "1011001001mmmddd"), // v6 INST(&V::thumb16_UXTH, "UXTH", "1011001010mmmddd"), // v6 diff --git a/src/frontend/disassembler/disassembler_thumb.cpp b/src/frontend/disassembler/disassembler_thumb.cpp index e40e5210..162cc20f 100644 --- a/src/frontend/disassembler/disassembler_thumb.cpp +++ b/src/frontend/disassembler/disassembler_thumb.cpp @@ -249,6 +249,21 @@ public: return Common::StringFromFormat("adr %s, +#%u", RegStr(d), imm32); } + std::string thumb16_ADD_sp_t1(Reg d, Imm8 imm8) { + u32 imm32 = imm8 << 2; + return Common::StringFromFormat("add %s, sp, #%u", RegStr(d), imm32); + } + + std::string thumb16_ADD_sp_t2(Imm7 imm7) { + u32 imm32 = imm7 << 2; + return Common::StringFromFormat("add sp, sp, #%u", imm32); + } + + std::string thumb16_SUB_sp(Imm7 imm7) { + u32 imm32 = imm7 << 2; + return Common::StringFromFormat("sub sp, sp, #%u", imm32); + } + std::string thumb16_SXTH(Reg m, Reg d) { return Common::StringFromFormat("sxth %s, %s", RegStr(d), RegStr(m)); } diff --git a/src/frontend/translate/translate_thumb.cpp b/src/frontend/translate/translate_thumb.cpp index 0a8d945f..7e2852fb 100644 --- a/src/frontend/translate/translate_thumb.cpp +++ b/src/frontend/translate/translate_thumb.cpp @@ -449,6 +449,32 @@ struct ThumbTranslatorVisitor final { return true; } + bool thumb16_ADD_sp_t1(Reg d, Imm8 imm8) { + u32 imm32 = imm8 << 2; + // ADD , SP, # + auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0)); + ir.SetRegister(d, result.result); + return true; + } + + bool thumb16_ADD_sp_t2(Imm7 imm7) { + u32 imm32 = imm7 << 2; + Reg d = Reg::SP; + // ADD SP, SP, # + auto result = ir.AddWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(0)); + ir.SetRegister(d, result.result); + return true; + } + + bool thumb16_SUB_sp(Imm7 imm7) { + u32 imm32 = imm7 << 2; + Reg d = Reg::SP; + // SUB SP, SP, # + auto result = ir.SubWithCarry(ir.GetRegister(Reg::SP), ir.Imm32(imm32), ir.Imm1(1)); + ir.SetRegister(d, result.result); + return true; + } + bool thumb16_SXTH(Reg m, Reg d) { // SXTH , // Rd cannot encode R15.