diff options
Diffstat (limited to 'source/Plugins/Instruction')
-rw-r--r-- | source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp | 22758 | ||||
-rw-r--r-- | source/Plugins/Instruction/ARM/EmulateInstructionARM.h | 1695 | ||||
-rw-r--r-- | source/Plugins/Instruction/ARM/EmulationStateARM.cpp | 669 | ||||
-rw-r--r-- | source/Plugins/Instruction/ARM/EmulationStateARM.h | 130 | ||||
-rw-r--r-- | source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp | 1896 | ||||
-rw-r--r-- | source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h | 418 | ||||
-rw-r--r-- | source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp | 4990 | ||||
-rw-r--r-- | source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h | 342 | ||||
-rw-r--r-- | source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp | 3811 | ||||
-rw-r--r-- | source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h | 284 |
10 files changed, 18643 insertions, 18350 deletions
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index 884078b27175..99caca99074b 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -11,11 +11,12 @@ #include "EmulateInstructionARM.h" #include "EmulationStateARM.h" -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Address.h" +#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Stream.h" +#include "lldb/Host/PosixApi.h" #include "lldb/Interpreter/OptionValueArray.h" #include "lldb/Interpreter/OptionValueDictionary.h" #include "lldb/Symbol/UnwindPlan.h" @@ -45,121 +46,113 @@ using namespace lldb_private; // A8.6.50 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition. -static uint32_t -CountITSize (uint32_t ITMask) { - // First count the trailing zeros of the IT mask. - uint32_t TZ = llvm::countTrailingZeros(ITMask); - if (TZ > 3) - { +static uint32_t CountITSize(uint32_t ITMask) { + // First count the trailing zeros of the IT mask. + uint32_t TZ = llvm::countTrailingZeros(ITMask); + if (TZ > 3) { #ifdef LLDB_CONFIGURATION_DEBUG - printf("Encoding error: IT Mask '0000'\n"); + printf("Encoding error: IT Mask '0000'\n"); #endif - return 0; - } - return (4 - TZ); + return 0; + } + return (4 - TZ); } // Init ITState. Note that at least one bit is always 1 in mask. -bool ITSession::InitIT(uint32_t bits7_0) -{ - ITCounter = CountITSize(Bits32(bits7_0, 3, 0)); - if (ITCounter == 0) - return false; +bool ITSession::InitIT(uint32_t bits7_0) { + ITCounter = CountITSize(Bits32(bits7_0, 3, 0)); + if (ITCounter == 0) + return false; - // A8.6.50 IT - unsigned short FirstCond = Bits32(bits7_0, 7, 4); - if (FirstCond == 0xF) - { + // A8.6.50 IT + unsigned short FirstCond = Bits32(bits7_0, 7, 4); + if (FirstCond == 0xF) { #ifdef LLDB_CONFIGURATION_DEBUG - printf("Encoding error: IT FirstCond '1111'\n"); + printf("Encoding error: IT FirstCond '1111'\n"); #endif - return false; - } - if (FirstCond == 0xE && ITCounter != 1) - { + return false; + } + if (FirstCond == 0xE && ITCounter != 1) { #ifdef LLDB_CONFIGURATION_DEBUG - printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n"); + printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n"); #endif - return false; - } + return false; + } - ITState = bits7_0; - return true; + ITState = bits7_0; + return true; } // Update ITState if necessary. -void ITSession::ITAdvance() -{ - //assert(ITCounter); - --ITCounter; - if (ITCounter == 0) - ITState = 0; - else - { - unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1; - SetBits32(ITState, 4, 0, NewITState4_0); - } +void ITSession::ITAdvance() { + // assert(ITCounter); + --ITCounter; + if (ITCounter == 0) + ITState = 0; + else { + unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1; + SetBits32(ITState, 4, 0, NewITState4_0); + } } // Return true if we're inside an IT Block. -bool ITSession::InITBlock() -{ - return ITCounter != 0; -} +bool ITSession::InITBlock() { return ITCounter != 0; } // Return true if we're the last instruction inside an IT Block. -bool ITSession::LastInITBlock() -{ - return ITCounter == 1; -} +bool ITSession::LastInITBlock() { return ITCounter == 1; } // Get condition bits for the current thumb instruction. -uint32_t ITSession::GetCond() -{ - if (InITBlock()) - return Bits32(ITState, 7, 4); - else - return COND_AL; +uint32_t ITSession::GetCond() { + if (InITBlock()) + return Bits32(ITState, 7, 4); + else + return COND_AL; } // ARM constants used during decoding -#define REG_RD 0 -#define LDM_REGLIST 1 -#define SP_REG 13 -#define LR_REG 14 -#define PC_REG 15 -#define PC_REGLIST_BIT 0x8000 - -#define ARMv4 (1u << 0) -#define ARMv4T (1u << 1) -#define ARMv5T (1u << 2) -#define ARMv5TE (1u << 3) -#define ARMv5TEJ (1u << 4) -#define ARMv6 (1u << 5) -#define ARMv6K (1u << 6) -#define ARMv6T2 (1u << 7) -#define ARMv7 (1u << 8) -#define ARMv7S (1u << 9) -#define ARMv8 (1u << 10) -#define ARMvAll (0xffffffffu) - -#define ARMV4T_ABOVE (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) -#define ARMV5_ABOVE (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) -#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) -#define ARMV5J_ABOVE (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) -#define ARMV6_ABOVE (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) -#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv7S|ARMv8) -#define ARMV7_ABOVE (ARMv7|ARMv7S|ARMv8) - -#define No_VFP 0 -#define VFPv1 (1u << 1) -#define VFPv2 (1u << 2) -#define VFPv3 (1u << 3) +#define REG_RD 0 +#define LDM_REGLIST 1 +#define SP_REG 13 +#define LR_REG 14 +#define PC_REG 15 +#define PC_REGLIST_BIT 0x8000 + +#define ARMv4 (1u << 0) +#define ARMv4T (1u << 1) +#define ARMv5T (1u << 2) +#define ARMv5TE (1u << 3) +#define ARMv5TEJ (1u << 4) +#define ARMv6 (1u << 5) +#define ARMv6K (1u << 6) +#define ARMv6T2 (1u << 7) +#define ARMv7 (1u << 8) +#define ARMv7S (1u << 9) +#define ARMv8 (1u << 10) +#define ARMvAll (0xffffffffu) + +#define ARMV4T_ABOVE \ + (ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | \ + ARMv7S | ARMv8) +#define ARMV5_ABOVE \ + (ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | \ + ARMv8) +#define ARMV5TE_ABOVE \ + (ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8) +#define ARMV5J_ABOVE \ + (ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8) +#define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8) +#define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8) +#define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8) + +#define No_VFP 0 +#define VFPv1 (1u << 1) +#define VFPv2 (1u << 2) +#define VFPv3 (1u << 3) #define AdvancedSIMD (1u << 4) #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD) #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD) -#define VFPv2v3 (VFPv2 | VFPv3) +#define VFPv2v3 (VFPv2 | VFPv3) //---------------------------------------------------------------------- // @@ -167,200 +160,194 @@ uint32_t ITSession::GetCond() // //---------------------------------------------------------------------- -void -EmulateInstructionARM::Initialize () -{ - PluginManager::RegisterPlugin (GetPluginNameStatic (), - GetPluginDescriptionStatic (), - CreateInstance); +void EmulateInstructionARM::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); } -void -EmulateInstructionARM::Terminate () -{ - PluginManager::UnregisterPlugin (CreateInstance); +void EmulateInstructionARM::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); } -ConstString -EmulateInstructionARM::GetPluginNameStatic () -{ - static ConstString g_name("arm"); - return g_name; +ConstString EmulateInstructionARM::GetPluginNameStatic() { + static ConstString g_name("arm"); + return g_name; } -const char * -EmulateInstructionARM::GetPluginDescriptionStatic () -{ - return "Emulate instructions for the ARM architecture."; +const char *EmulateInstructionARM::GetPluginDescriptionStatic() { + return "Emulate instructions for the ARM architecture."; } EmulateInstruction * -EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type) -{ - if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(inst_type)) - { - if (arch.GetTriple().getArch() == llvm::Triple::arm) - { - std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch)); - - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); - } - else if (arch.GetTriple().getArch() == llvm::Triple::thumb) - { - std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch)); - - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); - } +EmulateInstructionARM::CreateInstance(const ArchSpec &arch, + InstructionType inst_type) { + if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic( + inst_type)) { + if (arch.GetTriple().getArch() == llvm::Triple::arm) { + std::unique_ptr<EmulateInstructionARM> emulate_insn_ap( + new EmulateInstructionARM(arch)); + + if (emulate_insn_ap.get()) + return emulate_insn_ap.release(); + } else if (arch.GetTriple().getArch() == llvm::Triple::thumb) { + std::unique_ptr<EmulateInstructionARM> emulate_insn_ap( + new EmulateInstructionARM(arch)); + + if (emulate_insn_ap.get()) + return emulate_insn_ap.release(); } - - return NULL; -} + } -bool -EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch) -{ - if (arch.GetTriple().getArch () == llvm::Triple::arm) - return true; - else if (arch.GetTriple().getArch () == llvm::Triple::thumb) - return true; - - return false; + return NULL; } - -// Write "bits (32) UNKNOWN" to memory address "address". Helper function for many ARM instructions. -bool -EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address) -{ - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextWriteMemoryRandomBits; - context.SetNoArgs (); - uint32_t random_data = rand (); - const uint32_t addr_byte_size = GetAddressByteSize(); - - if (!MemAWrite (context, address, random_data, addr_byte_size)) - return false; - +bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) { + if (arch.GetTriple().getArch() == llvm::Triple::arm) return true; + else if (arch.GetTriple().getArch() == llvm::Triple::thumb) + return true; + + return false; } -// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM instructions. -bool -EmulateInstructionARM::WriteBits32Unknown (int n) -{ - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextWriteRegisterRandomBits; - context.SetNoArgs (); +// Write "bits (32) UNKNOWN" to memory address "address". Helper function for +// many ARM instructions. +bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) { + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextWriteMemoryRandomBits; + context.SetNoArgs(); - bool success; - uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) - return false; - - return true; -} + uint32_t random_data = rand(); + const uint32_t addr_byte_size = GetAddressByteSize(); -bool -EmulateInstructionARM::GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) -{ - if (reg_kind == eRegisterKindGeneric) - { - switch (reg_num) - { - case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc; break; - case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp; break; - case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r7; break; - case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_lr; break; - case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_cpsr; break; - default: return false; - } - } - - if (reg_kind == eRegisterKindDWARF) - return GetARMDWARFRegisterInfo(reg_num, reg_info); + if (!MemAWrite(context, address, random_data, addr_byte_size)) return false; + + return true; } -uint32_t -EmulateInstructionARM::GetFramePointerRegisterNumber () const -{ - if (m_arch.GetTriple().isAndroid()) - return LLDB_INVALID_REGNUM; // Don't use frame pointer on android - bool is_apple = false; - if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) - is_apple = true; - switch (m_arch.GetTriple().getOS()) - { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - case llvm::Triple::TvOS: - case llvm::Triple::WatchOS: - is_apple = true; - break; - default: - break; +// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM +// instructions. +bool EmulateInstructionARM::WriteBits32Unknown(int n) { + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextWriteRegisterRandomBits; + context.SetNoArgs(); + + bool success; + uint32_t data = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + + if (!success) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data)) + return false; + + return true; +} + +bool EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind, + uint32_t reg_num, + RegisterInfo ®_info) { + if (reg_kind == eRegisterKindGeneric) { + switch (reg_num) { + case LLDB_REGNUM_GENERIC_PC: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_pc; + break; + case LLDB_REGNUM_GENERIC_SP: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_sp; + break; + case LLDB_REGNUM_GENERIC_FP: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_r7; + break; + case LLDB_REGNUM_GENERIC_RA: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_lr; + break; + case LLDB_REGNUM_GENERIC_FLAGS: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_cpsr; + break; + default: + return false; } + } - /* On Apple iOS et al, the frame pointer register is always r7. - * Typically on other ARM systems, thumb code uses r7; arm code uses r11. - */ + if (reg_kind == eRegisterKindDWARF) + return GetARMDWARFRegisterInfo(reg_num, reg_info); + return false; +} + +uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const { + if (m_arch.GetTriple().isAndroid()) + return LLDB_INVALID_REGNUM; // Don't use frame pointer on android + bool is_apple = false; + if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) + is_apple = true; + switch (m_arch.GetTriple().getOS()) { + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: + case llvm::Triple::TvOS: + case llvm::Triple::WatchOS: + is_apple = true; + break; + default: + break; + } + + /* On Apple iOS et al, the frame pointer register is always r7. + * Typically on other ARM systems, thumb code uses r7; arm code uses r11. + */ - uint32_t fp_regnum = 11; + uint32_t fp_regnum = 11; - if (is_apple) - fp_regnum = 7; + if (is_apple) + fp_regnum = 7; - if (m_opcode_mode == eModeThumb) - fp_regnum = 7; + if (m_opcode_mode == eModeThumb) + fp_regnum = 7; - return fp_regnum; + return fp_regnum; } -uint32_t -EmulateInstructionARM::GetFramePointerDWARFRegisterNumber () const -{ - bool is_apple = false; - if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) - is_apple = true; - switch (m_arch.GetTriple().getOS()) - { - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - is_apple = true; - break; - default: - break; - } +uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const { + bool is_apple = false; + if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) + is_apple = true; + switch (m_arch.GetTriple().getOS()) { + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: + is_apple = true; + break; + default: + break; + } - /* On Apple iOS et al, the frame pointer register is always r7. - * Typically on other ARM systems, thumb code uses r7; arm code uses r11. - */ + /* On Apple iOS et al, the frame pointer register is always r7. + * Typically on other ARM systems, thumb code uses r7; arm code uses r11. + */ - uint32_t fp_regnum = dwarf_r11; + uint32_t fp_regnum = dwarf_r11; - if (is_apple) - fp_regnum = dwarf_r7; + if (is_apple) + fp_regnum = dwarf_r7; - if (m_opcode_mode == eModeThumb) - fp_regnum = dwarf_r7; + if (m_opcode_mode == eModeThumb) + fp_regnum = dwarf_r7; - return fp_regnum; + return fp_regnum; } // Push Multiple Registers stores multiple registers to the stack, storing to // consecutive memory locations ending just below the address in SP, and updates // SP to point to the start of the stored data. -bool -EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -388,105 +375,101 @@ EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding enc } #endif - bool success = false; - if (ConditionPassed(opcode)) - { - const uint32_t addr_byte_size = GetAddressByteSize(); - const addr_t sp = ReadCoreReg (SP_REG, &success); - if (!success) - return false; - uint32_t registers = 0; - uint32_t Rt; // the source register - switch (encoding) { - case eEncodingT1: - registers = Bits32(opcode, 7, 0); - // The M bit represents LR. - if (Bit32(opcode, 8)) - registers |= (1u << 14); - // if BitCount(registers) < 1 then UNPREDICTABLE; - if (BitCount(registers) < 1) - return false; - break; - case eEncodingT2: - // Ignore bits 15 & 13. - registers = Bits32(opcode, 15, 0) & ~0xa000; - // if BitCount(registers) < 2 then UNPREDICTABLE; - if (BitCount(registers) < 2) - return false; - break; - case eEncodingT3: - Rt = Bits32(opcode, 15, 12); - // if BadReg(t) then UNPREDICTABLE; - if (BadReg(Rt)) - return false; - registers = (1u << Rt); - break; - case eEncodingA1: - registers = Bits32(opcode, 15, 0); - // Instead of return false, let's handle the following case as well, - // which amounts to pushing one reg onto the full descending stacks. - // if BitCount(register_list) < 2 then SEE STMDB / STMFD; - break; - case eEncodingA2: - Rt = Bits32(opcode, 15, 12); - // if t == 13 then UNPREDICTABLE; - if (Rt == dwarf_sp) - return false; - registers = (1u << Rt); - break; - default: - return false; - } - addr_t sp_offset = addr_byte_size * BitCount (registers); - addr_t addr = sp - sp_offset; - uint32_t i; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextPushRegisterOnStack; - RegisterInfo reg_info; - RegisterInfo sp_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); - for (i=0; i<15; ++i) - { - if (BitIsSet (registers, i)) - { - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info); - context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp); - uint32_t reg_value = ReadCoreReg(i, &success); - if (!success) - return false; - if (!MemAWrite (context, addr, reg_value, addr_byte_size)) - return false; - addr += addr_byte_size; - } - } - - if (BitIsSet (registers, 15)) - { - GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info); - context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp); - const uint32_t pc = ReadCoreReg(PC_REG, &success); - if (!success) - return false; - if (!MemAWrite (context, addr, pc, addr_byte_size)) - return false; - } - - context.type = EmulateInstruction::eContextAdjustStackPointer; - context.SetImmediateSigned (-sp_offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) - return false; + bool success = false; + if (ConditionPassed(opcode)) { + const uint32_t addr_byte_size = GetAddressByteSize(); + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + uint32_t registers = 0; + uint32_t Rt; // the source register + switch (encoding) { + case eEncodingT1: + registers = Bits32(opcode, 7, 0); + // The M bit represents LR. + if (Bit32(opcode, 8)) + registers |= (1u << 14); + // if BitCount(registers) < 1 then UNPREDICTABLE; + if (BitCount(registers) < 1) + return false; + break; + case eEncodingT2: + // Ignore bits 15 & 13. + registers = Bits32(opcode, 15, 0) & ~0xa000; + // if BitCount(registers) < 2 then UNPREDICTABLE; + if (BitCount(registers) < 2) + return false; + break; + case eEncodingT3: + Rt = Bits32(opcode, 15, 12); + // if BadReg(t) then UNPREDICTABLE; + if (BadReg(Rt)) + return false; + registers = (1u << Rt); + break; + case eEncodingA1: + registers = Bits32(opcode, 15, 0); + // Instead of return false, let's handle the following case as well, + // which amounts to pushing one reg onto the full descending stacks. + // if BitCount(register_list) < 2 then SEE STMDB / STMFD; + break; + case eEncodingA2: + Rt = Bits32(opcode, 15, 12); + // if t == 13 then UNPREDICTABLE; + if (Rt == dwarf_sp) + return false; + registers = (1u << Rt); + break; + default: + return false; } - return true; + addr_t sp_offset = addr_byte_size * BitCount(registers); + addr_t addr = sp - sp_offset; + uint32_t i; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextPushRegisterOnStack; + RegisterInfo reg_info; + RegisterInfo sp_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + for (i = 0; i < 15; ++i) { + if (BitIsSet(registers, i)) { + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, reg_info); + context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp); + uint32_t reg_value = ReadCoreReg(i, &success); + if (!success) + return false; + if (!MemAWrite(context, addr, reg_value, addr_byte_size)) + return false; + addr += addr_byte_size; + } + } + + if (BitIsSet(registers, 15)) { + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, reg_info); + context.SetRegisterToRegisterPlusOffset(reg_info, sp_reg, addr - sp); + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + if (!MemAWrite(context, addr, pc, addr_byte_size)) + return false; + } + + context.type = EmulateInstruction::eContextAdjustStackPointer; + context.SetImmediateSigned(-sp_offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) + return false; + } + return true; } // Pop Multiple Registers loads multiple registers from the stack, loading from // consecutive memory locations staring at the address in SP, and updates // SP to point just above the loaded data. -bool -EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -506,115 +489,115 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco } #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - const uint32_t addr_byte_size = GetAddressByteSize(); - const addr_t sp = ReadCoreReg (SP_REG, &success); + if (ConditionPassed(opcode)) { + const uint32_t addr_byte_size = GetAddressByteSize(); + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + uint32_t registers = 0; + uint32_t Rt; // the destination register + switch (encoding) { + case eEncodingT1: + registers = Bits32(opcode, 7, 0); + // The P bit represents PC. + if (Bit32(opcode, 8)) + registers |= (1u << 15); + // if BitCount(registers) < 1 then UNPREDICTABLE; + if (BitCount(registers) < 1) + return false; + break; + case eEncodingT2: + // Ignore bit 13. + registers = Bits32(opcode, 15, 0) & ~0x2000; + // if BitCount(registers) < 2 || (P == '1' && M == '1') then + // UNPREDICTABLE; + if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14))) + return false; + // if registers<15> == '1' && InITBlock() && !LastInITBlock() then + // UNPREDICTABLE; + if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) + return false; + break; + case eEncodingT3: + Rt = Bits32(opcode, 15, 12); + // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then + // UNPREDICTABLE; + if (Rt == 13) + return false; + if (Rt == 15 && InITBlock() && !LastInITBlock()) + return false; + registers = (1u << Rt); + break; + case eEncodingA1: + registers = Bits32(opcode, 15, 0); + // Instead of return false, let's handle the following case as well, + // which amounts to popping one reg from the full descending stacks. + // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; + + // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE; + if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7) + return false; + break; + case eEncodingA2: + Rt = Bits32(opcode, 15, 12); + // if t == 13 then UNPREDICTABLE; + if (Rt == dwarf_sp) + return false; + registers = (1u << Rt); + break; + default: + return false; + } + addr_t sp_offset = addr_byte_size * BitCount(registers); + addr_t addr = sp; + uint32_t i, data; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextPopRegisterOffStack; + + RegisterInfo sp_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + + for (i = 0; i < 15; ++i) { + if (BitIsSet(registers, i)) { + context.SetAddress(addr); + data = MemARead(context, addr, 4, 0, &success); if (!success) - return false; - uint32_t registers = 0; - uint32_t Rt; // the destination register - switch (encoding) { - case eEncodingT1: - registers = Bits32(opcode, 7, 0); - // The P bit represents PC. - if (Bit32(opcode, 8)) - registers |= (1u << 15); - // if BitCount(registers) < 1 then UNPREDICTABLE; - if (BitCount(registers) < 1) - return false; - break; - case eEncodingT2: - // Ignore bit 13. - registers = Bits32(opcode, 15, 0) & ~0x2000; - // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; - if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14))) - return false; - // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; - if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) - return false; - break; - case eEncodingT3: - Rt = Bits32(opcode, 15, 12); - // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; - if (Rt == 13) - return false; - if (Rt == 15 && InITBlock() && !LastInITBlock()) - return false; - registers = (1u << Rt); - break; - case eEncodingA1: - registers = Bits32(opcode, 15, 0); - // Instead of return false, let's handle the following case as well, - // which amounts to popping one reg from the full descending stacks. - // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; - - // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE; - if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7) - return false; - break; - case eEncodingA2: - Rt = Bits32(opcode, 15, 12); - // if t == 13 then UNPREDICTABLE; - if (Rt == dwarf_sp) - return false; - registers = (1u << Rt); - break; - default: - return false; - } - addr_t sp_offset = addr_byte_size * BitCount (registers); - addr_t addr = sp; - uint32_t i, data; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextPopRegisterOffStack; - - RegisterInfo sp_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); + return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, + data)) + return false; + addr += addr_byte_size; + } + } - for (i=0; i<15; ++i) - { - if (BitIsSet (registers, i)) - { - context.SetAddress(addr); - data = MemARead(context, addr, 4, 0, &success); - if (!success) - return false; - if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data)) - return false; - addr += addr_byte_size; - } - } - - if (BitIsSet (registers, 15)) - { - context.SetRegisterPlusOffset (sp_reg, addr - sp); - data = MemARead(context, addr, 4, 0, &success); - if (!success) - return false; - // In ARMv5T and above, this is an interworking branch. - if (!LoadWritePC(context, data)) - return false; - //addr += addr_byte_size; - } - - context.type = EmulateInstruction::eContextAdjustStackPointer; - context.SetImmediateSigned (sp_offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) - return false; + if (BitIsSet(registers, 15)) { + context.SetRegisterPlusOffset(sp_reg, addr - sp); + data = MemARead(context, addr, 4, 0, &success); + if (!success) + return false; + // In ARMv5T and above, this is an interworking branch. + if (!LoadWritePC(context, data)) + return false; + // addr += addr_byte_size; } - return true; + + context.type = EmulateInstruction::eContextAdjustStackPointer; + context.SetImmediateSigned(sp_offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) + return false; + } + return true; } // Set r7 or ip to point to saved value residing within the stack. // ADD (SP plus immediate) -bool -EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -633,50 +616,49 @@ EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncodi } #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - const addr_t sp = ReadCoreReg (SP_REG, &success); - if (!success) - return false; - uint32_t Rd; // the destination register - uint32_t imm32; - switch (encoding) { - case eEncodingT1: - Rd = 7; - imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32) - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - break; - default: - return false; - } - addr_t sp_offset = imm32; - addr_t addr = sp + sp_offset; // a pointer to the stack area - - EmulateInstruction::Context context; - if (Rd == GetFramePointerRegisterNumber()) - context.type = eContextSetFramePointer; - else - context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo sp_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); - context.SetRegisterPlusOffset (sp_reg, sp_offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr)) - return false; + if (ConditionPassed(opcode)) { + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + uint32_t Rd; // the destination register + uint32_t imm32; + switch (encoding) { + case eEncodingT1: + Rd = 7; + imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32) + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + break; + default: + return false; } - return true; + addr_t sp_offset = imm32; + addr_t addr = sp + sp_offset; // a pointer to the stack area + + EmulateInstruction::Context context; + if (Rd == GetFramePointerRegisterNumber()) + context.type = eContextSetFramePointer; + else + context.type = EmulateInstruction::eContextRegisterPlusOffset; + RegisterInfo sp_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + context.SetRegisterPlusOffset(sp_reg, sp_offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, + addr)) + return false; + } + return true; } // Set r7 or ip to the current stack pointer. // MOV (register) -bool -EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -695,53 +677,50 @@ EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding } #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - const addr_t sp = ReadCoreReg (SP_REG, &success); - if (!success) - return false; - uint32_t Rd; // the destination register - switch (encoding) { - case eEncodingT1: - Rd = 7; - break; - case eEncodingA1: - Rd = 12; - break; - default: - return false; - } - - EmulateInstruction::Context context; - if (Rd == GetFramePointerRegisterNumber()) - context.type = EmulateInstruction::eContextSetFramePointer; - else - context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo sp_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); - context.SetRegisterPlusOffset (sp_reg, 0); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) - return false; + if (ConditionPassed(opcode)) { + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + uint32_t Rd; // the destination register + switch (encoding) { + case eEncodingT1: + Rd = 7; + break; + case eEncodingA1: + Rd = 12; + break; + default: + return false; } - return true; + + EmulateInstruction::Context context; + if (Rd == GetFramePointerRegisterNumber()) + context.type = EmulateInstruction::eContextSetFramePointer; + else + context.type = EmulateInstruction::eContextRegisterPlusOffset; + RegisterInfo sp_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + context.SetRegisterPlusOffset(sp_reg, 0); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) + return false; + } + return true; } // Move from high register (r8-r15) to low register (r0-r7). // MOV (register) -bool -EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding) -{ - return EmulateMOVRdRm (opcode, encoding); +bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode, + const ARMEncoding encoding) { + return EmulateMOVRdRm(opcode, encoding); } // Move from register to register. // MOV (register) -bool -EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -760,77 +739,77 @@ EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding } #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rm; // the source register - uint32_t Rd; // the destination register - bool setflags; - switch (encoding) { - case eEncodingT1: - Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 6, 3); - setflags = false; - if (Rd == 15 && InITBlock() && !LastInITBlock()) - return false; - break; - case eEncodingT2: - Rd = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - setflags = true; - if (InITBlock()) - return false; - break; - case eEncodingT3: - Rd = Bits32(opcode, 11, 8); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE; - if (setflags && (BadReg(Rd) || BadReg(Rm))) - return false; - // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE; - if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13))) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } - uint32_t result = ReadCoreReg(Rm, &success); - if (!success) - return false; + if (ConditionPassed(opcode)) { + uint32_t Rm; // the source register + uint32_t Rd; // the destination register + bool setflags; + switch (encoding) { + case eEncodingT1: + Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 6, 3); + setflags = false; + if (Rd == 15 && InITBlock() && !LastInITBlock()) + return false; + break; + case eEncodingT2: + Rd = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + setflags = true; + if (InITBlock()) + return false; + break; + case eEncodingT3: + Rd = Bits32(opcode, 11, 8); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE; + if (setflags && (BadReg(Rd) || BadReg(Rm))) + return false; + // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then + // UNPREDICTABLE; + if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13))) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } + uint32_t result = ReadCoreReg(Rm, &success); + if (!success) + return false; - // The context specifies that Rm is to be moved into Rd. - EmulateInstruction::Context context; - if (Rd == 13) - context.type = EmulateInstruction::eContextAdjustStackPointer; - else - context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); - context.SetRegisterPlusOffset (dwarf_reg, 0); + // The context specifies that Rm is to be moved into Rd. + EmulateInstruction::Context context; + if (Rd == 13) + context.type = EmulateInstruction::eContextAdjustStackPointer; + else + context.type = EmulateInstruction::eContextRegisterPlusOffset; + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); + context.SetRegisterPlusOffset(dwarf_reg, 0); - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags)) + return false; + } + return true; } // Move (immediate) writes an immediate value to the destination register. It // can optionally update the condition flags based on the value. // MOV (immediate) -bool -EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -849,101 +828,102 @@ EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding } #endif - if (ConditionPassed(opcode)) - { - uint32_t Rd; // the destination register - uint32_t imm32; // the immediate value to be written to Rd - uint32_t carry = 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C. - // for setflags == false, this value is a don't care - // initialized to 0 to silence the static analyzer - bool setflags; - switch (encoding) { - case eEncodingT1: - Rd = Bits32(opcode, 10, 8); - setflags = !InITBlock(); - imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) - carry = APSR_C; - - break; - - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); - if (BadReg(Rd)) - return false; - - break; - - case eEncodingT3: - { - // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32); - Rd = Bits32 (opcode, 11, 8); - setflags = false; - uint32_t imm4 = Bits32 (opcode, 19, 16); - uint32_t imm3 = Bits32 (opcode, 14, 12); - uint32_t i = Bit32 (opcode, 26); - uint32_t imm8 = Bits32 (opcode, 7, 0); - imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; - - // if BadReg(d) then UNPREDICTABLE; - if (BadReg (Rd)) - return false; - } - break; - - case eEncodingA1: - // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C); - Rd = Bits32 (opcode, 15, 12); - setflags = BitIsSet (opcode, 20); - imm32 = ARMExpandImm_C (opcode, APSR_C, carry); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if ((Rd == 15) && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - - break; - - case eEncodingA2: - { - // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32); - Rd = Bits32 (opcode, 15, 12); - setflags = false; - uint32_t imm4 = Bits32 (opcode, 19, 16); - uint32_t imm12 = Bits32 (opcode, 11, 0); - imm32 = (imm4 << 12) | imm12; - - // if d == 15 then UNPREDICTABLE; - if (Rd == 15) - return false; - } - break; - - default: - return false; - } - uint32_t result = imm32; + if (ConditionPassed(opcode)) { + uint32_t Rd; // the destination register + uint32_t imm32; // the immediate value to be written to Rd + uint32_t carry = + 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C. + // for setflags == false, this value is a don't care + // initialized to 0 to silence the static analyzer + bool setflags; + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 10, 8); + setflags = !InITBlock(); + imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) + carry = APSR_C; - // The context specifies that an immediate is to be moved into Rd. - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + break; - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); + if (BadReg(Rd)) + return false; + + break; + + case eEncodingT3: { + // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, + // 32); + Rd = Bits32(opcode, 11, 8); + setflags = false; + uint32_t imm4 = Bits32(opcode, 19, 16); + uint32_t imm3 = Bits32(opcode, 14, 12); + uint32_t i = Bit32(opcode, 26); + uint32_t imm8 = Bits32(opcode, 7, 0); + imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; + + // if BadReg(d) then UNPREDICTABLE; + if (BadReg(Rd)) + return false; + } break; + + case eEncodingA1: + // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) = + // ARMExpandImm_C(imm12, APSR.C); + Rd = Bits32(opcode, 15, 12); + setflags = BitIsSet(opcode, 20); + imm32 = ARMExpandImm_C(opcode, APSR_C, carry); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if ((Rd == 15) && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + + break; + + case eEncodingA2: { + // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32); + Rd = Bits32(opcode, 15, 12); + setflags = false; + uint32_t imm4 = Bits32(opcode, 19, 16); + uint32_t imm12 = Bits32(opcode, 11, 0); + imm32 = (imm4 << 12) | imm12; + + // if d == 15 then UNPREDICTABLE; + if (Rd == 15) + return false; + } break; + + default: + return false; } - return true; + uint32_t result = imm32; + + // The context specifies that an immediate is to be moved into Rd. + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// MUL multiplies two register values. The least significant 32 bits of the result are written to the destination -// register. These 32 bits do not depend on whether the source register values are considered to be signed values or +// MUL multiplies two register values. The least significant 32 bits of the +// result are written to the destination +// register. These 32 bits do not depend on whether the source register values +// are considered to be signed values or // unsigned values. // -// Optionally, it can update the condition flags based on the result. In the Thumb instruction set, this option is +// Optionally, it can update the condition flags based on the result. In the +// Thumb instruction set, this option is // limited to only a few forms of the instruction. -bool -EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -959,118 +939,120 @@ EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding enco // else APSR.C unchanged // APSR.V always unchanged #endif - - if (ConditionPassed(opcode)) - { - uint32_t d; - uint32_t n; - uint32_t m; - bool setflags; - - // EncodingSpecificOperations(); - switch (encoding) - { - case eEncodingT1: - // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock(); - d = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - m = Bits32 (opcode, 2, 0); - setflags = !InITBlock(); - - // if ArchVersion() < 6 && d == n then UNPREDICTABLE; - if ((ArchVersion() < ARMv6) && (d == n)) - return false; - - break; - - case eEncodingT2: - // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE; - d = Bits32 (opcode, 11, 8); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - setflags = false; - - // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE; - if (BadReg (d) || BadReg (n) || BadReg (m)) - return false; - - break; - - case eEncodingA1: - // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); - d = Bits32 (opcode, 19, 16); - n = Bits32 (opcode, 3, 0); - m = Bits32 (opcode, 11, 8); - setflags = BitIsSet (opcode, 20); - - // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; - if ((d == 15) || (n == 15) || (m == 15)) - return false; - - // if ArchVersion() < 6 && d == n then UNPREDICTABLE; - if ((ArchVersion() < ARMv6) && (d == n)) - return false; - - break; - - default: - return false; - } - bool success = false; + if (ConditionPassed(opcode)) { + uint32_t d; + uint32_t n; + uint32_t m; + bool setflags; - // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results - uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results - uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - // result = operand1 * operand2; - uint64_t result = operand1 * operand2; - - // R[d] = result<31:0>; - RegisterInfo op1_reg; - RegisterInfo op2_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg); - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg); - - EmulateInstruction::Context context; - context.type = eContextArithmetic; - context.SetRegisterRegisterOperands (op1_reg, op2_reg); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result))) - return false; - - // if setflags then - if (setflags) - { - // APSR.N = result<31>; - // APSR.Z = IsZeroBit(result); - m_new_inst_cpsr = m_opcode_cpsr; - SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31)); - SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); - if (m_new_inst_cpsr != m_opcode_cpsr) - { - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) - return false; - } - - // if ArchVersion() == 4 then - // APSR.C = bit UNKNOWN; - } + // EncodingSpecificOperations(); + switch (encoding) { + case eEncodingT1: + // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock(); + d = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + m = Bits32(opcode, 2, 0); + setflags = !InITBlock(); + + // if ArchVersion() < 6 && d == n then UNPREDICTABLE; + if ((ArchVersion() < ARMv6) && (d == n)) + return false; + + break; + + case eEncodingT2: + // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE; + d = Bits32(opcode, 11, 8); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + setflags = false; + + // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE; + if (BadReg(d) || BadReg(n) || BadReg(m)) + return false; + + break; + + case eEncodingA1: + // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); + d = Bits32(opcode, 19, 16); + n = Bits32(opcode, 3, 0); + m = Bits32(opcode, 11, 8); + setflags = BitIsSet(opcode, 20); + + // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; + if ((d == 15) || (n == 15) || (m == 15)) + return false; + + // if ArchVersion() < 6 && d == n then UNPREDICTABLE; + if ((ArchVersion() < ARMv6) && (d == n)) + return false; + + break; + + default: + return false; } - return true; -} - -// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register. + + bool success = false; + + // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final + // results + uint64_t operand1 = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final + // results + uint64_t operand2 = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + // result = operand1 * operand2; + uint64_t result = operand1 * operand2; + + // R[d] = result<31:0>; + RegisterInfo op1_reg; + RegisterInfo op2_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, op1_reg); + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, op2_reg); + + EmulateInstruction::Context context; + context.type = eContextArithmetic; + context.SetRegisterRegisterOperands(op1_reg, op2_reg); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, + (0x0000ffff & result))) + return false; + + // if setflags then + if (setflags) { + // APSR.N = result<31>; + // APSR.Z = IsZeroBit(result); + m_new_inst_cpsr = m_opcode_cpsr; + SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31)); + SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); + if (m_new_inst_cpsr != m_opcode_cpsr) { + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) + return false; + } + + // if ArchVersion() == 4 then + // APSR.C = bit UNKNOWN; + } + } + return true; +} + +// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to +// the destination register. // It can optionally update the condition flags based on the value. -bool -EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1089,48 +1071,48 @@ EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding e } #endif - if (ConditionPassed(opcode)) - { - uint32_t Rd; // the destination register - uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C - uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C - bool setflags; - switch (encoding) { - case eEncodingT1: - Rd = Bits32(opcode, 11, 8); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm_C(opcode, APSR_C, carry); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } - uint32_t result = ~imm32; - - // The context specifies that an immediate is to be moved into Rd. - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); - - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; + if (ConditionPassed(opcode)) { + uint32_t Rd; // the destination register + uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C + uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C + bool setflags; + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 11, 8); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + setflags = BitIsSet(opcode, 20); + imm32 = ARMExpandImm_C(opcode, APSR_C, carry); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; } - return true; + uint32_t result = ~imm32; + + // The context specifies that an immediate is to be moved into Rd. + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register. +// Bitwise NOT (register) writes the bitwise inverse of a register value to the +// destination register. // It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1150,68 +1132,68 @@ EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding e } #endif - if (ConditionPassed(opcode)) - { - uint32_t Rm; // the source register - uint32_t Rd; // the destination register - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - bool setflags; - uint32_t carry; // the carry bit after the shift operation - switch (encoding) { - case eEncodingT1: - Rd = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - shift_t = SRType_LSL; - shift_n = 0; - if (InITBlock()) - return false; - break; - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; - if (BadReg(Rd) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftARM(opcode, shift_t); - break; - default: - return false; - } - bool success = false; - uint32_t value = ReadCoreReg(Rm, &success); - if (!success) - return false; + if (ConditionPassed(opcode)) { + uint32_t Rm; // the source register + uint32_t Rd; // the destination register + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + bool setflags; + uint32_t carry; // the carry bit after the shift operation + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + shift_t = SRType_LSL; + shift_n = 0; + if (InITBlock()) + return false; + break; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; + if (BadReg(Rd) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftARM(opcode, shift_t); + break; + default: + return false; + } + bool success = false; + uint32_t value = ReadCoreReg(Rm, &success); + if (!success) + return false; - uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry, &success); - if (!success) - return false; - uint32_t result = ~shifted; - - // The context specifies that an immediate is to be moved into Rd. - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + uint32_t shifted = + Shift_C(value, shift_t, shift_n, APSR_C, carry, &success); + if (!success) + return false; + uint32_t result = ~shifted; - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + // The context specifies that an immediate is to be moved into Rd. + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// PC relative immediate load into register, possibly followed by ADD (SP plus register). +// PC relative immediate load into register, possibly followed by ADD (SP plus +// register). // LDR (literal) -bool -EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1232,82 +1214,74 @@ EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARME } #endif - if (ConditionPassed(opcode)) - { - bool success = false; - const uint32_t pc = ReadCoreReg(PC_REG, &success); - if (!success) - return false; - - // PC relative immediate load context - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo pc_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg); - context.SetRegisterPlusOffset (pc_reg, 0); - - uint32_t Rt; // the destination register - uint32_t imm32; // immediate offset from the PC - bool add; // +imm32 or -imm32? - addr_t base; // the base address - addr_t address; // the PC relative address - uint32_t data; // the literal data value from the PC relative load - switch (encoding) { - case eEncodingT1: - Rt = Bits32(opcode, 10, 8); - imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32); - add = true; - break; - case eEncodingT2: - Rt = Bits32(opcode, 15, 12); - imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32); - add = BitIsSet(opcode, 23); - if (Rt == 15 && InITBlock() && !LastInITBlock()) - return false; - break; - default: - return false; - } - - base = Align(pc, 4); - if (add) - address = base + imm32; - else - address = base - imm32; + if (ConditionPassed(opcode)) { + bool success = false; + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; - context.SetRegisterPlusOffset(pc_reg, address - base); - data = MemURead(context, address, 4, 0, &success); - if (!success) - return false; + // PC relative immediate load context + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterPlusOffset; + RegisterInfo pc_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg); + context.SetRegisterPlusOffset(pc_reg, 0); + + uint32_t Rt; // the destination register + uint32_t imm32; // immediate offset from the PC + bool add; // +imm32 or -imm32? + addr_t base; // the base address + addr_t address; // the PC relative address + uint32_t data; // the literal data value from the PC relative load + switch (encoding) { + case eEncodingT1: + Rt = Bits32(opcode, 10, 8); + imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32); + add = true; + break; + case eEncodingT2: + Rt = Bits32(opcode, 15, 12); + imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32); + add = BitIsSet(opcode, 23); + if (Rt == 15 && InITBlock() && !LastInITBlock()) + return false; + break; + default: + return false; + } - if (Rt == 15) - { - if (Bits32(address, 1, 0) == 0) - { - // In ARMv5T and above, this is an interworking branch. - if (!LoadWritePC(context, data)) - return false; - } - else - return false; - } - else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) - { - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) - return false; - } - else // We don't handle ARM for now. - return false; + base = Align(pc, 4); + if (add) + address = base + imm32; + else + address = base - imm32; - } - return true; + context.SetRegisterPlusOffset(pc_reg, address - base); + data = MemURead(context, address, 4, 0, &success); + if (!success) + return false; + + if (Rt == 15) { + if (Bits32(address, 1, 0) == 0) { + // In ARMv5T and above, this is an interworking branch. + if (!LoadWritePC(context, data)) + return false; + } else + return false; + } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) { + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt, + data)) + return false; + } else // We don't handle ARM for now. + return false; + } + return true; } // An add operation to adjust the SP. // ADD (SP plus immediate) -bool -EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1326,105 +1300,99 @@ EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding } #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - const addr_t sp = ReadCoreReg (SP_REG, &success); - if (!success) - return false; - uint32_t imm32; // the immediate operand - uint32_t d; - bool setflags; - switch (encoding) - { - case eEncodingT1: - // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32); - d = Bits32 (opcode, 10, 8); - imm32 = (Bits32 (opcode, 7, 0) << 2); - setflags = false; - break; - - case eEncodingT2: - // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32); - d = 13; - imm32 = ThumbImm7Scaled (opcode); // imm32 = ZeroExtend(imm7:'00', 32) - setflags = false; - break; - - case eEncodingT3: - // d = UInt(Rd); setflags = (S == "1"); imm32 = ThumbExpandImm(i:imm3:imm8); - d = Bits32 (opcode, 11, 8); - imm32 = ThumbExpandImm (opcode); - setflags = Bit32 (opcode, 20); - - // if Rd == "1111" && S == "1" then SEE CMN (immediate); - if (d == 15 && setflags == 1) - return false; // CMN (immediate) not yet supported - - // if d == 15 && S == "0" then UNPREDICTABLE; - if (d == 15 && setflags == 0) - return false; - break; - - case eEncodingT4: - { - // if Rn == '1111' then SEE ADR; - // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); - d = Bits32 (opcode, 11, 8); - setflags = false; - uint32_t i = Bit32 (opcode, 26); - uint32_t imm3 = Bits32 (opcode, 14, 12); - uint32_t imm8 = Bits32 (opcode, 7, 0); - imm32 = (i << 11) | (imm3 << 8) | imm8; - - // if d == 15 then UNPREDICTABLE; - if (d == 15) - return false; - } - break; + if (ConditionPassed(opcode)) { + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + uint32_t imm32; // the immediate operand + uint32_t d; + bool setflags; + switch (encoding) { + case eEncodingT1: + // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32); + d = Bits32(opcode, 10, 8); + imm32 = (Bits32(opcode, 7, 0) << 2); + setflags = false; + break; - default: - return false; - } - // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); - AddWithCarryResult res = AddWithCarry (sp, imm32, 0); + case eEncodingT2: + // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32); + d = 13; + imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) + setflags = false; + break; - EmulateInstruction::Context context; - if (d == 13) - context.type = EmulateInstruction::eContextAdjustStackPointer; - else - context.type = EmulateInstruction::eContextRegisterPlusOffset; + case eEncodingT3: + // d = UInt(Rd); setflags = (S == "1"); imm32 = + // ThumbExpandImm(i:imm3:imm8); + d = Bits32(opcode, 11, 8); + imm32 = ThumbExpandImm(opcode); + setflags = Bit32(opcode, 20); + + // if Rd == "1111" && S == "1" then SEE CMN (immediate); + if (d == 15 && setflags == 1) + return false; // CMN (immediate) not yet supported + + // if d == 15 && S == "0" then UNPREDICTABLE; + if (d == 15 && setflags == 0) + return false; + break; + + case eEncodingT4: { + // if Rn == '1111' then SEE ADR; + // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); + d = Bits32(opcode, 11, 8); + setflags = false; + uint32_t i = Bit32(opcode, 26); + uint32_t imm3 = Bits32(opcode, 14, 12); + uint32_t imm8 = Bits32(opcode, 7, 0); + imm32 = (i << 11) | (imm3 << 8) | imm8; + + // if d == 15 then UNPREDICTABLE; + if (d == 15) + return false; + } break; - RegisterInfo sp_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); - context.SetRegisterPlusOffset (sp_reg, res.result - sp); + default: + return false; + } + // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); + AddWithCarryResult res = AddWithCarry(sp, imm32, 0); - if (d == 15) - { - if (!ALUWritePC (context, res.result)) - return false; - } - else - { - // R[d] = result; - // if setflags then - // APSR.N = result<31>; - // APSR.Z = IsZeroBit(result); - // APSR.C = carry; - // APSR.V = overflow; - if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow)) - return false; - } + EmulateInstruction::Context context; + if (d == 13) + context.type = EmulateInstruction::eContextAdjustStackPointer; + else + context.type = EmulateInstruction::eContextRegisterPlusOffset; + + RegisterInfo sp_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + context.SetRegisterPlusOffset(sp_reg, res.result - sp); + + if (d == 15) { + if (!ALUWritePC(context, res.result)) + return false; + } else { + // R[d] = result; + // if setflags then + // APSR.N = result<31>; + // APSR.Z = IsZeroBit(result); + // APSR.C = carry; + // APSR.V = overflow; + if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags, + res.carry_out, res.overflow)) + return false; } - return true; + } + return true; } // An add operation to adjust the SP. // ADD (SP plus register) -bool -EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1444,49 +1412,48 @@ EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding } #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - const addr_t sp = ReadCoreReg (SP_REG, &success); - if (!success) - return false; - uint32_t Rm; // the second operand - switch (encoding) { - case eEncodingT2: - Rm = Bits32(opcode, 6, 3); - break; - default: - return false; - } - int32_t reg_value = ReadCoreReg(Rm, &success); - if (!success) - return false; - - addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value - - EmulateInstruction::Context context; - context.type = eContextArithmetic; - RegisterInfo sp_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); - - RegisterInfo other_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg); - context.SetRegisterRegisterOperands (sp_reg, other_reg); - - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr)) - return false; + if (ConditionPassed(opcode)) { + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + uint32_t Rm; // the second operand + switch (encoding) { + case eEncodingT2: + Rm = Bits32(opcode, 6, 3); + break; + default: + return false; } - return true; + int32_t reg_value = ReadCoreReg(Rm, &success); + if (!success) + return false; + + addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value + + EmulateInstruction::Context context; + context.type = eContextArithmetic; + RegisterInfo sp_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + + RegisterInfo other_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, other_reg); + context.SetRegisterRegisterOperands(sp_reg, other_reg); + + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP, addr)) + return false; + } + return true; } // Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine // at a PC-relative address, and changes instruction set from ARM to Thumb, or // from Thumb to ARM. // BLX (immediate) -bool -EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1505,91 +1472,92 @@ EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEnco } #endif - bool success = true; + bool success = true; - if (ConditionPassed(opcode)) - { - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - const uint32_t pc = ReadCoreReg(PC_REG, &success); - if (!success) - return false; - addr_t lr; // next instruction address - addr_t target; // target address - int32_t imm32; // PC-relative offset - switch (encoding) { - case eEncodingT1: - { - lr = pc | 1u; // return address - uint32_t S = Bit32(opcode, 26); - uint32_t imm10 = Bits32(opcode, 25, 16); - uint32_t J1 = Bit32(opcode, 13); - uint32_t J2 = Bit32(opcode, 11); - uint32_t imm11 = Bits32(opcode, 10, 0); - uint32_t I1 = !(J1 ^ S); - uint32_t I2 = !(J2 ^ S); - uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); - imm32 = llvm::SignExtend32<25>(imm25); - target = pc + imm32; - SelectInstrSet (eModeThumb); - context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); - if (InITBlock() && !LastInITBlock()) - return false; - break; - } - case eEncodingT2: - { - lr = pc | 1u; // return address - uint32_t S = Bit32(opcode, 26); - uint32_t imm10H = Bits32(opcode, 25, 16); - uint32_t J1 = Bit32(opcode, 13); - uint32_t J2 = Bit32(opcode, 11); - uint32_t imm10L = Bits32(opcode, 10, 1); - uint32_t I1 = !(J1 ^ S); - uint32_t I2 = !(J2 ^ S); - uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2); - imm32 = llvm::SignExtend32<25>(imm25); - target = Align(pc, 4) + imm32; - SelectInstrSet (eModeARM); - context.SetISAAndImmediateSigned (eModeARM, 4 + imm32); - if (InITBlock() && !LastInITBlock()) - return false; - break; - } - case eEncodingA1: - lr = pc - 4; // return address - imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); - target = Align(pc, 4) + imm32; - SelectInstrSet (eModeARM); - context.SetISAAndImmediateSigned (eModeARM, 8 + imm32); - break; - case eEncodingA2: - lr = pc - 4; // return address - imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1); - target = pc + imm32; - SelectInstrSet (eModeThumb); - context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32); - break; - default: - return false; - } - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) - return false; - if (!BranchWritePC(context, target)) - return false; - if (m_opcode_cpsr != m_new_inst_cpsr) - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) - return false; + if (ConditionPassed(opcode)) { + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + addr_t lr; // next instruction address + addr_t target; // target address + int32_t imm32; // PC-relative offset + switch (encoding) { + case eEncodingT1: { + lr = pc | 1u; // return address + uint32_t S = Bit32(opcode, 26); + uint32_t imm10 = Bits32(opcode, 25, 16); + uint32_t J1 = Bit32(opcode, 13); + uint32_t J2 = Bit32(opcode, 11); + uint32_t imm11 = Bits32(opcode, 10, 0); + uint32_t I1 = !(J1 ^ S); + uint32_t I2 = !(J2 ^ S); + uint32_t imm25 = + (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); + imm32 = llvm::SignExtend32<25>(imm25); + target = pc + imm32; + SelectInstrSet(eModeThumb); + context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); + if (InITBlock() && !LastInITBlock()) + return false; + break; + } + case eEncodingT2: { + lr = pc | 1u; // return address + uint32_t S = Bit32(opcode, 26); + uint32_t imm10H = Bits32(opcode, 25, 16); + uint32_t J1 = Bit32(opcode, 13); + uint32_t J2 = Bit32(opcode, 11); + uint32_t imm10L = Bits32(opcode, 10, 1); + uint32_t I1 = !(J1 ^ S); + uint32_t I2 = !(J2 ^ S); + uint32_t imm25 = + (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2); + imm32 = llvm::SignExtend32<25>(imm25); + target = Align(pc, 4) + imm32; + SelectInstrSet(eModeARM); + context.SetISAAndImmediateSigned(eModeARM, 4 + imm32); + if (InITBlock() && !LastInITBlock()) + return false; + break; } - return true; + case eEncodingA1: + lr = pc - 4; // return address + imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); + target = Align(pc, 4) + imm32; + SelectInstrSet(eModeARM); + context.SetISAAndImmediateSigned(eModeARM, 8 + imm32); + break; + case eEncodingA2: + lr = pc - 4; // return address + imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | + Bits32(opcode, 24, 24) << 1); + target = pc + imm32; + SelectInstrSet(eModeThumb); + context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32); + break; + default: + return false; + } + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_RA, lr)) + return false; + if (!BranchWritePC(context, target)) + return false; + if (m_opcode_cpsr != m_new_inst_cpsr) + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) + return false; + } + return true; } // Branch with Link and Exchange (register) calls a subroutine at an address and // instruction set specified by a register. // BLX (register) -bool -EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1606,55 +1574,55 @@ EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding en } #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextAbsoluteBranchRegister; - const uint32_t pc = ReadCoreReg(PC_REG, &success); - addr_t lr; // next instruction address - if (!success) - return false; - uint32_t Rm; // the register with the target address - switch (encoding) { - case eEncodingT1: - lr = (pc - 2) | 1u; // return address - Rm = Bits32(opcode, 6, 3); - // if m == 15 then UNPREDICTABLE; - if (Rm == 15) - return false; - if (InITBlock() && !LastInITBlock()) - return false; - break; - case eEncodingA1: - lr = pc - 4; // return address - Rm = Bits32(opcode, 3, 0); - // if m == 15 then UNPREDICTABLE; - if (Rm == 15) - return false; - break; - default: - return false; - } - addr_t target = ReadCoreReg (Rm, &success); - if (!success) - return false; - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); - context.SetRegister (dwarf_reg); - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) - return false; - if (!BXWritePC(context, target)) - return false; + if (ConditionPassed(opcode)) { + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextAbsoluteBranchRegister; + const uint32_t pc = ReadCoreReg(PC_REG, &success); + addr_t lr; // next instruction address + if (!success) + return false; + uint32_t Rm; // the register with the target address + switch (encoding) { + case eEncodingT1: + lr = (pc - 2) | 1u; // return address + Rm = Bits32(opcode, 6, 3); + // if m == 15 then UNPREDICTABLE; + if (Rm == 15) + return false; + if (InITBlock() && !LastInITBlock()) + return false; + break; + case eEncodingA1: + lr = pc - 4; // return address + Rm = Bits32(opcode, 3, 0); + // if m == 15 then UNPREDICTABLE; + if (Rm == 15) + return false; + break; + default: + return false; } - return true; -} - -// Branch and Exchange causes a branch to an address and instruction set specified by a register. -bool -EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding) -{ + addr_t target = ReadCoreReg(Rm, &success); + if (!success) + return false; + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); + context.SetRegister(dwarf_reg); + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_RA, lr)) + return false; + if (!BXWritePC(context, target)) + return false; + } + return true; +} + +// Branch and Exchange causes a branch to an address and instruction set +// specified by a register. +bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1664,45 +1632,46 @@ EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding enc } #endif - if (ConditionPassed(opcode)) - { - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextAbsoluteBranchRegister; - uint32_t Rm; // the register with the target address - switch (encoding) { - case eEncodingT1: - Rm = Bits32(opcode, 6, 3); - if (InITBlock() && !LastInITBlock()) - return false; - break; - case eEncodingA1: - Rm = Bits32(opcode, 3, 0); - break; - default: - return false; - } - bool success = false; - addr_t target = ReadCoreReg (Rm, &success); - if (!success) - return false; - - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); - context.SetRegister (dwarf_reg); - if (!BXWritePC(context, target)) - return false; + if (ConditionPassed(opcode)) { + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextAbsoluteBranchRegister; + uint32_t Rm; // the register with the target address + switch (encoding) { + case eEncodingT1: + Rm = Bits32(opcode, 6, 3); + if (InITBlock() && !LastInITBlock()) + return false; + break; + case eEncodingA1: + Rm = Bits32(opcode, 3, 0); + break; + default: + return false; } - return true; + bool success = false; + addr_t target = ReadCoreReg(Rm, &success); + if (!success) + return false; + + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); + context.SetRegister(dwarf_reg); + if (!BXWritePC(context, target)) + return false; + } + return true; } -// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an -// address and instruction set specified by a register as though it were a BX instruction. +// Branch and Exchange Jazelle attempts to change to Jazelle state. If the +// attempt fails, it branches to an +// address and instruction set specified by a register as though it were a BX +// instruction. // // TODO: Emulate Jazelle architecture? -// We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation. -bool -EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding) -{ +// We currently assume that switching to Jazelle state fails, thus +// treating BXJ as a BX operation. +bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1718,46 +1687,44 @@ EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding en } #endif - if (ConditionPassed(opcode)) - { - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextAbsoluteBranchRegister; - uint32_t Rm; // the register with the target address - switch (encoding) { - case eEncodingT1: - Rm = Bits32(opcode, 19, 16); - if (BadReg(Rm)) - return false; - if (InITBlock() && !LastInITBlock()) - return false; - break; - case eEncodingA1: - Rm = Bits32(opcode, 3, 0); - if (Rm == 15) - return false; - break; - default: - return false; - } - bool success = false; - addr_t target = ReadCoreReg (Rm, &success); - if (!success) - return false; - - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); - context.SetRegister (dwarf_reg); - if (!BXWritePC(context, target)) - return false; + if (ConditionPassed(opcode)) { + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextAbsoluteBranchRegister; + uint32_t Rm; // the register with the target address + switch (encoding) { + case eEncodingT1: + Rm = Bits32(opcode, 19, 16); + if (BadReg(Rm)) + return false; + if (InITBlock() && !LastInITBlock()) + return false; + break; + case eEncodingA1: + Rm = Bits32(opcode, 3, 0); + if (Rm == 15) + return false; + break; + default: + return false; } - return true; + bool success = false; + addr_t target = ReadCoreReg(Rm, &success); + if (!success) + return false; + + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg); + context.SetRegister(dwarf_reg); + if (!BXWritePC(context, target)) + return false; + } + return true; } // Set r7 to point to some ip offset. // SUB (immediate) -bool -EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1776,40 +1743,38 @@ EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncodi } #endif - if (ConditionPassed(opcode)) - { - bool success = false; - const addr_t ip = ReadCoreReg (12, &success); - if (!success) - return false; - uint32_t imm32; - switch (encoding) { - case eEncodingA1: - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - break; - default: - return false; - } - addr_t ip_offset = imm32; - addr_t addr = ip - ip_offset; // the adjusted ip value - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg); - context.SetRegisterPlusOffset (dwarf_reg, -ip_offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr)) - return false; + if (ConditionPassed(opcode)) { + bool success = false; + const addr_t ip = ReadCoreReg(12, &success); + if (!success) + return false; + uint32_t imm32; + switch (encoding) { + case eEncodingA1: + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + break; + default: + return false; } - return true; + addr_t ip_offset = imm32; + addr_t addr = ip - ip_offset; // the adjusted ip value + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterPlusOffset; + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r12, dwarf_reg); + context.SetRegisterPlusOffset(dwarf_reg, -ip_offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr)) + return false; + } + return true; } // Set ip to point to some stack offset. // SUB (SP minus immediate) -bool -EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1828,42 +1793,41 @@ EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncodi } #endif - if (ConditionPassed(opcode)) - { - bool success = false; - const addr_t sp = ReadCoreReg (SP_REG, &success); - if (!success) - return false; - uint32_t imm32; - switch (encoding) { - case eEncodingA1: - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - break; - default: - return false; - } - addr_t sp_offset = imm32; - addr_t addr = sp - sp_offset; // the adjusted stack pointer value - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg); - context.SetRegisterPlusOffset (dwarf_reg, -sp_offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr)) - return false; + if (ConditionPassed(opcode)) { + bool success = false; + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + uint32_t imm32; + switch (encoding) { + case eEncodingA1: + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + break; + default: + return false; } - return true; + addr_t sp_offset = imm32; + addr_t addr = sp - sp_offset; // the adjusted stack pointer value + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterPlusOffset; + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg); + context.SetRegisterPlusOffset(dwarf_reg, -sp_offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr)) + return false; + } + return true; } // This instruction subtracts an immediate value from the SP value, and writes // the result to the destination register. // -// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage. -bool -EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding) -{ +// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local +// storage. +bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1882,76 +1846,74 @@ EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding } #endif - bool success = false; - if (ConditionPassed(opcode)) - { - const addr_t sp = ReadCoreReg (SP_REG, &success); - if (!success) - return false; - - uint32_t Rd; - bool setflags; - uint32_t imm32; - switch (encoding) { - case eEncodingT1: - Rd = 13; - setflags = false; - imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) - break; - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) - if (Rd == 15 && setflags) - return EmulateCMPImm(opcode, eEncodingT2); - if (Rd == 15 && !setflags) - return false; - break; - case eEncodingT3: - Rd = Bits32(opcode, 11, 8); - setflags = false; - imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) - if (Rd == 15) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } - AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1); + bool success = false; + if (ConditionPassed(opcode)) { + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; - EmulateInstruction::Context context; - if (Rd == 13) - { - uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting to negate it, or the wrong - // value gets passed down to context.SetImmediateSigned. - context.type = EmulateInstruction::eContextAdjustStackPointer; - context.SetImmediateSigned (-imm64); // the stack pointer offset - } - else - { - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); - } + uint32_t Rd; + bool setflags; + uint32_t imm32; + switch (encoding) { + case eEncodingT1: + Rd = 13; + setflags = false; + imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) + break; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) + if (Rd == 15 && setflags) + return EmulateCMPImm(opcode, eEncodingT2); + if (Rd == 15 && !setflags) + return false; + break; + case eEncodingT3: + Rd = Bits32(opcode, 11, 8); + setflags = false; + imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) + if (Rd == 15) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + setflags = BitIsSet(opcode, 20); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } + AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; + EmulateInstruction::Context context; + if (Rd == 13) { + uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting + // to negate it, or the wrong + // value gets passed down to context.SetImmediateSigned. + context.type = EmulateInstruction::eContextAdjustStackPointer; + context.SetImmediateSigned(-imm64); // the stack pointer offset + } else { + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); } - return true; + + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; + } + return true; } // A store operation to the stack that also updates the SP. -bool -EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -1964,93 +1926,88 @@ EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding } #endif - bool success = false; - if (ConditionPassed(opcode)) - { - const uint32_t addr_byte_size = GetAddressByteSize(); - const addr_t sp = ReadCoreReg (SP_REG, &success); - if (!success) - return false; - uint32_t Rt; // the source register - uint32_t imm12; - uint32_t Rn; // This function assumes Rn is the SP, but we should verify that. - - bool index; - bool add; - bool wback; - switch (encoding) { - case eEncodingA1: - Rt = Bits32(opcode, 15, 12); - imm12 = Bits32(opcode, 11, 0); - Rn = Bits32 (opcode, 19, 16); - - if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP. - return false; - - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); - - if (wback && ((Rn == 15) || (Rn == Rt))) - return false; - break; - default: - return false; - } - addr_t offset_addr; - if (add) - offset_addr = sp + imm12; - else - offset_addr = sp - imm12; - - addr_t addr; - if (index) - addr = offset_addr; - else - addr = sp; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextPushRegisterOnStack; - RegisterInfo sp_reg; - RegisterInfo dwarf_reg; - - GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg); - context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp); - if (Rt != 15) - { - uint32_t reg_value = ReadCoreReg(Rt, &success); - if (!success) - return false; - if (!MemUWrite (context, addr, reg_value, addr_byte_size)) - return false; - } - else - { - const uint32_t pc = ReadCoreReg(PC_REG, &success); - if (!success) - return false; - if (!MemUWrite (context, addr, pc, addr_byte_size)) - return false; - } - + bool success = false; + if (ConditionPassed(opcode)) { + const uint32_t addr_byte_size = GetAddressByteSize(); + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + uint32_t Rt; // the source register + uint32_t imm12; + uint32_t + Rn; // This function assumes Rn is the SP, but we should verify that. + + bool index; + bool add; + bool wback; + switch (encoding) { + case eEncodingA1: + Rt = Bits32(opcode, 15, 12); + imm12 = Bits32(opcode, 11, 0); + Rn = Bits32(opcode, 19, 16); - if (wback) - { - context.type = EmulateInstruction::eContextAdjustStackPointer; - context.SetImmediateSigned (addr - sp); - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr)) - return false; - } + if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP. + return false; + + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); + + if (wback && ((Rn == 15) || (Rn == Rt))) + return false; + break; + default: + return false; } - return true; + addr_t offset_addr; + if (add) + offset_addr = sp + imm12; + else + offset_addr = sp - imm12; + + addr_t addr; + if (index) + addr = offset_addr; + else + addr = sp; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextPushRegisterOnStack; + RegisterInfo sp_reg; + RegisterInfo dwarf_reg; + + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg); + context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp); + if (Rt != 15) { + uint32_t reg_value = ReadCoreReg(Rt, &success); + if (!success) + return false; + if (!MemUWrite(context, addr, reg_value, addr_byte_size)) + return false; + } else { + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + if (!MemUWrite(context, addr, pc, addr_byte_size)) + return false; + } + + if (wback) { + context.type = EmulateInstruction::eContextAdjustStackPointer; + context.SetImmediateSigned(addr - sp); + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP, offset_addr)) + return false; + } + } + return true; } // Vector Push stores multiple extension registers to the stack. // It also updates SP to point to the start of the stored data. -bool -EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -2070,81 +2027,79 @@ EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding en } #endif - bool success = false; - if (ConditionPassed(opcode)) - { - const uint32_t addr_byte_size = GetAddressByteSize(); - const addr_t sp = ReadCoreReg (SP_REG, &success); - if (!success) - return false; - bool single_regs; - uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register - uint32_t imm32; // stack offset - uint32_t regs; // number of registers - switch (encoding) { - case eEncodingT1: - case eEncodingA1: - single_regs = false; - d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); - imm32 = Bits32(opcode, 7, 0) * addr_byte_size; - // If UInt(imm8) is odd, see "FSTMX". - regs = Bits32(opcode, 7, 0) / 2; - // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; - if (regs == 0 || regs > 16 || (d + regs) > 32) - return false; - break; - case eEncodingT2: - case eEncodingA2: - single_regs = true; - d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); - imm32 = Bits32(opcode, 7, 0) * addr_byte_size; - regs = Bits32(opcode, 7, 0); - // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; - if (regs == 0 || regs > 16 || (d + regs) > 32) - return false; - break; - default: - return false; - } - uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; - uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; - addr_t sp_offset = imm32; - addr_t addr = sp - sp_offset; - uint32_t i; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextPushRegisterOnStack; + bool success = false; + if (ConditionPassed(opcode)) { + const uint32_t addr_byte_size = GetAddressByteSize(); + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + bool single_regs; + uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register + uint32_t imm32; // stack offset + uint32_t regs; // number of registers + switch (encoding) { + case eEncodingT1: + case eEncodingA1: + single_regs = false; + d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); + imm32 = Bits32(opcode, 7, 0) * addr_byte_size; + // If UInt(imm8) is odd, see "FSTMX". + regs = Bits32(opcode, 7, 0) / 2; + // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; + if (regs == 0 || regs > 16 || (d + regs) > 32) + return false; + break; + case eEncodingT2: + case eEncodingA2: + single_regs = true; + d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); + imm32 = Bits32(opcode, 7, 0) * addr_byte_size; + regs = Bits32(opcode, 7, 0); + // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; + if (regs == 0 || regs > 16 || (d + regs) > 32) + return false; + break; + default: + return false; + } + uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; + uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; + addr_t sp_offset = imm32; + addr_t addr = sp - sp_offset; + uint32_t i; - RegisterInfo dwarf_reg; - RegisterInfo sp_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); - for (i=0; i<regs; ++i) - { - GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg); - context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp); - // uint64_t to accommodate 64-bit registers. - uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success); - if (!success) - return false; - if (!MemAWrite (context, addr, reg_value, reg_byte_size)) - return false; - addr += reg_byte_size; - } - - context.type = EmulateInstruction::eContextAdjustStackPointer; - context.SetImmediateSigned (-sp_offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) - return false; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextPushRegisterOnStack; + + RegisterInfo dwarf_reg; + RegisterInfo sp_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + for (i = 0; i < regs; ++i) { + GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg); + context.SetRegisterToRegisterPlusOffset(dwarf_reg, sp_reg, addr - sp); + // uint64_t to accommodate 64-bit registers. + uint64_t reg_value = ReadRegisterUnsigned(&dwarf_reg, 0, &success); + if (!success) + return false; + if (!MemAWrite(context, addr, reg_value, reg_byte_size)) + return false; + addr += reg_byte_size; } - return true; + + context.type = EmulateInstruction::eContextAdjustStackPointer; + context.SetImmediateSigned(-sp_offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) + return false; + } + return true; } // Vector Pop loads multiple extension registers from the stack. // It also updates SP to point just above the loaded data. -bool -EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -2163,80 +2118,78 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc } #endif - bool success = false; - if (ConditionPassed(opcode)) - { - const uint32_t addr_byte_size = GetAddressByteSize(); - const addr_t sp = ReadCoreReg (SP_REG, &success); - if (!success) - return false; - bool single_regs; - uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register - uint32_t imm32; // stack offset - uint32_t regs; // number of registers - switch (encoding) { - case eEncodingT1: - case eEncodingA1: - single_regs = false; - d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); - imm32 = Bits32(opcode, 7, 0) * addr_byte_size; - // If UInt(imm8) is odd, see "FLDMX". - regs = Bits32(opcode, 7, 0) / 2; - // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; - if (regs == 0 || regs > 16 || (d + regs) > 32) - return false; - break; - case eEncodingT2: - case eEncodingA2: - single_regs = true; - d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); - imm32 = Bits32(opcode, 7, 0) * addr_byte_size; - regs = Bits32(opcode, 7, 0); - // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; - if (regs == 0 || regs > 16 || (d + regs) > 32) - return false; - break; - default: - return false; - } - uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; - uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; - addr_t sp_offset = imm32; - addr_t addr = sp; - uint32_t i; - uint64_t data; // uint64_t to accommodate 64-bit registers. - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextPopRegisterOffStack; + bool success = false; + if (ConditionPassed(opcode)) { + const uint32_t addr_byte_size = GetAddressByteSize(); + const addr_t sp = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + bool single_regs; + uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register + uint32_t imm32; // stack offset + uint32_t regs; // number of registers + switch (encoding) { + case eEncodingT1: + case eEncodingA1: + single_regs = false; + d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); + imm32 = Bits32(opcode, 7, 0) * addr_byte_size; + // If UInt(imm8) is odd, see "FLDMX". + regs = Bits32(opcode, 7, 0) / 2; + // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; + if (regs == 0 || regs > 16 || (d + regs) > 32) + return false; + break; + case eEncodingT2: + case eEncodingA2: + single_regs = true; + d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); + imm32 = Bits32(opcode, 7, 0) * addr_byte_size; + regs = Bits32(opcode, 7, 0); + // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; + if (regs == 0 || regs > 16 || (d + regs) > 32) + return false; + break; + default: + return false; + } + uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; + uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; + addr_t sp_offset = imm32; + addr_t addr = sp; + uint32_t i; + uint64_t data; // uint64_t to accommodate 64-bit registers. - RegisterInfo dwarf_reg; - RegisterInfo sp_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); - for (i=0; i<regs; ++i) - { - GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg); - context.SetAddress(addr); - data = MemARead(context, addr, reg_byte_size, 0, &success); - if (!success) - return false; - if (!WriteRegisterUnsigned(context, &dwarf_reg, data)) - return false; - addr += reg_byte_size; - } - - context.type = EmulateInstruction::eContextAdjustStackPointer; - context.SetImmediateSigned (sp_offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) - return false; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextPopRegisterOffStack; + + RegisterInfo dwarf_reg; + RegisterInfo sp_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + for (i = 0; i < regs; ++i) { + GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i, dwarf_reg); + context.SetAddress(addr); + data = MemARead(context, addr, reg_byte_size, 0, &success); + if (!success) + return false; + if (!WriteRegisterUnsigned(context, &dwarf_reg, data)) + return false; + addr += reg_byte_size; } - return true; + + context.type = EmulateInstruction::eContextAdjustStackPointer; + context.SetImmediateSigned(sp_offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) + return false; + } + return true; } // SVC (previously SWI) -bool -EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -2246,65 +2199,62 @@ EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding enco } #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - const uint32_t pc = ReadCoreReg(PC_REG, &success); - addr_t lr; // next instruction address - if (!success) - return false; - uint32_t imm32; // the immediate constant - uint32_t mode; // ARM or Thumb mode - switch (encoding) { - case eEncodingT1: - lr = (pc + 2) | 1u; // return address - imm32 = Bits32(opcode, 7, 0); - mode = eModeThumb; - break; - case eEncodingA1: - lr = pc + 4; // return address - imm32 = Bits32(opcode, 23, 0); - mode = eModeARM; - break; - default: - return false; - } - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextSupervisorCall; - context.SetISAAndImmediate (mode, imm32); - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr)) - return false; + if (ConditionPassed(opcode)) { + const uint32_t pc = ReadCoreReg(PC_REG, &success); + addr_t lr; // next instruction address + if (!success) + return false; + uint32_t imm32; // the immediate constant + uint32_t mode; // ARM or Thumb mode + switch (encoding) { + case eEncodingT1: + lr = (pc + 2) | 1u; // return address + imm32 = Bits32(opcode, 7, 0); + mode = eModeThumb; + break; + case eEncodingA1: + lr = pc + 4; // return address + imm32 = Bits32(opcode, 23, 0); + mode = eModeARM; + break; + default: + return false; } - return true; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextSupervisorCall; + context.SetISAAndImmediate(mode, imm32); + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_RA, lr)) + return false; + } + return true; } // If Then makes up to four following instructions (the IT block) conditional. -bool -EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateIT(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... EncodingSpecificOperations(); ITSTATE.IT<7:0> = firstcond:mask; #endif - m_it_session.InitIT(Bits32(opcode, 7, 0)); - return true; + m_it_session.InitIT(Bits32(opcode, 7, 0)); + return true; } -bool -EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding) -{ - // NOP, nothing to do... - return true; +bool EmulateInstructionARM::EmulateNop(const uint32_t opcode, + const ARMEncoding encoding) { + // NOP, nothing to do... + return true; } // Branch causes a branch to a target address. -bool -EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateB(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -2314,81 +2264,83 @@ EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encodi } #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - const uint32_t pc = ReadCoreReg(PC_REG, &success); - if (!success) - return false; - addr_t target; // target address - int32_t imm32; // PC-relative offset - switch (encoding) { - case eEncodingT1: - // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). - imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1); - target = pc + imm32; - context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); - break; - case eEncodingT2: - imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1); - target = pc + imm32; - context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); - break; - case eEncodingT3: - // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). - { - if (Bits32(opcode, 25, 23) == 7) - return false; // See Branches and miscellaneous control on page A6-235. - - uint32_t S = Bit32(opcode, 26); - uint32_t imm6 = Bits32(opcode, 21, 16); - uint32_t J1 = Bit32(opcode, 13); - uint32_t J2 = Bit32(opcode, 11); - uint32_t imm11 = Bits32(opcode, 10, 0); - uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); - imm32 = llvm::SignExtend32<21>(imm21); - target = pc + imm32; - context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); - break; - } - case eEncodingT4: - { - uint32_t S = Bit32(opcode, 26); - uint32_t imm10 = Bits32(opcode, 25, 16); - uint32_t J1 = Bit32(opcode, 13); - uint32_t J2 = Bit32(opcode, 11); - uint32_t imm11 = Bits32(opcode, 10, 0); - uint32_t I1 = !(J1 ^ S); - uint32_t I2 = !(J2 ^ S); - uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); - imm32 = llvm::SignExtend32<25>(imm25); - target = pc + imm32; - context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); - break; - } - case eEncodingA1: - imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); - target = pc + imm32; - context.SetISAAndImmediateSigned (eModeARM, 8 + imm32); - break; - default: - return false; - } - if (!BranchWritePC(context, target)) - return false; + if (ConditionPassed(opcode)) { + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + addr_t target; // target address + int32_t imm32; // PC-relative offset + switch (encoding) { + case eEncodingT1: + // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). + imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1); + target = pc + imm32; + context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); + break; + case eEncodingT2: + imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1); + target = pc + imm32; + context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); + break; + case eEncodingT3: + // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). + { + if (Bits32(opcode, 25, 23) == 7) + return false; // See Branches and miscellaneous control on page + // A6-235. + + uint32_t S = Bit32(opcode, 26); + uint32_t imm6 = Bits32(opcode, 21, 16); + uint32_t J1 = Bit32(opcode, 13); + uint32_t J2 = Bit32(opcode, 11); + uint32_t imm11 = Bits32(opcode, 10, 0); + uint32_t imm21 = + (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); + imm32 = llvm::SignExtend32<21>(imm21); + target = pc + imm32; + context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); + break; + } + case eEncodingT4: { + uint32_t S = Bit32(opcode, 26); + uint32_t imm10 = Bits32(opcode, 25, 16); + uint32_t J1 = Bit32(opcode, 13); + uint32_t J2 = Bit32(opcode, 11); + uint32_t imm11 = Bits32(opcode, 10, 0); + uint32_t I1 = !(J1 ^ S); + uint32_t I2 = !(J2 ^ S); + uint32_t imm25 = + (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); + imm32 = llvm::SignExtend32<25>(imm25); + target = pc + imm32; + context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); + break; } - return true; + case eEncodingA1: + imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); + target = pc + imm32; + context.SetISAAndImmediateSigned(eModeARM, 8 + imm32); + break; + default: + return false; + } + if (!BranchWritePC(context, target)) + return false; + } + return true; } -// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with -// zero and conditionally branch forward a constant value. They do not affect the condition flags. +// Compare and Branch on Nonzero and Compare and Branch on Zero compare the +// value in a register with +// zero and conditionally branch forward a constant value. They do not affect +// the condition flags. // CBNZ, CBZ -bool -EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateCB(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... EncodingSpecificOperations(); @@ -2396,50 +2348,53 @@ EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encod BranchWritePC(PC + imm32); #endif - bool success = false; + bool success = false; - // Read the register value from the operand register Rn. - uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success); - if (!success) - return false; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - const uint32_t pc = ReadCoreReg(PC_REG, &success); - if (!success) - return false; + // Read the register value from the operand register Rn. + uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success); + if (!success) + return false; - addr_t target; // target address - uint32_t imm32; // PC-relative offset to branch forward - bool nonzero; - switch (encoding) { - case eEncodingT1: - imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1; - nonzero = BitIsSet(opcode, 11); - target = pc + imm32; - context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); - break; - default: - return false; - } - if (m_ignore_conditions || (nonzero ^ (reg_val == 0))) - if (!BranchWritePC(context, target)) - return false; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; - return true; + addr_t target; // target address + uint32_t imm32; // PC-relative offset to branch forward + bool nonzero; + switch (encoding) { + case eEncodingT1: + imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1; + nonzero = BitIsSet(opcode, 11); + target = pc + imm32; + context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); + break; + default: + return false; + } + if (m_ignore_conditions || (nonzero ^ (reg_val == 0))) + if (!BranchWritePC(context, target)) + return false; + + return true; } -// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets. -// A base register provides a pointer to the table, and a second register supplies an index into the table. +// Table Branch Byte causes a PC-relative forward branch using a table of single +// byte offsets. +// A base register provides a pointer to the table, and a second register +// supplies an index into the table. // The branch length is twice the value of the byte returned from the table. // -// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets. -// A base register provides a pointer to the table, and a second register supplies an index into the table. +// Table Branch Halfword causes a PC-relative forward branch using a table of +// single halfword offsets. +// A base register provides a pointer to the table, and a second register +// supplies an index into the table. // The branch length is twice the value of the halfword returned from the table. // TBB, TBH -bool -EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateTB(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -2450,69 +2405,71 @@ EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encod BranchWritePC(PC + 2*halfwords); #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rn; // the base register which contains the address of the table of branch lengths - uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table - bool is_tbh; // true if table branch halfword - switch (encoding) { - case eEncodingT1: - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - is_tbh = BitIsSet(opcode, 4); - if (Rn == 13 || BadReg(Rm)) - return false; - if (InITBlock() && !LastInITBlock()) - return false; - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rn; // the base register which contains the address of the table of + // branch lengths + uint32_t Rm; // the index register which contains an integer pointing to a + // byte/halfword in the table + bool is_tbh; // true if table branch halfword + switch (encoding) { + case eEncodingT1: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + is_tbh = BitIsSet(opcode, 4); + if (Rn == 13 || BadReg(Rm)) + return false; + if (InITBlock() && !LastInITBlock()) + return false; + break; + default: + return false; + } - // Read the address of the table from the operand register Rn. - // The PC can be used, in which case the table immediately follows this instruction. - uint32_t base = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the address of the table from the operand register Rn. + // The PC can be used, in which case the table immediately follows this + // instruction. + uint32_t base = ReadCoreReg(Rn, &success); + if (!success) + return false; - // the table index - uint32_t index = ReadCoreReg(Rm, &success); - if (!success) - return false; + // the table index + uint32_t index = ReadCoreReg(Rm, &success); + if (!success) + return false; - // the offsetted table address - addr_t addr = base + (is_tbh ? index*2 : index); + // the offsetted table address + addr_t addr = base + (is_tbh ? index * 2 : index); - // PC-relative offset to branch forward - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextTableBranchReadMemory; - uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; - if (!success) - return false; + // PC-relative offset to branch forward + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextTableBranchReadMemory; + uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; + if (!success) + return false; - const uint32_t pc = ReadCoreReg(PC_REG, &success); - if (!success) - return false; + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; - // target address - addr_t target = pc + offset; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - context.SetISAAndImmediateSigned (eModeThumb, 4 + offset); + // target address + addr_t target = pc + offset; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + context.SetISAAndImmediateSigned(eModeThumb, 4 + offset); - if (!BranchWritePC(context, target)) - return false; - } + if (!BranchWritePC(context, target)) + return false; + } - return true; + return true; } -// This instruction adds an immediate value to a register value, and writes the result to the destination register. +// This instruction adds an immediate value to a register value, and writes the +// result to the destination register. // It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -2525,114 +2482,116 @@ EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncod APSR.V = overflow; #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t d; - uint32_t n; - bool setflags; - uint32_t imm32; - uint32_t carry_out; - - //EncodingSpecificOperations(); - switch (encoding) - { - case eEncodingT1: - // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32); - d = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - setflags = !InITBlock(); - imm32 = Bits32 (opcode, 8,6); - - break; - - case eEncodingT2: - // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32); - d = Bits32 (opcode, 10, 8); - n = Bits32 (opcode, 10, 8); - setflags = !InITBlock(); - imm32 = Bits32 (opcode, 7, 0); - - break; - - case eEncodingT3: - // if Rd == '1111' && S == '1' then SEE CMN (immediate); - // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8); - d = Bits32 (opcode, 11, 8); - n = Bits32 (opcode, 19, 16); - setflags = BitIsSet (opcode, 20); - imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out); - - // if Rn == '1101' then SEE ADD (SP plus immediate); - if (n == 13) - return EmulateADDSPImm(opcode, eEncodingT3); - - // if BadReg(d) || n == 15 then UNPREDICTABLE; - if (BadReg (d) || (n == 15)) - return false; - - break; - - case eEncodingT4: - { - // if Rn == '1111' then SEE ADR; - // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); - d = Bits32 (opcode, 11, 8); - n = Bits32 (opcode, 19, 16); - setflags = false; - uint32_t i = Bit32 (opcode, 26); - uint32_t imm3 = Bits32 (opcode, 14, 12); - uint32_t imm8 = Bits32 (opcode, 7, 0); - imm32 = (i << 11) | (imm3 << 8) | imm8; - - // if Rn == '1101' then SEE ADD (SP plus immediate); - if (n == 13) - return EmulateADDSPImm(opcode, eEncodingT4); - - // if BadReg(d) then UNPREDICTABLE; - if (BadReg (d)) - return false; - - break; - } + if (ConditionPassed(opcode)) { + uint32_t d; + uint32_t n; + bool setflags; + uint32_t imm32; + uint32_t carry_out; - default: - return false; - } + // EncodingSpecificOperations(); + switch (encoding) { + case eEncodingT1: + // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = + // ZeroExtend(imm3, 32); + d = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + imm32 = Bits32(opcode, 8, 6); - uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; + break; + + case eEncodingT2: + // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = + // ZeroExtend(imm8, 32); + d = Bits32(opcode, 10, 8); + n = Bits32(opcode, 10, 8); + setflags = !InITBlock(); + imm32 = Bits32(opcode, 7, 0); - //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); - AddWithCarryResult res = AddWithCarry (Rn, imm32, 0); + break; - RegisterInfo reg_n; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n); + case eEncodingT3: + // if Rd == '1111' && S == '1' then SEE CMN (immediate); + // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = + // ThumbExpandImm(i:imm3:imm8); + d = Bits32(opcode, 11, 8); + n = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out); + + // if Rn == '1101' then SEE ADD (SP plus immediate); + if (n == 13) + return EmulateADDSPImm(opcode, eEncodingT3); + + // if BadReg(d) || n == 15 then UNPREDICTABLE; + if (BadReg(d) || (n == 15)) + return false; - EmulateInstruction::Context context; - context.type = eContextArithmetic; - context.SetRegisterPlusOffset (reg_n, imm32); + break; + + case eEncodingT4: { + // if Rn == '1111' then SEE ADR; + // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = + // ZeroExtend(i:imm3:imm8, 32); + d = Bits32(opcode, 11, 8); + n = Bits32(opcode, 19, 16); + setflags = false; + uint32_t i = Bit32(opcode, 26); + uint32_t imm3 = Bits32(opcode, 14, 12); + uint32_t imm8 = Bits32(opcode, 7, 0); + imm32 = (i << 11) | (imm3 << 8) | imm8; + + // if Rn == '1101' then SEE ADD (SP plus immediate); + if (n == 13) + return EmulateADDSPImm(opcode, eEncodingT4); + + // if BadReg(d) then UNPREDICTABLE; + if (BadReg(d)) + return false; - //R[d] = result; - //if setflags then - //APSR.N = result<31>; - //APSR.Z = IsZeroBit(result); - //APSR.C = carry; - //APSR.V = overflow; - if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow)) - return false; + break; + } + default: + return false; } - return true; -} - -// This instruction adds an immediate value to a register value, and writes the result to the destination + + uint64_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); + AddWithCarryResult res = AddWithCarry(Rn, imm32, 0); + + RegisterInfo reg_n; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n); + + EmulateInstruction::Context context; + context.type = eContextArithmetic; + context.SetRegisterPlusOffset(reg_n, imm32); + + // R[d] = result; + // if setflags then + // APSR.N = result<31>; + // APSR.Z = IsZeroBit(result); + // APSR.C = carry; + // APSR.V = overflow; + if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags, + res.carry_out, res.overflow)) + return false; + } + return true; +} + +// This instruction adds an immediate value to a register value, and writes the +// result to the destination // register. It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -2649,55 +2608,56 @@ EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncodin APSR.V = overflow; #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn; - uint32_t imm32; // the immediate value to be added to the value obtained from Rn - bool setflags; - switch (encoding) - { - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn; + uint32_t + imm32; // the immediate value to be added to the value obtained from Rn + bool setflags; + switch (encoding) { + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - AddWithCarryResult res = AddWithCarry(val1, imm32, 0); + AddWithCarryResult res = AddWithCarry(val1, imm32, 0); - EmulateInstruction::Context context; - if (Rd == 13) - context.type = EmulateInstruction::eContextAdjustStackPointer; - else if (Rd == GetFramePointerRegisterNumber()) - context.type = EmulateInstruction::eContextSetFramePointer; - else - context.type = EmulateInstruction::eContextRegisterPlusOffset; + EmulateInstruction::Context context; + if (Rd == 13) + context.type = EmulateInstruction::eContextAdjustStackPointer; + else if (Rd == GetFramePointerRegisterNumber()) + context.type = EmulateInstruction::eContextSetFramePointer; + else + context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg); - context.SetRegisterPlusOffset (dwarf_reg, imm32); + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg); + context.SetRegisterPlusOffset(dwarf_reg, imm32); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; + } + return true; } -// This instruction adds a register value and an optionally-shifted register value, and writes the result -// to the destination register. It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding) -{ +// This instruction adds a register value and an optionally-shifted register +// value, and writes the result +// to the destination register. It can optionally update the condition flags +// based on the result. +bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -2715,80 +2675,78 @@ EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn, Rm; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - bool setflags; - switch (encoding) - { - case eEncodingT1: - Rd = Bits32(opcode, 2, 0); - Rn = Bits32(opcode, 5, 3); - Rm = Bits32(opcode, 8, 6); - setflags = !InITBlock(); - shift_t = SRType_LSL; - shift_n = 0; - break; - case eEncodingT2: - Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 6, 3); - setflags = false; - shift_t = SRType_LSL; - shift_n = 0; - if (Rn == 15 && Rm == 15) - return false; - if (Rd == 15 && InITBlock() && !LastInITBlock()) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftARM(opcode, shift_t); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn, Rm; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + bool setflags; + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 2, 0); + Rn = Bits32(opcode, 5, 3); + Rm = Bits32(opcode, 8, 6); + setflags = !InITBlock(); + shift_t = SRType_LSL; + shift_n = 0; + break; + case eEncodingT2: + Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 6, 3); + setflags = false; + shift_t = SRType_LSL; + shift_n = 0; + if (Rn == 15 && Rm == 15) + return false; + if (Rd == 15 && InITBlock() && !LastInITBlock()) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftARM(opcode, shift_t); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - // Read the second operand. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; + // Read the second operand. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - AddWithCarryResult res = AddWithCarry(val1, shifted, 0); + uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + AddWithCarryResult res = AddWithCarry(val1, shifted, 0); - EmulateInstruction::Context context; - context.type = eContextArithmetic; - RegisterInfo op1_reg; - RegisterInfo op2_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg); - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg); - context.SetRegisterRegisterOperands (op1_reg, op2_reg); + EmulateInstruction::Context context; + context.type = eContextArithmetic; + RegisterInfo op1_reg; + RegisterInfo op2_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg); + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg); + context.SetRegisterRegisterOperands(op1_reg, op2_reg); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; + } + return true; } // Compare Negative (immediate) adds a register value and an immediate value. // It updates the condition flags based on the result, and discards the result. -bool -EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -2800,45 +2758,45 @@ EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; + + uint32_t Rn; // the first operand + uint32_t imm32; // the immediate value to be compared with + switch (encoding) { + case eEncodingT1: + Rn = Bits32(opcode, 19, 16); + imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) + if (Rn == 15) + return false; + break; + case eEncodingA1: + Rn = Bits32(opcode, 19, 16); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + break; + default: + return false; + } + // Read the register value from the operand register Rn. + uint32_t reg_val = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t Rn; // the first operand - uint32_t imm32; // the immediate value to be compared with - switch (encoding) { - case eEncodingT1: - Rn = Bits32(opcode, 19, 16); - imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) - if (Rn == 15) - return false; - break; - case eEncodingA1: - Rn = Bits32(opcode, 19, 16); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - break; - default: - return false; - } - // Read the register value from the operand register Rn. - uint32_t reg_val = ReadCoreReg(Rn, &success); - if (!success) - return false; - - AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0); + AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); - if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) - return false; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) + return false; - return true; + return true; } -// Compare Negative (register) adds a register value and an optionally-shifted register value. +// Compare Negative (register) adds a register value and an optionally-shifted +// register value. // It updates the condition flags based on the result, and discards the result. -bool -EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -2851,64 +2809,63 @@ EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; + + uint32_t Rn; // the first operand + uint32_t Rm; // the second operand + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + switch (encoding) { + case eEncodingT1: + Rn = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + shift_t = SRType_LSL; + shift_n = 0; + break; + case eEncodingT2: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + // if n == 15 || BadReg(m) then UNPREDICTABLE; + if (Rn == 15 || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + shift_n = DecodeImmShiftARM(opcode, shift_t); + break; + default: + return false; + } + // Read the register value from register Rn. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t Rn; // the first operand - uint32_t Rm; // the second operand - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - switch (encoding) { - case eEncodingT1: - Rn = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - shift_t = SRType_LSL; - shift_n = 0; - break; - case eEncodingT2: - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - // if n == 15 || BadReg(m) then UNPREDICTABLE; - if (Rn == 15 || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - shift_n = DecodeImmShiftARM(opcode, shift_t); - break; - default: - return false; - } - // Read the register value from register Rn. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the register value from register Rm. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - // Read the register value from register Rm. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; - - uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - AddWithCarryResult res = AddWithCarry(val1, shifted, 0); + uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + AddWithCarryResult res = AddWithCarry(val1, shifted, 0); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs(); - if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) - return false; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) + return false; - return true; + return true; } // Compare (immediate) subtracts an immediate value from a register value. // It updates the condition flags based on the result, and discards the result. -bool -EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -2920,49 +2877,49 @@ EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; + + uint32_t Rn; // the first operand + uint32_t imm32; // the immediate value to be compared with + switch (encoding) { + case eEncodingT1: + Rn = Bits32(opcode, 10, 8); + imm32 = Bits32(opcode, 7, 0); + break; + case eEncodingT2: + Rn = Bits32(opcode, 19, 16); + imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) + if (Rn == 15) + return false; + break; + case eEncodingA1: + Rn = Bits32(opcode, 19, 16); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + break; + default: + return false; + } + // Read the register value from the operand register Rn. + uint32_t reg_val = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t Rn; // the first operand - uint32_t imm32; // the immediate value to be compared with - switch (encoding) { - case eEncodingT1: - Rn = Bits32(opcode, 10, 8); - imm32 = Bits32(opcode, 7, 0); - break; - case eEncodingT2: - Rn = Bits32(opcode, 19, 16); - imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) - if (Rn == 15) - return false; - break; - case eEncodingA1: - Rn = Bits32(opcode, 19, 16); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - break; - default: - return false; - } - // Read the register value from the operand register Rn. - uint32_t reg_val = ReadCoreReg(Rn, &success); - if (!success) - return false; - - AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); + AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); - if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) - return false; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) + return false; - return true; + return true; } -// Compare (register) subtracts an optionally-shifted register value from a register value. +// Compare (register) subtracts an optionally-shifted register value from a +// register value. // It updates the condition flags based on the result, and discards the result. -bool -EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -2975,74 +2932,75 @@ EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; + + uint32_t Rn; // the first operand + uint32_t Rm; // the second operand + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + switch (encoding) { + case eEncodingT1: + Rn = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + shift_t = SRType_LSL; + shift_n = 0; + break; + case eEncodingT2: + Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 6, 3); + shift_t = SRType_LSL; + shift_n = 0; + if (Rn < 8 && Rm < 8) + return false; + if (Rn == 15 || Rm == 15) + return false; + break; + case eEncodingT3: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + if (Rn == 15 || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + shift_n = DecodeImmShiftARM(opcode, shift_t); + break; + default: + return false; + } + // Read the register value from register Rn. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t Rn; // the first operand - uint32_t Rm; // the second operand - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - switch (encoding) { - case eEncodingT1: - Rn = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - shift_t = SRType_LSL; - shift_n = 0; - break; - case eEncodingT2: - Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 6, 3); - shift_t = SRType_LSL; - shift_n = 0; - if (Rn < 8 && Rm < 8) - return false; - if (Rn == 15 || Rm == 15) - return false; - break; - case eEncodingT3: - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - if (Rn == 15 || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - shift_n = DecodeImmShiftARM(opcode, shift_t); - break; - default: - return false; - } - // Read the register value from register Rn. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the register value from register Rm. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - // Read the register value from register Rm. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; - - uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); + uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs(); - if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) - return false; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + if (!WriteFlags(context, res.result, res.carry_out, res.overflow)) + return false; - return true; + return true; } -// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits, -// shifting in copies of its sign bit, and writes the result to the destination register. It can +// Arithmetic Shift Right (immediate) shifts a register value right by an +// immediate number of bits, +// shifting in copies of its sign bit, and writes the result to the destination +// register. It can // optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3059,16 +3017,18 @@ EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - return EmulateShiftImm (opcode, encoding, SRType_ASR); + return EmulateShiftImm(opcode, encoding, SRType_ASR); } -// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits, -// shifting in copies of its sign bit, and writes the result to the destination register. -// The variable number of bits is read from the bottom byte of a register. It can optionally update +// Arithmetic Shift Right (register) shifts a register value right by a variable +// number of bits, +// shifting in copies of its sign bit, and writes the result to the destination +// register. +// The variable number of bits is read from the bottom byte of a register. It +// can optionally update // the condition flags based on the result. -bool -EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3083,15 +3043,16 @@ EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - return EmulateShiftReg (opcode, encoding, SRType_ASR); + return EmulateShiftReg(opcode, encoding, SRType_ASR); } -// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits, -// shifting in zeros, and writes the result to the destination register. It can optionally +// Logical Shift Left (immediate) shifts a register value left by an immediate +// number of bits, +// shifting in zeros, and writes the result to the destination register. It can +// optionally // update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3108,16 +3069,18 @@ EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - return EmulateShiftImm (opcode, encoding, SRType_LSL); + return EmulateShiftImm(opcode, encoding, SRType_LSL); } -// Logical Shift Left (register) shifts a register value left by a variable number of bits, -// shifting in zeros, and writes the result to the destination register. The variable number -// of bits is read from the bottom byte of a register. It can optionally update the condition +// Logical Shift Left (register) shifts a register value left by a variable +// number of bits, +// shifting in zeros, and writes the result to the destination register. The +// variable number +// of bits is read from the bottom byte of a register. It can optionally update +// the condition // flags based on the result. -bool -EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3132,15 +3095,16 @@ EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - return EmulateShiftReg (opcode, encoding, SRType_LSL); + return EmulateShiftReg(opcode, encoding, SRType_LSL); } -// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits, -// shifting in zeros, and writes the result to the destination register. It can optionally +// Logical Shift Right (immediate) shifts a register value right by an immediate +// number of bits, +// shifting in zeros, and writes the result to the destination register. It can +// optionally // update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3157,16 +3121,18 @@ EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - return EmulateShiftImm (opcode, encoding, SRType_LSR); + return EmulateShiftImm(opcode, encoding, SRType_LSR); } -// Logical Shift Right (register) shifts a register value right by a variable number of bits, -// shifting in zeros, and writes the result to the destination register. The variable number -// of bits is read from the bottom byte of a register. It can optionally update the condition +// Logical Shift Right (register) shifts a register value right by a variable +// number of bits, +// shifting in zeros, and writes the result to the destination register. The +// variable number +// of bits is read from the bottom byte of a register. It can optionally update +// the condition // flags based on the result. -bool -EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3181,15 +3147,16 @@ EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - return EmulateShiftReg (opcode, encoding, SRType_LSR); + return EmulateShiftReg(opcode, encoding, SRType_LSR); } -// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value. -// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. +// Rotate Right (immediate) provides the value of the contents of a register +// rotated by a constant value. +// The bits that are rotated off the right end are inserted into the vacated bit +// positions on the left. // It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3206,16 +3173,18 @@ EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - return EmulateShiftImm (opcode, encoding, SRType_ROR); + return EmulateShiftImm(opcode, encoding, SRType_ROR); } -// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits. -// The bits that are rotated off the right end are inserted into the vacated bit positions on the left. -// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition +// Rotate Right (register) provides the value of the contents of a register +// rotated by a variable number of bits. +// The bits that are rotated off the right end are inserted into the vacated bit +// positions on the left. +// The variable number of bits is read from the bottom byte of a register. It +// can optionally update the condition // flags based on the result. -bool -EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3230,17 +3199,17 @@ EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - return EmulateShiftReg (opcode, encoding, SRType_ROR); + return EmulateShiftReg(opcode, encoding, SRType_ROR); } -// Rotate Right with Extend provides the value of the contents of a register shifted right by one place, +// Rotate Right with Extend provides the value of the contents of a register +// shifted right by one place, // with the carry flag shifted into bit [31]. // // RRX can optionally update the condition flags based on the result. // In that case, bit [0] is shifted into the carry flag. -bool -EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3257,176 +3226,177 @@ EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding enco // APSR.V unchanged #endif - return EmulateShiftImm (opcode, encoding, SRType_RRX); + return EmulateShiftImm(opcode, encoding, SRType_RRX); } -bool -EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) -{ -// assert(shift_type == SRType_ASR -// || shift_type == SRType_LSL -// || shift_type == SRType_LSR -// || shift_type == SRType_ROR -// || shift_type == SRType_RRX); +bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode, + const ARMEncoding encoding, + ARM_ShifterType shift_type) { + // assert(shift_type == SRType_ASR + // || shift_type == SRType_LSL + // || shift_type == SRType_LSR + // || shift_type == SRType_ROR + // || shift_type == SRType_RRX); - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd; // the destination register - uint32_t Rm; // the first operand register - uint32_t imm5; // encoding for the shift amount - uint32_t carry; // the carry bit after the shift operation - bool setflags; - - // Special case handling! - // A8.6.139 ROR (immediate) -- Encoding T1 - ARMEncoding use_encoding = encoding; - if (shift_type == SRType_ROR && use_encoding == eEncodingT1) - { - // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to - // have the same decoding of bit fields as the other Thumb2 shift operations. - use_encoding = eEncodingT2; - } + if (ConditionPassed(opcode)) { + uint32_t Rd; // the destination register + uint32_t Rm; // the first operand register + uint32_t imm5; // encoding for the shift amount + uint32_t carry; // the carry bit after the shift operation + bool setflags; - switch (use_encoding) { - case eEncodingT1: - // Due to the above special case handling! - if (shift_type == SRType_ROR) - return false; + // Special case handling! + // A8.6.139 ROR (immediate) -- Encoding T1 + ARMEncoding use_encoding = encoding; + if (shift_type == SRType_ROR && use_encoding == eEncodingT1) { + // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding + // to + // have the same decoding of bit fields as the other Thumb2 shift + // operations. + use_encoding = eEncodingT2; + } - Rd = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - imm5 = Bits32(opcode, 10, 6); - break; - case eEncodingT2: - // A8.6.141 RRX - // There's no imm form of RRX instructions. - if (shift_type == SRType_RRX) - return false; + switch (use_encoding) { + case eEncodingT1: + // Due to the above special case handling! + if (shift_type == SRType_ROR) + return false; - Rd = Bits32(opcode, 11, 8); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6); - if (BadReg(Rd) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - imm5 = Bits32(opcode, 11, 7); - break; - default: - return false; - } + Rd = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + imm5 = Bits32(opcode, 10, 6); + break; + case eEncodingT2: + // A8.6.141 RRX + // There's no imm form of RRX instructions. + if (shift_type == SRType_RRX) + return false; - // A8.6.139 ROR (immediate) - if (shift_type == SRType_ROR && imm5 == 0) - shift_type = SRType_RRX; + Rd = Bits32(opcode, 11, 8); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6); + if (BadReg(Rd) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + imm5 = Bits32(opcode, 11, 7); + break; + default: + return false; + } - // Get the first operand. - uint32_t value = ReadCoreReg (Rm, &success); - if (!success) - return false; + // A8.6.139 ROR (immediate) + if (shift_type == SRType_ROR && imm5 == 0) + shift_type = SRType_RRX; - // Decode the shift amount if not RRX. - uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5)); + // Get the first operand. + uint32_t value = ReadCoreReg(Rm, &success); + if (!success) + return false; - uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success); - if (!success) - return false; + // Decode the shift amount if not RRX. + uint32_t amt = + (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5)); - // The context specifies that an immediate is to be moved into Rd. - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); - - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success); + if (!success) + return false; + + // The context specifies that an immediate is to be moved into Rd. + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -bool -EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) -{ - // assert(shift_type == SRType_ASR - // || shift_type == SRType_LSL - // || shift_type == SRType_LSR - // || shift_type == SRType_ROR); +bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode, + const ARMEncoding encoding, + ARM_ShifterType shift_type) { + // assert(shift_type == SRType_ASR + // || shift_type == SRType_LSL + // || shift_type == SRType_LSR + // || shift_type == SRType_ROR); - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd; // the destination register - uint32_t Rn; // the first operand register - uint32_t Rm; // the register whose bottom byte contains the amount to shift by - uint32_t carry; // the carry bit after the shift operation - bool setflags; - switch (encoding) { - case eEncodingT1: - Rd = Bits32(opcode, 2, 0); - Rn = Rd; - Rm = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - break; - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 3, 0); - Rm = Bits32(opcode, 11, 8); - setflags = BitIsSet(opcode, 20); - if (Rd == 15 || Rn == 15 || Rm == 15) - return false; - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd; // the destination register + uint32_t Rn; // the first operand register + uint32_t + Rm; // the register whose bottom byte contains the amount to shift by + uint32_t carry; // the carry bit after the shift operation + bool setflags; + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 2, 0); + Rn = Rd; + Rm = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + break; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 3, 0); + Rm = Bits32(opcode, 11, 8); + setflags = BitIsSet(opcode, 20); + if (Rd == 15 || Rn == 15 || Rm == 15) + return false; + break; + default: + return false; + } - // Get the first operand. - uint32_t value = ReadCoreReg (Rn, &success); - if (!success) - return false; - // Get the Rm register content. - uint32_t val = ReadCoreReg (Rm, &success); - if (!success) - return false; + // Get the first operand. + uint32_t value = ReadCoreReg(Rn, &success); + if (!success) + return false; + // Get the Rm register content. + uint32_t val = ReadCoreReg(Rm, &success); + if (!success) + return false; - // Get the shift amount. - uint32_t amt = Bits32(val, 7, 0); + // Get the shift amount. + uint32_t amt = Bits32(val, 7, 0); - uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success); - if (!success) - return false; + uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success); + if (!success) + return false; - // The context specifies that an immediate is to be moved into Rd. - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); - - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + // The context specifies that an immediate is to be moved into Rd. + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } // LDM loads multiple registers from consecutive memory locations, using an -// address from a base register. Optionally the address just above the highest of those locations +// address from a base register. Optionally the address just above the highest +// of those locations // can be written back to the base register. -bool -EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() @@ -3443,133 +3413,133 @@ EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding enco if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 #endif - - bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t n; - uint32_t registers = 0; - bool wback; - const uint32_t addr_byte_size = GetAddressByteSize(); - switch (encoding) + + bool success = false; + if (ConditionPassed(opcode)) { + uint32_t n; + uint32_t registers = 0; + bool wback; + const uint32_t addr_byte_size = GetAddressByteSize(); + switch (encoding) { + case eEncodingT1: + // n = UInt(Rn); registers = '00000000':register_list; wback = + // (registers<n> == '0'); + n = Bits32(opcode, 10, 8); + registers = Bits32(opcode, 7, 0); + registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. + wback = BitIsClear(registers, n); + // if BitCount(registers) < 1 then UNPREDICTABLE; + if (BitCount(registers) < 1) + return false; + break; + case eEncodingT2: + // if W == '1' && Rn == '1101' then SEE POP; + // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + registers = registers & 0xdfff; // Make sure bit 13 is zero. + wback = BitIsSet(opcode, 21); + + // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then + // UNPREDICTABLE; + if ((n == 15) || (BitCount(registers) < 2) || + (BitIsSet(opcode, 14) && BitIsSet(opcode, 15))) + return false; + + // if registers<15> == '1' && InITBlock() && !LastInITBlock() then + // UNPREDICTABLE; + if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) + return false; + + // if wback && registers<n> == '1' then UNPREDICTABLE; + if (wback && BitIsSet(registers, n)) + return false; + break; + + case eEncodingA1: + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + wback = BitIsSet(opcode, 21); + if ((n == 15) || (BitCount(registers) < 1)) + return false; + break; + default: + return false; + } + + int32_t offset = 0; + const addr_t base_address = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterPlusOffset; + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); + context.SetRegisterPlusOffset(dwarf_reg, offset); + + for (int i = 0; i < 14; ++i) { + if (BitIsSet(registers, i)) { + context.type = EmulateInstruction::eContextRegisterPlusOffset; + context.SetRegisterPlusOffset(dwarf_reg, offset); + if (wback && (n == 13)) // Pop Instruction { - case eEncodingT1: - // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0'); - n = Bits32 (opcode, 10, 8); - registers = Bits32 (opcode, 7, 0); - registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. - wback = BitIsClear (registers, n); - // if BitCount(registers) < 1 then UNPREDICTABLE; - if (BitCount(registers) < 1) - return false; - break; - case eEncodingT2: - // if W == '1' && Rn == '1101' then SEE POP; - // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - registers = registers & 0xdfff; // Make sure bit 13 is zero. - wback = BitIsSet (opcode, 21); - - // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; - if ((n == 15) - || (BitCount (registers) < 2) - || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) - return false; - - // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; - if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) - return false; - - // if wback && registers<n> == '1' then UNPREDICTABLE; - if (wback - && BitIsSet (registers, n)) - return false; - break; - - case eEncodingA1: - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - wback = BitIsSet (opcode, 21); - if ((n == 15) - || (BitCount (registers) < 1)) - return false; - break; - default: - return false; + context.type = EmulateInstruction::eContextPopRegisterOffStack; + context.SetAddress(base_address + offset); } - - int32_t offset = 0; - const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + + // R[i] = MemA [address, 4]; address = address + 4; + uint32_t data = MemARead(context, base_address + offset, addr_byte_size, + 0, &success); if (!success) - return false; + return false; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); - context.SetRegisterPlusOffset (dwarf_reg, offset); - - for (int i = 0; i < 14; ++i) - { - if (BitIsSet (registers, i)) - { - context.type = EmulateInstruction::eContextRegisterPlusOffset; - context.SetRegisterPlusOffset (dwarf_reg, offset); - if (wback && (n == 13)) // Pop Instruction - { - context.type = EmulateInstruction::eContextPopRegisterOffStack; - context.SetAddress(base_address + offset); - } - - // R[i] = MemA [address, 4]; address = address + 4; - uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, + data)) + return false; - offset += addr_byte_size; - } - } - - if (BitIsSet (registers, 15)) - { - //LoadWritePC (MemA [address, 4]); - context.type = EmulateInstruction::eContextRegisterPlusOffset; - context.SetRegisterPlusOffset (dwarf_reg, offset); - uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success); - if (!success) - return false; - // In ARMv5T and above, this is an interworking branch. - if (!LoadWritePC(context, data)) - return false; - } - - if (wback && BitIsClear (registers, n)) - { - // R[n] = R[n] + 4 * BitCount (registers) - int32_t offset = addr_byte_size * BitCount (registers); - context.type = EmulateInstruction::eContextAdjustBaseRegister; - context.SetRegisterPlusOffset (dwarf_reg, offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset)) - return false; - } - if (wback && BitIsSet (registers, n)) - // R[n] bits(32) UNKNOWN; - return WriteBits32Unknown (n); + offset += addr_byte_size; + } } - return true; + + if (BitIsSet(registers, 15)) { + // LoadWritePC (MemA [address, 4]); + context.type = EmulateInstruction::eContextRegisterPlusOffset; + context.SetRegisterPlusOffset(dwarf_reg, offset); + uint32_t data = + MemARead(context, base_address + offset, addr_byte_size, 0, &success); + if (!success) + return false; + // In ARMv5T and above, this is an interworking branch. + if (!LoadWritePC(context, data)) + return false; + } + + if (wback && BitIsClear(registers, n)) { + // R[n] = R[n] + 4 * BitCount (registers) + int32_t offset = addr_byte_size * BitCount(registers); + context.type = EmulateInstruction::eContextAdjustBaseRegister; + context.SetRegisterPlusOffset(dwarf_reg, offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + base_address + offset)) + return false; + } + if (wback && BitIsSet(registers, n)) + // R[n] bits(32) UNKNOWN; + return WriteBits32Unknown(n); + } + return true; } - -// LDMDA loads multiple registers from consecutive memory locations using an address from a base register. -// The consecutive memory locations end at this address and the address just below the lowest of those locations + +// LDMDA loads multiple registers from consecutive memory locations using an +// address from a base register. +// The consecutive memory locations end at this address and the address just +// below the lowest of those locations // can optionally be written back to the base register. -bool -EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3586,107 +3556,107 @@ EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding en if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t n; - uint32_t registers = 0; - bool wback; - const uint32_t addr_byte_size = GetAddressByteSize(); - - // EncodingSpecificOperations(); - switch (encoding) - { - case eEncodingA1: - // n = UInt(Rn); registers = register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - wback = BitIsSet (opcode, 21); - - // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; - if ((n == 15) || (BitCount (registers) < 1)) - return false; - - break; - default: - return false; - } - // address = R[n] - 4*BitCount(registers) + 4; - - int32_t offset = 0; - addr_t Rn = ReadCoreReg (n, &success); - - if (!success) - return false; - - addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); - context.SetRegisterPlusOffset (dwarf_reg, offset); - - // for i = 0 to 14 - for (int i = 0; i < 14; ++i) - { - // if registers<i> == '1' then - if (BitIsSet (registers, i)) - { - // R[i] = MemA[address,4]; address = address + 4; - context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); - uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); - if (!success) - return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) - return false; - offset += addr_byte_size; - } - } - - // if registers<15> == '1' then - // LoadWritePC(MemA[address,4]); - if (BitIsSet (registers, 15)) - { - context.SetRegisterPlusOffset (dwarf_reg, offset); - uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); - if (!success) - return false; - // In ARMv5T and above, this is an interworking branch. - if (!LoadWritePC(context, data)) - return false; - } - - // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); - if (wback && BitIsClear (registers, n)) - { - if (!success) - return false; + bool success = false; - offset = (addr_byte_size * BitCount (registers)) * -1; - context.type = EmulateInstruction::eContextAdjustBaseRegister; - context.SetImmediateSigned (offset); - addr_t addr = Rn + offset; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) - return false; - } - - // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; - if (wback && BitIsSet (registers, n)) - return WriteBits32Unknown (n); + if (ConditionPassed(opcode)) { + uint32_t n; + uint32_t registers = 0; + bool wback; + const uint32_t addr_byte_size = GetAddressByteSize(); + + // EncodingSpecificOperations(); + switch (encoding) { + case eEncodingA1: + // n = UInt(Rn); registers = register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + wback = BitIsSet(opcode, 21); + + // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; + if ((n == 15) || (BitCount(registers) < 1)) + return false; + + break; + + default: + return false; } - return true; + // address = R[n] - 4*BitCount(registers) + 4; + + int32_t offset = 0; + addr_t Rn = ReadCoreReg(n, &success); + + if (!success) + return false; + + addr_t address = + Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterPlusOffset; + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); + context.SetRegisterPlusOffset(dwarf_reg, offset); + + // for i = 0 to 14 + for (int i = 0; i < 14; ++i) { + // if registers<i> == '1' then + if (BitIsSet(registers, i)) { + // R[i] = MemA[address,4]; address = address + 4; + context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset)); + uint32_t data = + MemARead(context, address + offset, addr_byte_size, 0, &success); + if (!success) + return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, + data)) + return false; + offset += addr_byte_size; + } + } + + // if registers<15> == '1' then + // LoadWritePC(MemA[address,4]); + if (BitIsSet(registers, 15)) { + context.SetRegisterPlusOffset(dwarf_reg, offset); + uint32_t data = + MemARead(context, address + offset, addr_byte_size, 0, &success); + if (!success) + return false; + // In ARMv5T and above, this is an interworking branch. + if (!LoadWritePC(context, data)) + return false; + } + + // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); + if (wback && BitIsClear(registers, n)) { + if (!success) + return false; + + offset = (addr_byte_size * BitCount(registers)) * -1; + context.type = EmulateInstruction::eContextAdjustBaseRegister; + context.SetImmediateSigned(offset); + addr_t addr = Rn + offset; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + addr)) + return false; + } + + // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; + if (wback && BitIsSet(registers, n)) + return WriteBits32Unknown(n); + } + return true; } - -// LDMDB loads multiple registers from consecutive memory locations using an address from a base register. The -// consecutive memory locations end just below this address, and the address of the lowest of those locations can + +// LDMDB loads multiple registers from consecutive memory locations using an +// address from a base register. The +// consecutive memory locations end just below this address, and the address of +// the lowest of those locations can // be optionally written back to the base register. -bool -EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -3702,128 +3672,130 @@ EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding en if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t n; - uint32_t registers = 0; - bool wback; - const uint32_t addr_byte_size = GetAddressByteSize(); - switch (encoding) - { - case eEncodingT1: - // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - registers = registers & 0xdfff; // Make sure bit 13 is a zero. - wback = BitIsSet (opcode, 21); - - // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; - if ((n == 15) - || (BitCount (registers) < 2) - || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15))) - return false; - - // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; - if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock()) - return false; - - // if wback && registers<n> == '1' then UNPREDICTABLE; - if (wback && BitIsSet (registers, n)) - return false; - - break; - - case eEncodingA1: - // n = UInt(Rn); registers = register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - wback = BitIsSet (opcode, 21); - - // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; - if ((n == 15) || (BitCount (registers) < 1)) - return false; - - break; - - default: - return false; - } - - // address = R[n] - 4*BitCount(registers); - - int32_t offset = 0; - addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - - if (!success) - return false; - - addr_t address = Rn - (addr_byte_size * BitCount (registers)); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); - context.SetRegisterPlusOffset (dwarf_reg, Rn - address); - - for (int i = 0; i < 14; ++i) - { - if (BitIsSet (registers, i)) - { - // R[i] = MemA[address,4]; address = address + 4; - context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset)); - uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) - return false; - - offset += addr_byte_size; - } - } - - // if registers<15> == '1' then - // LoadWritePC(MemA[address,4]); - if (BitIsSet (registers, 15)) - { - context.SetRegisterPlusOffset (dwarf_reg, offset); - uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); - if (!success) - return false; - // In ARMv5T and above, this is an interworking branch. - if (!LoadWritePC(context, data)) - return false; - } - - // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); - if (wback && BitIsClear (registers, n)) - { - if (!success) - return false; - - offset = (addr_byte_size * BitCount (registers)) * -1; - context.type = EmulateInstruction::eContextAdjustBaseRegister; - context.SetImmediateSigned (offset); - addr_t addr = Rn + offset; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) - return false; - } - - // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 - if (wback && BitIsSet (registers, n)) - return WriteBits32Unknown (n); + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t n; + uint32_t registers = 0; + bool wback; + const uint32_t addr_byte_size = GetAddressByteSize(); + switch (encoding) { + case eEncodingT1: + // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + registers = registers & 0xdfff; // Make sure bit 13 is a zero. + wback = BitIsSet(opcode, 21); + + // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then + // UNPREDICTABLE; + if ((n == 15) || (BitCount(registers) < 2) || + (BitIsSet(opcode, 14) && BitIsSet(opcode, 15))) + return false; + + // if registers<15> == '1' && InITBlock() && !LastInITBlock() then + // UNPREDICTABLE; + if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) + return false; + + // if wback && registers<n> == '1' then UNPREDICTABLE; + if (wback && BitIsSet(registers, n)) + return false; + + break; + + case eEncodingA1: + // n = UInt(Rn); registers = register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + wback = BitIsSet(opcode, 21); + + // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; + if ((n == 15) || (BitCount(registers) < 1)) + return false; + + break; + + default: + return false; } - return true; + + // address = R[n] - 4*BitCount(registers); + + int32_t offset = 0; + addr_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + + if (!success) + return false; + + addr_t address = Rn - (addr_byte_size * BitCount(registers)); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterPlusOffset; + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); + context.SetRegisterPlusOffset(dwarf_reg, Rn - address); + + for (int i = 0; i < 14; ++i) { + if (BitIsSet(registers, i)) { + // R[i] = MemA[address,4]; address = address + 4; + context.SetRegisterPlusOffset(dwarf_reg, Rn - (address + offset)); + uint32_t data = + MemARead(context, address + offset, addr_byte_size, 0, &success); + if (!success) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, + data)) + return false; + + offset += addr_byte_size; + } + } + + // if registers<15> == '1' then + // LoadWritePC(MemA[address,4]); + if (BitIsSet(registers, 15)) { + context.SetRegisterPlusOffset(dwarf_reg, offset); + uint32_t data = + MemARead(context, address + offset, addr_byte_size, 0, &success); + if (!success) + return false; + // In ARMv5T and above, this is an interworking branch. + if (!LoadWritePC(context, data)) + return false; + } + + // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); + if (wback && BitIsClear(registers, n)) { + if (!success) + return false; + + offset = (addr_byte_size * BitCount(registers)) * -1; + context.type = EmulateInstruction::eContextAdjustBaseRegister; + context.SetImmediateSigned(offset); + addr_t addr = Rn + offset; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + addr)) + return false; + } + + // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only + // possible for encoding A1 + if (wback && BitIsSet(registers, n)) + return WriteBits32Unknown(n); + } + return true; } -// LDMIB loads multiple registers from consecutive memory locations using an address from a base register. The -// consecutive memory locations start just above this address, and thea ddress of the last of those locations can +// LDMIB loads multiple registers from consecutive memory locations using an +// address from a base register. The +// consecutive memory locations start just above this address, and thea ddress +// of the last of those locations can // optinoally be written back to the base register. -bool -EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -3838,105 +3810,105 @@ EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding en if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t n; - uint32_t registers = 0; - bool wback; - const uint32_t addr_byte_size = GetAddressByteSize(); - switch (encoding) - { - case eEncodingA1: - // n = UInt(Rn); registers = register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - wback = BitIsSet (opcode, 21); - - // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; - if ((n == 15) || (BitCount (registers) < 1)) - return false; - - break; - default: - return false; - } - // address = R[n] + 4; - - int32_t offset = 0; - addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t n; + uint32_t registers = 0; + bool wback; + const uint32_t addr_byte_size = GetAddressByteSize(); + switch (encoding) { + case eEncodingA1: + // n = UInt(Rn); registers = register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + wback = BitIsSet(opcode, 21); + + // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; + if ((n == 15) || (BitCount(registers) < 1)) + return false; + + break; + default: + return false; + } + // address = R[n] + 4; + + int32_t offset = 0; + addr_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + + if (!success) + return false; + + addr_t address = Rn + addr_byte_size; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterPlusOffset; + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); + context.SetRegisterPlusOffset(dwarf_reg, offset); + + for (int i = 0; i < 14; ++i) { + if (BitIsSet(registers, i)) { + // R[i] = MemA[address,4]; address = address + 4; + + context.SetRegisterPlusOffset(dwarf_reg, offset + addr_byte_size); + uint32_t data = + MemARead(context, address + offset, addr_byte_size, 0, &success); if (!success) - return false; - - addr_t address = Rn + addr_byte_size; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterPlusOffset; - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg); - context.SetRegisterPlusOffset (dwarf_reg, offset); + return false; - for (int i = 0; i < 14; ++i) - { - if (BitIsSet (registers, i)) - { - // R[i] = MemA[address,4]; address = address + 4; - - context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size); - uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data)) - return false; - - offset += addr_byte_size; - } - } - - // if registers<15> == '1' then - // LoadWritePC(MemA[address,4]); - if (BitIsSet (registers, 15)) - { - context.SetRegisterPlusOffset (dwarf_reg, offset); - uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success); - if (!success) - return false; - // In ARMv5T and above, this is an interworking branch. - if (!LoadWritePC(context, data)) - return false; - } - - // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); - if (wback && BitIsClear (registers, n)) - { - if (!success) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, + data)) + return false; - offset = addr_byte_size * BitCount (registers); - context.type = EmulateInstruction::eContextAdjustBaseRegister; - context.SetImmediateSigned (offset); - addr_t addr = Rn + offset; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr)) - return false; - } - - // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 - if (wback && BitIsSet (registers, n)) - return WriteBits32Unknown (n); + offset += addr_byte_size; + } } - return true; + + // if registers<15> == '1' then + // LoadWritePC(MemA[address,4]); + if (BitIsSet(registers, 15)) { + context.SetRegisterPlusOffset(dwarf_reg, offset); + uint32_t data = + MemARead(context, address + offset, addr_byte_size, 0, &success); + if (!success) + return false; + // In ARMv5T and above, this is an interworking branch. + if (!LoadWritePC(context, data)) + return false; + } + + // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); + if (wback && BitIsClear(registers, n)) { + if (!success) + return false; + + offset = addr_byte_size * BitCount(registers); + context.type = EmulateInstruction::eContextAdjustBaseRegister; + context.SetImmediateSigned(offset); + addr_t addr = Rn + offset; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + addr)) + return false; + } + + // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only + // possible for encoding A1 + if (wback && BitIsSet(registers, n)) + return WriteBits32Unknown(n); + } + return true; } - -// Load Register (immediate) calculates an address from a base register value and + +// Load Register (immediate) calculates an address from a base register value +// and // an immediate offset, loads a word from memory, and writes to a register. // LDR (immediate, Thumb) -bool -EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if (ConditionPassed()) @@ -3954,160 +3926,152 @@ EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncodi } #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rt; // the destination register - uint32_t Rn; // the base register - uint32_t imm32; // the immediate offset used to form the address - addr_t offset_addr; // the offset address - addr_t address; // the calculated address - uint32_t data; // the literal data value from memory load - bool add, index, wback; - switch (encoding) { - case eEncodingT1: - Rt = Bits32(opcode, 2, 0); - Rn = Bits32(opcode, 5, 3); - imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32); - // index = TRUE; add = TRUE; wback = FALSE - add = true; - index = true; - wback = false; - - break; - - case eEncodingT2: - // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); - Rt = Bits32 (opcode, 10, 8); - Rn = 13; - imm32 = Bits32 (opcode, 7, 0) << 2; - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - break; - - case eEncodingT3: - // if Rn == '1111' then SEE LDR (literal); - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); - Rt = Bits32 (opcode, 15, 12); - Rn = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 11, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; - if ((Rt == 15) && InITBlock() && !LastInITBlock()) - return false; - - break; - - case eEncodingT4: - // if Rn == '1111' then SEE LDR (literal); - // if P == '1' && U == '1' && W == '0' then SEE LDRT; - // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP; - // if P == '0' && W == '0' then UNDEFINED; - if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) - return false; - - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); - Rt = Bits32 (opcode, 15, 12); - Rn = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0); - - // index = (P == '1'); add = (U == '1'); wback = (W == '1'); - index = BitIsSet (opcode, 10); - add = BitIsSet (opcode, 9); - wback = BitIsSet (opcode, 8); - - // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE; - if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock())) - return false; - - break; - - default: - return false; - } - uint32_t base = ReadCoreReg (Rn, &success); - if (!success) - return false; - if (add) - offset_addr = base + imm32; - else - offset_addr = base - imm32; + if (ConditionPassed(opcode)) { + uint32_t Rt; // the destination register + uint32_t Rn; // the base register + uint32_t imm32; // the immediate offset used to form the address + addr_t offset_addr; // the offset address + addr_t address; // the calculated address + uint32_t data; // the literal data value from memory load + bool add, index, wback; + switch (encoding) { + case eEncodingT1: + Rt = Bits32(opcode, 2, 0); + Rn = Bits32(opcode, 5, 3); + imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32); + // index = TRUE; add = TRUE; wback = FALSE + add = true; + index = true; + wback = false; - address = (index ? offset_addr : base); + break; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg); - if (wback) - { - EmulateInstruction::Context ctx; - if (Rn == 13) - { - ctx.type = eContextAdjustStackPointer; - ctx.SetImmediateSigned((int32_t) (offset_addr - base)); - } - else if (Rn == GetFramePointerRegisterNumber()) - { - ctx.type = eContextSetFramePointer; - ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); - } - else - { - ctx.type = EmulateInstruction::eContextAdjustBaseRegister; - ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); - } - + case eEncodingT2: + // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); + Rt = Bits32(opcode, 10, 8); + Rn = 13; + imm32 = Bits32(opcode, 7, 0) << 2; - if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr)) - return false; - } + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; - // Prepare to write to the Rt register. - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); + break; - // Read memory from the address. - data = MemURead(context, address, 4, 0, &success); - if (!success) - return false; + case eEncodingT3: + // if Rn == '1111' then SEE LDR (literal); + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); + Rt = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 11, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; + if ((Rt == 15) && InITBlock() && !LastInITBlock()) + return false; - if (Rt == 15) - { - if (Bits32(address, 1, 0) == 0) - { - if (!LoadWritePC(context, data)) - return false; - } - else - return false; - } - else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) - { - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data)) - return false; - } - else - WriteBits32Unknown (Rt); + break; + + case eEncodingT4: + // if Rn == '1111' then SEE LDR (literal); + // if P == '1' && U == '1' && W == '0' then SEE LDRT; + // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == + // '00000100' then SEE POP; + // if P == '0' && W == '0' then UNDEFINED; + if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) + return false; + + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); + Rt = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0); + + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); + index = BitIsSet(opcode, 10); + add = BitIsSet(opcode, 9); + wback = BitIsSet(opcode, 8); + + // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) + // then UNPREDICTABLE; + if ((wback && (Rn == Rt)) || + ((Rt == 15) && InITBlock() && !LastInITBlock())) + return false; + + break; + + default: + return false; } - return true; + uint32_t base = ReadCoreReg(Rn, &success); + if (!success) + return false; + if (add) + offset_addr = base + imm32; + else + offset_addr = base - imm32; + + address = (index ? offset_addr : base); + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn, base_reg); + if (wback) { + EmulateInstruction::Context ctx; + if (Rn == 13) { + ctx.type = eContextAdjustStackPointer; + ctx.SetImmediateSigned((int32_t)(offset_addr - base)); + } else if (Rn == GetFramePointerRegisterNumber()) { + ctx.type = eContextSetFramePointer; + ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base)); + } else { + ctx.type = EmulateInstruction::eContextAdjustBaseRegister; + ctx.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base)); + } + + if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn, + offset_addr)) + return false; + } + + // Prepare to write to the Rt register. + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, (int32_t)(offset_addr - base)); + + // Read memory from the address. + data = MemURead(context, address, 4, 0, &success); + if (!success) + return false; + + if (Rt == 15) { + if (Bits32(address, 1, 0) == 0) { + if (!LoadWritePC(context, data)) + return false; + } else + return false; + } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) { + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt, + data)) + return false; + } else + WriteBits32Unknown(Rt); + } + return true; } -// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address -// from a base register. The consecutive memory locations start at this address, and the address just above the last +// STM (Store Multiple Increment After) stores multiple registers to consecutive +// memory locations using an address +// from a base register. The consecutive memory locations start at this +// address, and the address just above the last // of those locations can optionally be written back to the base register. -bool -EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -4125,143 +4089,141 @@ EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding enco MemA[address,4] = PCStoreValue(); if wback then R[n] = R[n] + 4*BitCount(registers); #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t n; - uint32_t registers = 0; - bool wback; - const uint32_t addr_byte_size = GetAddressByteSize(); - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE; - n = Bits32 (opcode, 10, 8); - registers = Bits32 (opcode, 7, 0); - registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. - wback = true; - - // if BitCount(registers) < 1 then UNPREDICTABLE; - if (BitCount (registers) < 1) - return false; - - break; - - case eEncodingT2: - // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. - wback = BitIsSet (opcode, 21); - - // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; - if ((n == 15) || (BitCount (registers) < 2)) - return false; - - // if wback && registers<n> == '1' then UNPREDICTABLE; - if (wback && BitIsSet (registers, n)) - return false; - - break; - - case eEncodingA1: - // n = UInt(Rn); registers = register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - wback = BitIsSet (opcode, 21); - - // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; - if ((n == 15) || (BitCount (registers) < 1)) - return false; - - break; - - default: - return false; - } - - // address = R[n]; - int32_t offset = 0; - const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - // for i = 0 to 14 - uint32_t lowest_set_bit = 14; - for (uint32_t i = 0; i < 14; ++i) - { - // if registers<i> == '1' then - if (BitIsSet (registers, i)) - { - if (i < lowest_set_bit) - lowest_set_bit = i; - // if i == n && wback && i != LowestSetBit(registers) then - if ((i == n) && wback && (i != lowest_set_bit)) - // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 - WriteBits32UnknownToMemory (address + offset); - else - { - // MemA[address,4] = R[i]; - uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); - if (!success) - return false; - - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg); - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); - if (!MemAWrite (context, address + offset, data, addr_byte_size)) - return false; - } - - // address = address + 4; - offset += addr_byte_size; - } - } - - // if registers<15> == '1' then // Only possible for encoding A1 - // MemA[address,4] = PCStoreValue(); - if (BitIsSet (registers, 15)) - { - RegisterInfo pc_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg); - context.SetRegisterPlusOffset (pc_reg, 8); - const uint32_t pc = ReadCoreReg (PC_REG, &success); - if (!success) - return false; - - if (!MemAWrite (context, address + offset, pc, addr_byte_size)) - return false; - } - - // if wback then R[n] = R[n] + 4*BitCount(registers); - if (wback) - { - offset = addr_byte_size * BitCount (registers); - context.type = EmulateInstruction::eContextAdjustBaseRegister; - context.SetImmediateSigned (offset); - addr_t data = address + offset; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) - return false; - } + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t n; + uint32_t registers = 0; + bool wback; + const uint32_t addr_byte_size = GetAddressByteSize(); + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE; + n = Bits32(opcode, 10, 8); + registers = Bits32(opcode, 7, 0); + registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. + wback = true; + + // if BitCount(registers) < 1 then UNPREDICTABLE; + if (BitCount(registers) < 1) + return false; + + break; + + case eEncodingT2: + // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. + wback = BitIsSet(opcode, 21); + + // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; + if ((n == 15) || (BitCount(registers) < 2)) + return false; + + // if wback && registers<n> == '1' then UNPREDICTABLE; + if (wback && BitIsSet(registers, n)) + return false; + + break; + + case eEncodingA1: + // n = UInt(Rn); registers = register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + wback = BitIsSet(opcode, 21); + + // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; + if ((n == 15) || (BitCount(registers) < 1)) + return false; + + break; + + default: + return false; } - return true; + + // address = R[n]; + int32_t offset = 0; + const addr_t address = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterStore; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + // for i = 0 to 14 + uint32_t lowest_set_bit = 14; + for (uint32_t i = 0; i < 14; ++i) { + // if registers<i> == '1' then + if (BitIsSet(registers, i)) { + if (i < lowest_set_bit) + lowest_set_bit = i; + // if i == n && wback && i != LowestSetBit(registers) then + if ((i == n) && wback && (i != lowest_set_bit)) + // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings + // T1 and A1 + WriteBits32UnknownToMemory(address + offset); + else { + // MemA[address,4] = R[i]; + uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, + 0, &success); + if (!success) + return false; + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg); + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset); + if (!MemAWrite(context, address + offset, data, addr_byte_size)) + return false; + } + + // address = address + 4; + offset += addr_byte_size; + } + } + + // if registers<15> == '1' then // Only possible for encoding A1 + // MemA[address,4] = PCStoreValue(); + if (BitIsSet(registers, 15)) { + RegisterInfo pc_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg); + context.SetRegisterPlusOffset(pc_reg, 8); + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + + if (!MemAWrite(context, address + offset, pc, addr_byte_size)) + return false; + } + + // if wback then R[n] = R[n] + 4*BitCount(registers); + if (wback) { + offset = addr_byte_size * BitCount(registers); + context.type = EmulateInstruction::eContextAdjustBaseRegister; + context.SetImmediateSigned(offset); + addr_t data = address + offset; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + data)) + return false; + } + } + return true; } -// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address -// from a base register. The consecutive memory locations end at this address, and the address just below the lowest +// STMDA (Store Multiple Decrement After) stores multiple registers to +// consecutive memory locations using an address +// from a base register. The consecutive memory locations end at this address, +// and the address just below the lowest // of those locations can optionally be written back to the base register. -bool -EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -4280,113 +4242,110 @@ EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding en if wback then R[n] = R[n] - 4*BitCount(registers); #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t n; - uint32_t registers = 0; - bool wback; - const uint32_t addr_byte_size = GetAddressByteSize(); - - // EncodingSpecificOperations(); - switch (encoding) - { - case eEncodingA1: - // n = UInt(Rn); registers = register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - wback = BitIsSet (opcode, 21); - - // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; - if ((n == 15) || (BitCount (registers) < 1)) - return false; - break; - default: - return false; - } - - // address = R[n] - 4*BitCount(registers) + 4; - int32_t offset = 0; - addr_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - // for i = 0 to 14 - uint32_t lowest_bit_set = 14; - for (uint32_t i = 0; i < 14; ++i) - { - // if registers<i> == '1' then - if (BitIsSet (registers, i)) - { - if (i < lowest_bit_set) - lowest_bit_set = i; - //if i == n && wback && i != LowestSetBit(registers) then - if ((i == n) && wback && (i != lowest_bit_set)) - // MemA[address,4] = bits(32) UNKNOWN; - WriteBits32UnknownToMemory (address + offset); - else - { - // MemA[address,4] = R[i]; - uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); - if (!success) - return false; - - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg); - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); - if (!MemAWrite (context, address + offset, data, addr_byte_size)) - return false; - } - - // address = address + 4; - offset += addr_byte_size; - } - } - - // if registers<15> == '1' then - // MemA[address,4] = PCStoreValue(); - if (BitIsSet (registers, 15)) - { - RegisterInfo pc_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg); - context.SetRegisterPlusOffset (pc_reg, 8); - const uint32_t pc = ReadCoreReg (PC_REG, &success); - if (!success) - return false; - - if (!MemAWrite (context, address + offset, pc, addr_byte_size)) - return false; - } - - // if wback then R[n] = R[n] - 4*BitCount(registers); - if (wback) - { - offset = (addr_byte_size * BitCount (registers)) * -1; - context.type = EmulateInstruction::eContextAdjustBaseRegister; - context.SetImmediateSigned (offset); - addr_t data = Rn + offset; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) - return false; - } + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t n; + uint32_t registers = 0; + bool wback; + const uint32_t addr_byte_size = GetAddressByteSize(); + + // EncodingSpecificOperations(); + switch (encoding) { + case eEncodingA1: + // n = UInt(Rn); registers = register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + wback = BitIsSet(opcode, 21); + + // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; + if ((n == 15) || (BitCount(registers) < 1)) + return false; + break; + default: + return false; } - return true; + + // address = R[n] - 4*BitCount(registers) + 4; + int32_t offset = 0; + addr_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterStore; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + // for i = 0 to 14 + uint32_t lowest_bit_set = 14; + for (uint32_t i = 0; i < 14; ++i) { + // if registers<i> == '1' then + if (BitIsSet(registers, i)) { + if (i < lowest_bit_set) + lowest_bit_set = i; + // if i == n && wback && i != LowestSetBit(registers) then + if ((i == n) && wback && (i != lowest_bit_set)) + // MemA[address,4] = bits(32) UNKNOWN; + WriteBits32UnknownToMemory(address + offset); + else { + // MemA[address,4] = R[i]; + uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, + 0, &success); + if (!success) + return false; + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg); + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + Rn - (address + offset)); + if (!MemAWrite(context, address + offset, data, addr_byte_size)) + return false; + } + + // address = address + 4; + offset += addr_byte_size; + } + } + + // if registers<15> == '1' then + // MemA[address,4] = PCStoreValue(); + if (BitIsSet(registers, 15)) { + RegisterInfo pc_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg); + context.SetRegisterPlusOffset(pc_reg, 8); + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + + if (!MemAWrite(context, address + offset, pc, addr_byte_size)) + return false; + } + + // if wback then R[n] = R[n] - 4*BitCount(registers); + if (wback) { + offset = (addr_byte_size * BitCount(registers)) * -1; + context.type = EmulateInstruction::eContextAdjustBaseRegister; + context.SetImmediateSigned(offset); + addr_t data = Rn + offset; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + data)) + return false; + } + } + return true; } - -// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address -// from a base register. The consecutive memory locations end just below this address, and the address of the first of + +// STMDB (Store Multiple Decrement Before) stores multiple registers to +// consecutive memory locations using an address +// from a base register. The consecutive memory locations end just below this +// address, and the address of the first of // those locations can optionally be written back to the base register. -bool -EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -4406,138 +4365,136 @@ EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding en if wback then R[n] = R[n] - 4*BitCount(registers); #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t n; - uint32_t registers = 0; - bool wback; - const uint32_t addr_byte_size = GetAddressByteSize(); - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // if W == '1' && Rn == '1101' then SEE PUSH; - if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13)) - { - // See PUSH - } - // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. - wback = BitIsSet (opcode, 21); - // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; - if ((n == 15) || BitCount (registers) < 2) - return false; - // if wback && registers<n> == '1' then UNPREDICTABLE; - if (wback && BitIsSet (registers, n)) - return false; - break; - - case eEncodingA1: - // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE PUSH; - if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2) - { - // See Push - } - // n = UInt(Rn); registers = register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - wback = BitIsSet (opcode, 21); - // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; - if ((n == 15) || BitCount (registers) < 1) - return false; - break; - - default: - return false; - } - - // address = R[n] - 4*BitCount(registers); - - int32_t offset = 0; - addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t n; + uint32_t registers = 0; + bool wback; + const uint32_t addr_byte_size = GetAddressByteSize(); + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // if W == '1' && Rn == '1101' then SEE PUSH; + if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) { + // See PUSH + } + // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. + wback = BitIsSet(opcode, 21); + // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; + if ((n == 15) || BitCount(registers) < 2) return false; - - addr_t address = Rn - (addr_byte_size * BitCount (registers)); - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - // for i = 0 to 14 - uint32_t lowest_set_bit = 14; - for (uint32_t i = 0; i < 14; ++i) - { - // if registers<i> == '1' then - if (BitIsSet (registers, i)) - { - if (i < lowest_set_bit) - lowest_set_bit = i; - // if i == n && wback && i != LowestSetBit(registers) then - if ((i == n) && wback && (i != lowest_set_bit)) - // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 - WriteBits32UnknownToMemory (address + offset); - else - { - // MemA[address,4] = R[i]; - uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); - if (!success) - return false; - - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg); - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset)); - if (!MemAWrite (context, address + offset, data, addr_byte_size)) - return false; - } - - // address = address + 4; - offset += addr_byte_size; - } - } - - // if registers<15> == '1' then // Only possible for encoding A1 - // MemA[address,4] = PCStoreValue(); - if (BitIsSet (registers, 15)) - { - RegisterInfo pc_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg); - context.SetRegisterPlusOffset (pc_reg, 8); - const uint32_t pc = ReadCoreReg (PC_REG, &success); - if (!success) - return false; - - if (!MemAWrite (context, address + offset, pc, addr_byte_size)) - return false; - } - - // if wback then R[n] = R[n] - 4*BitCount(registers); - if (wback) - { - offset = (addr_byte_size * BitCount (registers)) * -1; - context.type = EmulateInstruction::eContextAdjustBaseRegister; - context.SetImmediateSigned (offset); - addr_t data = Rn + offset; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) - return false; - } + // if wback && registers<n> == '1' then UNPREDICTABLE; + if (wback && BitIsSet(registers, n)) + return false; + break; + + case eEncodingA1: + // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE + // PUSH; + if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) && + BitCount(Bits32(opcode, 15, 0)) >= 2) { + // See Push + } + // n = UInt(Rn); registers = register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + wback = BitIsSet(opcode, 21); + // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; + if ((n == 15) || BitCount(registers) < 1) + return false; + break; + + default: + return false; } - return true; + + // address = R[n] - 4*BitCount(registers); + + int32_t offset = 0; + addr_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + addr_t address = Rn - (addr_byte_size * BitCount(registers)); + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterStore; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + // for i = 0 to 14 + uint32_t lowest_set_bit = 14; + for (uint32_t i = 0; i < 14; ++i) { + // if registers<i> == '1' then + if (BitIsSet(registers, i)) { + if (i < lowest_set_bit) + lowest_set_bit = i; + // if i == n && wback && i != LowestSetBit(registers) then + if ((i == n) && wback && (i != lowest_set_bit)) + // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding + // A1 + WriteBits32UnknownToMemory(address + offset); + else { + // MemA[address,4] = R[i]; + uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, + 0, &success); + if (!success) + return false; + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg); + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + Rn - (address + offset)); + if (!MemAWrite(context, address + offset, data, addr_byte_size)) + return false; + } + + // address = address + 4; + offset += addr_byte_size; + } + } + + // if registers<15> == '1' then // Only possible for encoding A1 + // MemA[address,4] = PCStoreValue(); + if (BitIsSet(registers, 15)) { + RegisterInfo pc_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg); + context.SetRegisterPlusOffset(pc_reg, 8); + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + + if (!MemAWrite(context, address + offset, pc, addr_byte_size)) + return false; + } + + // if wback then R[n] = R[n] - 4*BitCount(registers); + if (wback) { + offset = (addr_byte_size * BitCount(registers)) * -1; + context.type = EmulateInstruction::eContextAdjustBaseRegister; + context.SetImmediateSigned(offset); + addr_t data = Rn + offset; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + data)) + return false; + } + } + return true; } - -// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address -// from a base register. The consecutive memory locations start just above this address, and the address of the last + +// STMIB (Store Multiple Increment Before) stores multiple registers to +// consecutive memory locations using an address +// from a base register. The consecutive memory locations start just above this +// address, and the address of the last // of those locations can optionally be written back to the base register. -bool -EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -4555,114 +4512,111 @@ EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding en MemA[address,4] = PCStoreValue(); if wback then R[n] = R[n] + 4*BitCount(registers); -#endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t n; - uint32_t registers = 0; - bool wback; - const uint32_t addr_byte_size = GetAddressByteSize(); - - // EncodingSpecificOperations(); - switch (encoding) - { - case eEncodingA1: - // n = UInt(Rn); registers = register_list; wback = (W == '1'); - n = Bits32 (opcode, 19, 16); - registers = Bits32 (opcode, 15, 0); - wback = BitIsSet (opcode, 21); - - // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; - if ((n == 15) && (BitCount (registers) < 1)) - return false; - break; - default: - return false; - } - // address = R[n] + 4; - - int32_t offset = 0; - addr_t Rn = ReadCoreReg (n, &success); - if (!success) +#endif + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t n; + uint32_t registers = 0; + bool wback; + const uint32_t addr_byte_size = GetAddressByteSize(); + + // EncodingSpecificOperations(); + switch (encoding) { + case eEncodingA1: + // n = UInt(Rn); registers = register_list; wback = (W == '1'); + n = Bits32(opcode, 19, 16); + registers = Bits32(opcode, 15, 0); + wback = BitIsSet(opcode, 21); + + // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; + if ((n == 15) && (BitCount(registers) < 1)) + return false; + break; + default: + return false; + } + // address = R[n] + 4; + + int32_t offset = 0; + addr_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + addr_t address = Rn + addr_byte_size; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRegisterStore; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t lowest_set_bit = 14; + // for i = 0 to 14 + for (uint32_t i = 0; i < 14; ++i) { + // if registers<i> == '1' then + if (BitIsSet(registers, i)) { + if (i < lowest_set_bit) + lowest_set_bit = i; + // if i == n && wback && i != LowestSetBit(registers) then + if ((i == n) && wback && (i != lowest_set_bit)) + // MemA[address,4] = bits(32) UNKNOWN; + WriteBits32UnknownToMemory(address + offset); + // else + else { + // MemA[address,4] = R[i]; + uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, + 0, &success); + if (!success) return false; - - addr_t address = Rn + addr_byte_size; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t lowest_set_bit = 14; - // for i = 0 to 14 - for (uint32_t i = 0; i < 14; ++i) - { - // if registers<i> == '1' then - if (BitIsSet (registers, i)) - { - if (i < lowest_set_bit) - lowest_set_bit = i; - // if i == n && wback && i != LowestSetBit(registers) then - if ((i == n) && wback && (i != lowest_set_bit)) - // MemA[address,4] = bits(32) UNKNOWN; - WriteBits32UnknownToMemory (address + offset); - // else - else - { - // MemA[address,4] = R[i]; - uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success); - if (!success) - return false; - - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg); - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size); - if (!MemAWrite (context, address + offset, data, addr_byte_size)) - return false; - } - - // address = address + 4; - offset += addr_byte_size; - } - } - - // if registers<15> == '1' then - // MemA[address,4] = PCStoreValue(); - if (BitIsSet (registers, 15)) - { - RegisterInfo pc_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg); - context.SetRegisterPlusOffset (pc_reg, 8); - const uint32_t pc = ReadCoreReg (PC_REG, &success); - if (!success) + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i, data_reg); + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + offset + addr_byte_size); + if (!MemAWrite(context, address + offset, data, addr_byte_size)) return false; - - if (!MemAWrite (context, address + offset, pc, addr_byte_size)) - return false; - } - - // if wback then R[n] = R[n] + 4*BitCount(registers); - if (wback) - { - offset = addr_byte_size * BitCount (registers); - context.type = EmulateInstruction::eContextAdjustBaseRegister; - context.SetImmediateSigned (offset); - addr_t data = Rn + offset; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data)) - return false; } + + // address = address + 4; + offset += addr_byte_size; + } } - return true; + + // if registers<15> == '1' then + // MemA[address,4] = PCStoreValue(); + if (BitIsSet(registers, 15)) { + RegisterInfo pc_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_pc, pc_reg); + context.SetRegisterPlusOffset(pc_reg, 8); + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + + if (!MemAWrite(context, address + offset, pc, addr_byte_size)) + return false; + } + + // if wback then R[n] = R[n] + 4*BitCount(registers); + if (wback) { + offset = addr_byte_size * BitCount(registers); + context.type = EmulateInstruction::eContextAdjustBaseRegister; + context.SetImmediateSigned(offset); + addr_t data = Rn + offset; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + data)) + return false; + } + } + return true; } -// STR (store immediate) calculates an address from a base register value and an immediate offset, and stores a word -// from a register to memory. It can use offset, post-indexed, or pre-indexed addressing. -bool -EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding) -{ +// STR (store immediate) calculates an address from a base register value and an +// immediate offset, and stores a word +// from a register to memory. It can use offset, post-indexed, or pre-indexed +// addressing. +bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -4674,163 +4628,162 @@ EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding MemU[address,4] = bits(32) UNKNOWN; if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - const uint32_t addr_byte_size = GetAddressByteSize(); - - uint32_t t; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - // EncodingSpecificOperations (); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - imm32 = Bits32 (opcode, 10, 6) << 2; - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = false; - wback = false; - break; - - case eEncodingT2: - // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); - t = Bits32 (opcode, 10, 8); - n = 13; - imm32 = Bits32 (opcode, 7, 0) << 2; - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - break; - - case eEncodingT3: - // if Rn == '1111' then UNDEFINED; - if (Bits32 (opcode, 19, 16) == 15) - return false; - - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 11, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // if t == 15 then UNPREDICTABLE; - if (t == 15) - return false; - break; - - case eEncodingT4: - // if P == '1' && U == '1' && W == '0' then SEE STRT; - // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH; - // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; - if ((Bits32 (opcode, 19, 16) == 15) - || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))) - return false; - - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0); - - // index = (P == '1'); add = (U == '1'); wback = (W == '1'); - index = BitIsSet (opcode, 10); - add = BitIsSet (opcode, 9); - wback = BitIsSet (opcode, 8); - - // if t == 15 || (wback && n == t) then UNPREDICTABLE; - if ((t == 15) || (wback && (n == t))) - return false; - break; - - default: - return false; - } - - addr_t offset_addr; - addr_t address; - - // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - uint32_t base_address = ReadCoreReg (n, &success); - if (!success) - return false; - - if (add) - offset_addr = base_address + imm32; - else - offset_addr = base_address - imm32; - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = base_address; - - EmulateInstruction::Context context; - if (n == 13) - context.type = eContextPushRegisterOnStack; - else - context.type = eContextRegisterStore; + bool success = false; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - // if UnalignedSupport() || address<1:0> == '00' then - if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) - { - // MemU[address,4] = R[t]; - uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); - if (!success) - return false; - - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); - int32_t offset = address - base_address; - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset); - if (!MemUWrite (context, address, data, addr_byte_size)) - return false; - } - else - { - // MemU[address,4] = bits(32) UNKNOWN; - WriteBits32UnknownToMemory (address); - } - - // if wback then R[n] = offset_addr; - if (wback) - { - if (n == 13) - context.type = eContextAdjustStackPointer; - else - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); + if (ConditionPassed(opcode)) { + const uint32_t addr_byte_size = GetAddressByteSize(); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + uint32_t t; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + // EncodingSpecificOperations (); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + imm32 = Bits32(opcode, 10, 6) << 2; + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = false; + wback = false; + break; + + case eEncodingT2: + // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); + t = Bits32(opcode, 10, 8); + n = 13; + imm32 = Bits32(opcode, 7, 0) << 2; + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + break; + + case eEncodingT3: + // if Rn == '1111' then UNDEFINED; + if (Bits32(opcode, 19, 16) == 15) + return false; + + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 11, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // if t == 15 then UNPREDICTABLE; + if (t == 15) + return false; + break; + + case eEncodingT4: + // if P == '1' && U == '1' && W == '0' then SEE STRT; + // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == + // '00000100' then SEE PUSH; + // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; + if ((Bits32(opcode, 19, 16) == 15) || + (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))) + return false; + + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0); + + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); + index = BitIsSet(opcode, 10); + add = BitIsSet(opcode, 9); + wback = BitIsSet(opcode, 8); + + // if t == 15 || (wback && n == t) then UNPREDICTABLE; + if ((t == 15) || (wback && (n == t))) + return false; + break; + + default: + return false; } - return true; + + addr_t offset_addr; + addr_t address; + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + uint32_t base_address = ReadCoreReg(n, &success); + if (!success) + return false; + + if (add) + offset_addr = base_address + imm32; + else + offset_addr = base_address - imm32; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = base_address; + + EmulateInstruction::Context context; + if (n == 13) + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + // if UnalignedSupport() || address<1:0> == '00' then + if (UnalignedSupport() || + (BitIsClear(address, 1) && BitIsClear(address, 0))) { + // MemU[address,4] = R[t]; + uint32_t data = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); + if (!success) + return false; + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + int32_t offset = address - base_address; + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, offset); + if (!MemUWrite(context, address, data, addr_byte_size)) + return false; + } else { + // MemU[address,4] = bits(32) UNKNOWN; + WriteBits32UnknownToMemory(address); + } + + // if wback then R[n] = offset_addr; + if (wback) { + if (n == 13) + context.type = eContextAdjustStackPointer; + else + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } - -// STR (Store Register) calculates an address from a base register value and an offset register value, stores a -// word from a register to memory. The offset register value can optionally be shifted. -bool -EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding) -{ + +// STR (Store Register) calculates an address from a base register value and an +// offset register value, stores a +// word from a register to memory. The offset register value can optionally be +// shifted. +bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -4847,180 +4800,180 @@ EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncod MemU[address,4] = bits(32) UNKNOWN; if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - const uint32_t addr_byte_size = GetAddressByteSize(); - - uint32_t t; - uint32_t n; - uint32_t m; - ARM_ShifterType shift_t; - uint32_t shift_n; - bool index; - bool add; - bool wback; - - // EncodingSpecificOperations (); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - m = Bits32 (opcode, 8, 6); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - break; - - case eEncodingT2: - // if Rn == '1111' then UNDEFINED; - if (Bits32 (opcode, 19, 16) == 15) - return false; - - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); - shift_t = SRType_LSL; - shift_n = Bits32 (opcode, 5, 4); - - // if t == 15 || BadReg(m) then UNPREDICTABLE; - if ((t == 15) || (BadReg (m))) - return false; - break; - - case eEncodingA1: - { - // if P == '0' && W == '1' then SEE STRT; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); - - // (shift_t, shift_n) = DecodeImmShift(type, imm5); - uint32_t typ = Bits32 (opcode, 6, 5); - uint32_t imm5 = Bits32 (opcode, 11, 7); - shift_n = DecodeImmShift(typ, imm5, shift_t); - - // if m == 15 then UNPREDICTABLE; - if (m == 15) - return false; - - // if wback && (n == 15 || n == t) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t))) - return false; - - break; - } - default: - return false; - } - - addr_t offset_addr; - addr_t address; - int32_t offset = 0; - - addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - // offset = Shift(R[m], shift_t, shift_n, APSR.C); - offset = Shift (Rm_data, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - - // offset_addr = if add then (R[n] + offset) else (R[n] - offset); - if (add) - offset_addr = base_address + offset; - else - offset_addr = base_address - offset; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = base_address; - - uint32_t data; - // if t == 15 then // Only possible for encoding A1 - if (t == 15) - // data = PCStoreValue(); - data = ReadCoreReg (PC_REG, &success); - else - // data = R[t]; - data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); - - if (!success) - return false; - - EmulateInstruction::Context context; - context.type = eContextRegisterStore; - - // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then - if (UnalignedSupport () - || (BitIsClear (address, 1) && BitIsClear (address, 0)) - || CurrentInstrSet() == eModeARM) - { - // MemU[address,4] = data; - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); - - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); - if (!MemUWrite (context, address, data, addr_byte_size)) - return false; - - } - else - // MemU[address,4] = bits(32) UNKNOWN; - WriteBits32UnknownToMemory (address); - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextRegisterLoad; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + bool success = false; + + if (ConditionPassed(opcode)) { + const uint32_t addr_byte_size = GetAddressByteSize(); + + uint32_t t; + uint32_t n; + uint32_t m; + ARM_ShifterType shift_t; + uint32_t shift_n; + bool index; + bool add; + bool wback; + + // EncodingSpecificOperations (); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation + // in ThumbEE"; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + m = Bits32(opcode, 8, 6); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + break; + + case eEncodingT2: + // if Rn == '1111' then UNDEFINED; + if (Bits32(opcode, 19, 16) == 15) + return false; + + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); + shift_t = SRType_LSL; + shift_n = Bits32(opcode, 5, 4); + + // if t == 15 || BadReg(m) then UNPREDICTABLE; + if ((t == 15) || (BadReg(m))) + return false; + break; + + case eEncodingA1: { + // if P == '0' && W == '1' then SEE STRT; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || + // (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); + + // (shift_t, shift_n) = DecodeImmShift(type, imm5); + uint32_t typ = Bits32(opcode, 6, 5); + uint32_t imm5 = Bits32(opcode, 11, 7); + shift_n = DecodeImmShift(typ, imm5, shift_t); + + // if m == 15 then UNPREDICTABLE; + if (m == 15) + return false; + + // if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t))) + return false; + + break; } - return true; + default: + return false; + } + + addr_t offset_addr; + addr_t address; + int32_t offset = 0; + + addr_t base_address = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + uint32_t Rm_data = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + // offset = Shift(R[m], shift_t, shift_n, APSR.C); + offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + + // offset_addr = if add then (R[n] + offset) else (R[n] - offset); + if (add) + offset_addr = base_address + offset; + else + offset_addr = base_address - offset; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = base_address; + + uint32_t data; + // if t == 15 then // Only possible for encoding A1 + if (t == 15) + // data = PCStoreValue(); + data = ReadCoreReg(PC_REG, &success); + else + // data = R[t]; + data = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); + + if (!success) + return false; + + EmulateInstruction::Context context; + context.type = eContextRegisterStore; + + // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == + // InstrSet_ARM then + if (UnalignedSupport() || + (BitIsClear(address, 1) && BitIsClear(address, 0)) || + CurrentInstrSet() == eModeARM) { + // MemU[address,4] = data; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + address - base_address); + if (!MemUWrite(context, address, data, addr_byte_size)) + return false; + + } else + // MemU[address,4] = bits(32) UNKNOWN; + WriteBits32UnknownToMemory(address); + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextRegisterLoad; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } - -bool -EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding) -{ + +bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -5030,134 +4983,134 @@ EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncodin if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - imm32 = Bits32 (opcode, 10, 6); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - break; - - case eEncodingT2: - // if Rn == '1111' then UNDEFINED; - if (Bits32 (opcode, 19, 16) == 15) - return false; - - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 11, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // if BadReg(t) then UNPREDICTABLE; - if (BadReg (t)) - return false; - break; - - case eEncodingT3: - // if P == '1' && U == '1' && W == '0' then SEE STRBT; - // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; - if (Bits32 (opcode, 19, 16) == 15) - return false; - - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0); - - // index = (P == '1'); add = (U == '1'); wback = (W == '1'); - index = BitIsSet (opcode, 10); - add = BitIsSet (opcode, 9); - wback = BitIsSet (opcode, 8); - - // if BadReg(t) || (wback && n == t) then UNPREDICTABLE - if ((BadReg (t)) || (wback && (n == t))) - return false; - break; - - default: - return false; - } - - addr_t offset_addr; - addr_t address; - addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - if (add) - offset_addr = base_address + imm32; - else - offset_addr = base_address - imm32; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = base_address; - - // MemU[address,1] = R[t]<7:0> - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address); - - uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); - if (!success) - return false; - - data = Bits32 (data, 7, 0); + bool success = false; - if (!MemUWrite (context, address, data, 1)) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextRegisterLoad; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } - + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + imm32 = Bits32(opcode, 10, 6); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + break; + + case eEncodingT2: + // if Rn == '1111' then UNDEFINED; + if (Bits32(opcode, 19, 16) == 15) + return false; + + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 11, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // if BadReg(t) then UNPREDICTABLE; + if (BadReg(t)) + return false; + break; + + case eEncodingT3: + // if P == '1' && U == '1' && W == '0' then SEE STRBT; + // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; + if (Bits32(opcode, 19, 16) == 15) + return false; + + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0); + + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); + index = BitIsSet(opcode, 10); + add = BitIsSet(opcode, 9); + wback = BitIsSet(opcode, 8); + + // if BadReg(t) || (wback && n == t) then UNPREDICTABLE + if ((BadReg(t)) || (wback && (n == t))) + return false; + break; + + default: + return false; } - return true; + addr_t offset_addr; + addr_t address; + addr_t base_address = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + if (add) + offset_addr = base_address + imm32; + else + offset_addr = base_address - imm32; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = base_address; + + // MemU[address,1] = R[t]<7:0> + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterStore; + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + address - base_address); + + uint32_t data = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); + if (!success) + return false; + + data = Bits32(data, 7, 0); + + if (!MemUWrite(context, address, data, 1)) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextRegisterLoad; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + + return true; } -// STRH (register) calculates an address from a base register value and an offset register value, and stores a -// halfword from a register to memory. The offset register value can be shifted left by 0, 1, 2, or 3 bits. -bool -EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding) -{ +// STRH (register) calculates an address from a base register value and an +// offset register value, and stores a +// halfword from a register to memory. The offset register value can be shifted +// left by 0, 1, 2, or 3 bits. +bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -5170,174 +5123,174 @@ EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEnco MemU[address,2] = bits(16) UNKNOWN; if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t m; + bool index; + bool add; + bool wback; + ARM_ShifterType shift_t; + uint32_t shift_n; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation + // in ThumbEE"; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + m = Bits32(opcode, 8, 6); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + + break; + + case eEncodingT2: + // if Rn == '1111' then UNDEFINED; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + if (n == 15) + return false; + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); + shift_t = SRType_LSL; + shift_n = Bits32(opcode, 5, 4); + + // if BadReg(t) || BadReg(m) then UNPREDICTABLE; + if (BadReg(t) || BadReg(m)) + return false; + + break; + + case eEncodingA1: + // if P == '0' && W == '1' then SEE STRHT; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || + // (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + + // if t == 15 || m == 15 then UNPREDICTABLE; + if ((t == 15) || (m == 15)) + return false; + + // if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t))) + return false; + + break; + + default: + return false; + } + + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // offset = Shift(R[m], shift_t, shift_n, APSR.C); + uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + + // offset_addr = if add then (R[n] + offset) else (R[n] - offset); + addr_t offset_addr; + if (add) + offset_addr = Rn + offset; + else + offset_addr = Rn - offset; + + // address = if index then offset_addr else R[n]; + addr_t address; + if (index) + address = offset_addr; + else + address = Rn; + + EmulateInstruction::Context context; + context.type = eContextRegisterStore; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + RegisterInfo offset_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); + + // if UnalignedSupport() || address<0> == '0' then + if (UnalignedSupport() || BitIsClear(address, 0)) { + // MemU[address,2] = R[t]<15:0>; + uint32_t Rt = ReadCoreReg(t, &success); + if (!success) + return false; + + EmulateInstruction::Context context; + context.type = eContextRegisterStore; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + RegisterInfo offset_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg, + data_reg); + + if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2)) + return false; + } else // Can only occur before ARMv7 { - uint32_t t; - uint32_t n; - uint32_t m; - bool index; - bool add; - bool wback; - ARM_ShifterType shift_t; - uint32_t shift_n; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - m = Bits32 (opcode, 8, 6); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - - break; - - case eEncodingT2: - // if Rn == '1111' then UNDEFINED; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - if (n == 15) - return false; - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); - shift_t = SRType_LSL; - shift_n = Bits32 (opcode, 5, 4); - - // if BadReg(t) || BadReg(m) then UNPREDICTABLE; - if (BadReg (t) || BadReg (m)) - return false; - - break; - - case eEncodingA1: - // if P == '0' && W == '1' then SEE STRHT; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - - // if t == 15 || m == 15 then UNPREDICTABLE; - if ((t == 15) || (m == 15)) - return false; - - // if wback && (n == 15 || n == t) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t))) - return false; - - break; - - default: - return false; - } - - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - // offset = Shift(R[m], shift_t, shift_n, APSR.C); - uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - - // offset_addr = if add then (R[n] + offset) else (R[n] - offset); - addr_t offset_addr; - if (add) - offset_addr = Rn + offset; - else - offset_addr = Rn - offset; - - // address = if index then offset_addr else R[n]; - addr_t address; - if (index) - address = offset_addr; - else - address = Rn; - - EmulateInstruction::Context context; - context.type = eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo offset_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); - - // if UnalignedSupport() || address<0> == '0' then - if (UnalignedSupport() || BitIsClear (address, 0)) - { - // MemU[address,2] = R[t]<15:0>; - uint32_t Rt = ReadCoreReg (t, &success); - if (!success) - return false; - - EmulateInstruction::Context context; - context.type = eContextRegisterStore; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo offset_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); - context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); - - if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2)) - return false; - } - else // Can only occur before ARMv7 - { - // MemU[address,2] = bits(16) UNKNOWN; - } - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + // MemU[address,2] = bits(16) UNKNOWN; } - return true; + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + + return true; } - -// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value, -// and writes the result to the destination register. It can optionally update the condition flags + +// Add with Carry (immediate) adds an immediate value and the carry flag value +// to a register value, +// and writes the result to the destination register. It can optionally update +// the condition flags // based on the result. -bool -EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -5354,59 +5307,60 @@ EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn; - uint32_t imm32; // the immediate value to be added to the value obtained from Rn - bool setflags; - switch (encoding) - { - case eEncodingT1: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) - if (BadReg(Rd) || BadReg(Rn)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn; + uint32_t + imm32; // the immediate value to be added to the value obtained from Rn + bool setflags; + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) + if (BadReg(Rd) || BadReg(Rn)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } - // Read the first operand. - int32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + int32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C); + AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; + } + return true; } -// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted -// register value, and writes the result to the destination register. It can optionally update the +// Add with Carry (register) adds a register value, the carry flag value, and an +// optionally-shifted +// register value, and writes the result to the destination register. It can +// optionally update the // condition flags based on the result. -bool -EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -5424,76 +5378,75 @@ EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn, Rm; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - bool setflags; - switch (encoding) - { - case eEncodingT1: - Rd = Rn = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - shift_t = SRType_LSL; - shift_n = 0; - break; - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftARM(opcode, shift_t); - - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn, Rm; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + bool setflags; + switch (encoding) { + case eEncodingT1: + Rd = Rn = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + shift_t = SRType_LSL; + shift_n = 0; + break; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftARM(opcode, shift_t); + + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } - // Read the first operand. - int32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + int32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - // Read the second operand. - int32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; + // Read the second operand. + int32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C); + uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; + } + return true; } -// This instruction adds an immediate value to the PC value to form a PC-relative address, +// This instruction adds an immediate value to the PC value to form a +// PC-relative address, // and writes the result to the destination register. -bool -EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateADR(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -5505,60 +5458,59 @@ EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding enco R[d] = result; #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd; - uint32_t imm32; // the immediate value to be added/subtracted to/from the PC - bool add; - switch (encoding) - { - case eEncodingT1: - Rd = Bits32(opcode, 10, 8); - imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32) - add = true; - break; - case eEncodingT2: - case eEncodingT3: - Rd = Bits32(opcode, 11, 8); - imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) - add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB - if (BadReg(Rd)) - return false; - break; - case eEncodingA1: - case eEncodingA2: - Rd = Bits32(opcode, 15, 12); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd; + uint32_t imm32; // the immediate value to be added/subtracted to/from the PC + bool add; + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 10, 8); + imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32) + add = true; + break; + case eEncodingT2: + case eEncodingT3: + Rd = Bits32(opcode, 11, 8); + imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) + add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB + if (BadReg(Rd)) + return false; + break; + case eEncodingA1: + case eEncodingA2: + Rd = Bits32(opcode, 15, 12); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB + break; + default: + return false; + } - // Read the PC value. - uint32_t pc = ReadCoreReg(PC_REG, &success); - if (!success) - return false; + // Read the PC value. + uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; - uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32); + uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreReg(context, result, Rd)) - return false; - } - return true; + if (!WriteCoreReg(context, result, Rd)) + return false; + } + return true; } -// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result -// to the destination register. It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding) -{ +// This instruction performs a bitwise AND of a register value and an immediate +// value, and writes the result +// to the destination register. It can optionally update the condition flags +// based on the result. +bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -5575,63 +5527,67 @@ EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn; - uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn - bool setflags; - uint32_t carry; // the carry bit after ARM/Thumb Expand operation - switch (encoding) - { - case eEncodingT1: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) - // if Rd == '1111' && S == '1' then SEE TST (immediate); - if (Rd == 15 && setflags) - return EmulateTSTImm(opcode, eEncodingT1); - if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) - - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn; + uint32_t + imm32; // the immediate value to be ANDed to the value obtained from Rn + bool setflags; + uint32_t carry; // the carry bit after ARM/Thumb Expand operation + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm_C( + opcode, APSR_C, + carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) + // if Rd == '1111' && S == '1' then SEE TST (immediate); + if (Rd == 15 && setflags) + return EmulateTSTImm(opcode, eEncodingT1); + if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = + ARMExpandImm_C(opcode, APSR_C, + carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) + + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t result = val1 & imm32; + uint32_t result = val1 & imm32; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// This instruction performs a bitwise AND of a register value and an optionally-shifted register value, -// and writes the result to the destination register. It can optionally update the condition flags +// This instruction performs a bitwise AND of a register value and an +// optionally-shifted register value, +// and writes the result to the destination register. It can optionally update +// the condition flags // based on the result. -bool -EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -5649,81 +5605,80 @@ EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn, Rm; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - bool setflags; - uint32_t carry; - switch (encoding) - { - case eEncodingT1: - Rd = Rn = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - shift_t = SRType_LSL; - shift_n = 0; - break; - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - // if Rd == '1111' && S == '1' then SEE TST (register); - if (Rd == 15 && setflags) - return EmulateTSTReg(opcode, eEncodingT2); - if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftARM(opcode, shift_t); - - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn, Rm; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + bool setflags; + uint32_t carry; + switch (encoding) { + case eEncodingT1: + Rd = Rn = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + shift_t = SRType_LSL; + shift_n = 0; + break; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + // if Rd == '1111' && S == '1' then SEE TST (register); + if (Rd == 15 && setflags) + return EmulateTSTReg(opcode, eEncodingT2); + if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftARM(opcode, shift_t); + + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - // Read the second operand. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; + // Read the second operand. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); - if (!success) - return false; - uint32_t result = val1 & shifted; + uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); + if (!success) + return false; + uint32_t result = val1 & shifted; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an -// immediate value, and writes the result to the destination register. It can optionally update the +// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and +// the complement of an +// immediate value, and writes the result to the destination register. It can +// optionally update the // condition flags based on the result. -bool -EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -5740,61 +5695,66 @@ EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn; - uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn - bool setflags; - uint32_t carry; // the carry bit after ARM/Thumb Expand operation - switch (encoding) - { - case eEncodingT1: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) - if (BadReg(Rd) || BadReg(Rn)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn; + uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to + // the value obtained from Rn + bool setflags; + uint32_t carry; // the carry bit after ARM/Thumb Expand operation + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm_C( + opcode, APSR_C, + carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) + if (BadReg(Rd) || BadReg(Rn)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = + ARMExpandImm_C(opcode, APSR_C, + carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t result = val1 & ~imm32; + uint32_t result = val1 & ~imm32; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an -// optionally-shifted register value, and writes the result to the destination register. +// Bitwise Bit Clear (register) performs a bitwise AND of a register value and +// the complement of an +// optionally-shifted register value, and writes the result to the destination +// register. // It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -5812,78 +5772,78 @@ EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn, Rm; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - bool setflags; - uint32_t carry; - switch (encoding) - { - case eEncodingT1: - Rd = Rn = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - shift_t = SRType_LSL; - shift_n = 0; - break; - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftARM(opcode, shift_t); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn, Rm; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + bool setflags; + uint32_t carry; + switch (encoding) { + case eEncodingT1: + Rd = Rn = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + shift_t = SRType_LSL; + shift_n = 0; + break; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftARM(opcode, shift_t); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - // Read the second operand. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; + // Read the second operand. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); - if (!success) - return false; - uint32_t result = val1 & ~shifted; + uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); + if (!success) + return false; + uint32_t result = val1 & ~shifted; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word -// from memory, and writes it to a register. It can use offset, post-indexed, or pre-indexed addressing. -bool -EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding) -{ +// LDR (immediate, ARM) calculates an address from a base register value and an +// immediate offset, loads a word +// from memory, and writes it to a register. It can use offset, post-indexed, +// or pre-indexed addressing. +bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -5898,131 +5858,129 @@ EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARME else // Can only apply before ARMv7 R[t] = ROR(data, 8*UInt(address<1:0>)); #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - const uint32_t addr_byte_size = GetAddressByteSize(); - - uint32_t t; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - - switch (encoding) - { - case eEncodingA1: - // if Rn == '1111' then SEE LDR (literal); - // if P == '0' && W == '1' then SEE LDRT; - // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP; - // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 11, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); - - // if wback && n == t then UNPREDICTABLE; - if (wback && (n == t)) - return false; - - break; - - default: - return false; - } - - addr_t address; - addr_t offset_addr; - addr_t base_address = ReadCoreReg (n, &success); - if (!success) - return false; - - // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - if (add) - offset_addr = base_address + imm32; - else - offset_addr = base_address - imm32; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = base_address; - - // data = MemU[address,4]; - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - base_address); - - uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); - if (!success) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } - - // if t == 15 then - if (t == 15) - { - // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; - if (BitIsClear (address, 1) && BitIsClear (address, 0)) - { - // LoadWritePC (data); - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - base_address); - LoadWritePC (context, data); - } - else - return false; - } - // elsif UnalignedSupport() || address<1:0> = '00' then - else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0))) - { - // R[t] = data; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - base_address); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - } - // else // Can only apply before ARMv7 - else - { - // R[t] = ROR(data, 8*UInt(address<1:0>)); - data = ROR (data, Bits32 (address, 1, 0), &success); - if (!success) - return false; - context.type = eContextRegisterLoad; - context.SetImmediate (data); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - } + bool success = false; + + if (ConditionPassed(opcode)) { + const uint32_t addr_byte_size = GetAddressByteSize(); + + uint32_t t; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + + switch (encoding) { + case eEncodingA1: + // if Rn == '1111' then SEE LDR (literal); + // if P == '0' && W == '1' then SEE LDRT; + // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == + // '000000000100' then SEE POP; + // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 11, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || + // (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); + + // if wback && n == t then UNPREDICTABLE; + if (wback && (n == t)) + return false; + + break; + + default: + return false; } - return true; + + addr_t address; + addr_t offset_addr; + addr_t base_address = ReadCoreReg(n, &success); + if (!success) + return false; + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + if (add) + offset_addr = base_address + imm32; + else + offset_addr = base_address - imm32; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = base_address; + + // data = MemU[address,4]; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - base_address); + + uint64_t data = MemURead(context, address, addr_byte_size, 0, &success); + if (!success) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + + // if t == 15 then + if (t == 15) { + // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; + if (BitIsClear(address, 1) && BitIsClear(address, 0)) { + // LoadWritePC (data); + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - base_address); + LoadWritePC(context, data); + } else + return false; + } + // elsif UnalignedSupport() || address<1:0> = '00' then + else if (UnalignedSupport() || + (BitIsClear(address, 1) && BitIsClear(address, 0))) { + // R[t] = data; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - base_address); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + data)) + return false; + } + // else // Can only apply before ARMv7 + else { + // R[t] = ROR(data, 8*UInt(address<1:0>)); + data = ROR(data, Bits32(address, 1, 0), &success); + if (!success) + return false; + context.type = eContextRegisterLoad; + context.SetImmediate(data); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + data)) + return false; + } + } + return true; } - -// LDR (register) calculates an address from a base register value and an offset register value, loads a word -// from memory, and writes it to a register. The offset register value can optionally be shifted. -bool -EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding) -{ + +// LDR (register) calculates an address from a base register value and an offset +// register value, loads a word +// from memory, and writes it to a register. The offset register value can +// optionally be shifted. +bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -6041,200 +5999,195 @@ EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncod else R[t] = bits(32) UNKNOWN; #endif - - bool success = false; - - if (ConditionPassed(opcode)) + + bool success = false; + + if (ConditionPassed(opcode)) { + const uint32_t addr_byte_size = GetAddressByteSize(); + + uint32_t t; + uint32_t n; + uint32_t m; + bool index; + bool add; + bool wback; + ARM_ShifterType shift_t; + uint32_t shift_n; + + switch (encoding) { + case eEncodingT1: + // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation + // in ThumbEE"; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + m = Bits32(opcode, 8, 6); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + + break; + + case eEncodingT2: + // if Rn == '1111' then SEE LDR (literal); + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); + shift_t = SRType_LSL; + shift_n = Bits32(opcode, 5, 4); + + // if BadReg(m) then UNPREDICTABLE; + if (BadReg(m)) + return false; + + // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; + if ((t == 15) && InITBlock() && !LastInITBlock()) + return false; + + break; + + case eEncodingA1: { + // if P == '0' && W == '1' then SEE LDRT; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || + // (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); + + // (shift_t, shift_n) = DecodeImmShift(type, imm5); + uint32_t type = Bits32(opcode, 6, 5); + uint32_t imm5 = Bits32(opcode, 11, 7); + shift_n = DecodeImmShift(type, imm5, shift_t); + + // if m == 15 then UNPREDICTABLE; + if (m == 15) + return false; + + // if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t))) + return false; + } break; + + default: + return false; + } + + uint32_t Rm = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + uint32_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + addr_t offset_addr; + addr_t address; + + // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an + // application level alias for the CPSR". + addr_t offset = + Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success); + if (!success) + return false; + + // offset_addr = if add then (R[n] + offset) else (R[n] - offset); + if (add) + offset_addr = Rn + offset; + else + offset_addr = Rn - offset; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = Rn; + + // data = MemU[address,4]; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - Rn); + + uint64_t data = MemURead(context, address, addr_byte_size, 0, &success); + if (!success) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + + // if t == 15 then + if (t == 15) { + // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; + if (BitIsClear(address, 1) && BitIsClear(address, 0)) { + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - Rn); + LoadWritePC(context, data); + } else + return false; + } + // elsif UnalignedSupport() || address<1:0> = '00' then + else if (UnalignedSupport() || + (BitIsClear(address, 1) && BitIsClear(address, 0))) { + // R[t] = data; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - Rn); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + data)) + return false; + } else // Can only apply before ARMv7 { - const uint32_t addr_byte_size = GetAddressByteSize(); - - uint32_t t; - uint32_t n; - uint32_t m; - bool index; - bool add; - bool wback; - ARM_ShifterType shift_t; - uint32_t shift_n; - - switch (encoding) - { - case eEncodingT1: - // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - m = Bits32 (opcode, 8, 6); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - - break; - - case eEncodingT2: - // if Rn == '1111' then SEE LDR (literal); - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); - shift_t = SRType_LSL; - shift_n = Bits32 (opcode, 5, 4); - - // if BadReg(m) then UNPREDICTABLE; - if (BadReg (m)) - return false; - - // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; - if ((t == 15) && InITBlock() && !LastInITBlock()) - return false; - - break; - - case eEncodingA1: - { - // if P == '0' && W == '1' then SEE LDRT; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); - - // (shift_t, shift_n) = DecodeImmShift(type, imm5); - uint32_t type = Bits32 (opcode, 6, 5); - uint32_t imm5 = Bits32 (opcode, 11, 7); - shift_n = DecodeImmShift (type, imm5, shift_t); - - // if m == 15 then UNPREDICTABLE; - if (m == 15) - return false; - - // if wback && (n == 15 || n == t) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t))) - return false; - } - break; - - - default: - return false; - } - - uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + // if CurrentInstrSet() == InstrSet_ARM then + if (CurrentInstrSet() == eModeARM) { + // R[t] = ROR(data, 8*UInt(address<1:0>)); + data = ROR(data, Bits32(address, 1, 0), &success); if (!success) - return false; - - addr_t offset_addr; - addr_t address; - - // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is an application level alias for the CPSR". - addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C), &success); - if (!success) - return false; - - // offset_addr = if add then (R[n] + offset) else (R[n] - offset); - if (add) - offset_addr = Rn + offset; - else - offset_addr = Rn - offset; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = Rn; - - // data = MemU[address,4]; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - EmulateInstruction::Context context; + return false; context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); - - uint64_t data = MemURead (context, address, addr_byte_size, 0, &success); - if (!success) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } - - // if t == 15 then - if (t == 15) - { - // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; - if (BitIsClear (address, 1) && BitIsClear (address, 0)) - { - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); - LoadWritePC (context, data); - } - else - return false; - } - // elsif UnalignedSupport() || address<1:0> = '00' then - else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0))) - { - // R[t] = data; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - } - else // Can only apply before ARMv7 - { - // if CurrentInstrSet() == InstrSet_ARM then - if (CurrentInstrSet () == eModeARM) - { - // R[t] = ROR(data, 8*UInt(address<1:0>)); - data = ROR (data, Bits32 (address, 1, 0), &success); - if (!success) - return false; - context.type = eContextRegisterLoad; - context.SetImmediate (data); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - } - else - { - // R[t] = bits(32) UNKNOWN; - WriteBits32Unknown (t); - } - } + context.SetImmediate(data); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + data)) + return false; + } else { + // R[t] = bits(32) UNKNOWN; + WriteBits32Unknown(t); + } } - return true; + } + return true; } // LDRB (immediate, Thumb) -bool -EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -6243,146 +6196,145 @@ EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEnc R[t] = ZeroExtend(MemU[address,1], 32); if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - imm32 = Bits32 (opcode, 10, 6); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback= false; - - break; - - case eEncodingT2: - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 11, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // if Rt == '1111' then SEE PLD; - if (t == 15) - return false; // PLD is not implemented yet - - // if Rn == '1111' then SEE LDRB (literal); - if (n == 15) - return EmulateLDRBLiteral(opcode, eEncodingT1); - - // if t == 13 then UNPREDICTABLE; - if (t == 13) - return false; - - break; - - case eEncodingT3: - // if P == '1' && U == '1' && W == '0' then SEE LDRBT; - // if P == '0' && W == '0' then UNDEFINED; - if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) - return false; - - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0); - - // index = (P == '1'); add = (U == '1'); wback = (W == '1'); - index = BitIsSet (opcode, 10); - add = BitIsSet (opcode, 9); - wback = BitIsSet (opcode, 8); - - // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; - if (t == 15) - return false; // PLD is not implemented yet - - // if Rn == '1111' then SEE LDRB (literal); - if (n == 15) - return EmulateLDRBLiteral(opcode, eEncodingT1); - - // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; - if (BadReg (t) || (wback && (n == t))) - return false; - - break; - - default: - return false; - } - - uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - addr_t address; - addr_t offset_addr; - - // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - if (add) - offset_addr = Rn + imm32; - else - offset_addr = Rn - imm32; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = Rn; - - // R[t] = ZeroExtend(MemU[address,1], 32); - RegisterInfo base_reg; - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); - - uint64_t data = MemURead (context, address, 1, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + imm32 = Bits32(opcode, 10, 6); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + break; + + case eEncodingT2: + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 11, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // if Rt == '1111' then SEE PLD; + if (t == 15) + return false; // PLD is not implemented yet + + // if Rn == '1111' then SEE LDRB (literal); + if (n == 15) + return EmulateLDRBLiteral(opcode, eEncodingT1); + + // if t == 13 then UNPREDICTABLE; + if (t == 13) + return false; + + break; + + case eEncodingT3: + // if P == '1' && U == '1' && W == '0' then SEE LDRBT; + // if P == '0' && W == '0' then UNDEFINED; + if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) + return false; + + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0); + + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); + index = BitIsSet(opcode, 10); + add = BitIsSet(opcode, 9); + wback = BitIsSet(opcode, 8); + + // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; + if (t == 15) + return false; // PLD is not implemented yet + + // if Rn == '1111' then SEE LDRB (literal); + if (n == 15) + return EmulateLDRBLiteral(opcode, eEncodingT1); + + // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; + if (BadReg(t) || (wback && (n == t))) + return false; + + break; + + default: + return false; } - return true; + + uint32_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + addr_t address; + addr_t offset_addr; + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + if (add) + offset_addr = Rn + imm32; + else + offset_addr = Rn - imm32; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = Rn; + + // R[t] = ZeroExtend(MemU[address,1], 32); + RegisterInfo base_reg; + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + + uint64_t data = MemURead(context, address, 1, 0, &success); + if (!success) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } - -// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, + +// LDRB (literal) calculates an address from the PC value and an immediate +// offset, loads a byte from memory, // zero-extends it to form a 32-bit word and writes it to a register. -bool -EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(15); @@ -6390,82 +6342,81 @@ EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncod address = if add then (base + imm32) else (base - imm32); R[t] = ZeroExtend(MemU[address,1], 32); #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t imm32; - bool add; - switch (encoding) - { - case eEncodingT1: - // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); - t = Bits32 (opcode, 15, 12); - imm32 = Bits32 (opcode, 11, 0); - add = BitIsSet (opcode, 23); - - // if Rt == '1111' then SEE PLD; - if (t == 15) - return false; // PLD is not implemented yet - - // if t == 13 then UNPREDICTABLE; - if (t == 13) - return false; - - break; - - case eEncodingA1: - // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); - t = Bits32 (opcode, 15, 12); - imm32 = Bits32 (opcode, 11, 0); - add = BitIsSet (opcode, 23); - - // if t == 15 then UNPREDICTABLE; - if (t == 15) - return false; - break; - - default: - return false; - } - - // base = Align(PC,4); - uint32_t pc_val = ReadCoreReg (PC_REG, &success); - if (!success) - return false; - - uint32_t base = AlignPC (pc_val); - - addr_t address; - // address = if add then (base + imm32) else (base - imm32); - if (add) - address = base + imm32; - else - address = base - imm32; - - // R[t] = ZeroExtend(MemU[address,1], 32); - EmulateInstruction::Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (address - base); - - uint64_t data = MemURead (context, address, 1, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t imm32; + bool add; + switch (encoding) { + case eEncodingT1: + // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); + t = Bits32(opcode, 15, 12); + imm32 = Bits32(opcode, 11, 0); + add = BitIsSet(opcode, 23); + + // if Rt == '1111' then SEE PLD; + if (t == 15) + return false; // PLD is not implemented yet + + // if t == 13 then UNPREDICTABLE; + if (t == 13) + return false; + + break; + + case eEncodingA1: + // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); + t = Bits32(opcode, 15, 12); + imm32 = Bits32(opcode, 11, 0); + add = BitIsSet(opcode, 23); + + // if t == 15 then UNPREDICTABLE; + if (t == 15) + return false; + break; + + default: + return false; } - return true; + + // base = Align(PC,4); + uint32_t pc_val = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + + uint32_t base = AlignPC(pc_val); + + addr_t address; + // address = if add then (base + imm32) else (base - imm32); + if (add) + address = base + imm32; + else + address = base - imm32; + + // R[t] = ZeroExtend(MemU[address,1], 32); + EmulateInstruction::Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(address - base); + + uint64_t data = MemURead(context, address, 1, 0, &success); + if (!success) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) + return false; + } + return true; } - -// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from -// memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can + +// LDRB (register) calculates an address from a base register value and an +// offset rigister value, loads a byte from +// memory, zero-extends it to form a 32-bit word, and writes it to a register. +// The offset register value can // optionally be shifted. -bool -EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -6475,160 +6426,160 @@ EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEnco R[t] = ZeroExtend(MemU[address,1],32); if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t n; - uint32_t m; - bool index; - bool add; - bool wback; - ARM_ShifterType shift_t; - uint32_t shift_n; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - m = Bits32 (opcode, 8, 6); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - break; - - case eEncodingT2: - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); - shift_t = SRType_LSL; - shift_n = Bits32 (opcode, 5, 4); - // if Rt == '1111' then SEE PLD; - if (t == 15) - return false; // PLD is not implemented yet + bool success = false; - // if Rn == '1111' then SEE LDRB (literal); - if (n == 15) - return EmulateLDRBLiteral(opcode, eEncodingT1); - - // if t == 13 || BadReg(m) then UNPREDICTABLE; - if ((t == 13) || BadReg (m)) - return false; - break; - - case eEncodingA1: - { - // if P == '0' && W == '1' then SEE LDRBT; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); - - // (shift_t, shift_n) = DecodeImmShift(type, imm5); - uint32_t type = Bits32 (opcode, 6, 5); - uint32_t imm5 = Bits32 (opcode, 11, 7); - shift_n = DecodeImmShift (type, imm5, shift_t); - - // if t == 15 || m == 15 then UNPREDICTABLE; - if ((t == 15) || (m == 15)) - return false; - - // if wback && (n == 15 || n == t) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t))) - return false; - } - break; - - default: - return false; - } - - addr_t offset_addr; - addr_t address; - - // offset = Shift(R[m], shift_t, shift_n, APSR.C); - uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - - // offset_addr = if add then (R[n] + offset) else (R[n] - offset); - uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - if (add) - offset_addr = Rn + offset; - else - offset_addr = Rn - offset; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = Rn; - - // R[t] = ZeroExtend(MemU[address,1],32); - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); - - uint64_t data = MemURead (context, address, 1, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t m; + bool index; + bool add; + bool wback; + ARM_ShifterType shift_t; + uint32_t shift_n; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + m = Bits32(opcode, 8, 6); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + break; + + case eEncodingT2: + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); + shift_t = SRType_LSL; + shift_n = Bits32(opcode, 5, 4); + + // if Rt == '1111' then SEE PLD; + if (t == 15) + return false; // PLD is not implemented yet + + // if Rn == '1111' then SEE LDRB (literal); + if (n == 15) + return EmulateLDRBLiteral(opcode, eEncodingT1); + + // if t == 13 || BadReg(m) then UNPREDICTABLE; + if ((t == 13) || BadReg(m)) + return false; + break; + + case eEncodingA1: { + // if P == '0' && W == '1' then SEE LDRBT; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || + // (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); + + // (shift_t, shift_n) = DecodeImmShift(type, imm5); + uint32_t type = Bits32(opcode, 6, 5); + uint32_t imm5 = Bits32(opcode, 11, 7); + shift_n = DecodeImmShift(type, imm5, shift_t); + + // if t == 15 || m == 15 then UNPREDICTABLE; + if ((t == 15) || (m == 15)) + return false; + + // if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t))) + return false; + } break; + + default: + return false; } - return true; + + addr_t offset_addr; + addr_t address; + + // offset = Shift(R[m], shift_t, shift_n, APSR.C); + uint32_t Rm = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + + // offset_addr = if add then (R[n] + offset) else (R[n] - offset); + uint32_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + if (add) + offset_addr = Rn + offset; + else + offset_addr = Rn - offset; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = Rn; + + // R[t] = ZeroExtend(MemU[address,1],32); + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - Rn); + + uint64_t data = MemURead(context, address, 1, 0, &success); + if (!success) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } - -// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a -// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register. It can use offset, + +// LDRH (immediate, Thumb) calculates an address from a base register value and +// an immediate offset, loads a +// halfword from memory, zero-extends it to form a 32-bit word, and writes it to +// a register. It can use offset, // post-indexed, or pre-indexed addressing. -bool -EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -6641,143 +6592,141 @@ EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEnc else // Can only apply before ARMv7 R[t] = bits(32) UNKNOWN; #endif - - - bool success = false; - - if (ConditionPassed(opcode)) + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + imm32 = Bits32(opcode, 10, 6) << 1; + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + break; + + case eEncodingT2: + // if Rt == '1111' then SEE "Unallocated memory hints"; + // if Rn == '1111' then SEE LDRH (literal); + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 11, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // if t == 13 then UNPREDICTABLE; + if (t == 13) + return false; + break; + + case eEncodingT3: + // if Rn == '1111' then SEE LDRH (literal); + // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE + // "Unallocated memory hints"; + // if P == '1' && U == '1' && W == '0' then SEE LDRHT; + // if P == '0' && W == '0' then UNDEFINED; + if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) + return false; + + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0); + + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); + index = BitIsSet(opcode, 10); + add = BitIsSet(opcode, 9); + wback = BitIsSet(opcode, 8); + + // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; + if (BadReg(t) || (wback && (n == t))) + return false; + break; + + default: + return false; + } + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + uint32_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + addr_t offset_addr; + addr_t address; + + if (add) + offset_addr = Rn + imm32; + else + offset_addr = Rn - imm32; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = Rn; + + // data = MemU[address,2]; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - Rn); + + uint64_t data = MemURead(context, address, 2, 0, &success); + if (!success) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + + // if UnalignedSupport() || address<0> = '0' then + if (UnalignedSupport() || BitIsClear(address, 0)) { + // R[t] = ZeroExtend(data, 32); + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - Rn); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + data)) + return false; + } else // Can only apply before ARMv7 { - uint32_t t; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - imm32 = Bits32 (opcode, 10, 6) << 1; - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - break; - - case eEncodingT2: - // if Rt == '1111' then SEE "Unallocated memory hints"; - // if Rn == '1111' then SEE LDRH (literal); - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 11, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // if t == 13 then UNPREDICTABLE; - if (t == 13) - return false; - break; - - case eEncodingT3: - // if Rn == '1111' then SEE LDRH (literal); - // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; - // if P == '1' && U == '1' && W == '0' then SEE LDRHT; - // if P == '0' && W == '0' then UNDEFINED; - if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) - return false; - - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0); - - // index = (P == '1'); add = (U == '1'); wback = (W == '1'); - index = BitIsSet (opcode, 10); - add = BitIsSet (opcode, 9); - wback = BitIsSet (opcode, 8); - - // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; - if (BadReg (t) || (wback && (n == t))) - return false; - break; - - default: - return false; - } - - // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - addr_t offset_addr; - addr_t address; - - if (add) - offset_addr = Rn + imm32; - else - offset_addr = Rn - imm32; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = Rn; - - // data = MemU[address,2]; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); - - uint64_t data = MemURead (context, address, 2, 0, &success); - if (!success) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } - - // if UnalignedSupport() || address<0> = '0' then - if (UnalignedSupport () || BitIsClear (address, 0)) - { - // R[t] = ZeroExtend(data, 32); - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - } - else // Can only apply before ARMv7 - { - // R[t] = bits(32) UNKNOWN; - WriteBits32Unknown (t); - } + // R[t] = bits(32) UNKNOWN; + WriteBits32Unknown(t); } - return true; + } + return true; } - -// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory, -// zero-extends it to form a 32-bit word, and writes it to a register. -bool -EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding) -{ + +// LDRH (literal) caculates an address from the PC value and an immediate +// offset, loads a halfword from memory, +// zero-extends it to form a 32-bit word, and writes it to a register. +bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(15); @@ -6789,103 +6738,99 @@ EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncod else // Can only apply before ARMv7 R[t] = bits(32) UNKNOWN; #endif - - bool success = false; - - if (ConditionPassed(opcode)) + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t imm32; + bool add; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(15); + switch (encoding) { + case eEncodingT1: + // if Rt == '1111' then SEE "Unallocated memory hints"; + // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); + t = Bits32(opcode, 15, 12); + imm32 = Bits32(opcode, 11, 0); + add = BitIsSet(opcode, 23); + + // if t == 13 then UNPREDICTABLE; + if (t == 13) + return false; + + break; + + case eEncodingA1: { + uint32_t imm4H = Bits32(opcode, 11, 8); + uint32_t imm4L = Bits32(opcode, 3, 0); + + // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); + t = Bits32(opcode, 15, 12); + imm32 = (imm4H << 4) | imm4L; + add = BitIsSet(opcode, 23); + + // if t == 15 then UNPREDICTABLE; + if (t == 15) + return false; + break; + } + + default: + return false; + } + + // base = Align(PC,4); + uint64_t pc_value = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + + addr_t base = AlignPC(pc_value); + addr_t address; + + // address = if add then (base + imm32) else (base - imm32); + if (add) + address = base + imm32; + else + address = base - imm32; + + // data = MemU[address,2]; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - base); + + uint64_t data = MemURead(context, address, 2, 0, &success); + if (!success) + return false; + + // if UnalignedSupport() || address<0> = '0' then + if (UnalignedSupport() || BitIsClear(address, 0)) { + // R[t] = ZeroExtend(data, 32); + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - base); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + data)) + return false; + + } else // Can only apply before ARMv7 { - uint32_t t; - uint32_t imm32; - bool add; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(15); - switch (encoding) - { - case eEncodingT1: - // if Rt == '1111' then SEE "Unallocated memory hints"; - // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); - t = Bits32 (opcode, 15, 12); - imm32 = Bits32 (opcode, 11, 0); - add = BitIsSet (opcode, 23); - - // if t == 13 then UNPREDICTABLE; - if (t == 13) - return false; - - break; - - case eEncodingA1: - { - uint32_t imm4H = Bits32 (opcode, 11, 8); - uint32_t imm4L = Bits32 (opcode, 3, 0); - - // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); - t = Bits32 (opcode, 15, 12); - imm32 = (imm4H << 4) | imm4L; - add = BitIsSet (opcode, 23); - - // if t == 15 then UNPREDICTABLE; - if (t == 15) - return false; - break; - } - - default: - return false; - } - - // base = Align(PC,4); - uint64_t pc_value = ReadCoreReg (PC_REG, &success); - if (!success) - return false; - - addr_t base = AlignPC (pc_value); - addr_t address; - - // address = if add then (base + imm32) else (base - imm32); - if (add) - address = base + imm32; - else - address = base - imm32; - - // data = MemU[address,2]; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - base); - - uint64_t data = MemURead (context, address, 2, 0, &success); - if (!success) - return false; - - - // if UnalignedSupport() || address<0> = '0' then - if (UnalignedSupport () || BitIsClear (address, 0)) - { - // R[t] = ZeroExtend(data, 32); - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - base); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - - } - else // Can only apply before ARMv7 - { - // R[t] = bits(32) UNKNOWN; - WriteBits32Unknown (t); - } + // R[t] = bits(32) UNKNOWN; + WriteBits32Unknown(t); } - return true; + } + return true; } - -// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword -// from memory, zero-extends it to form a 32-bit word, and writes it to a register. The offset register value can + +// LDRH (literal) calculates an address from a base register value and an offset +// register value, loads a halfword +// from memory, zero-extends it to form a 32-bit word, and writes it to a +// register. The offset register value can // be shifted left by 0, 1, 2, or 3 bits. -bool -EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -6899,168 +6844,170 @@ EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEnco else // Can only apply before ARMv7 R[t] = bits(32) UNKNOWN; #endif - - bool success = false; - - if (ConditionPassed(opcode)) + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t m; + bool index; + bool add; + bool wback; + ARM_ShifterType shift_t; + uint32_t shift_n; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation + // in ThumbEE"; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + m = Bits32(opcode, 8, 6); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + + break; + + case eEncodingT2: + // if Rn == '1111' then SEE LDRH (literal); + // if Rt == '1111' then SEE "Unallocated memory hints"; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); + shift_t = SRType_LSL; + shift_n = Bits32(opcode, 5, 4); + + // if t == 13 || BadReg(m) then UNPREDICTABLE; + if ((t == 13) || BadReg(m)) + return false; + break; + + case eEncodingA1: + // if P == '0' && W == '1' then SEE LDRHT; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || + // (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + + // if t == 15 || m == 15 then UNPREDICTABLE; + if ((t == 15) || (m == 15)) + return false; + + // if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t))) + return false; + + break; + + default: + return false; + } + + // offset = Shift(R[m], shift_t, shift_n, APSR.C); + + uint64_t Rm = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + + addr_t offset_addr; + addr_t address; + + // offset_addr = if add then (R[n] + offset) else (R[n] - offset); + uint64_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + if (add) + offset_addr = Rn + offset; + else + offset_addr = Rn - offset; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = Rn; + + // data = MemU[address,2]; + RegisterInfo base_reg; + RegisterInfo offset_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusIndirectOffset(base_reg, offset_reg); + uint64_t data = MemURead(context, address, 2, 0, &success); + if (!success) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + + // if UnalignedSupport() || address<0> = '0' then + if (UnalignedSupport() || BitIsClear(address, 0)) { + // R[t] = ZeroExtend(data, 32); + context.type = eContextRegisterLoad; + context.SetRegisterPlusIndirectOffset(base_reg, offset_reg); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + data)) + return false; + } else // Can only apply before ARMv7 { - uint32_t t; - uint32_t n; - uint32_t m; - bool index; - bool add; - bool wback; - ARM_ShifterType shift_t; - uint32_t shift_n; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - m = Bits32 (opcode, 8, 6); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - - break; - - case eEncodingT2: - // if Rn == '1111' then SEE LDRH (literal); - // if Rt == '1111' then SEE "Unallocated memory hints"; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); - shift_t = SRType_LSL; - shift_n = Bits32 (opcode, 5, 4); - - // if t == 13 || BadReg(m) then UNPREDICTABLE; - if ((t == 13) || BadReg (m)) - return false; - break; - - case eEncodingA1: - // if P == '0' && W == '1' then SEE LDRHT; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - - // if t == 15 || m == 15 then UNPREDICTABLE; - if ((t == 15) || (m == 15)) - return false; - - // if wback && (n == 15 || n == t) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t))) - return false; - - break; - - default: - return false; - } - - // offset = Shift(R[m], shift_t, shift_n, APSR.C); - - uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - - addr_t offset_addr; - addr_t address; - - // offset_addr = if add then (R[n] + offset) else (R[n] - offset); - uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - if (add) - offset_addr = Rn + offset; - else - offset_addr = Rn - offset; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = Rn; - - // data = MemU[address,2]; - RegisterInfo base_reg; - RegisterInfo offset_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); - uint64_t data = MemURead (context, address, 2, 0, &success); - if (!success) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } - - // if UnalignedSupport() || address<0> = '0' then - if (UnalignedSupport() || BitIsClear (address, 0)) - { - // R[t] = ZeroExtend(data, 32); - context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - } - else // Can only apply before ARMv7 - { - // R[t] = bits(32) UNKNOWN; - WriteBits32Unknown (t); - } - } - return true; + // R[t] = bits(32) UNKNOWN; + WriteBits32Unknown(t); + } + } + return true; } - -// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from -// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, + +// LDRSB (immediate) calculates an address from a base register value and an +// immediate offset, loads a byte from +// memory, sign-extends it to form a 32-bit word, and writes it to a register. +// It can use offset, post-indexed, // or pre-indexed addressing. -bool -EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -7069,147 +7016,147 @@ EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEn R[t] = SignExtend(MemU[address,1], 32); if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // if Rt == '1111' then SEE PLI; - // if Rn == '1111' then SEE LDRSB (literal); - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 11, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // if t == 13 then UNPREDICTABLE; - if (t == 13) - return false; - - break; - - case eEncodingT2: - // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI; - // if Rn == '1111' then SEE LDRSB (literal); - // if P == '1' && U == '1' && W == '0' then SEE LDRSBT; - // if P == '0' && W == '0' then UNDEFINED; - if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) - return false; - - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0); - - // index = (P == '1'); add = (U == '1'); wback = (W == '1'); - index = BitIsSet (opcode, 10); - add = BitIsSet (opcode, 9); - wback = BitIsSet (opcode, 8); - - // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; - if (((t == 13) || ((t == 15) - && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8)))) - || (wback && (n == t))) - return false; - - break; - - case eEncodingA1: - { - // if Rn == '1111' then SEE LDRSB (literal); - // if P == '0' && W == '1' then SEE LDRSBT; - // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - - uint32_t imm4H = Bits32 (opcode, 11, 8); - uint32_t imm4L = Bits32 (opcode, 3, 0); - imm32 = (imm4H << 4) | imm4L; - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21)); - - // if t == 15 || (wback && n == t) then UNPREDICTABLE; - if ((t == 15) || (wback && (n == t))) - return false; - - break; - } - - default: - return false; - } - - uint64_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - addr_t offset_addr; - addr_t address; - - // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - if (add) - offset_addr = Rn + imm32; - else - offset_addr = Rn - imm32; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = Rn; - - // R[t] = SignExtend(MemU[address,1], 32); - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); - - uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); - if (!success) - return false; - - int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // if Rt == '1111' then SEE PLI; + // if Rn == '1111' then SEE LDRSB (literal); + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 11, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // if t == 13 then UNPREDICTABLE; + if (t == 13) + return false; + + break; + + case eEncodingT2: + // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI; + // if Rn == '1111' then SEE LDRSB (literal); + // if P == '1' && U == '1' && W == '0' then SEE LDRSBT; + // if P == '0' && W == '0' then UNDEFINED; + if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) + return false; + + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0); + + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); + index = BitIsSet(opcode, 10); + add = BitIsSet(opcode, 9); + wback = BitIsSet(opcode, 8); + + // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; + if (((t == 13) || + ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) || + BitIsSet(opcode, 8)))) || + (wback && (n == t))) + return false; + + break; + + case eEncodingA1: { + // if Rn == '1111' then SEE LDRSB (literal); + // if P == '0' && W == '1' then SEE LDRSBT; + // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + + uint32_t imm4H = Bits32(opcode, 11, 8); + uint32_t imm4L = Bits32(opcode, 3, 0); + imm32 = (imm4H << 4) | imm4L; + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || + // (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); + + // if t == 15 || (wback && n == t) then UNPREDICTABLE; + if ((t == 15) || (wback && (n == t))) + return false; + + break; } - - return true; + + default: + return false; + } + + uint64_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + addr_t offset_addr; + addr_t address; + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + if (add) + offset_addr = Rn + imm32; + else + offset_addr = Rn - imm32; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = Rn; + + // R[t] = SignExtend(MemU[address,1], 32); + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - Rn); + + uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); + if (!success) + return false; + + int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + (uint64_t)signed_data)) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + + return true; } - -// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, + +// LDRSB (literal) calculates an address from the PC value and an immediate +// offset, loads a byte from memory, // sign-extends it to form a 32-bit word, and writes tit to a register. -bool -EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(15); @@ -7217,89 +7164,88 @@ EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEnco address = if add then (base + imm32) else (base - imm32); R[t] = SignExtend(MemU[address,1], 32); #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t imm32; - bool add; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(15); - switch (encoding) - { - case eEncodingT1: - // if Rt == '1111' then SEE PLI; - // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); - t = Bits32 (opcode, 15, 12); - imm32 = Bits32 (opcode, 11, 0); - add = BitIsSet (opcode, 23); - - // if t == 13 then UNPREDICTABLE; - if (t == 13) - return false; - - break; - - case eEncodingA1: - { - // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); - t = Bits32 (opcode, 15, 12); - uint32_t imm4H = Bits32 (opcode, 11, 8); - uint32_t imm4L = Bits32 (opcode, 3, 0); - imm32 = (imm4H << 4) | imm4L; - add = BitIsSet (opcode, 23); - - // if t == 15 then UNPREDICTABLE; - if (t == 15) - return false; - - break; - } - - default: - return false; - } - - // base = Align(PC,4); - uint64_t pc_value = ReadCoreReg (PC_REG, &success); - if (!success) - return false; - uint64_t base = AlignPC (pc_value); - // address = if add then (base + imm32) else (base - imm32); - addr_t address; - if (add) - address = base + imm32; - else - address = base - imm32; - - // R[t] = SignExtend(MemU[address,1], 32); - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - base); - - uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); - if (!success) - return false; - - int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) - return false; + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t imm32; + bool add; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(15); + switch (encoding) { + case eEncodingT1: + // if Rt == '1111' then SEE PLI; + // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); + t = Bits32(opcode, 15, 12); + imm32 = Bits32(opcode, 11, 0); + add = BitIsSet(opcode, 23); + + // if t == 13 then UNPREDICTABLE; + if (t == 13) + return false; + + break; + + case eEncodingA1: { + // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); + t = Bits32(opcode, 15, 12); + uint32_t imm4H = Bits32(opcode, 11, 8); + uint32_t imm4L = Bits32(opcode, 3, 0); + imm32 = (imm4H << 4) | imm4L; + add = BitIsSet(opcode, 23); + + // if t == 15 then UNPREDICTABLE; + if (t == 15) + return false; + + break; } - return true; + + default: + return false; + } + + // base = Align(PC,4); + uint64_t pc_value = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + uint64_t base = AlignPC(pc_value); + + // address = if add then (base + imm32) else (base - imm32); + addr_t address; + if (add) + address = base + imm32; + else + address = base - imm32; + + // R[t] = SignExtend(MemU[address,1], 32); + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - base); + + uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); + if (!success) + return false; + + int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + (uint64_t)signed_data)) + return false; + } + return true; } - -// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from -// memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be + +// LDRSB (register) calculates an address from a base register value and an +// offset register value, loadsa byte from +// memory, sign-extends it to form a 32-bit word, and writes it to a register. +// The offset register value can be // shifted left by 0, 1, 2, or 3 bits. -bool -EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -7309,155 +7255,158 @@ EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEnc R[t] = SignExtend(MemU[address,1], 32); if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t n; - uint32_t m; - bool index; - bool add; - bool wback; - ARM_ShifterType shift_t; - uint32_t shift_n; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - m = Bits32 (opcode, 8, 6); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - - break; - - case eEncodingT2: - // if Rt == '1111' then SEE PLI; - // if Rn == '1111' then SEE LDRSB (literal); - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); - shift_t = SRType_LSL; - shift_n = Bits32 (opcode, 5, 4); - - // if t == 13 || BadReg(m) then UNPREDICTABLE; - if ((t == 13) || BadReg (m)) - return false; - break; - - case eEncodingA1: - // if P == '0' && W == '1' then SEE LDRSBT; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - - // if t == 15 || m == 15 then UNPREDICTABLE; - if ((t == 15) || (m == 15)) - return false; - - // if wback && (n == 15 || n == t) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t))) - return false; - break; - - default: - return false; - } - - uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - // offset = Shift(R[m], shift_t, shift_n, APSR.C); - addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - - addr_t offset_addr; - addr_t address; - - // offset_addr = if add then (R[n] + offset) else (R[n] - offset); - uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - if (add) - offset_addr = Rn + offset; - else - offset_addr = Rn - offset; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = Rn; - - // R[t] = SignExtend(MemU[address,1], 32); - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo offset_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); - - uint64_t unsigned_data = MemURead (context, address, 1, 0, &success); - if (!success) - return false; - - int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t m; + bool index; + bool add; + bool wback; + ARM_ShifterType shift_t; + uint32_t shift_n; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + m = Bits32(opcode, 8, 6); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + + break; + + case eEncodingT2: + // if Rt == '1111' then SEE PLI; + // if Rn == '1111' then SEE LDRSB (literal); + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); + shift_t = SRType_LSL; + shift_n = Bits32(opcode, 5, 4); + + // if t == 13 || BadReg(m) then UNPREDICTABLE; + if ((t == 13) || BadReg(m)) + return false; + break; + + case eEncodingA1: + // if P == '0' && W == '1' then SEE LDRSBT; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || + // (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + + // if t == 15 || m == 15 then UNPREDICTABLE; + if ((t == 15) || (m == 15)) + return false; + + // if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t))) + return false; + break; + + default: + return false; } - return true; + + uint64_t Rm = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + // offset = Shift(R[m], shift_t, shift_n, APSR.C); + addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + + addr_t offset_addr; + addr_t address; + + // offset_addr = if add then (R[n] + offset) else (R[n] - offset); + uint64_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + if (add) + offset_addr = Rn + offset; + else + offset_addr = Rn - offset; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = Rn; + + // R[t] = SignExtend(MemU[address,1], 32); + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + RegisterInfo offset_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusIndirectOffset(base_reg, offset_reg); + + uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); + if (!success) + return false; + + int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + (uint64_t)signed_data)) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } - -// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from -// memory, sign-extends it to form a 32-bit word, and writes it to a register. It can use offset, post-indexed, or + +// LDRSH (immediate) calculates an address from a base register value and an +// immediate offset, loads a halfword from +// memory, sign-extends it to form a 32-bit word, and writes it to a register. +// It can use offset, post-indexed, or // pre-indexed addressing. -bool -EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -7471,153 +7420,152 @@ EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEn R[t] = bits(32) UNKNOWN; #endif - bool success = false; - - if (ConditionPassed(opcode)) + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // if Rn == '1111' then SEE LDRSH (literal); + // if Rt == '1111' then SEE "Unallocated memory hints"; + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 11, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // if t == 13 then UNPREDICTABLE; + if (t == 13) + return false; + + break; + + case eEncodingT2: + // if Rn == '1111' then SEE LDRSH (literal); + // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE + // "Unallocated memory hints"; + // if P == '1' && U == '1' && W == '0' then SEE LDRSHT; + // if P == '0' && W == '0' then UNDEFINED; + if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) + return false; + + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0); + + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); + index = BitIsSet(opcode, 10); + add = BitIsSet(opcode, 9); + wback = BitIsSet(opcode, 8); + + // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; + if (BadReg(t) || (wback && (n == t))) + return false; + + break; + + case eEncodingA1: { + // if Rn == '1111' then SEE LDRSH (literal); + // if P == '0' && W == '1' then SEE LDRSHT; + // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + uint32_t imm4H = Bits32(opcode, 11, 8); + uint32_t imm4L = Bits32(opcode, 3, 0); + imm32 = (imm4H << 4) | imm4L; + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || + // (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); + + // if t == 15 || (wback && n == t) then UNPREDICTABLE; + if ((t == 15) || (wback && (n == t))) + return false; + + break; + } + + default: + return false; + } + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + uint64_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + addr_t offset_addr; + if (add) + offset_addr = Rn + imm32; + else + offset_addr = Rn - imm32; + + // address = if index then offset_addr else R[n]; + addr_t address; + if (index) + address = offset_addr; + else + address = Rn; + + // data = MemU[address,2]; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - Rn); + + uint64_t data = MemURead(context, address, 2, 0, &success); + if (!success) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + + // if UnalignedSupport() || address<0> = '0' then + if (UnalignedSupport() || BitIsClear(address, 0)) { + // R[t] = SignExtend(data, 32); + int64_t signed_data = llvm::SignExtend64<16>(data); + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - Rn); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + (uint64_t)signed_data)) + return false; + } else // Can only apply before ARMv7 { - uint32_t t; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // if Rn == '1111' then SEE LDRSH (literal); - // if Rt == '1111' then SEE "Unallocated memory hints"; - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 11, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // if t == 13 then UNPREDICTABLE; - if (t == 13) - return false; - - break; - - case eEncodingT2: - // if Rn == '1111' then SEE LDRSH (literal); - // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; - // if P == '1' && U == '1' && W == '0' then SEE LDRSHT; - // if P == '0' && W == '0' then UNDEFINED; - if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) - return false; - - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0); - - // index = (P == '1'); add = (U == '1'); wback = (W == '1'); - index = BitIsSet (opcode, 10); - add = BitIsSet (opcode, 9); - wback = BitIsSet (opcode, 8); - - // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; - if (BadReg (t) || (wback && (n == t))) - return false; - - break; - - case eEncodingA1: - { - // if Rn == '1111' then SEE LDRSH (literal); - // if P == '0' && W == '1' then SEE LDRSHT; - // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - uint32_t imm4H = Bits32 (opcode, 11,8); - uint32_t imm4L = Bits32 (opcode, 3, 0); - imm32 = (imm4H << 4) | imm4L; - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - - // if t == 15 || (wback && n == t) then UNPREDICTABLE; - if ((t == 15) || (wback && (n == t))) - return false; - - break; - } - - default: - return false; - } - - // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - addr_t offset_addr; - if (add) - offset_addr = Rn + imm32; - else - offset_addr = Rn - imm32; - - // address = if index then offset_addr else R[n]; - addr_t address; - if (index) - address = offset_addr; - else - address = Rn; - - // data = MemU[address,2]; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); - - uint64_t data = MemURead (context, address, 2, 0, &success); - if (!success) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } - - // if UnalignedSupport() || address<0> = '0' then - if (UnalignedSupport() || BitIsClear (address, 0)) - { - // R[t] = SignExtend(data, 32); - int64_t signed_data = llvm::SignExtend64<16>(data); - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) - return false; - } - else // Can only apply before ARMv7 - { - // R[t] = bits(32) UNKNOWN; - WriteBits32Unknown (t); - } + // R[t] = bits(32) UNKNOWN; + WriteBits32Unknown(t); } - return true; + } + return true; } - -// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory, + +// LDRSH (literal) calculates an address from the PC value and an immediate +// offset, loads a halfword from memory, // sign-extends it to from a 32-bit word, and writes it to a register. -bool -EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(15); @@ -7629,99 +7577,96 @@ EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEnco else // Can only apply before ARMv7 R[t] = bits(32) UNKNOWN; #endif - - bool success = false; - - if (ConditionPassed(opcode)) + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t imm32; + bool add; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(15); + switch (encoding) { + case eEncodingT1: + // if Rt == '1111' then SEE "Unallocated memory hints"; + // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); + t = Bits32(opcode, 15, 12); + imm32 = Bits32(opcode, 11, 0); + add = BitIsSet(opcode, 23); + + // if t == 13 then UNPREDICTABLE; + if (t == 13) + return false; + + break; + + case eEncodingA1: { + // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); + t = Bits32(opcode, 15, 12); + uint32_t imm4H = Bits32(opcode, 11, 8); + uint32_t imm4L = Bits32(opcode, 3, 0); + imm32 = (imm4H << 4) | imm4L; + add = BitIsSet(opcode, 23); + + // if t == 15 then UNPREDICTABLE; + if (t == 15) + return false; + + break; + } + default: + return false; + } + + // base = Align(PC,4); + uint64_t pc_value = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + + uint64_t base = AlignPC(pc_value); + + addr_t address; + // address = if add then (base + imm32) else (base - imm32); + if (add) + address = base + imm32; + else + address = base - imm32; + + // data = MemU[address,2]; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, imm32); + + uint64_t data = MemURead(context, address, 2, 0, &success); + if (!success) + return false; + + // if UnalignedSupport() || address<0> = '0' then + if (UnalignedSupport() || BitIsClear(address, 0)) { + // R[t] = SignExtend(data, 32); + int64_t signed_data = llvm::SignExtend64<16>(data); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + (uint64_t)signed_data)) + return false; + } else // Can only apply before ARMv7 { - uint32_t t; - uint32_t imm32; - bool add; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(15); - switch (encoding) - { - case eEncodingT1: - // if Rt == '1111' then SEE "Unallocated memory hints"; - // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); - t = Bits32 (opcode, 15, 12); - imm32 = Bits32 (opcode, 11, 0); - add = BitIsSet (opcode, 23); - - // if t == 13 then UNPREDICTABLE; - if (t == 13) - return false; - - break; - - case eEncodingA1: - { - // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); - t = Bits32 (opcode, 15, 12); - uint32_t imm4H = Bits32 (opcode, 11, 8); - uint32_t imm4L = Bits32 (opcode, 3, 0); - imm32 = (imm4H << 4) | imm4L; - add = BitIsSet (opcode, 23); - - // if t == 15 then UNPREDICTABLE; - if (t == 15) - return false; - - break; - } - default: - return false; - } - - // base = Align(PC,4); - uint64_t pc_value = ReadCoreReg (PC_REG, &success); - if (!success) - return false; - - uint64_t base = AlignPC (pc_value); - - addr_t address; - // address = if add then (base + imm32) else (base - imm32); - if (add) - address = base + imm32; - else - address = base - imm32; - - // data = MemU[address,2]; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, imm32); - - uint64_t data = MemURead (context, address, 2, 0, &success); - if (!success) - return false; - - // if UnalignedSupport() || address<0> = '0' then - if (UnalignedSupport() || BitIsClear (address, 0)) - { - // R[t] = SignExtend(data, 32); - int64_t signed_data = llvm::SignExtend64<16>(data); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) - return false; - } - else // Can only apply before ARMv7 - { - // R[t] = bits(32) UNKNOWN; - WriteBits32Unknown (t); - } + // R[t] = bits(32) UNKNOWN; + WriteBits32Unknown(t); } - return true; + } + return true; } - -// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword -// from memory, sign-extends it to form a 32-bit word, and writes it to a register. The offset register value can be + +// LDRSH (register) calculates an address from a base register value and an +// offset register value, loads a halfword +// from memory, sign-extends it to form a 32-bit word, and writes it to a +// register. The offset register value can be // shifted left by 0, 1, 2, or 3 bits. -bool -EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -7735,502 +7680,507 @@ EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEnc else // Can only apply before ARMv7 R[t] = bits(32) UNKNOWN; #endif - - bool success = false; - - if (ConditionPassed(opcode)) + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t m; + bool index; + bool add; + bool wback; + ARM_ShifterType shift_t; + uint32_t shift_n; + + // EncodingSpecificOperations(); NullCheckIfThumbEE(n); + switch (encoding) { + case eEncodingT1: + // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation + // in ThumbEE"; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + m = Bits32(opcode, 8, 6); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + + break; + + case eEncodingT2: + // if Rn == '1111' then SEE LDRSH (literal); + // if Rt == '1111' then SEE "Unallocated memory hints"; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = TRUE; add = TRUE; wback = FALSE; + index = true; + add = true; + wback = false; + + // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); + shift_t = SRType_LSL; + shift_n = Bits32(opcode, 5, 4); + + // if t == 13 || BadReg(m) then UNPREDICTABLE; + if ((t == 13) || BadReg(m)) + return false; + + break; + + case eEncodingA1: + // if P == '0' && W == '1' then SEE LDRSHT; + // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || + // (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + + // if t == 15 || m == 15 then UNPREDICTABLE; + if ((t == 15) || (m == 15)) + return false; + + // if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t))) + return false; + + break; + + default: + return false; + } + + uint64_t Rm = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + uint64_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + // offset = Shift(R[m], shift_t, shift_n, APSR.C); + addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + + addr_t offset_addr; + addr_t address; + + // offset_addr = if add then (R[n] + offset) else (R[n] - offset); + if (add) + offset_addr = Rn + offset; + else + offset_addr = Rn - offset; + + // address = if index then offset_addr else R[n]; + if (index) + address = offset_addr; + else + address = Rn; + + // data = MemU[address,2]; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + RegisterInfo offset_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusIndirectOffset(base_reg, offset_reg); + + uint64_t data = MemURead(context, address, 2, 0, &success); + if (!success) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + + // if UnalignedSupport() || address<0> = '0' then + if (UnalignedSupport() || BitIsClear(address, 0)) { + // R[t] = SignExtend(data, 32); + context.type = eContextRegisterLoad; + context.SetRegisterPlusIndirectOffset(base_reg, offset_reg); + + int64_t signed_data = llvm::SignExtend64<16>(data); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, + (uint64_t)signed_data)) + return false; + } else // Can only apply before ARMv7 { - uint32_t t; - uint32_t n; - uint32_t m; - bool index; - bool add; - bool wback; - ARM_ShifterType shift_t; - uint32_t shift_n; - - // EncodingSpecificOperations(); NullCheckIfThumbEE(n); - switch (encoding) - { - case eEncodingT1: - // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - m = Bits32 (opcode, 8, 6); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - - break; - - case eEncodingT2: - // if Rn == '1111' then SEE LDRSH (literal); - // if Rt == '1111' then SEE "Unallocated memory hints"; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = TRUE; add = TRUE; wback = FALSE; - index = true; - add = true; - wback = false; - - // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); - shift_t = SRType_LSL; - shift_n = Bits32 (opcode, 5, 4); - - // if t == 13 || BadReg(m) then UNPREDICTABLE; - if ((t == 13) || BadReg (m)) - return false; - - break; - - case eEncodingA1: - // if P == '0' && W == '1' then SEE LDRSHT; - // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - - // if t == 15 || m == 15 then UNPREDICTABLE; - if ((t == 15) || (m == 15)) - return false; - - // if wback && (n == 15 || n == t) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t))) - return false; - - break; - - default: - return false; - } - - uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - // offset = Shift(R[m], shift_t, shift_n, APSR.C); - addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - - addr_t offset_addr; - addr_t address; - - // offset_addr = if add then (R[n] + offset) else (R[n] - offset); - if (add) - offset_addr = Rn + offset; - else - offset_addr = Rn - offset; - - // address = if index then offset_addr else R[n]; - if (index) - address = offset_addr; - else - address = Rn; - - // data = MemU[address,2]; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - RegisterInfo offset_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); - - uint64_t data = MemURead (context, address, 2, 0, &success); - if (!success) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } - - // if UnalignedSupport() || address<0> = '0' then - if (UnalignedSupport() || BitIsClear (address, 0)) - { - // R[t] = SignExtend(data, 32); - context.type = eContextRegisterLoad; - context.SetRegisterPlusIndirectOffset (base_reg, offset_reg); - - int64_t signed_data = llvm::SignExtend64<16>(data); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data)) - return false; - } - else // Can only apply before ARMv7 - { - // R[t] = bits(32) UNKNOWN; - WriteBits32Unknown (t); - } + // R[t] = bits(32) UNKNOWN; + WriteBits32Unknown(t); } - return true; + } + return true; } - -// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination -// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. -bool -EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding) -{ + +// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and +// writes the result to the destination +// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before +// extracting the 8-bit value. +bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); rotated = ROR(R[m], rotation); R[d] = SignExtend(rotated<7:0>, 32); #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t d; - uint32_t m; - uint32_t rotation; - - // EncodingSpecificOperations(); - switch (encoding) - { - case eEncodingT1: - // d = UInt(Rd); m = UInt(Rm); rotation = 0; - d = Bits32 (opcode, 2, 0); - m = Bits32 (opcode, 5, 3); - rotation = 0; - - break; - - case eEncodingT2: - // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); - d = Bits32 (opcode, 11, 8); - m = Bits32 (opcode, 3, 0); - rotation = Bits32 (opcode, 5, 4) << 3; - - // if BadReg(d) || BadReg(m) then UNPREDICTABLE; - if (BadReg (d) || BadReg (m)) - return false; - - break; - - case eEncodingA1: - // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); - d = Bits32 (opcode, 15, 12); - m = Bits32 (opcode, 3, 0); - rotation = Bits32 (opcode, 11, 10) << 3; - - // if d == 15 || m == 15 then UNPREDICTABLE; - if ((d == 15) || (m == 15)) - return false; - - break; - - default: - return false; - } - - uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - // rotated = ROR(R[m], rotation); - uint64_t rotated = ROR (Rm, rotation, &success); - if (!success) - return false; - - // R[d] = SignExtend(rotated<7:0>, 32); - int64_t data = llvm::SignExtend64<8>(rotated); - - RegisterInfo source_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegister (source_reg); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) - return false; + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t d; + uint32_t m; + uint32_t rotation; + + // EncodingSpecificOperations(); + switch (encoding) { + case eEncodingT1: + // d = UInt(Rd); m = UInt(Rm); rotation = 0; + d = Bits32(opcode, 2, 0); + m = Bits32(opcode, 5, 3); + rotation = 0; + + break; + + case eEncodingT2: + // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); + d = Bits32(opcode, 11, 8); + m = Bits32(opcode, 3, 0); + rotation = Bits32(opcode, 5, 4) << 3; + + // if BadReg(d) || BadReg(m) then UNPREDICTABLE; + if (BadReg(d) || BadReg(m)) + return false; + + break; + + case eEncodingA1: + // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); + d = Bits32(opcode, 15, 12); + m = Bits32(opcode, 3, 0); + rotation = Bits32(opcode, 11, 10) << 3; + + // if d == 15 || m == 15 then UNPREDICTABLE; + if ((d == 15) || (m == 15)) + return false; + + break; + + default: + return false; } - return true; -} - -// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination -// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. -bool -EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding) -{ + + uint64_t Rm = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + // rotated = ROR(R[m], rotation); + uint64_t rotated = ROR(Rm, rotation, &success); + if (!success) + return false; + + // R[d] = SignExtend(rotated<7:0>, 32); + int64_t data = llvm::SignExtend64<8>(rotated); + + RegisterInfo source_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegister(source_reg); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, + (uint64_t)data)) + return false; + } + return true; +} + +// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and +// writes the result to the destination +// register. You can specify a rotation by 0, 8, 16, or 24 bits before +// extracting the 16-bit value. +bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); rotated = ROR(R[m], rotation); R[d] = SignExtend(rotated<15:0>, 32); #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t d; - uint32_t m; - uint32_t rotation; - - // EncodingSpecificOperations(); - switch (encoding) - { - case eEncodingT1: - // d = UInt(Rd); m = UInt(Rm); rotation = 0; - d = Bits32 (opcode, 2, 0); - m = Bits32 (opcode, 5, 3); - rotation = 0; - - break; - - case eEncodingT2: - // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); - d = Bits32 (opcode, 11, 8); - m = Bits32 (opcode, 3, 0); - rotation = Bits32 (opcode, 5, 4) << 3; - - // if BadReg(d) || BadReg(m) then UNPREDICTABLE; - if (BadReg (d) || BadReg (m)) - return false; - - break; - - case eEncodingA1: - // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); - d = Bits32 (opcode, 15, 12); - m = Bits32 (opcode, 3, 0); - rotation = Bits32 (opcode, 11, 10) << 3; - - // if d == 15 || m == 15 then UNPREDICTABLE; - if ((d == 15) || (m == 15)) - return false; - - break; - - default: - return false; - } - - uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - // rotated = ROR(R[m], rotation); - uint64_t rotated = ROR (Rm, rotation, &success); - if (!success) - return false; - - // R[d] = SignExtend(rotated<15:0>, 32); - RegisterInfo source_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegister (source_reg); - - int64_t data = llvm::SignExtend64<16> (rotated); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data)) - return false; + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t d; + uint32_t m; + uint32_t rotation; + + // EncodingSpecificOperations(); + switch (encoding) { + case eEncodingT1: + // d = UInt(Rd); m = UInt(Rm); rotation = 0; + d = Bits32(opcode, 2, 0); + m = Bits32(opcode, 5, 3); + rotation = 0; + + break; + + case eEncodingT2: + // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); + d = Bits32(opcode, 11, 8); + m = Bits32(opcode, 3, 0); + rotation = Bits32(opcode, 5, 4) << 3; + + // if BadReg(d) || BadReg(m) then UNPREDICTABLE; + if (BadReg(d) || BadReg(m)) + return false; + + break; + + case eEncodingA1: + // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); + d = Bits32(opcode, 15, 12); + m = Bits32(opcode, 3, 0); + rotation = Bits32(opcode, 11, 10) << 3; + + // if d == 15 || m == 15 then UNPREDICTABLE; + if ((d == 15) || (m == 15)) + return false; + + break; + + default: + return false; } - - return true; + + uint64_t Rm = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + // rotated = ROR(R[m], rotation); + uint64_t rotated = ROR(Rm, rotation, &success); + if (!success) + return false; + + // R[d] = SignExtend(rotated<15:0>, 32); + RegisterInfo source_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegister(source_reg); + + int64_t data = llvm::SignExtend64<16>(rotated); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, + (uint64_t)data)) + return false; + } + + return true; } - -// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination -// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value. -bool -EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding) -{ + +// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and +// writes the result to the destination +// register. You can specify a rotation by 0, 8, 16, or 24 bits before +// extracting the 8-bit value. +bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); rotated = ROR(R[m], rotation); R[d] = ZeroExtend(rotated<7:0>, 32); #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t d; - uint32_t m; - uint32_t rotation; - - // EncodingSpecificOperations(); - switch (encoding) - { - case eEncodingT1: - // d = UInt(Rd); m = UInt(Rm); rotation = 0; - d = Bits32 (opcode, 2, 0); - m = Bits32 (opcode, 5, 3); - rotation = 0; - - break; - - case eEncodingT2: - // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); - d = Bits32 (opcode, 11, 8); - m = Bits32 (opcode, 3, 0); - rotation = Bits32 (opcode, 5, 4) << 3; - - // if BadReg(d) || BadReg(m) then UNPREDICTABLE; - if (BadReg (d) || BadReg (m)) - return false; - - break; - - case eEncodingA1: - // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); - d = Bits32 (opcode, 15, 12); - m = Bits32 (opcode, 3, 0); - rotation = Bits32 (opcode, 11, 10) << 3; - - // if d == 15 || m == 15 then UNPREDICTABLE; - if ((d == 15) || (m == 15)) - return false; - - break; - - default: - return false; - } - - uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - // rotated = ROR(R[m], rotation); - uint64_t rotated = ROR (Rm, rotation, &success); - if (!success) - return false; - - // R[d] = ZeroExtend(rotated<7:0>, 32); - RegisterInfo source_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegister (source_reg); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0))) - return false; + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t d; + uint32_t m; + uint32_t rotation; + + // EncodingSpecificOperations(); + switch (encoding) { + case eEncodingT1: + // d = UInt(Rd); m = UInt(Rm); rotation = 0; + d = Bits32(opcode, 2, 0); + m = Bits32(opcode, 5, 3); + rotation = 0; + + break; + + case eEncodingT2: + // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); + d = Bits32(opcode, 11, 8); + m = Bits32(opcode, 3, 0); + rotation = Bits32(opcode, 5, 4) << 3; + + // if BadReg(d) || BadReg(m) then UNPREDICTABLE; + if (BadReg(d) || BadReg(m)) + return false; + + break; + + case eEncodingA1: + // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); + d = Bits32(opcode, 15, 12); + m = Bits32(opcode, 3, 0); + rotation = Bits32(opcode, 11, 10) << 3; + + // if d == 15 || m == 15 then UNPREDICTABLE; + if ((d == 15) || (m == 15)) + return false; + + break; + + default: + return false; } - return true; -} - -// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination -// register. You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. -bool -EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding) -{ + + uint64_t Rm = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + // rotated = ROR(R[m], rotation); + uint64_t rotated = ROR(Rm, rotation, &success); + if (!success) + return false; + + // R[d] = ZeroExtend(rotated<7:0>, 32); + RegisterInfo source_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegister(source_reg); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, + Bits32(rotated, 7, 0))) + return false; + } + return true; +} + +// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and +// writes the result to the destination +// register. You can specify a rotation by 0, 8, 16, or 24 bits before +// extracting the 16-bit value. +bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); rotated = ROR(R[m], rotation); R[d] = ZeroExtend(rotated<15:0>, 32); #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t d; - uint32_t m; - uint32_t rotation; - - switch (encoding) - { - case eEncodingT1: - // d = UInt(Rd); m = UInt(Rm); rotation = 0; - d = Bits32 (opcode, 2, 0); - m = Bits32 (opcode, 5, 3); - rotation = 0; - - break; - - case eEncodingT2: - // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); - d = Bits32 (opcode, 11, 8); - m = Bits32 (opcode, 3, 0); - rotation = Bits32 (opcode, 5, 4) << 3; - - // if BadReg(d) || BadReg(m) then UNPREDICTABLE; - if (BadReg (d) || BadReg (m)) - return false; - - break; - - case eEncodingA1: - // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); - d = Bits32 (opcode, 15, 12); - m = Bits32 (opcode, 3, 0); - rotation = Bits32 (opcode, 11, 10) << 3; - - // if d == 15 || m == 15 then UNPREDICTABLE; - if ((d == 15) || (m == 15)) - return false; - - break; - - default: - return false; - } - - uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success); - if (!success) - return false; - - // rotated = ROR(R[m], rotation); - uint64_t rotated = ROR (Rm, rotation, &success); - if (!success) - return false; - - // R[d] = ZeroExtend(rotated<15:0>, 32); - RegisterInfo source_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg); - - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegister (source_reg); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0))) - return false; + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t d; + uint32_t m; + uint32_t rotation; + + switch (encoding) { + case eEncodingT1: + // d = UInt(Rd); m = UInt(Rm); rotation = 0; + d = Bits32(opcode, 2, 0); + m = Bits32(opcode, 5, 3); + rotation = 0; + + break; + + case eEncodingT2: + // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); + d = Bits32(opcode, 11, 8); + m = Bits32(opcode, 3, 0); + rotation = Bits32(opcode, 5, 4) << 3; + + // if BadReg(d) || BadReg(m) then UNPREDICTABLE; + if (BadReg(d) || BadReg(m)) + return false; + + break; + + case eEncodingA1: + // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); + d = Bits32(opcode, 15, 12); + m = Bits32(opcode, 3, 0); + rotation = Bits32(opcode, 11, 10) << 3; + + // if d == 15 || m == 15 then UNPREDICTABLE; + if ((d == 15) || (m == 15)) + return false; + + break; + + default: + return false; } - return true; + + uint64_t Rm = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); + if (!success) + return false; + + // rotated = ROR(R[m], rotation); + uint64_t rotated = ROR(Rm, rotation, &success); + if (!success) + return false; + + // R[d] = ZeroExtend(rotated<15:0>, 32); + RegisterInfo source_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, source_reg); + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegister(source_reg); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, + Bits32(rotated, 15, 0))) + return false; + } + return true; } - -// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following -// word respectively. -bool -EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding) -{ + +// RFE (Return From Exception) loads the PC and the CPSR from the word at the +// specified address and the following +// word respectively. +bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -8243,142 +8193,141 @@ EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding enco BranchWritePC(MemA[address,4]); if wback then R[n] = if increment then R[n]+8 else R[n]-8; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t n; - bool wback; - bool increment; - bool wordhigher; - - // EncodingSpecificOperations(); - switch (encoding) - { - case eEncodingT1: - // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE; - n = Bits32 (opcode, 19, 16); - wback = BitIsSet (opcode, 21); - increment = false; - wordhigher = false; - - // if n == 15 then UNPREDICTABLE; - if (n == 15) - return false; - - // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; - if (InITBlock() && !LastInITBlock()) - return false; - - break; - - case eEncodingT2: - // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE; - n = Bits32 (opcode, 19, 16); - wback = BitIsSet (opcode, 21); - increment = true; - wordhigher = false; - - // if n == 15 then UNPREDICTABLE; - if (n == 15) - return false; - - // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; - if (InITBlock() && !LastInITBlock()) - return false; - - break; - - case eEncodingA1: - // n = UInt(Rn); - n = Bits32 (opcode, 19, 16); - - // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U); - wback = BitIsSet (opcode, 21); - increment = BitIsSet (opcode, 23); - wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23)); - - // if n == 15 then UNPREDICTABLE; - if (n == 15) - return false; - - break; - - default: - return false; - } - - // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then - if (!CurrentModeIsPrivileged ()) - // UNPREDICTABLE; + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t n; + bool wback; + bool increment; + bool wordhigher; + + // EncodingSpecificOperations(); + switch (encoding) { + case eEncodingT1: + // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = + // FALSE; + n = Bits32(opcode, 19, 16); + wback = BitIsSet(opcode, 21); + increment = false; + wordhigher = false; + + // if n == 15 then UNPREDICTABLE; + if (n == 15) + return false; + + // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; + if (InITBlock() && !LastInITBlock()) + return false; + + break; + + case eEncodingT2: + // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE; + n = Bits32(opcode, 19, 16); + wback = BitIsSet(opcode, 21); + increment = true; + wordhigher = false; + + // if n == 15 then UNPREDICTABLE; + if (n == 15) + return false; + + // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; + if (InITBlock() && !LastInITBlock()) + return false; + + break; + + case eEncodingA1: + // n = UInt(Rn); + n = Bits32(opcode, 19, 16); + + // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U); + wback = BitIsSet(opcode, 21); + increment = BitIsSet(opcode, 23); + wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23)); + + // if n == 15 then UNPREDICTABLE; + if (n == 15) + return false; + + break; + + default: + return false; + } + + // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE + // then + if (!CurrentModeIsPrivileged()) + // UNPREDICTABLE; + return false; + else { + uint64_t Rn = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); + if (!success) + return false; + + addr_t address; + // address = if increment then R[n] else R[n]-8; + if (increment) + address = Rn; + else + address = Rn - 8; + + // if wordhigher then address = address+4; + if (wordhigher) + address = address + 4; + + // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + EmulateInstruction::Context context; + context.type = eContextReturnFromException; + context.SetRegisterPlusOffset(base_reg, address - Rn); + + uint64_t data = MemARead(context, address + 4, 4, 0, &success); + if (!success) + return false; + + CPSRWriteByInstr(data, 15, true); + + // BranchWritePC(MemA[address,4]); + uint64_t data2 = MemARead(context, address, 4, 0, &success); + if (!success) + return false; + + BranchWritePC(context, data2); + + // if wback then R[n] = if increment then R[n]+8 else R[n]-8; + if (wback) { + context.type = eContextAdjustBaseRegister; + if (increment) { + context.SetOffset(8); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + Rn + 8)) + return false; + } else { + context.SetOffset(-8); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + Rn - 8)) return false; - else - { - uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); - if (!success) - return false; - - addr_t address; - // address = if increment then R[n] else R[n]-8; - if (increment) - address = Rn; - else - address = Rn - 8; - - // if wordhigher then address = address+4; - if (wordhigher) - address = address + 4; - - // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - EmulateInstruction::Context context; - context.type = eContextReturnFromException; - context.SetRegisterPlusOffset (base_reg, address - Rn); - - uint64_t data = MemARead (context, address + 4, 4, 0, &success); - if (!success) - return false; - - CPSRWriteByInstr (data, 15, true); - - // BranchWritePC(MemA[address,4]); - uint64_t data2 = MemARead (context, address, 4, 0, &success); - if (!success) - return false; - - BranchWritePC (context, data2); - - // if wback then R[n] = if increment then R[n]+8 else R[n]-8; - if (wback) - { - context.type = eContextAdjustBaseRegister; - if (increment) - { - context.SetOffset (8); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8)) - return false; - } - else - { - context.SetOffset (-8); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8)) - return false; - } - } // if wback } - } // if ConditionPassed() - return true; + } // if wback + } + } // if ConditionPassed() + return true; } - -// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value, -// and writes the result to the destination register. It can optionally update the condition flags based on + +// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a +// register value and an immediate value, +// and writes the result to the destination register. It can optionally update +// the condition flags based on // the result. -bool -EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -8395,64 +8344,69 @@ EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn; - uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn - bool setflags; - uint32_t carry; // the carry bit after ARM/Thumb Expand operation - switch (encoding) - { - case eEncodingT1: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) - // if Rd == '1111' && S == '1' then SEE TEQ (immediate); - if (Rd == 15 && setflags) - return EmulateTEQImm (opcode, eEncodingT1); - if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn; + uint32_t + imm32; // the immediate value to be ORed to the value obtained from Rn + bool setflags; + uint32_t carry; // the carry bit after ARM/Thumb Expand operation + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm_C( + opcode, APSR_C, + carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) + // if Rd == '1111' && S == '1' then SEE TEQ (immediate); + if (Rd == 15 && setflags) + return EmulateTEQImm(opcode, eEncodingT1); + if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = + ARMExpandImm_C(opcode, APSR_C, + carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t result = val1 ^ imm32; + uint32_t result = val1 ^ imm32; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an -// optionally-shifted register value, and writes the result to the destination register. +// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register +// value and an +// optionally-shifted register value, and writes the result to the destination +// register. // It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -8470,82 +8424,82 @@ EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn, Rm; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - bool setflags; - uint32_t carry; - switch (encoding) - { - case eEncodingT1: - Rd = Rn = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - shift_t = SRType_LSL; - shift_n = 0; - break; - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - // if Rd == '1111' && S == '1' then SEE TEQ (register); - if (Rd == 15 && setflags) - return EmulateTEQReg (opcode, eEncodingT1); - if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftARM(opcode, shift_t); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn, Rm; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + bool setflags; + uint32_t carry; + switch (encoding) { + case eEncodingT1: + Rd = Rn = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + shift_t = SRType_LSL; + shift_n = 0; + break; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + // if Rd == '1111' && S == '1' then SEE TEQ (register); + if (Rd == 15 && setflags) + return EmulateTEQReg(opcode, eEncodingT1); + if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftARM(opcode, shift_t); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - // Read the second operand. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; + // Read the second operand. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); - if (!success) - return false; - uint32_t result = val1 ^ shifted; + uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); + if (!success) + return false; + uint32_t result = val1 ^ shifted; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and -// writes the result to the destination register. It can optionally update the condition flags based +// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value +// and an immediate value, and +// writes the result to the destination register. It can optionally update the +// condition flags based // on the result. -bool -EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -8562,63 +8516,67 @@ EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn; - uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn - bool setflags; - uint32_t carry; // the carry bit after ARM/Thumb Expand operation - switch (encoding) - { - case eEncodingT1: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) - // if Rn == '1111' then SEE MOV (immediate); - if (Rn == 15) - return EmulateMOVRdImm (opcode, eEncodingT2); - if (BadReg(Rd) || Rn == 13) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) - - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn; + uint32_t + imm32; // the immediate value to be ORed to the value obtained from Rn + bool setflags; + uint32_t carry; // the carry bit after ARM/Thumb Expand operation + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm_C( + opcode, APSR_C, + carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) + // if Rn == '1111' then SEE MOV (immediate); + if (Rn == 15) + return EmulateMOVRdImm(opcode, eEncodingT2); + if (BadReg(Rd) || Rn == 13) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = + ARMExpandImm_C(opcode, APSR_C, + carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) + + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t result = val1 | imm32; + uint32_t result = val1 | imm32; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register -// value, and writes the result to the destination register. It can optionally update the condition flags based +// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value +// and an optionally-shifted register +// value, and writes the result to the destination register. It can optionally +// update the condition flags based // on the result. -bool -EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -8636,80 +8594,79 @@ EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rd, Rn, Rm; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - bool setflags; - uint32_t carry; - switch (encoding) - { - case eEncodingT1: - Rd = Rn = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - shift_t = SRType_LSL; - shift_n = 0; - break; - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - // if Rn == '1111' then SEE MOV (register); - if (Rn == 15) - return EmulateMOVRdRm (opcode, eEncodingT3); - if (BadReg(Rd) || Rn == 13 || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftARM(opcode, shift_t); - - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rd, Rn, Rm; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + bool setflags; + uint32_t carry; + switch (encoding) { + case eEncodingT1: + Rd = Rn = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + shift_t = SRType_LSL; + shift_n = 0; + break; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + // if Rn == '1111' then SEE MOV (register); + if (Rn == 15) + return EmulateMOVRdRm(opcode, eEncodingT3); + if (BadReg(Rd) || Rn == 13 || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftARM(opcode, shift_t); + + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - // Read the second operand. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; + // Read the second operand. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); - if (!success) - return false; - uint32_t result = val1 | shifted; + uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); + if (!success) + return false; + uint32_t result = val1 | shifted; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) - return false; - } - return true; + if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) + return false; + } + return true; } -// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to -// the destination register. It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding) -{ +// Reverse Subtract (immediate) subtracts a register value from an immediate +// value, and writes the result to +// the destination register. It can optionally update the condition flags based +// on the result. +bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -8726,62 +8683,66 @@ EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; + + uint32_t Rd; // the destination register + uint32_t Rn; // the first operand + bool setflags; + uint32_t + imm32; // the immediate value to be added to the value obtained from Rn + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 2, 0); + Rn = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + imm32 = 0; + break; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) + if (BadReg(Rd) || BadReg(Rn)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } + // Read the register value from the operand register Rn. + uint32_t reg_val = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t Rd; // the destination register - uint32_t Rn; // the first operand - bool setflags; - uint32_t imm32; // the immediate value to be added to the value obtained from Rn - switch (encoding) { - case eEncodingT1: - Rd = Bits32(opcode, 2, 0); - Rn = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - imm32 = 0; - break; - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) - if (BadReg(Rd) || BadReg(Rn)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } - // Read the register value from the operand register Rn. - uint32_t reg_val = ReadCoreReg(Rn, &success); - if (!success) - return false; - - AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1); + AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; - return true; + return true; } -// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the -// result to the destination register. It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding) -{ +// Reverse Subtract (register) subtracts a register value from an +// optionally-shifted register value, and writes the +// result to the destination register. It can optionally update the condition +// flags based on the result. +bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -8799,69 +8760,72 @@ EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; + + uint32_t Rd; // the destination register + uint32_t Rn; // the first operand + uint32_t Rm; // the second operand + bool setflags; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; + if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftARM(opcode, shift_t); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } + // Read the register value from register Rn. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t Rd; // the destination register - uint32_t Rn; // the first operand - uint32_t Rm; // the second operand - bool setflags; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - switch (encoding) { - case eEncodingT1: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; - if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftARM(opcode, shift_t); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } - // Read the register value from register Rn. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the register value from register Rm. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - // Read the register value from register Rm. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; - - uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - AddWithCarryResult res = AddWithCarry(~val1, shifted, 1); + uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + AddWithCarryResult res = AddWithCarry(~val1, shifted, 1); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; - return true; + return true; } -// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from -// an immediate value, and writes the result to the destination register. It can optionally update the condition +// Reverse Subtract with Carry (immediate) subtracts a register value and the +// value of NOT (Carry flag) from +// an immediate value, and writes the result to the destination register. It can +// optionally update the condition // flags based on the result. -bool -EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -8878,49 +8842,53 @@ EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; + + uint32_t Rd; // the destination register + uint32_t Rn; // the first operand + bool setflags; + uint32_t + imm32; // the immediate value to be added to the value obtained from Rn + switch (encoding) { + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } + // Read the register value from the operand register Rn. + uint32_t reg_val = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t Rd; // the destination register - uint32_t Rn; // the first operand - bool setflags; - uint32_t imm32; // the immediate value to be added to the value obtained from Rn - switch (encoding) { - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } - // Read the register value from the operand register Rn. - uint32_t reg_val = ReadCoreReg(Rn, &success); - if (!success) - return false; - - AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C); + AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; - return true; + return true; } -// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an -// optionally-shifted register value, and writes the result to the destination register. It can optionally update the +// Reverse Subtract with Carry (register) subtracts a register value and the +// value of NOT (Carry flag) from an +// optionally-shifted register value, and writes the result to the destination +// register. It can optionally update the // condition flags based on the result. -bool -EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -8938,59 +8906,61 @@ EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; + + uint32_t Rd; // the destination register + uint32_t Rn; // the first operand + uint32_t Rm; // the second operand + bool setflags; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + switch (encoding) { + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftARM(opcode, shift_t); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } + // Read the register value from register Rn. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t Rd; // the destination register - uint32_t Rn; // the first operand - uint32_t Rm; // the second operand - bool setflags; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - switch (encoding) { - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftARM(opcode, shift_t); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } - // Read the register value from register Rn. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the register value from register Rm. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - // Read the register value from register Rm. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; - - uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C); + uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; - return true; + return true; } // Subtract with Carry (immediate) subtracts an immediate value and the value of -// NOT (Carry flag) from a register value, and writes the result to the destination register. +// NOT (Carry flag) from a register value, and writes the result to the +// destination register. // It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -9007,57 +8977,61 @@ EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; + + uint32_t Rd; // the destination register + uint32_t Rn; // the first operand + bool setflags; + uint32_t + imm32; // the immediate value to be added to the value obtained from Rn + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) + if (BadReg(Rd) || BadReg(Rn)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } + // Read the register value from the operand register Rn. + uint32_t reg_val = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t Rd; // the destination register - uint32_t Rn; // the first operand - bool setflags; - uint32_t imm32; // the immediate value to be added to the value obtained from Rn - switch (encoding) { - case eEncodingT1: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) - if (BadReg(Rd) || BadReg(Rn)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } - // Read the register value from the operand register Rn. - uint32_t reg_val = ReadCoreReg(Rn, &success); - if (!success) - return false; - - AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C); + AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; - return true; + return true; } -// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of -// NOT (Carry flag) from a register value, and writes the result to the destination register. +// Subtract with Carry (register) subtracts an optionally-shifted register value +// and the value of +// NOT (Carry flag) from a register value, and writes the result to the +// destination register. // It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -9075,74 +9049,77 @@ EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding e APSR.V = overflow; #endif - bool success = false; + bool success = false; + + uint32_t Rd; // the destination register + uint32_t Rn; // the first operand + uint32_t Rm; // the second operand + bool setflags; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + switch (encoding) { + case eEncodingT1: + Rd = Rn = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + shift_t = SRType_LSL; + shift_n = 0; + break; + case eEncodingT2: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + shift_n = DecodeImmShiftARM(opcode, shift_t); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; + } + // Read the register value from register Rn. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t Rd; // the destination register - uint32_t Rn; // the first operand - uint32_t Rm; // the second operand - bool setflags; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - switch (encoding) { - case eEncodingT1: - Rd = Rn = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - shift_t = SRType_LSL; - shift_n = 0; - break; - case eEncodingT2: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - setflags = BitIsSet(opcode, 20); - shift_n = DecodeImmShiftARM(opcode, shift_t); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } - // Read the register value from register Rn. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the register value from register Rm. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - // Read the register value from register Rm. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; - - uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C); + uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; - return true; + return true; } -// This instruction subtracts an immediate value from a register value, and writes the result -// to the destination register. It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding) -{ +// This instruction subtracts an immediate value from a register value, and +// writes the result +// to the destination register. It can optionally update the condition flags +// based on the result. +bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -9156,84 +9133,87 @@ EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncod APSR.V = overflow; #endif - bool success = false; - - uint32_t Rd; // the destination register - uint32_t Rn; // the first operand - bool setflags; - uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn - switch (encoding) { - case eEncodingT1: - Rd = Bits32(opcode, 2, 0); - Rn = Bits32(opcode, 5, 3); - setflags = !InITBlock(); - imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32) - break; - case eEncodingT2: - Rd = Rn = Bits32(opcode, 10, 8); - setflags = !InITBlock(); - imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) - break; - case eEncodingT3: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) - - // if Rd == '1111' && S == '1' then SEE CMP (immediate); - if (Rd == 15 && setflags) - return EmulateCMPImm (opcode, eEncodingT2); - - // if Rn == '1101' then SEE SUB (SP minus immediate); - if (Rn == 13) - return EmulateSUBSPImm (opcode, eEncodingT2); - - // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE; - if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15) - return false; - break; - case eEncodingT4: - Rd = Bits32(opcode, 11, 8); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) - - // if Rn == '1111' then SEE ADR; - if (Rn == 15) - return EmulateADR (opcode, eEncodingT2); - - // if Rn == '1101' then SEE SUB (SP minus immediate); - if (Rn == 13) - return EmulateSUBSPImm (opcode, eEncodingT3); + bool success = false; + + uint32_t Rd; // the destination register + uint32_t Rn; // the first operand + bool setflags; + uint32_t imm32; // the immediate value to be subtracted from the value + // obtained from Rn + switch (encoding) { + case eEncodingT1: + Rd = Bits32(opcode, 2, 0); + Rn = Bits32(opcode, 5, 3); + setflags = !InITBlock(); + imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32) + break; + case eEncodingT2: + Rd = Rn = Bits32(opcode, 10, 8); + setflags = !InITBlock(); + imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) + break; + case eEncodingT3: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) + + // if Rd == '1111' && S == '1' then SEE CMP (immediate); + if (Rd == 15 && setflags) + return EmulateCMPImm(opcode, eEncodingT2); + + // if Rn == '1101' then SEE SUB (SP minus immediate); + if (Rn == 13) + return EmulateSUBSPImm(opcode, eEncodingT2); + + // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE; + if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15) + return false; + break; + case eEncodingT4: + Rd = Bits32(opcode, 11, 8); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) + + // if Rn == '1111' then SEE ADR; + if (Rn == 15) + return EmulateADR(opcode, eEncodingT2); + + // if Rn == '1101' then SEE SUB (SP minus immediate); + if (Rn == 13) + return EmulateSUBSPImm(opcode, eEncodingT3); + + if (BadReg(Rd)) + return false; + break; + default: + return false; + } + // Read the register value from the operand register Rn. + uint32_t reg_val = ReadCoreReg(Rn, &success); + if (!success) + return false; - if (BadReg(Rd)) - return false; - break; - default: - return false; - } - // Read the register value from the operand register Rn. - uint32_t reg_val = ReadCoreReg(Rn, &success); - if (!success) - return false; - - AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); + AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; - return true; + return true; } -// This instruction subtracts an immediate value from a register value, and writes the result -// to the destination register. It can optionally update the condition flags based on the result. -bool -EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding) -{ +// This instruction subtracts an immediate value from a register value, and +// writes the result +// to the destination register. It can optionally update the condition flags +// based on the result. +bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -9250,65 +9230,68 @@ EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncodin APSR.V = overflow; #endif - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t Rd; // the destination register - uint32_t Rn; // the first operand - bool setflags; - uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn - switch (encoding) { - case eEncodingA1: - Rd = Bits32(opcode, 15, 12); - Rn = Bits32(opcode, 19, 16); - setflags = BitIsSet(opcode, 20); - imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) - - // if Rn == '1111' && S == '0' then SEE ADR; - if (Rn == 15 && !setflags) - return EmulateADR (opcode, eEncodingA2); - - // if Rn == '1101' then SEE SUB (SP minus immediate); - if (Rn == 13) - return EmulateSUBSPImm (opcode, eEncodingA1); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (Rd == 15 && setflags) - return EmulateSUBSPcLrEtc (opcode, encoding); - break; - default: - return false; - } - // Read the register value from the operand register Rn. - uint32_t reg_val = ReadCoreReg(Rn, &success); - if (!success) - return false; - - AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); + bool success = false; - EmulateInstruction::Context context; - if (Rd == 13) - context.type = EmulateInstruction::eContextAdjustStackPointer; - else - context.type = EmulateInstruction::eContextRegisterPlusOffset; - - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg); - int64_t imm32_signed = imm32; - context.SetRegisterPlusOffset (dwarf_reg, -imm32_signed); - - if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow)) - return false; + if (ConditionPassed(opcode)) { + uint32_t Rd; // the destination register + uint32_t Rn; // the first operand + bool setflags; + uint32_t imm32; // the immediate value to be subtracted from the value + // obtained from Rn + switch (encoding) { + case eEncodingA1: + Rd = Bits32(opcode, 15, 12); + Rn = Bits32(opcode, 19, 16); + setflags = BitIsSet(opcode, 20); + imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) + + // if Rn == '1111' && S == '0' then SEE ADR; + if (Rn == 15 && !setflags) + return EmulateADR(opcode, eEncodingA2); + + // if Rn == '1101' then SEE SUB (SP minus immediate); + if (Rn == 13) + return EmulateSUBSPImm(opcode, eEncodingA1); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (Rd == 15 && setflags) + return EmulateSUBSPcLrEtc(opcode, encoding); + break; + default: + return false; } - return true; -} + // Read the register value from the operand register Rn. + uint32_t reg_val = ReadCoreReg(Rn, &success); + if (!success) + return false; -// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an -// immediate value. It updates the condition flags based on the result, and discards the result. -bool -EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding) -{ + AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); + + EmulateInstruction::Context context; + if (Rd == 13) + context.type = EmulateInstruction::eContextAdjustStackPointer; + else + context.type = EmulateInstruction::eContextRegisterPlusOffset; + + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, Rn, dwarf_reg); + int64_t imm32_signed = imm32; + context.SetRegisterPlusOffset(dwarf_reg, -imm32_signed); + + if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, + res.carry_out, res.overflow)) + return false; + } + return true; +} + +// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a +// register value and an +// immediate value. It updates the condition flags based on the result, and +// discards the result. +bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -9320,52 +9303,56 @@ EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rn; - uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn - uint32_t carry; // the carry bit after ARM/Thumb Expand operation - switch (encoding) - { - case eEncodingT1: - Rn = Bits32(opcode, 19, 16); - imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) - if (BadReg(Rn)) - return false; - break; - case eEncodingA1: - Rn = Bits32(opcode, 19, 16); - imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rn; + uint32_t + imm32; // the immediate value to be ANDed to the value obtained from Rn + uint32_t carry; // the carry bit after ARM/Thumb Expand operation + switch (encoding) { + case eEncodingT1: + Rn = Bits32(opcode, 19, 16); + imm32 = ThumbExpandImm_C( + opcode, APSR_C, + carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) + if (BadReg(Rn)) + return false; + break; + case eEncodingA1: + Rn = Bits32(opcode, 19, 16); + imm32 = + ARMExpandImm_C(opcode, APSR_C, + carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t result = val1 ^ imm32; + uint32_t result = val1 ^ imm32; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteFlags(context, result, carry)) - return false; - } - return true; + if (!WriteFlags(context, result, carry)) + return false; + } + return true; } -// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an -// optionally-shifted register value. It updates the condition flags based on the result, and discards +// Test Equivalence (register) performs a bitwise exclusive OR operation on a +// register value and an +// optionally-shifted register value. It updates the condition flags based on +// the result, and discards // the result. -bool -EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -9378,62 +9365,60 @@ EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rn, Rm; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - uint32_t carry; - switch (encoding) - { - case eEncodingT1: - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - if (BadReg(Rn) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - shift_n = DecodeImmShiftARM(opcode, shift_t); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rn, Rm; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + uint32_t carry; + switch (encoding) { + case eEncodingT1: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + if (BadReg(Rn) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + shift_n = DecodeImmShiftARM(opcode, shift_t); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - // Read the second operand. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; + // Read the second operand. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); - if (!success) - return false; - uint32_t result = val1 ^ shifted; + uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); + if (!success) + return false; + uint32_t result = val1 ^ shifted; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteFlags(context, result, carry)) - return false; - } - return true; + if (!WriteFlags(context, result, carry)) + return false; + } + return true; } -// Test (immediate) performs a bitwise AND operation on a register value and an immediate value. +// Test (immediate) performs a bitwise AND operation on a register value and an +// immediate value. // It updates the condition flags based on the result, and discards the result. -bool -EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -9445,51 +9430,54 @@ EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rn; - uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn - uint32_t carry; // the carry bit after ARM/Thumb Expand operation - switch (encoding) - { - case eEncodingT1: - Rn = Bits32(opcode, 19, 16); - imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) - if (BadReg(Rn)) - return false; - break; - case eEncodingA1: - Rn = Bits32(opcode, 19, 16); - imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rn; + uint32_t + imm32; // the immediate value to be ANDed to the value obtained from Rn + uint32_t carry; // the carry bit after ARM/Thumb Expand operation + switch (encoding) { + case eEncodingT1: + Rn = Bits32(opcode, 19, 16); + imm32 = ThumbExpandImm_C( + opcode, APSR_C, + carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) + if (BadReg(Rn)) + return false; + break; + case eEncodingA1: + Rn = Bits32(opcode, 19, 16); + imm32 = + ARMExpandImm_C(opcode, APSR_C, + carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - uint32_t result = val1 & imm32; + uint32_t result = val1 & imm32; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteFlags(context, result, carry)) - return false; - } - return true; + if (!WriteFlags(context, result, carry)) + return false; + } + return true; } -// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value. +// Test (register) performs a bitwise AND operation on a register value and an +// optionally-shifted register value. // It updates the condition flags based on the result, and discards the result. -bool -EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 // ARM pseudo code... if ConditionPassed() then @@ -9502,67 +9490,64 @@ EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding e // APSR.V unchanged #endif - bool success = false; + bool success = false; - if (ConditionPassed(opcode)) - { - uint32_t Rn, Rm; - ARM_ShifterType shift_t; - uint32_t shift_n; // the shift applied to the value read from Rm - uint32_t carry; - switch (encoding) - { - case eEncodingT1: - Rn = Bits32(opcode, 2, 0); - Rm = Bits32(opcode, 5, 3); - shift_t = SRType_LSL; - shift_n = 0; - break; - case eEncodingT2: - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - shift_n = DecodeImmShiftThumb(opcode, shift_t); - if (BadReg(Rn) || BadReg(Rm)) - return false; - break; - case eEncodingA1: - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - shift_n = DecodeImmShiftARM(opcode, shift_t); - break; - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t Rn, Rm; + ARM_ShifterType shift_t; + uint32_t shift_n; // the shift applied to the value read from Rm + uint32_t carry; + switch (encoding) { + case eEncodingT1: + Rn = Bits32(opcode, 2, 0); + Rm = Bits32(opcode, 5, 3); + shift_t = SRType_LSL; + shift_n = 0; + break; + case eEncodingT2: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + if (BadReg(Rn) || BadReg(Rm)) + return false; + break; + case eEncodingA1: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + shift_n = DecodeImmShiftARM(opcode, shift_t); + break; + default: + return false; + } - // Read the first operand. - uint32_t val1 = ReadCoreReg(Rn, &success); - if (!success) - return false; + // Read the first operand. + uint32_t val1 = ReadCoreReg(Rn, &success); + if (!success) + return false; - // Read the second operand. - uint32_t val2 = ReadCoreReg(Rm, &success); - if (!success) - return false; + // Read the second operand. + uint32_t val2 = ReadCoreReg(Rm, &success); + if (!success) + return false; - uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); - if (!success) - return false; - uint32_t result = val1 & shifted; + uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); + if (!success) + return false; + uint32_t result = val1 & shifted; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextImmediate; - context.SetNoArgs (); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextImmediate; + context.SetNoArgs(); - if (!WriteFlags(context, result, carry)) - return false; - } - return true; + if (!WriteFlags(context, result, carry)) + return false; + } + return true; } - + // A8.6.216 SUB (SP minus register) -bool -EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -9578,90 +9563,89 @@ EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding APSR.C = carry; APSR.V = overflow; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t d; - uint32_t m; - bool setflags; - ARM_ShifterType shift_t; - uint32_t shift_n; - switch (encoding) - { - case eEncodingT1: - // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); - d = Bits32 (opcode, 11, 8); - m = Bits32 (opcode, 3, 0); - setflags = BitIsSet (opcode, 20); - - // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); - shift_n = DecodeImmShiftThumb (opcode, shift_t); - - // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE; - if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3))) - return false; - - // if d == 15 || BadReg(m) then UNPREDICTABLE; - if ((d == 15) || BadReg (m)) - return false; - break; - - case eEncodingA1: - // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); - d = Bits32 (opcode, 15, 12); - m = Bits32 (opcode, 3, 0); - setflags = BitIsSet (opcode, 20); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if (d == 15 && setflags) - EmulateSUBSPcLrEtc (opcode, encoding); - - // (shift_t, shift_n) = DecodeImmShift(type, imm5); - shift_n = DecodeImmShiftARM (opcode, shift_t); - break; - - default: - return false; - } + bool success = false; - // shifted = Shift(R[m], shift_t, shift_n, APSR.C); - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; + if (ConditionPassed(opcode)) { + uint32_t d; + uint32_t m; + bool setflags; + ARM_ShifterType shift_t; + uint32_t shift_n; - uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; + switch (encoding) { + case eEncodingT1: + // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); + d = Bits32(opcode, 11, 8); + m = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); - // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1'); - uint32_t sp_val = ReadCoreReg (SP_REG, &success); - if (!success) - return false; + // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); + shift_n = DecodeImmShiftThumb(opcode, shift_t); - AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1); + // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then + // UNPREDICTABLE; + if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3))) + return false; - EmulateInstruction::Context context; - context.type = eContextArithmetic; - RegisterInfo sp_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); - RegisterInfo dwarf_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg); - context.SetRegisterRegisterOperands (sp_reg, dwarf_reg); + // if d == 15 || BadReg(m) then UNPREDICTABLE; + if ((d == 15) || BadReg(m)) + return false; + break; - if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) - return false; + case eEncodingA1: + // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); + d = Bits32(opcode, 15, 12); + m = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if (d == 15 && setflags) + EmulateSUBSPcLrEtc(opcode, encoding); + + // (shift_t, shift_n) = DecodeImmShift(type, imm5); + shift_n = DecodeImmShiftARM(opcode, shift_t); + break; + + default: + return false; } - return true; + + // shifted = Shift(R[m], shift_t, shift_n, APSR.C); + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + + uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + + // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1'); + uint32_t sp_val = ReadCoreReg(SP_REG, &success); + if (!success) + return false; + + AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1); + + EmulateInstruction::Context context; + context.type = eContextArithmetic; + RegisterInfo sp_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_sp, sp_reg); + RegisterInfo dwarf_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg); + context.SetRegisterRegisterOperands(sp_reg, dwarf_reg); + + if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, + res.carry_out, res.overflow)) + return false; + } + return true; } - - + // A8.6.7 ADD (register-shifted register) -bool -EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -9675,91 +9659,89 @@ EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncod APSR.C = carry; APSR.V = overflow; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t d; - uint32_t n; - uint32_t m; - uint32_t s; - bool setflags; - ARM_ShifterType shift_t; - - switch (encoding) - { - case eEncodingA1: - // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs); - d = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - s = Bits32 (opcode, 11, 8); - - // setflags = (S == '1'); shift_t = DecodeRegShift(type); - setflags = BitIsSet (opcode, 20); - shift_t = DecodeRegShift (Bits32 (opcode, 6, 5)); - - // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE; - if ((d == 15) || (m == 15) || (m == 15) || (s == 15)) - return false; - break; - - default: - return false; - } - - // shift_n = UInt(R[s]<7:0>); - uint32_t Rs = ReadCoreReg (s, &success); - if (!success) - return false; - - uint32_t shift_n = Bits32 (Rs, 7, 0); - - // shifted = Shift(R[m], shift_t, shift_n, APSR.C); - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - - uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - AddWithCarryResult res = AddWithCarry (Rn, shifted, 0); - - // R[d] = result; - EmulateInstruction::Context context; - context.type = eContextArithmetic; - RegisterInfo reg_n; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n); - RegisterInfo reg_m; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m); - - context.SetRegisterRegisterOperands (reg_n, reg_m); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result)) - return false; - - // if setflags then - // APSR.N = result<31>; - // APSR.Z = IsZeroBit(result); - // APSR.C = carry; - // APSR.V = overflow; - if (setflags) - return WriteFlags (context, res.result, res.carry_out, res.overflow); + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t d; + uint32_t n; + uint32_t m; + uint32_t s; + bool setflags; + ARM_ShifterType shift_t; + + switch (encoding) { + case eEncodingA1: + // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs); + d = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + s = Bits32(opcode, 11, 8); + + // setflags = (S == '1'); shift_t = DecodeRegShift(type); + setflags = BitIsSet(opcode, 20); + shift_t = DecodeRegShift(Bits32(opcode, 6, 5)); + + // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE; + if ((d == 15) || (m == 15) || (m == 15) || (s == 15)) + return false; + break; + + default: + return false; } - return true; + + // shift_n = UInt(R[s]<7:0>); + uint32_t Rs = ReadCoreReg(s, &success); + if (!success) + return false; + + uint32_t shift_n = Bits32(Rs, 7, 0); + + // shifted = Shift(R[m], shift_t, shift_n, APSR.C); + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + + uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + + // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + AddWithCarryResult res = AddWithCarry(Rn, shifted, 0); + + // R[d] = result; + EmulateInstruction::Context context; + context.type = eContextArithmetic; + RegisterInfo reg_n; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n); + RegisterInfo reg_m; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m); + + context.SetRegisterRegisterOperands(reg_n, reg_m); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, + res.result)) + return false; + + // if setflags then + // APSR.N = result<31>; + // APSR.Z = IsZeroBit(result); + // APSR.C = carry; + // APSR.V = overflow; + if (setflags) + return WriteFlags(context, res.result, res.carry_out, res.overflow); + } + return true; } // A8.6.213 SUB (register) -bool -EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -9775,124 +9757,127 @@ EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding e APSR.C = carry; APSR.V = overflow; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t d; - uint32_t n; - uint32_t m; - bool setflags; - ARM_ShifterType shift_t; - uint32_t shift_n; - - switch (encoding) - { - case eEncodingT1: - // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock(); - d = Bits32 (opcode, 2, 0); - n = Bits32 (opcode, 5, 3); - m = Bits32 (opcode, 8, 6); - setflags = !InITBlock(); - - // (shift_t, shift_n) = (SRType_LSL, 0); - shift_t = SRType_LSL; - shift_n = 0; - - break; - - case eEncodingT2: - // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1"); - d = Bits32 (opcode, 11, 8); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - setflags = BitIsSet (opcode, 20); - - // if Rd == "1111" && S == "1" then SEE CMP (register); - if (d == 15 && setflags == 1) - return EmulateCMPImm (opcode, eEncodingT3); - - // if Rn == "1101" then SEE SUB (SP minus register); - if (n == 13) - return EmulateSUBSPReg (opcode, eEncodingT1); - // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); - shift_n = DecodeImmShiftThumb (opcode, shift_t); - - // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE; - if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m)) - return false; - - break; - - case eEncodingA1: - // if Rn == '1101' then SEE SUB (SP minus register); - // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); - d = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - setflags = BitIsSet (opcode, 20); - - // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions; - if ((d == 15) && setflags) - EmulateSUBSPcLrEtc (opcode, encoding); - - // (shift_t, shift_n) = DecodeImmShift(type, imm5); - shift_n = DecodeImmShiftARM (opcode, shift_t); - - break; - - default: - return false; - } - - // shifted = Shift(R[m], shift_t, shift_n, APSR.C); - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - - uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - - // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1); - - // if d == 15 then // Can only occur for ARM encoding - // ALUWritePC(result); // setflags is always FALSE here - // else - // R[d] = result; - // if setflags then - // APSR.N = result<31>; - // APSR.Z = IsZeroBit(result); - // APSR.C = carry; - // APSR.V = overflow; - - EmulateInstruction::Context context; - context.type = eContextArithmetic; - RegisterInfo reg_n; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n); - RegisterInfo reg_m; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m); - context.SetRegisterRegisterOperands (reg_n, reg_m); - - if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow)) - return false; + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t d; + uint32_t n; + uint32_t m; + bool setflags; + ARM_ShifterType shift_t; + uint32_t shift_n; + + switch (encoding) { + case eEncodingT1: + // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock(); + d = Bits32(opcode, 2, 0); + n = Bits32(opcode, 5, 3); + m = Bits32(opcode, 8, 6); + setflags = !InITBlock(); + + // (shift_t, shift_n) = (SRType_LSL, 0); + shift_t = SRType_LSL; + shift_n = 0; + + break; + + case eEncodingT2: + // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1"); + d = Bits32(opcode, 11, 8); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + + // if Rd == "1111" && S == "1" then SEE CMP (register); + if (d == 15 && setflags == 1) + return EmulateCMPImm(opcode, eEncodingT3); + + // if Rn == "1101" then SEE SUB (SP minus register); + if (n == 13) + return EmulateSUBSPReg(opcode, eEncodingT1); + + // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + + // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then + // UNPREDICTABLE; + if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) || + BadReg(m)) + return false; + + break; + + case eEncodingA1: + // if Rn == '1101' then SEE SUB (SP minus register); + // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); + d = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + setflags = BitIsSet(opcode, 20); + + // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related + // instructions; + if ((d == 15) && setflags) + EmulateSUBSPcLrEtc(opcode, encoding); + + // (shift_t, shift_n) = DecodeImmShift(type, imm5); + shift_n = DecodeImmShiftARM(opcode, shift_t); + + break; + + default: + return false; } - return true; + + // shifted = Shift(R[m], shift_t, shift_n, APSR.C); + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + + uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + + // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1); + + // if d == 15 then // Can only occur for ARM encoding + // ALUWritePC(result); // setflags is always FALSE here + // else + // R[d] = result; + // if setflags then + // APSR.N = result<31>; + // APSR.Z = IsZeroBit(result); + // APSR.C = carry; + // APSR.V = overflow; + + EmulateInstruction::Context context; + context.type = eContextArithmetic; + RegisterInfo reg_n; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, reg_n); + RegisterInfo reg_m; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, reg_m); + context.SetRegisterRegisterOperands(reg_n, reg_m); + + if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, + res.carry_out, res.overflow)) + return false; + } + return true; } - + // A8.6.202 STREX -// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a -// word from a register to memory if the executing processor has exclusive access to the memory addressed. -bool -EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding) -{ +// Store Register Exclusive calculates an address from a base register value and +// an immediate offset, and stores a +// word from a register to memory if the executing processor has exclusive +// access to the memory addressed. +bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -9903,90 +9888,92 @@ EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding en else R[d] = 1; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t d; - uint32_t t; - uint32_t n; - uint32_t imm32; - const uint32_t addr_byte_size = GetAddressByteSize(); - - switch (encoding) - { - case eEncodingT1: - // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); - d = Bits32 (opcode, 11, 8); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0) << 2; - - // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE; - if (BadReg (d) || BadReg (t) || (n == 15)) - return false; - - // if d == n || d == t then UNPREDICTABLE; - if ((d == n) || (d == t)) - return false; - - break; - - case eEncodingA1: - // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset - d = Bits32 (opcode, 15, 12); - t = Bits32 (opcode, 3, 0); - n = Bits32 (opcode, 19, 16); - imm32 = 0; - - // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE; - if ((d == 15) || (t == 15) || (n == 15)) - return false; - - // if d == n || d == t then UNPREDICTABLE; - if ((d == n) || (d == t)) - return false; - - break; - - default: - return false; - } - - // address = R[n] + imm32; - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - addr_t address = Rn + imm32; - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); - EmulateInstruction::Context context; - context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32); - - // if ExclusiveMonitorsPass(address,4) then - // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this - // always return true. - if (true) - { - // MemA[address,4] = R[t]; - uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success); - if (!success) - return false; - - if (!MemAWrite (context, address, Rt, addr_byte_size)) - return false; - - // R[d] = 0; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0)) - return false; - } -#if 0 // unreachable because if true + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t d; + uint32_t t; + uint32_t n; + uint32_t imm32; + const uint32_t addr_byte_size = GetAddressByteSize(); + + switch (encoding) { + case eEncodingT1: + // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', + // 32); + d = Bits32(opcode, 11, 8); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0) << 2; + + // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE; + if (BadReg(d) || BadReg(t) || (n == 15)) + return false; + + // if d == n || d == t then UNPREDICTABLE; + if ((d == n) || (d == t)) + return false; + + break; + + case eEncodingA1: + // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero + // offset + d = Bits32(opcode, 15, 12); + t = Bits32(opcode, 3, 0); + n = Bits32(opcode, 19, 16); + imm32 = 0; + + // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE; + if ((d == 15) || (t == 15) || (n == 15)) + return false; + + // if d == n || d == t then UNPREDICTABLE; + if ((d == n) || (d == t)) + return false; + + break; + + default: + return false; + } + + // address = R[n] + imm32; + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + addr_t address = Rn + imm32; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + EmulateInstruction::Context context; + context.type = eContextRegisterStore; + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, imm32); + + // if ExclusiveMonitorsPass(address,4) then + // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the + // sake of emulation, we will say this + // always return + // true. + if (true) { + // MemA[address,4] = R[t]; + uint32_t Rt = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); + if (!success) + return false; + + if (!MemAWrite(context, address, Rt, addr_byte_size)) + return false; + + // R[d] = 0; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0)) + return false; + } +#if 0 // unreachable because if true else { // R[d] = 1; @@ -9994,14 +9981,13 @@ EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding en return false; } #endif // unreachable because if true - } - return true; + } + return true; } // A8.6.197 STRB (immediate, ARM) -bool -EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -10010,94 +9996,91 @@ EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncodi MemU[address,1] = R[t]<7:0>; if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - - switch (encoding) - { - case eEncodingA1: - // if P == '0' && W == '1' then SEE STRBT; - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 11, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - - // if t == 15 then UNPREDICTABLE; - if (t == 15) - return false; - - // if wback && (n == 15 || n == t) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t))) - return false; - - break; - - default: - return false; - } - - // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - addr_t offset_addr; - if (add) - offset_addr = Rn + imm32; - else - offset_addr = Rn - imm32; - - // address = if index then offset_addr else R[n]; - addr_t address; - if (index) - address = offset_addr; - else - address = Rn; - - // MemU[address,1] = R[t]<7:0>; - uint32_t Rt = ReadCoreReg (t, &success); - if (!success) - return false; - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); - EmulateInstruction::Context context; - context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); - - if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1)) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + + switch (encoding) { + case eEncodingA1: + // if P == '0' && W == '1' then SEE STRBT; + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 11, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); + + // if t == 15 then UNPREDICTABLE; + if (t == 15) + return false; + + // if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t))) + return false; + + break; + + default: + return false; } - return true; + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + addr_t offset_addr; + if (add) + offset_addr = Rn + imm32; + else + offset_addr = Rn - imm32; + + // address = if index then offset_addr else R[n]; + addr_t address; + if (index) + address = offset_addr; + else + address = Rn; + + // MemU[address,1] = R[t]<7:0>; + uint32_t Rt = ReadCoreReg(t, &success); + if (!success) + return false; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + EmulateInstruction::Context context; + context.type = eContextRegisterStore; + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + + if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1)) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } // A8.6.194 STR (immediate, ARM) -bool -EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -10106,110 +10089,107 @@ EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncodin MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - - const uint32_t addr_byte_size = GetAddressByteSize(); - - switch (encoding) - { - case eEncodingA1: - // if P == '0' && W == '1' then SEE STRT; - // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == '000000000100' then SEE PUSH; - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); - t = Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 11, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - - // if wback && (n == 15 || n == t) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t))) - return false; - - break; - - default: - return false; - } - - // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - addr_t offset_addr; - if (add) - offset_addr = Rn + imm32; - else - offset_addr = Rn - imm32; - - // address = if index then offset_addr else R[n]; - addr_t address; - if (index) - address = offset_addr; - else - address = Rn; - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); - EmulateInstruction::Context context; - context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); - - // MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; - uint32_t Rt = ReadCoreReg (t, &success); - if (!success) - return false; - - if (t == 15) - { - uint32_t pc_value = ReadCoreReg (PC_REG, &success); - if (!success) - return false; - - if (!MemUWrite (context, address, pc_value, addr_byte_size)) - return false; - } - else - { - if (!MemUWrite (context, address, Rt, addr_byte_size)) - return false; - } - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetImmediate (offset_addr); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + + const uint32_t addr_byte_size = GetAddressByteSize(); + + switch (encoding) { + case eEncodingA1: + // if P == '0' && W == '1' then SEE STRT; + // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == + // '000000000100' then SEE PUSH; + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); + t = Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 11, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); + + // if wback && (n == 15 || n == t) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t))) + return false; + + break; + + default: + return false; } - return true; + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + addr_t offset_addr; + if (add) + offset_addr = Rn + imm32; + else + offset_addr = Rn - imm32; + + // address = if index then offset_addr else R[n]; + addr_t address; + if (index) + address = offset_addr; + else + address = Rn; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + EmulateInstruction::Context context; + context.type = eContextRegisterStore; + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + + // MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; + uint32_t Rt = ReadCoreReg(t, &success); + if (!success) + return false; + + if (t == 15) { + uint32_t pc_value = ReadCoreReg(PC_REG, &success); + if (!success) + return false; + + if (!MemUWrite(context, address, pc_value, addr_byte_size)) + return false; + } else { + if (!MemUWrite(context, address, Rt, addr_byte_size)) + return false; + } + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetImmediate(offset_addr); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } // A8.6.66 LDRD (immediate) -// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two -// words from memory, and writes them to two registers. It can use offset, post-indexed, or pre-indexed addressing. -bool -EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding) -{ +// Load Register Dual (immediate) calculates an address from a base register +// value and an immediate offset, loads two +// words from memory, and writes them to two registers. It can use offset, +// post-indexed, or pre-indexed addressing. +bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -10219,144 +10199,146 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc R[t2] = MemA[address+4,4]; if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t t2; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - - switch (encoding) - { - case eEncodingT1: - //if P == '0' && W == '0' then SEE 'Related encodings'; - //if Rn == '1111' then SEE LDRD (literal); - //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); - t = Bits32 (opcode, 15, 12); - t2 = Bits32 (opcode, 11, 8); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0) << 2; - - //index = (P == '1'); add = (U == '1'); wback = (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsSet (opcode, 21); - - //if wback && (n == t || n == t2) then UNPREDICTABLE; - if (wback && ((n == t) || (n == t2))) - return false; - - //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE; - if (BadReg (t) || BadReg (t2) || (t == t2)) - return false; - - break; - - case eEncodingA1: - //if Rn == '1111' then SEE LDRD (literal); - //if Rt<0> == '1' then UNPREDICTABLE; - //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); - t = Bits32 (opcode, 15, 12); - if (BitIsSet (t, 0)) - return false; - t2 = t + 1; - n = Bits32 (opcode, 19, 16); - imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); - - //index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - - //if P == '0' && W == '1' then UNPREDICTABLE; - if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) - return false; - - //if wback && (n == t || n == t2) then UNPREDICTABLE; - if (wback && ((n == t) || (n == t2))) - return false; - - //if t2 == 15 then UNPREDICTABLE; - if (t2 == 15) - return false; - - break; - - default: - return false; - } - - //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - addr_t offset_addr; - if (add) - offset_addr = Rn + imm32; - else - offset_addr = Rn - imm32; - - //address = if index then offset_addr else R[n]; - addr_t address; - if (index) - address = offset_addr; - else - address = Rn; - - //R[t] = MemA[address,4]; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - EmulateInstruction::Context context; - if (n == 13) - context.type = eContextPopRegisterOffStack; - else - context.type = eContextRegisterLoad; - context.SetAddress(address); - - const uint32_t addr_byte_size = GetAddressByteSize(); - uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - - //R[t2] = MemA[address+4,4]; - context.SetAddress(address + 4); - data = MemARead (context, address + 4, addr_byte_size, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data)) - return false; - - //if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t t2; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + + switch (encoding) { + case eEncodingT1: + // if P == '0' && W == '0' then SEE 'Related encodings'; + // if Rn == '1111' then SEE LDRD (literal); + // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = + // ZeroExtend(imm8:'00', 32); + t = Bits32(opcode, 15, 12); + t2 = Bits32(opcode, 11, 8); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0) << 2; + + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsSet(opcode, 21); + + // if wback && (n == t || n == t2) then UNPREDICTABLE; + if (wback && ((n == t) || (n == t2))) + return false; + + // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE; + if (BadReg(t) || BadReg(t2) || (t == t2)) + return false; + + break; + + case eEncodingA1: + // if Rn == '1111' then SEE LDRD (literal); + // if Rt<0> == '1' then UNPREDICTABLE; + // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, + // 32); + t = Bits32(opcode, 15, 12); + if (BitIsSet(t, 0)) + return false; + t2 = t + 1; + n = Bits32(opcode, 19, 16); + imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); + + // if P == '0' && W == '1' then UNPREDICTABLE; + if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) + return false; + + // if wback && (n == t || n == t2) then UNPREDICTABLE; + if (wback && ((n == t) || (n == t2))) + return false; + + // if t2 == 15 then UNPREDICTABLE; + if (t2 == 15) + return false; + + break; + + default: + return false; } - return true; + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + addr_t offset_addr; + if (add) + offset_addr = Rn + imm32; + else + offset_addr = Rn - imm32; + + // address = if index then offset_addr else R[n]; + addr_t address; + if (index) + address = offset_addr; + else + address = Rn; + + // R[t] = MemA[address,4]; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + EmulateInstruction::Context context; + if (n == 13) + context.type = eContextPopRegisterOffStack; + else + context.type = eContextRegisterLoad; + context.SetAddress(address); + + const uint32_t addr_byte_size = GetAddressByteSize(); + uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); + if (!success) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) + return false; + + // R[t2] = MemA[address+4,4]; + context.SetAddress(address + 4); + data = MemARead(context, address + 4, addr_byte_size, 0, &success); + if (!success) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2, + data)) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } - + // A8.6.68 LDRD (register) -// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two -// words from memory, and writes them to two registers. It can use offset, post-indexed or pre-indexed addressing. -bool -EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding) -{ +// Load Register Dual (register) calculates an address from a base register +// value and a register offset, loads two +// words from memory, and writes them to two registers. It can use offset, +// post-indexed or pre-indexed addressing. +bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -10366,127 +10348,127 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco R[t2] = MemA[address+4,4]; if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t t2; - uint32_t n; - uint32_t m; - bool index; - bool add; - bool wback; - - switch (encoding) - { - case eEncodingA1: - // if Rt<0> == '1' then UNPREDICTABLE; - // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - if (BitIsSet (t, 0)) - return false; - t2 = t + 1; - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - - // if P == '0' && W == '1' then UNPREDICTABLE; - if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) - return false; - - // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE; - if ((t2 == 15) || (m == 15) || (m == t) || (m == t2)) - return false; - - // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t) || (n == t2))) - return false; - - // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; - if ((ArchVersion() < 6) && wback && (m == n)) - return false; - break; - - default: - return false; - } - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - RegisterInfo offset_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); - - // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); - addr_t offset_addr; - if (add) - offset_addr = Rn + Rm; - else - offset_addr = Rn - Rm; - - // address = if index then offset_addr else R[n]; - addr_t address; - if (index) - address = offset_addr; - else - address = Rn; - - EmulateInstruction::Context context; - if (n == 13) - context.type = eContextPopRegisterOffStack; - else - context.type = eContextRegisterLoad; - context.SetAddress(address); - - // R[t] = MemA[address,4]; - const uint32_t addr_byte_size = GetAddressByteSize(); - uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data)) - return false; - - // R[t2] = MemA[address+4,4]; - - data = MemARead (context, address + 4, addr_byte_size, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data)) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t t2; + uint32_t n; + uint32_t m; + bool index; + bool add; + bool wback; + + switch (encoding) { + case eEncodingA1: + // if Rt<0> == '1' then UNPREDICTABLE; + // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + if (BitIsSet(t, 0)) + return false; + t2 = t + 1; + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); + + // if P == '0' && W == '1' then UNPREDICTABLE; + if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) + return false; + + // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE; + if ((t2 == 15) || (m == 15) || (m == t) || (m == t2)) + return false; + + // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t) || (n == t2))) + return false; + + // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; + if ((ArchVersion() < 6) && wback && (m == n)) + return false; + break; + + default: + return false; } - return true; + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + RegisterInfo offset_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); + + // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); + addr_t offset_addr; + if (add) + offset_addr = Rn + Rm; + else + offset_addr = Rn - Rm; + + // address = if index then offset_addr else R[n]; + addr_t address; + if (index) + address = offset_addr; + else + address = Rn; + + EmulateInstruction::Context context; + if (n == 13) + context.type = eContextPopRegisterOffStack; + else + context.type = eContextRegisterLoad; + context.SetAddress(address); + + // R[t] = MemA[address,4]; + const uint32_t addr_byte_size = GetAddressByteSize(); + uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); + if (!success) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) + return false; + + // R[t2] = MemA[address+4,4]; + + data = MemARead(context, address + 4, addr_byte_size, 0, &success); + if (!success) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2, + data)) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } // A8.6.200 STRD (immediate) -// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and -// stores two words from two registers to memory. It can use offset, post-indexed, or pre-indexed addressing. -bool -EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding) -{ +// Store Register Dual (immediate) calculates an address from a base register +// value and an immediate offset, and +// stores two words from two registers to memory. It can use offset, +// post-indexed, or pre-indexed addressing. +bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); NullCheckIfThumbEE(n); @@ -10496,151 +10478,150 @@ EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding MemA[address+4,4] = R[t2]; if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t t2; - uint32_t n; - uint32_t imm32; - bool index; - bool add; - bool wback; - - switch (encoding) - { - case eEncodingT1: - // if P == '0' && W == '0' then SEE 'Related encodings'; - // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); - t = Bits32 (opcode, 15, 12); - t2 = Bits32 (opcode, 11, 8); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0) << 2; - - // index = (P == '1'); add = (U == '1'); wback = (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsSet (opcode, 21); - - // if wback && (n == t || n == t2) then UNPREDICTABLE; - if (wback && ((n == t) || (n == t2))) - return false; - - // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE; - if ((n == 15) || BadReg (t) || BadReg (t2)) - return false; - - break; - - case eEncodingA1: - // if Rt<0> == '1' then UNPREDICTABLE; - // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); - t = Bits32 (opcode, 15, 12); - if (BitIsSet (t, 0)) - return false; - - t2 = t + 1; - n = Bits32 (opcode, 19, 16); - imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - - // if P == '0' && W == '1' then UNPREDICTABLE; - if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) - return false; - - // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t) || (n == t2))) - return false; - - // if t2 == 15 then UNPREDICTABLE; - if (t2 == 15) - return false; - - break; - - default: - return false; - } - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); - addr_t offset_addr; - if (add) - offset_addr = Rn + imm32; - else - offset_addr = Rn - imm32; - - //address = if index then offset_addr else R[n]; - addr_t address; - if (index) - address = offset_addr; - else - address = Rn; - - //MemA[address,4] = R[t]; - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); - - uint32_t data = ReadCoreReg (t, &success); - if (!success) - return false; - - EmulateInstruction::Context context; - if (n == 13) - context.type = eContextPushRegisterOnStack; - else - context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); - - const uint32_t addr_byte_size = GetAddressByteSize(); - - if (!MemAWrite (context, address, data, addr_byte_size)) - return false; - //MemA[address+4,4] = R[t2]; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg); - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); - - data = ReadCoreReg (t2, &success); - if (!success) - return false; - - if (!MemAWrite (context, address + 4, data, addr_byte_size)) - return false; - - //if wback then R[n] = offset_addr; - if (wback) - { - if (n == 13) - context.type = eContextAdjustStackPointer; - else - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); + bool success = false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - } + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t t2; + uint32_t n; + uint32_t imm32; + bool index; + bool add; + bool wback; + + switch (encoding) { + case eEncodingT1: + // if P == '0' && W == '0' then SEE 'Related encodings'; + // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = + // ZeroExtend(imm8:'00', 32); + t = Bits32(opcode, 15, 12); + t2 = Bits32(opcode, 11, 8); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0) << 2; + + // index = (P == '1'); add = (U == '1'); wback = (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsSet(opcode, 21); + + // if wback && (n == t || n == t2) then UNPREDICTABLE; + if (wback && ((n == t) || (n == t2))) + return false; + + // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE; + if ((n == 15) || BadReg(t) || BadReg(t2)) + return false; + + break; + + case eEncodingA1: + // if Rt<0> == '1' then UNPREDICTABLE; + // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, + // 32); + t = Bits32(opcode, 15, 12); + if (BitIsSet(t, 0)) + return false; + + t2 = t + 1; + n = Bits32(opcode, 19, 16); + imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); + + // if P == '0' && W == '1' then UNPREDICTABLE; + if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) + return false; + + // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t) || (n == t2))) + return false; + + // if t2 == 15 then UNPREDICTABLE; + if (t2 == 15) + return false; + + break; + + default: + return false; } - return true; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); + addr_t offset_addr; + if (add) + offset_addr = Rn + imm32; + else + offset_addr = Rn - imm32; + + // address = if index then offset_addr else R[n]; + addr_t address; + if (index) + address = offset_addr; + else + address = Rn; + + // MemA[address,4] = R[t]; + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + + uint32_t data = ReadCoreReg(t, &success); + if (!success) + return false; + + EmulateInstruction::Context context; + if (n == 13) + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + + const uint32_t addr_byte_size = GetAddressByteSize(); + + if (!MemAWrite(context, address, data, addr_byte_size)) + return false; + + // MemA[address+4,4] = R[t2]; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg); + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + (address + 4) - Rn); + + data = ReadCoreReg(t2, &success); + if (!success) + return false; + + if (!MemAWrite(context, address + 4, data, addr_byte_size)) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + if (n == 13) + context.type = eContextAdjustStackPointer; + else + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } - - + // A8.6.201 STRD (register) -bool -EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -10650,137 +10631,136 @@ EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding MemA[address+4,4] = R[t2]; if wback then R[n] = offset_addr; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - uint32_t t; - uint32_t t2; - uint32_t n; - uint32_t m; - bool index; - bool add; - bool wback; - - switch (encoding) - { - case eEncodingA1: - // if Rt<0> == '1' then UNPREDICTABLE; - // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); - t = Bits32 (opcode, 15, 12); - if (BitIsSet (t, 0)) - return false; - - t2 = t+1; - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); - index = BitIsSet (opcode, 24); - add = BitIsSet (opcode, 23); - wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21); - - // if P == '0' && W == '1' then UNPREDICTABLE; - if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21)) - return false; - - // if t2 == 15 || m == 15 then UNPREDICTABLE; - if ((t2 == 15) || (m == 15)) - return false; - - // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; - if (wback && ((n == 15) || (n == t) || (n == t2))) - return false; - - // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; - if ((ArchVersion() < 6) && wback && (m == n)) - return false; - - break; - - default: - return false; - } - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - RegisterInfo offset_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg); - RegisterInfo data_reg; - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - - // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); - addr_t offset_addr; - if (add) - offset_addr = Rn + Rm; - else - offset_addr = Rn - Rm; - - // address = if index then offset_addr else R[n]; - addr_t address; - if (index) - address = offset_addr; - else - address = Rn; - // MemA[address,4] = R[t]; - uint32_t Rt = ReadCoreReg (t, &success); - if (!success) - return false; - - EmulateInstruction::Context context; - if (t == 13) - context.type = eContextPushRegisterOnStack; - else - context.type = eContextRegisterStore; - - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg); - context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); - - const uint32_t addr_byte_size = GetAddressByteSize(); - - if (!MemAWrite (context, address, Rt, addr_byte_size)) - return false; - - // MemA[address+4,4] = R[t2]; - uint32_t Rt2 = ReadCoreReg (t2, &success); - if (!success) - return false; - - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg); - - context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg); - - if (!MemAWrite (context, address + 4, Rt2, addr_byte_size)) - return false; - - // if wback then R[n] = offset_addr; - if (wback) - { - context.type = eContextAdjustBaseRegister; - context.SetAddress (offset_addr); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr)) - return false; - - } + + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t t; + uint32_t t2; + uint32_t n; + uint32_t m; + bool index; + bool add; + bool wback; + + switch (encoding) { + case eEncodingA1: + // if Rt<0> == '1' then UNPREDICTABLE; + // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); + t = Bits32(opcode, 15, 12); + if (BitIsSet(t, 0)) + return false; + + t2 = t + 1; + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); + index = BitIsSet(opcode, 24); + add = BitIsSet(opcode, 23); + wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); + + // if P == '0' && W == '1' then UNPREDICTABLE; + if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) + return false; + + // if t2 == 15 || m == 15 then UNPREDICTABLE; + if ((t2 == 15) || (m == 15)) + return false; + + // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; + if (wback && ((n == 15) || (n == t) || (n == t2))) + return false; + + // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; + if ((ArchVersion() < 6) && wback && (m == n)) + return false; + + break; + + default: + return false; } - return true; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + RegisterInfo offset_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m, offset_reg); + RegisterInfo data_reg; + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + + // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); + addr_t offset_addr; + if (add) + offset_addr = Rn + Rm; + else + offset_addr = Rn - Rm; + + // address = if index then offset_addr else R[n]; + addr_t address; + if (index) + address = offset_addr; + else + address = Rn; + // MemA[address,4] = R[t]; + uint32_t Rt = ReadCoreReg(t, &success); + if (!success) + return false; + + EmulateInstruction::Context context; + if (t == 13) + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; + + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t, data_reg); + context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg, + data_reg); + + const uint32_t addr_byte_size = GetAddressByteSize(); + + if (!MemAWrite(context, address, Rt, addr_byte_size)) + return false; + + // MemA[address+4,4] = R[t2]; + uint32_t Rt2 = ReadCoreReg(t2, &success); + if (!success) + return false; + + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2, data_reg); + + context.SetRegisterToRegisterPlusIndirectOffset(base_reg, offset_reg, + data_reg); + + if (!MemAWrite(context, address + 4, Rt2, addr_byte_size)) + return false; + + // if wback then R[n] = offset_addr; + if (wback) { + context.type = eContextAdjustBaseRegister; + context.SetAddress(offset_addr); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + offset_addr)) + return false; + } + } + return true; } - + // A8.6.319 VLDM -// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from +// Vector Load Multiple loads multiple extension registers from consecutive +// memory locations using an address from // an ARM core register. -bool -EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); @@ -10794,184 +10774,185 @@ EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding enc // Combine the word-aligned words in the correct order for current endianness. D[d+r] = if BigEndian() then word1:word2 else word2:word1; #endif - - bool success = false; - - if (ConditionPassed(opcode)) - { - bool single_regs; - bool add; - bool wback; - uint32_t d; - uint32_t n; - uint32_t imm32; - uint32_t regs; - - switch (encoding) - { - case eEncodingT1: - case eEncodingA1: - // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; - // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; - // if P == '1' && W == '0' then SEE VLDR; - // if P == U && W == '1' then UNDEFINED; - if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) - return false; - - // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); - single_regs = false; - add = BitIsSet (opcode, 23); - wback = BitIsSet (opcode, 21); - - // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); - d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0) << 2; - - // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'. - regs = Bits32 (opcode, 7, 0) / 2; - - // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; - if (n == 15 && (wback || CurrentInstrSet() != eModeARM)) - return false; - - // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; - if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) - return false; - - break; - - case eEncodingT2: - case eEncodingA2: - // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; - // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; - // if P == '1' && W == '0' then SEE VLDR; - // if P == U && W == '1' then UNDEFINED; - if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) - return false; - - // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn); - single_regs = true; - add = BitIsSet (opcode, 23); - wback = BitIsSet (opcode, 21); - d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); - n = Bits32 (opcode, 19, 16); - - // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); - imm32 = Bits32 (opcode, 7, 0) << 2; - regs = Bits32 (opcode, 7, 0); - - // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; - if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) - return false; - - // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; - if ((regs == 0) || ((d + regs) > 32)) - return false; - break; - - default: - return false; - } - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rn = ReadCoreReg (n, &success); + + bool success = false; + + if (ConditionPassed(opcode)) { + bool single_regs; + bool add; + bool wback; + uint32_t d; + uint32_t n; + uint32_t imm32; + uint32_t regs; + + switch (encoding) { + case eEncodingT1: + case eEncodingA1: + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; + // if P == '1' && W == '0' then SEE VLDR; + // if P == U && W == '1' then UNDEFINED; + if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) + return false; + + // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with + // !), 101 (DB with !) + // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); + single_regs = false; + add = BitIsSet(opcode, 23); + wback = BitIsSet(opcode, 21); + + // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); + d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0) << 2; + + // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'. + regs = Bits32(opcode, 7, 0) / 2; + + // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then + // UNPREDICTABLE; + if (n == 15 && (wback || CurrentInstrSet() != eModeARM)) + return false; + + // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; + if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) + return false; + + break; + + case eEncodingT2: + case eEncodingA2: + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; + // if P == '1' && W == '0' then SEE VLDR; + // if P == U && W == '1' then UNDEFINED; + if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) + return false; + + // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with + // !), 101 (DB with !) + // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = + // UInt(Vd:D); n = UInt(Rn); + single_regs = true; + add = BitIsSet(opcode, 23); + wback = BitIsSet(opcode, 21); + d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); + n = Bits32(opcode, 19, 16); + + // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); + imm32 = Bits32(opcode, 7, 0) << 2; + regs = Bits32(opcode, 7, 0); + + // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then + // UNPREDICTABLE; + if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) + return false; + + // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; + if ((regs == 0) || ((d + regs) > 32)) + return false; + break; + + default: + return false; + } + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // address = if add then R[n] else R[n]-imm32; + addr_t address; + if (add) + address = Rn; + else + address = Rn - imm32; + + // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; + EmulateInstruction::Context context; + + if (wback) { + uint32_t value; + if (add) + value = Rn + imm32; + else + value = Rn - imm32; + + context.type = eContextAdjustBaseRegister; + context.SetImmediateSigned(value - Rn); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + value)) + return false; + } + + const uint32_t addr_byte_size = GetAddressByteSize(); + uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; + + context.type = eContextRegisterLoad; + + // for r = 0 to regs-1 + for (uint32_t r = 0; r < regs; ++r) { + if (single_regs) { + // S[d+r] = MemA[address,4]; address = address+4; + context.SetRegisterPlusOffset(base_reg, address - Rn); + + uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); if (!success) - return false; - - // address = if add then R[n] else R[n]-imm32; - addr_t address; - if (add) - address = Rn; - else - address = Rn - imm32; - - // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; - EmulateInstruction::Context context; - - if (wback) - { - uint32_t value; - if (add) - value = Rn + imm32; - else - value = Rn - imm32; - - context.type = eContextAdjustBaseRegister; - context.SetImmediateSigned (value - Rn); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) - return false; - - } - - const uint32_t addr_byte_size = GetAddressByteSize(); - uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; + return false; - context.type = eContextRegisterLoad; - - // for r = 0 to regs-1 - for (uint32_t r = 0; r < regs; ++r) - { - if (single_regs) - { - // S[d+r] = MemA[address,4]; address = address+4; - context.SetRegisterPlusOffset (base_reg, address - Rn); - - uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data)) - return false; - - address = address + 4; - } - else - { - // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; - context.SetRegisterPlusOffset (base_reg, address - Rn); - uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success); - if (!success) - return false; - - context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn); - uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success); - if (!success) - return false; - - address = address + 8; - // // Combine the word-aligned words in the correct order for current endianness. - // D[d+r] = if BigEndian() then word1:word2 else word2:word1; - uint64_t data; - if (GetByteOrder() == eByteOrderBig) - { - data = word1; - data = (data << 32) | word2; - } - else - { - data = word2; - data = (data << 32) | word1; - } - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data)) - return false; - } + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, + start_reg + d + r, data)) + return false; + + address = address + 4; + } else { + // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = + // address+8; + context.SetRegisterPlusOffset(base_reg, address - Rn); + uint32_t word1 = + MemARead(context, address, addr_byte_size, 0, &success); + if (!success) + return false; + + context.SetRegisterPlusOffset(base_reg, (address + 4) - Rn); + uint32_t word2 = + MemARead(context, address + 4, addr_byte_size, 0, &success); + if (!success) + return false; + + address = address + 8; + // // Combine the word-aligned words in the correct order for current + // endianness. + // D[d+r] = if BigEndian() then word1:word2 else word2:word1; + uint64_t data; + if (GetByteOrder() == eByteOrderBig) { + data = word1; + data = (data << 32) | word2; + } else { + data = word2; + data = (data << 32) | word1; } + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, + start_reg + d + r, data)) + return false; + } } - return true; + } + return true; } // A8.6.399 VSTM -// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an +// Vector Store Multiple stores multiple extension registers to consecutive +// memory locations using an address from an // ARM core register. -bool -EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); @@ -10986,189 +10967,198 @@ EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding enc MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; address = address+8; #endif - - bool success = false; - - if (ConditionPassed (opcode)) - { - bool single_regs; - bool add; - bool wback; - uint32_t d; - uint32_t n; - uint32_t imm32; - uint32_t regs; - - switch (encoding) - { - case eEncodingT1: - case eEncodingA1: - // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; - // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; - // if P == '1' && W == '0' then SEE VSTR; - // if P == U && W == '1' then UNDEFINED; - if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) - return false; - - // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); - single_regs = false; - add = BitIsSet (opcode, 23); - wback = BitIsSet (opcode, 21); - - // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); - d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - imm32 = Bits32 (opcode, 7, 0) << 2; - - // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'. - regs = Bits32 (opcode, 7, 0) / 2; - - // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; - if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) - return false; - - // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; - if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) - return false; - - break; - - case eEncodingT2: - case eEncodingA2: - // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; - // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; - // if P == '1' && W == '0' then SEE VSTR; - // if P == U && W == '1' then UNDEFINED; - if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21)) - return false; - - // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !) - // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = UInt(Vd:D); n = UInt(Rn); - single_regs = true; - add = BitIsSet (opcode, 23); - wback = BitIsSet (opcode, 21); - d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); - n = Bits32 (opcode, 19, 16); - - // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); - imm32 = Bits32 (opcode, 7, 0) << 2; - regs = Bits32 (opcode, 7, 0); - - // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE; - if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM))) - return false; - - // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; - if ((regs == 0) || ((d + regs) > 32)) - return false; - - break; - - default: - return false; - } - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rn = ReadCoreReg (n, &success); + + bool success = false; + + if (ConditionPassed(opcode)) { + bool single_regs; + bool add; + bool wback; + uint32_t d; + uint32_t n; + uint32_t imm32; + uint32_t regs; + + switch (encoding) { + case eEncodingT1: + case eEncodingA1: + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; + // if P == '1' && W == '0' then SEE VSTR; + // if P == U && W == '1' then UNDEFINED; + if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) + return false; + + // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with + // !), 101 (DB with !) + // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); + single_regs = false; + add = BitIsSet(opcode, 23); + wback = BitIsSet(opcode, 21); + + // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); + d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + imm32 = Bits32(opcode, 7, 0) << 2; + + // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'. + regs = Bits32(opcode, 7, 0) / 2; + + // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then + // UNPREDICTABLE; + if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) + return false; + + // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; + if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) + return false; + + break; + + case eEncodingT2: + case eEncodingA2: + // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; + // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; + // if P == '1' && W == '0' then SEE VSTR; + // if P == U && W == '1' then UNDEFINED; + if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) + return false; + + // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with + // !), 101 (DB with !) + // single_regs = TRUE; add = (U == '1'); wback = (W == '1'); d = + // UInt(Vd:D); n = UInt(Rn); + single_regs = true; + add = BitIsSet(opcode, 23); + wback = BitIsSet(opcode, 21); + d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); + n = Bits32(opcode, 19, 16); + + // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); + imm32 = Bits32(opcode, 7, 0) << 2; + regs = Bits32(opcode, 7, 0); + + // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then + // UNPREDICTABLE; + if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) + return false; + + // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; + if ((regs == 0) || ((d + regs) > 32)) + return false; + + break; + + default: + return false; + } + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // address = if add then R[n] else R[n]-imm32; + addr_t address; + if (add) + address = Rn; + else + address = Rn - imm32; + + EmulateInstruction::Context context; + // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; + if (wback) { + uint32_t value; + if (add) + value = Rn + imm32; + else + value = Rn - imm32; + + context.type = eContextAdjustBaseRegister; + context.SetRegisterPlusOffset(base_reg, value - Rn); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + value)) + return false; + } + + const uint32_t addr_byte_size = GetAddressByteSize(); + uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; + + context.type = eContextRegisterStore; + // for r = 0 to regs-1 + for (uint32_t r = 0; r < regs; ++r) { + + if (single_regs) { + // MemA[address,4] = S[d+r]; address = address+4; + uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, + start_reg + d + r, 0, &success); if (!success) + return false; + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg); + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + address - Rn); + if (!MemAWrite(context, address, data, addr_byte_size)) + return false; + + address = address + 4; + } else { + // // Store as two word-aligned words in the correct order for current + // endianness. + // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else + // D[d+r]<31:0>; + // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else + // D[d+r]<63:32>; + uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF, + start_reg + d + r, 0, &success); + if (!success) + return false; + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r, data_reg); + + if (GetByteOrder() == eByteOrderBig) { + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + address - Rn); + if (!MemAWrite(context, address, Bits64(data, 63, 32), + addr_byte_size)) return false; - - // address = if add then R[n] else R[n]-imm32; - addr_t address; - if (add) - address = Rn; - else - address = Rn - imm32; - - EmulateInstruction::Context context; - // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; - if (wback) - { - uint32_t value; - if (add) - value = Rn + imm32; - else - value = Rn - imm32; - - context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset (base_reg, value - Rn); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) - return false; - } - - const uint32_t addr_byte_size = GetAddressByteSize(); - uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; - context.type = eContextRegisterStore; - // for r = 0 to regs-1 - for (uint32_t r = 0; r < regs; ++r) - { - - if (single_regs) - { - // MemA[address,4] = S[d+r]; address = address+4; - uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success); - if (!success) - return false; - - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg); - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); - if (!MemAWrite (context, address, data, addr_byte_size)) - return false; - - address = address + 4; - } - else - { - // // Store as two word-aligned words in the correct order for current endianness. - // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; - // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; - uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success); - if (!success) - return false; - - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg); - - if (GetByteOrder() == eByteOrderBig) - { - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); - if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size)) - return false; - - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); - if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size)) - return false; - } - else - { - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); - if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size)) - return false; - - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); - if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size)) - return false; - } - // address = address+8; - address = address + 8; - } + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + (address + 4) - Rn); + if (!MemAWrite(context, address + 4, Bits64(data, 31, 0), + addr_byte_size)) + return false; + } else { + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + address - Rn); + if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size)) + return false; + + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + (address + 4) - Rn); + if (!MemAWrite(context, address + 4, Bits64(data, 63, 32), + addr_byte_size)) + return false; } + // address = address+8; + address = address + 8; + } } - return true; + } + return true; } - + // A8.6.320 -// This instruction loads a single extension register from memory, using an address from an ARM core register, with +// This instruction loads a single extension register from memory, using an +// address from an ARM core register, with // an optional offset. -bool -EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode, + ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); @@ -11180,125 +11170,122 @@ EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding) word1 = MemA[address,4]; word2 = MemA[address+4,4]; // Combine the word-aligned words in the correct order for current endianness. D[d] = if BigEndian() then word1:word2 else word2:word1; -#endif - - bool success = false; - - if (ConditionPassed (opcode)) - { - bool single_reg; - bool add; - uint32_t imm32; - uint32_t d; - uint32_t n; - - switch (encoding) - { - case eEncodingT1: - case eEncodingA1: - // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); - single_reg = false; - add = BitIsSet (opcode, 23); - imm32 = Bits32 (opcode, 7, 0) << 2; - - // d = UInt(D:Vd); n = UInt(Rn); - d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - - break; - - case eEncodingT2: - case eEncodingA2: - // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); - single_reg = true; - add = BitIsSet (opcode, 23); - imm32 = Bits32 (opcode, 7, 0) << 2; - - // d = UInt(Vd:D); n = UInt(Rn); - d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); - n = Bits32 (opcode, 19, 16); - - break; - - default: - return false; - } - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - // base = if n == 15 then Align(PC,4) else R[n]; - uint32_t base; - if (n == 15) - base = AlignPC (Rn); - else - base = Rn; - - // address = if add then (base + imm32) else (base - imm32); - addr_t address; - if (add) - address = base + imm32; - else - address = base - imm32; - - const uint32_t addr_byte_size = GetAddressByteSize(); - uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; +#endif - EmulateInstruction::Context context; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - base); - - if (single_reg) - { - // S[d] = MemA[address,4]; - uint32_t data = MemARead (context, address, addr_byte_size, 0, &success); - if (!success) - return false; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data)) - return false; - } - else - { - // word1 = MemA[address,4]; word2 = MemA[address+4,4]; - uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success); - if (!success) - return false; - - context.SetRegisterPlusOffset (base_reg, (address + 4) - base); - uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success); - if (!success) - return false; - // // Combine the word-aligned words in the correct order for current endianness. - // D[d] = if BigEndian() then word1:word2 else word2:word1; - uint64_t data64; - if (GetByteOrder() == eByteOrderBig) - { - data64 = word1; - data64 = (data64 << 32) | word2; - } - else - { - data64 = word2; - data64 = (data64 << 32) | word1; - } - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64)) - return false; - } + bool success = false; + + if (ConditionPassed(opcode)) { + bool single_reg; + bool add; + uint32_t imm32; + uint32_t d; + uint32_t n; + + switch (encoding) { + case eEncodingT1: + case eEncodingA1: + // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', + // 32); + single_reg = false; + add = BitIsSet(opcode, 23); + imm32 = Bits32(opcode, 7, 0) << 2; + + // d = UInt(D:Vd); n = UInt(Rn); + d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + + break; + + case eEncodingT2: + case eEncodingA2: + // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); + single_reg = true; + add = BitIsSet(opcode, 23); + imm32 = Bits32(opcode, 7, 0) << 2; + + // d = UInt(Vd:D); n = UInt(Rn); + d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); + n = Bits32(opcode, 19, 16); + + break; + + default: + return false; } - return true; + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // base = if n == 15 then Align(PC,4) else R[n]; + uint32_t base; + if (n == 15) + base = AlignPC(Rn); + else + base = Rn; + + // address = if add then (base + imm32) else (base - imm32); + addr_t address; + if (add) + address = base + imm32; + else + address = base - imm32; + + const uint32_t addr_byte_size = GetAddressByteSize(); + uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; + + EmulateInstruction::Context context; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - base); + + if (single_reg) { + // S[d] = MemA[address,4]; + uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); + if (!success) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d, + data)) + return false; + } else { + // word1 = MemA[address,4]; word2 = MemA[address+4,4]; + uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success); + if (!success) + return false; + + context.SetRegisterPlusOffset(base_reg, (address + 4) - base); + uint32_t word2 = + MemARead(context, address + 4, addr_byte_size, 0, &success); + if (!success) + return false; + // // Combine the word-aligned words in the correct order for current + // endianness. + // D[d] = if BigEndian() then word1:word2 else word2:word1; + uint64_t data64; + if (GetByteOrder() == eByteOrderBig) { + data64 = word1; + data64 = (data64 << 32) | word2; + } else { + data64 = word2; + data64 = (data64 << 32) | word1; + } + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d, + data64)) + return false; + } + } + return true; } // A8.6.400 VSTR -// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an +// This instruction stores a signle extension register to memory, using an +// address from an ARM core register, with an // optional offset. -bool -EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode, + ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); @@ -11311,127 +11298,127 @@ EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding) MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; #endif - bool success = false; - - if (ConditionPassed (opcode)) - { - bool single_reg; - bool add; - uint32_t imm32; - uint32_t d; - uint32_t n; - - switch (encoding) - { - case eEncodingT1: - case eEncodingA1: - // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); - single_reg = false; - add = BitIsSet (opcode, 23); - imm32 = Bits32 (opcode, 7, 0) << 2; - - // d = UInt(D:Vd); n = UInt(Rn); - d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - - // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; - if ((n == 15) && (CurrentInstrSet() != eModeARM)) - return false; - - break; - - case eEncodingT2: - case eEncodingA2: - // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); - single_reg = true; - add = BitIsSet (opcode, 23); - imm32 = Bits32 (opcode, 7, 0) << 2; - - // d = UInt(Vd:D); n = UInt(Rn); - d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22); - n = Bits32 (opcode, 19, 16); - - // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; - if ((n == 15) && (CurrentInstrSet() != eModeARM)) - return false; - - break; - - default: - return false; - } - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - // address = if add then (R[n] + imm32) else (R[n] - imm32); - addr_t address; - if (add) - address = Rn + imm32; - else - address = Rn - imm32; - - const uint32_t addr_byte_size = GetAddressByteSize(); - uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; + bool success = false; - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg); - EmulateInstruction::Context context; - context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); - - if (single_reg) - { - // MemA[address,4] = S[d]; - uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success); - if (!success) - return false; - - if (!MemAWrite (context, address, data, addr_byte_size)) - return false; - } - else - { - // // Store as two word-aligned words in the correct order for current endianness. - // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; - // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; - uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success); - if (!success) - return false; - - if (GetByteOrder() == eByteOrderBig) - { - if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size)) - return false; - - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); - if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size)) - return false; - } - else - { - if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size)) - return false; - - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn); - if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size)) - return false; - } - } + if (ConditionPassed(opcode)) { + bool single_reg; + bool add; + uint32_t imm32; + uint32_t d; + uint32_t n; + + switch (encoding) { + case eEncodingT1: + case eEncodingA1: + // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', + // 32); + single_reg = false; + add = BitIsSet(opcode, 23); + imm32 = Bits32(opcode, 7, 0) << 2; + + // d = UInt(D:Vd); n = UInt(Rn); + d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + + // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; + if ((n == 15) && (CurrentInstrSet() != eModeARM)) + return false; + + break; + + case eEncodingT2: + case eEncodingA2: + // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); + single_reg = true; + add = BitIsSet(opcode, 23); + imm32 = Bits32(opcode, 7, 0) << 2; + + // d = UInt(Vd:D); n = UInt(Rn); + d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); + n = Bits32(opcode, 19, 16); + + // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; + if ((n == 15) && (CurrentInstrSet() != eModeARM)) + return false; + + break; + + default: + return false; } - return true; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // address = if add then (R[n] + imm32) else (R[n] - imm32); + addr_t address; + if (add) + address = Rn + imm32; + else + address = Rn - imm32; + + const uint32_t addr_byte_size = GetAddressByteSize(); + uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, start_reg + d, data_reg); + EmulateInstruction::Context context; + context.type = eContextRegisterStore; + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + + if (single_reg) { + // MemA[address,4] = S[d]; + uint32_t data = + ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success); + if (!success) + return false; + + if (!MemAWrite(context, address, data, addr_byte_size)) + return false; + } else { + // // Store as two word-aligned words in the correct order for current + // endianness. + // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; + // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; + uint64_t data = + ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success); + if (!success) + return false; + + if (GetByteOrder() == eByteOrderBig) { + if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size)) + return false; + + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + (address + 4) - Rn); + if (!MemAWrite(context, address + 4, Bits64(data, 31, 0), + addr_byte_size)) + return false; + } else { + if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size)) + return false; + + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + (address + 4) - Rn); + if (!MemAWrite(context, address + 4, Bits64(data, 63, 32), + addr_byte_size)) + return false; + } + } + } + return true; } // A8.6.307 VLDI1 (multiple single elements) -// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving. Every +// This instruction loads elements from memory into one, two, three or four +// registers, without de-interleaving. Every // element of each register is loaded. -bool -EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode, + ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); @@ -11443,161 +11430,153 @@ EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding e address = address + ebytes; #endif - bool success = false; - - if (ConditionPassed (opcode)) - { - uint32_t regs; - uint32_t alignment; - uint32_t ebytes; - uint32_t esize; - uint32_t elements; - uint32_t d; - uint32_t n; - uint32_t m; - bool wback; - bool register_index; - - switch (encoding) - { - case eEncodingT1: - case eEncodingA1: - { - // case type of - // when '0111' - // regs = 1; if align<1> == '1' then UNDEFINED; - // when '1010' - // regs = 2; if align == '11' then UNDEFINED; - // when '0110' - // regs = 3; if align<1> == '1' then UNDEFINED; - // when '0010' - // regs = 4; - // otherwise - // SEE 'Related encodings'; - uint32_t type = Bits32 (opcode, 11, 8); - uint32_t align = Bits32 (opcode, 5, 4); - if (type == 7) // '0111' - { - regs = 1; - if (BitIsSet (align, 1)) - return false; - } - else if (type == 10) // '1010' - { - regs = 2; - if (align == 3) - return false; - - } - else if (type == 6) // '0110' - { - regs = 3; - if (BitIsSet (align, 1)) - return false; - } - else if (type == 2) // '0010' - { - regs = 4; - } - else - return false; - - // alignment = if align == '00' then 1 else 4 << UInt(align); - if (align == 0) - alignment = 1; - else - alignment = 4 << align; - - // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; - ebytes = 1 << Bits32 (opcode, 7, 6); - esize = 8 * ebytes; - elements = 8 / ebytes; - - // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); - d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 15); - m = Bits32 (opcode, 3, 0); - - // wback = (m != 15); register_index = (m != 15 && m != 13); - wback = (m != 15); - register_index = ((m != 15) && (m != 13)); - - // if d+regs > 32 then UNPREDICTABLE; - if ((d + regs) > 32) - return false; - } - break; - - default: - return false; - } - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rn = ReadCoreReg (n, &success); + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t regs; + uint32_t alignment; + uint32_t ebytes; + uint32_t esize; + uint32_t elements; + uint32_t d; + uint32_t n; + uint32_t m; + bool wback; + bool register_index; + + switch (encoding) { + case eEncodingT1: + case eEncodingA1: { + // case type of + // when '0111' + // regs = 1; if align<1> == '1' then UNDEFINED; + // when '1010' + // regs = 2; if align == '11' then UNDEFINED; + // when '0110' + // regs = 3; if align<1> == '1' then UNDEFINED; + // when '0010' + // regs = 4; + // otherwise + // SEE 'Related encodings'; + uint32_t type = Bits32(opcode, 11, 8); + uint32_t align = Bits32(opcode, 5, 4); + if (type == 7) // '0111' + { + regs = 1; + if (BitIsSet(align, 1)) + return false; + } else if (type == 10) // '1010' + { + regs = 2; + if (align == 3) + return false; + + } else if (type == 6) // '0110' + { + regs = 3; + if (BitIsSet(align, 1)) + return false; + } else if (type == 2) // '0010' + { + regs = 4; + } else + return false; + + // alignment = if align == '00' then 1 else 4 << UInt(align); + if (align == 0) + alignment = 1; + else + alignment = 4 << align; + + // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; + ebytes = 1 << Bits32(opcode, 7, 6); + esize = 8 * ebytes; + elements = 8 / ebytes; + + // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); + d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 15); + m = Bits32(opcode, 3, 0); + + // wback = (m != 15); register_index = (m != 15 && m != 13); + wback = (m != 15); + register_index = ((m != 15) && (m != 13)); + + // if d+regs > 32 then UNPREDICTABLE; + if ((d + regs) > 32) + return false; + } break; + + default: + return false; + } + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // address = R[n]; if (address MOD alignment) != 0 then + // GenerateAlignmentException(); + addr_t address = Rn; + if ((address % alignment) != 0) + return false; + + EmulateInstruction::Context context; + // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); + if (wback) { + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + + uint32_t offset; + if (register_index) + offset = Rm; + else + offset = 8 * regs; + + uint32_t value = Rn + offset; + context.type = eContextAdjustBaseRegister; + context.SetRegisterPlusOffset(base_reg, offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + value)) + return false; + } + + // for r = 0 to regs-1 + for (uint32_t r = 0; r < regs; ++r) { + // for e = 0 to elements-1 + uint64_t assembled_data = 0; + for (uint32_t e = 0; e < elements; ++e) { + // Elem[D[d+r],e,esize] = MemU[address,ebytes]; + context.type = eContextRegisterLoad; + context.SetRegisterPlusOffset(base_reg, address - Rn); + uint64_t data = MemURead(context, address, ebytes, 0, &success); if (!success) - return false; - - // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); - addr_t address = Rn; - if ((address % alignment) != 0) - return false; - - EmulateInstruction::Context context; - // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); - if (wback) - { - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - - uint32_t offset; - if (register_index) - offset = Rm; - else - offset = 8 * regs; - - uint32_t value = Rn + offset; - context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset (base_reg, offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) - return false; - - } - - // for r = 0 to regs-1 - for (uint32_t r = 0; r < regs; ++r) - { - // for e = 0 to elements-1 - uint64_t assembled_data = 0; - for (uint32_t e = 0; e < elements; ++e) - { - // Elem[D[d+r],e,esize] = MemU[address,ebytes]; - context.type = eContextRegisterLoad; - context.SetRegisterPlusOffset (base_reg, address - Rn); - uint64_t data = MemURead (context, address, ebytes, 0, &success); - if (!success) - return false; - - assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data - - // address = address + ebytes; - address = address + ebytes; - } - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data)) - return false; - } + return false; + + assembled_data = + (data << (e * esize)) | + assembled_data; // New data goes to the left of existing data + + // address = address + ebytes; + address = address + ebytes; + } + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r, + assembled_data)) + return false; } - return true; + } + return true; } // A8.6.308 VLD1 (single element to one lane) // -bool -EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); @@ -11606,174 +11585,177 @@ EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncodi Elem[D[d],index,esize] = MemU[address,ebytes]; #endif - bool success = false; - - if (ConditionPassed (opcode)) - { - uint32_t ebytes; - uint32_t esize; - uint32_t index; - uint32_t alignment; - uint32_t d; - uint32_t n; - uint32_t m; - bool wback; - bool register_index; - - switch (encoding) - { - case eEncodingT1: - case eEncodingA1: - { - uint32_t size = Bits32 (opcode, 11, 10); - uint32_t index_align = Bits32 (opcode, 7, 4); - // if size == '11' then SEE VLD1 (single element to all lanes); - if (size == 3) - return EmulateVLD1SingleAll (opcode, encoding); - // case size of - if (size == 0) // when '00' - { - // if index_align<0> != '0' then UNDEFINED; - if (BitIsClear (index_align, 0)) - return false; - - // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; - ebytes = 1; - esize = 8; - index = Bits32 (index_align, 3, 1); - alignment = 1; - } - else if (size == 1) // when '01' - { - // if index_align<1> != '0' then UNDEFINED; - if (BitIsClear (index_align, 1)) - return false; - - // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); - ebytes = 2; - esize = 16; - index = Bits32 (index_align, 3, 2); - - // alignment = if index_align<0> == '0' then 1 else 2; - if (BitIsClear (index_align, 0)) - alignment = 1; - else - alignment = 2; - } - else if (size == 2) // when '10' - { - // if index_align<2> != '0' then UNDEFINED; - if (BitIsClear (index_align, 2)) - return false; - - // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED; - if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) - return false; - - // ebytes = 4; esize = 32; index = UInt(index_align<3>); - ebytes = 4; - esize = 32; - index = Bit32 (index_align, 3); - - // alignment = if index_align<1:0> == '00' then 1 else 4; - if (Bits32 (index_align, 1, 0) == 0) - alignment = 1; - else - alignment = 4; - } - else - { - return false; - } - // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); - d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE; - wback = (m != 15); - register_index = ((m != 15) && (m != 13)); - - if (n == 15) - return false; - - } - break; - - default: - return false; - } - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); - addr_t address = Rn; - if ((address % alignment) != 0) - return false; - - EmulateInstruction::Context context; - // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); - if (wback) - { - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - - uint32_t offset; - if (register_index) - offset = Rm; - else - offset = ebytes; - - uint32_t value = Rn + offset; - - context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset (base_reg, offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value)) - return false; - } - - // Elem[D[d],index,esize] = MemU[address,ebytes]; - uint32_t element = MemURead (context, address, esize, 0, &success); - if (!success) - return false; - - element = element << (index * esize); - - uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success); - if (!success) - return false; - - uint64_t all_ones = -1; - uint64_t mask = all_ones << ((index+1) * esize); // mask is all 1's to left of where 'element' goes, & all 0's - // at element & to the right of element. - if (index > 0) - mask = mask | Bits64 (all_ones, (index * esize) - 1, 0); // add 1's to the right of where 'element' goes. - // now mask should be 0's where element goes & 1's - // everywhere else. - - uint64_t masked_reg = reg_data & mask; // Take original reg value & zero out 'element' bits - reg_data = masked_reg & element; // Put 'element' into those bits in reg_data. - - context.type = eContextRegisterLoad; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data)) - return false; + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t ebytes; + uint32_t esize; + uint32_t index; + uint32_t alignment; + uint32_t d; + uint32_t n; + uint32_t m; + bool wback; + bool register_index; + + switch (encoding) { + case eEncodingT1: + case eEncodingA1: { + uint32_t size = Bits32(opcode, 11, 10); + uint32_t index_align = Bits32(opcode, 7, 4); + // if size == '11' then SEE VLD1 (single element to all lanes); + if (size == 3) + return EmulateVLD1SingleAll(opcode, encoding); + // case size of + if (size == 0) // when '00' + { + // if index_align<0> != '0' then UNDEFINED; + if (BitIsClear(index_align, 0)) + return false; + + // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; + ebytes = 1; + esize = 8; + index = Bits32(index_align, 3, 1); + alignment = 1; + } else if (size == 1) // when '01' + { + // if index_align<1> != '0' then UNDEFINED; + if (BitIsClear(index_align, 1)) + return false; + + // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); + ebytes = 2; + esize = 16; + index = Bits32(index_align, 3, 2); + + // alignment = if index_align<0> == '0' then 1 else 2; + if (BitIsClear(index_align, 0)) + alignment = 1; + else + alignment = 2; + } else if (size == 2) // when '10' + { + // if index_align<2> != '0' then UNDEFINED; + if (BitIsClear(index_align, 2)) + return false; + + // if index_align<1:0> != '00' && index_align<1:0> != '11' then + // UNDEFINED; + if ((Bits32(index_align, 1, 0) != 0) && + (Bits32(index_align, 1, 0) != 3)) + return false; + + // ebytes = 4; esize = 32; index = UInt(index_align<3>); + ebytes = 4; + esize = 32; + index = Bit32(index_align, 3); + + // alignment = if index_align<1:0> == '00' then 1 else 4; + if (Bits32(index_align, 1, 0) == 0) + alignment = 1; + else + alignment = 4; + } else { + return false; + } + // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); + d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 + // then UNPREDICTABLE; + wback = (m != 15); + register_index = ((m != 15) && (m != 13)); + + if (n == 15) + return false; + + } break; + + default: + return false; } - return true; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // address = R[n]; if (address MOD alignment) != 0 then + // GenerateAlignmentException(); + addr_t address = Rn; + if ((address % alignment) != 0) + return false; + + EmulateInstruction::Context context; + // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); + if (wback) { + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + + uint32_t offset; + if (register_index) + offset = Rm; + else + offset = ebytes; + + uint32_t value = Rn + offset; + + context.type = eContextAdjustBaseRegister; + context.SetRegisterPlusOffset(base_reg, offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + value)) + return false; + } + + // Elem[D[d],index,esize] = MemU[address,ebytes]; + uint32_t element = MemURead(context, address, esize, 0, &success); + if (!success) + return false; + + element = element << (index * esize); + + uint64_t reg_data = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success); + if (!success) + return false; + + uint64_t all_ones = -1; + uint64_t mask = all_ones + << ((index + 1) * esize); // mask is all 1's to left of + // where 'element' goes, & all 0's + // at element & to the right of element. + if (index > 0) + mask = mask | Bits64(all_ones, (index * esize) - 1, + 0); // add 1's to the right of where 'element' goes. + // now mask should be 0's where element goes & 1's + // everywhere else. + + uint64_t masked_reg = + reg_data & mask; // Take original reg value & zero out 'element' bits + reg_data = + masked_reg & element; // Put 'element' into those bits in reg_data. + + context.type = eContextRegisterLoad; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, + reg_data)) + return false; + } + return true; } // A8.6.391 VST1 (multiple single elements) -// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four registers, without +// Vector Store (multiple single elements) stores elements to memory from one, +// two, three, or four registers, without // interleaving. Every element of each register is stored. -bool -EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding) -{ +bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode, + ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); @@ -11784,159 +11766,152 @@ EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding e MemU[address,ebytes] = Elem[D[d+r],e,esize]; address = address + ebytes; #endif - - bool success = false; - - if (ConditionPassed (opcode)) - { - uint32_t regs; - uint32_t alignment; - uint32_t ebytes; - uint32_t esize; - uint32_t elements; - uint32_t d; - uint32_t n; - uint32_t m; - bool wback; - bool register_index; - - switch (encoding) - { - case eEncodingT1: - case eEncodingA1: - { - uint32_t type = Bits32 (opcode, 11, 8); - uint32_t align = Bits32 (opcode, 5, 4); - - // case type of - if (type == 7) // when '0111' - { - // regs = 1; if align<1> == '1' then UNDEFINED; - regs = 1; - if (BitIsSet (align, 1)) - return false; - } - else if (type == 10) // when '1010' - { - // regs = 2; if align == '11' then UNDEFINED; - regs = 2; - if (align == 3) - return false; - } - else if (type == 6) // when '0110' - { - // regs = 3; if align<1> == '1' then UNDEFINED; - regs = 3; - if (BitIsSet (align, 1)) - return false; - } - else if (type == 2) // when '0010' - // regs = 4; - regs = 4; - else // otherwise - // SEE 'Related encodings'; - return false; - - // alignment = if align == '00' then 1 else 4 << UInt(align); - if (align == 0) - alignment = 1; - else - alignment = 4 << align; - - // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; - ebytes = 1 << Bits32 (opcode,7, 6); - esize = 8 * ebytes; - elements = 8 / ebytes; - - // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); - d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // wback = (m != 15); register_index = (m != 15 && m != 13); - wback = (m != 15); - register_index = ((m != 15) && (m != 13)); - - // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; - if ((d + regs) > 32) - return false; - - if (n == 15) - return false; - - } - break; - - default: - return false; - } - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); - addr_t address = Rn; - if ((address % alignment) != 0) - return false; - - EmulateInstruction::Context context; - // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); - if (wback) - { - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - - uint32_t offset; - if (register_index) - offset = Rm; - else - offset = 8 * regs; - - context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset (base_reg, offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) - return false; - } - - RegisterInfo data_reg; - context.type = eContextRegisterStore; - // for r = 0 to regs-1 - for (uint32_t r = 0; r < regs; ++r) - { - GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg); - uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success); - if (!success) - return false; - // for e = 0 to elements-1 - for (uint32_t e = 0; e < elements; ++e) - { - // MemU[address,ebytes] = Elem[D[d+r],e,esize]; - uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize); - - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); - if (!MemUWrite (context, address, word, ebytes)) - return false; - - // address = address + ebytes; - address = address + ebytes; - } - } + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t regs; + uint32_t alignment; + uint32_t ebytes; + uint32_t esize; + uint32_t elements; + uint32_t d; + uint32_t n; + uint32_t m; + bool wback; + bool register_index; + + switch (encoding) { + case eEncodingT1: + case eEncodingA1: { + uint32_t type = Bits32(opcode, 11, 8); + uint32_t align = Bits32(opcode, 5, 4); + + // case type of + if (type == 7) // when '0111' + { + // regs = 1; if align<1> == '1' then UNDEFINED; + regs = 1; + if (BitIsSet(align, 1)) + return false; + } else if (type == 10) // when '1010' + { + // regs = 2; if align == '11' then UNDEFINED; + regs = 2; + if (align == 3) + return false; + } else if (type == 6) // when '0110' + { + // regs = 3; if align<1> == '1' then UNDEFINED; + regs = 3; + if (BitIsSet(align, 1)) + return false; + } else if (type == 2) // when '0010' + // regs = 4; + regs = 4; + else // otherwise + // SEE 'Related encodings'; + return false; + + // alignment = if align == '00' then 1 else 4 << UInt(align); + if (align == 0) + alignment = 1; + else + alignment = 4 << align; + + // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; + ebytes = 1 << Bits32(opcode, 7, 6); + esize = 8 * ebytes; + elements = 8 / ebytes; + + // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); + d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // wback = (m != 15); register_index = (m != 15 && m != 13); + wback = (m != 15); + register_index = ((m != 15) && (m != 13)); + + // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; + if ((d + regs) > 32) + return false; + + if (n == 15) + return false; + + } break; + + default: + return false; } - return true; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // address = R[n]; if (address MOD alignment) != 0 then + // GenerateAlignmentException(); + addr_t address = Rn; + if ((address % alignment) != 0) + return false; + + EmulateInstruction::Context context; + // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); + if (wback) { + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + + uint32_t offset; + if (register_index) + offset = Rm; + else + offset = 8 * regs; + + context.type = eContextAdjustBaseRegister; + context.SetRegisterPlusOffset(base_reg, offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + Rn + offset)) + return false; + } + + RegisterInfo data_reg; + context.type = eContextRegisterStore; + // for r = 0 to regs-1 + for (uint32_t r = 0; r < regs; ++r) { + GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r, data_reg); + uint64_t register_data = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success); + if (!success) + return false; + + // for e = 0 to elements-1 + for (uint32_t e = 0; e < elements; ++e) { + // MemU[address,ebytes] = Elem[D[d+r],e,esize]; + uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize); + + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, + address - Rn); + if (!MemUWrite(context, address, word, ebytes)) + return false; + + // address = address + ebytes; + address = address + ebytes; + } + } + } + return true; } // A8.6.392 VST1 (single element from one lane) -// This instruction stores one element to memory from one element of a register. -bool -EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding) -{ +// This instruction stores one element to memory from one element of a register. +bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode, + ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); @@ -11945,160 +11920,158 @@ EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding enc MemU[address,ebytes] = Elem[D[d],index,esize]; #endif - bool success = false; - - if (ConditionPassed (opcode)) - { - uint32_t ebytes; - uint32_t esize; - uint32_t index; - uint32_t alignment; - uint32_t d; - uint32_t n; - uint32_t m; - bool wback; - bool register_index; - - switch (encoding) - { - case eEncodingT1: - case eEncodingA1: - { - uint32_t size = Bits32 (opcode, 11, 10); - uint32_t index_align = Bits32 (opcode, 7, 4); - - // if size == '11' then UNDEFINED; - if (size == 3) - return false; - - // case size of - if (size == 0) // when '00' - { - // if index_align<0> != '0' then UNDEFINED; - if (BitIsClear (index_align, 0)) - return false; - // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; - ebytes = 1; - esize = 8; - index = Bits32 (index_align, 3, 1); - alignment = 1; - } - else if (size == 1) // when '01' - { - // if index_align<1> != '0' then UNDEFINED; - if (BitIsClear (index_align, 1)) - return false; - - // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); - ebytes = 2; - esize = 16; - index = Bits32 (index_align, 3, 2); - - // alignment = if index_align<0> == '0' then 1 else 2; - if (BitIsClear (index_align, 0)) - alignment = 1; - else - alignment = 2; - } - else if (size == 2) // when '10' - { - // if index_align<2> != '0' then UNDEFINED; - if (BitIsClear (index_align, 2)) - return false; - - // if index_align<1:0> != '00' && index_align<1:0> != '11' then UNDEFINED; - if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3)) - return false; - - // ebytes = 4; esize = 32; index = UInt(index_align<3>); - ebytes = 4; - esize = 32; - index = Bit32 (index_align, 3); - - // alignment = if index_align<1:0> == '00' then 1 else 4; - if (Bits32 (index_align, 1, 0) == 0) - alignment = 1; - else - alignment = 4; - } - else - { - return false; - } - // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); - d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE; - wback = (m != 15); - register_index = ((m != 15) && (m != 13)); - - if (n == 15) - return false; - } - break; - - default: - return false; - } - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); - addr_t address = Rn; - if ((address % alignment) != 0) - return false; - - EmulateInstruction::Context context; - // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); - if (wback) - { - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - - uint32_t offset; - if (register_index) - offset = Rm; - else - offset = ebytes; - - context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset (base_reg, offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) - return false; - } - - // MemU[address,ebytes] = Elem[D[d],index,esize]; - uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success); - if (!success) - return false; - - uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1, index * esize); - - RegisterInfo data_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg); - context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn); - - if (!MemUWrite (context, address, word, ebytes)) - return false; + bool success = false; + + if (ConditionPassed(opcode)) { + uint32_t ebytes; + uint32_t esize; + uint32_t index; + uint32_t alignment; + uint32_t d; + uint32_t n; + uint32_t m; + bool wback; + bool register_index; + + switch (encoding) { + case eEncodingT1: + case eEncodingA1: { + uint32_t size = Bits32(opcode, 11, 10); + uint32_t index_align = Bits32(opcode, 7, 4); + + // if size == '11' then UNDEFINED; + if (size == 3) + return false; + + // case size of + if (size == 0) // when '00' + { + // if index_align<0> != '0' then UNDEFINED; + if (BitIsClear(index_align, 0)) + return false; + // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; + ebytes = 1; + esize = 8; + index = Bits32(index_align, 3, 1); + alignment = 1; + } else if (size == 1) // when '01' + { + // if index_align<1> != '0' then UNDEFINED; + if (BitIsClear(index_align, 1)) + return false; + + // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); + ebytes = 2; + esize = 16; + index = Bits32(index_align, 3, 2); + + // alignment = if index_align<0> == '0' then 1 else 2; + if (BitIsClear(index_align, 0)) + alignment = 1; + else + alignment = 2; + } else if (size == 2) // when '10' + { + // if index_align<2> != '0' then UNDEFINED; + if (BitIsClear(index_align, 2)) + return false; + + // if index_align<1:0> != '00' && index_align<1:0> != '11' then + // UNDEFINED; + if ((Bits32(index_align, 1, 0) != 0) && + (Bits32(index_align, 1, 0) != 3)) + return false; + + // ebytes = 4; esize = 32; index = UInt(index_align<3>); + ebytes = 4; + esize = 32; + index = Bit32(index_align, 3); + + // alignment = if index_align<1:0> == '00' then 1 else 4; + if (Bits32(index_align, 1, 0) == 0) + alignment = 1; + else + alignment = 4; + } else { + return false; + } + // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); + d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 + // then UNPREDICTABLE; + wback = (m != 15); + register_index = ((m != 15) && (m != 13)); + + if (n == 15) + return false; + } break; + + default: + return false; } - return true; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // address = R[n]; if (address MOD alignment) != 0 then + // GenerateAlignmentException(); + addr_t address = Rn; + if ((address % alignment) != 0) + return false; + + EmulateInstruction::Context context; + // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); + if (wback) { + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + + uint32_t offset; + if (register_index) + offset = Rm; + else + offset = ebytes; + + context.type = eContextAdjustBaseRegister; + context.SetRegisterPlusOffset(base_reg, offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + Rn + offset)) + return false; + } + + // MemU[address,ebytes] = Elem[D[d],index,esize]; + uint64_t register_data = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success); + if (!success) + return false; + + uint64_t word = + Bits64(register_data, ((index + 1) * esize) - 1, index * esize); + + RegisterInfo data_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d, data_reg); + context.type = eContextRegisterStore; + context.SetRegisterToRegisterPlusOffset(data_reg, base_reg, address - Rn); + + if (!MemUWrite(context, address, word, ebytes)) + return false; + } + return true; } // A8.6.309 VLD1 (single element to all lanes) -// This instruction loads one element from memory into every element of one or two vectors. -bool -EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding) -{ +// This instruction loads one element from memory into every element of one or +// two vectors. +bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); @@ -12109,128 +12082,128 @@ EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEnc D[d+r] = replicated_element; #endif - bool success = false; - - if (ConditionPassed (opcode)) - { - uint32_t ebytes; - uint32_t elements; - uint32_t regs; - uint32_t alignment; - uint32_t d; - uint32_t n; - uint32_t m; - bool wback; - bool register_index; - - switch (encoding) - { - case eEncodingT1: - case eEncodingA1: - { - //if size == '11' || (size == '00' && a == '1') then UNDEFINED; - uint32_t size = Bits32 (opcode, 7, 6); - if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4))) - return false; - - //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0' then 1 else 2; - ebytes = 1 << size; - elements = 8 / ebytes; - if (BitIsClear (opcode, 5)) - regs = 1; - else - regs = 2; - - //alignment = if a == '0' then 1 else ebytes; - if (BitIsClear (opcode, 4)) - alignment = 1; - else - alignment = ebytes; - - //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); - d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12); - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - - //wback = (m != 15); register_index = (m != 15 && m != 13); - wback = (m != 15); - register_index = ((m != 15) && (m != 13)); - - //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; - if ((d + regs) > 32) - return false; - - if (n == 15) - return false; - } - break; - - default: - return false; - } - - RegisterInfo base_reg; - GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg); - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); - addr_t address = Rn; - if ((address % alignment) != 0) - return false; - - EmulateInstruction::Context context; - // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); - if (wback) - { - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - - uint32_t offset; - if (register_index) - offset = Rm; - else - offset = ebytes; - - context.type = eContextAdjustBaseRegister; - context.SetRegisterPlusOffset (base_reg, offset); - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset)) - return false; - } - - // replicated_element = Replicate(MemU[address,ebytes], elements); - - context.type = eContextRegisterLoad; - uint64_t word = MemURead (context, address, ebytes, 0, &success); - if (!success) - return false; - - uint64_t replicated_element = 0; - uint32_t esize = ebytes * 8; - for (uint32_t e = 0; e < elements; ++e) - replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0); + bool success = false; - // for r = 0 to regs-1 - for (uint32_t r = 0; r < regs; ++r) - { - // D[d+r] = replicated_element; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element)) - return false; - } + if (ConditionPassed(opcode)) { + uint32_t ebytes; + uint32_t elements; + uint32_t regs; + uint32_t alignment; + uint32_t d; + uint32_t n; + uint32_t m; + bool wback; + bool register_index; + + switch (encoding) { + case eEncodingT1: + case eEncodingA1: { + // if size == '11' || (size == '00' && a == '1') then UNDEFINED; + uint32_t size = Bits32(opcode, 7, 6); + if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4))) + return false; + + // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0' + // then 1 else 2; + ebytes = 1 << size; + elements = 8 / ebytes; + if (BitIsClear(opcode, 5)) + regs = 1; + else + regs = 2; + + // alignment = if a == '0' then 1 else ebytes; + if (BitIsClear(opcode, 4)) + alignment = 1; + else + alignment = ebytes; + + // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); + d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + + // wback = (m != 15); register_index = (m != 15 && m != 13); + wback = (m != 15); + register_index = ((m != 15) && (m != 13)); + + // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; + if ((d + regs) > 32) + return false; + + if (n == 15) + return false; + } break; + + default: + return false; } - return true; + + RegisterInfo base_reg; + GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n, base_reg); + + uint32_t Rn = ReadCoreReg(n, &success); + if (!success) + return false; + + // address = R[n]; if (address MOD alignment) != 0 then + // GenerateAlignmentException(); + addr_t address = Rn; + if ((address % alignment) != 0) + return false; + + EmulateInstruction::Context context; + // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); + if (wback) { + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; + + uint32_t offset; + if (register_index) + offset = Rm; + else + offset = ebytes; + + context.type = eContextAdjustBaseRegister; + context.SetRegisterPlusOffset(base_reg, offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, + Rn + offset)) + return false; + } + + // replicated_element = Replicate(MemU[address,ebytes], elements); + + context.type = eContextRegisterLoad; + uint64_t word = MemURead(context, address, ebytes, 0, &success); + if (!success) + return false; + + uint64_t replicated_element = 0; + uint32_t esize = ebytes * 8; + for (uint32_t e = 0; e < elements; ++e) + replicated_element = + (replicated_element << esize) | Bits64(word, esize - 1, 0); + + // for r = 0 to regs-1 + for (uint32_t r = 0; r < regs; ++r) { + // D[d+r] = replicated_element; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r, + replicated_element)) + return false; + } + } + return true; } // B6.2.13 SUBS PC, LR and related instructions -//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack. It subtracts the -// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR. -bool -EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding) -{ +// The SUBS PC, LR, #<const? instruction provides an exception return without +// the use of the stack. It subtracts the +// immediate constant from the LR, branches to the resulting address, and also +// copies the SPSR to the CPSR. +bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode, + const ARMEncoding encoding) { #if 0 if ConditionPassed() then EncodingSpecificOperations(); @@ -12254,1240 +12227,1597 @@ EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncod BranchWritePC(result); #endif - bool success = false; + bool success = false; - if (ConditionPassed (opcode)) - { - uint32_t n; - uint32_t m; - uint32_t imm32; - bool register_form; - ARM_ShifterType shift_t; - uint32_t shift_n; - uint32_t code; - - switch (encoding) - { - case eEncodingT1: - // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE - // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010'; // = SUB - n = 14; - imm32 = Bits32 (opcode, 7, 0); - register_form = false; - code = 2; - - // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; - if (InITBlock() && !LastInITBlock()) - return false; - - break; - - case eEncodingA1: - // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE; - n = Bits32 (opcode, 19, 16); - imm32 = ARMExpandImm (opcode); - register_form = false; - code = Bits32 (opcode, 24, 21); - - break; - - case eEncodingA2: - // n = UInt(Rn); m = UInt(Rm); register_form = TRUE; - n = Bits32 (opcode, 19, 16); - m = Bits32 (opcode, 3, 0); - register_form = true; - - // (shift_t, shift_n) = DecodeImmShift(type, imm5); - shift_n = DecodeImmShiftARM (opcode, shift_t); - - break; - - default: - return false; - } + if (ConditionPassed(opcode)) { + uint32_t n; + uint32_t m; + uint32_t imm32; + bool register_form; + ARM_ShifterType shift_t; + uint32_t shift_n; + uint32_t code; - // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; - uint32_t operand2; - if (register_form) - { - uint32_t Rm = ReadCoreReg (m, &success); - if (!success) - return false; - - operand2 = Shift (Rm, shift_t, shift_n, APSR_C, &success); - if (!success) - return false; - } - else - { - operand2 = imm32; - } - - uint32_t Rn = ReadCoreReg (n, &success); - if (!success) - return false; - - AddWithCarryResult result; - - // case opcode of - switch (code) - { - case 0: // when '0000' - // result = R[n] AND operand2; // AND - result.result = Rn & operand2; - break; - - case 1: // when '0001' - // result = R[n] EOR operand2; // EOR - result.result = Rn ^ operand2; - break; - - case 2: // when '0010' - // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB - result = AddWithCarry (Rn, ~(operand2), 1); - break; - - case 3: // when '0011' - // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB - result = AddWithCarry (~(Rn), operand2, 1); - break; - - case 4: // when '0100' - // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD - result = AddWithCarry (Rn, operand2, 0); - break; - - case 5: // when '0101' - // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC - result = AddWithCarry (Rn, operand2, APSR_C); - break; - - case 6: // when '0110' - // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC - result = AddWithCarry (Rn, ~(operand2), APSR_C); - break; - - case 7: // when '0111' - // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC - result = AddWithCarry (~(Rn), operand2, APSR_C); - break; - - case 10: // when '1100' - // result = R[n] OR operand2; // ORR - result.result = Rn | operand2; - break; - - case 11: // when '1101' - // result = operand2; // MOV - result.result = operand2; - break; - - case 12: // when '1110' - // result = R[n] AND NOT(operand2); // BIC - result.result = Rn & ~(operand2); - break; - - case 15: // when '1111' - // result = NOT(operand2); // MVN - result.result = ~(operand2); - break; - - default: - return false; - } - // CPSRWriteByInstr(SPSR[], '1111', TRUE); - - // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for - // the best. - uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success); - if (!success) - return false; - - CPSRWriteByInstr (spsr, 15, true); - - // BranchWritePC(result); - EmulateInstruction::Context context; - context.type = eContextAdjustPC; - context.SetImmediate (result.result); - - BranchWritePC (context, result.result); - } - return true; -} - -EmulateInstructionARM::ARMOpcode* -EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa) -{ - static ARMOpcode - g_arm_opcodes[] = - { - //---------------------------------------------------------------------- - // Prologue instructions - //---------------------------------------------------------------------- - - // push register(s) - { 0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, - { 0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" }, - - // set r7 to point to a stack offset - { 0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" }, - { 0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"}, - // copy the stack pointer to ip - { 0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" }, - { 0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" }, - { 0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"}, - - // adjust the stack pointer - { 0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"}, - { 0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, - - // push one register - // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH; - { 0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" }, - - // vector push consecutive extension register(s) - { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, - { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, - - //---------------------------------------------------------------------- - // Epilogue instructions - //---------------------------------------------------------------------- - - { 0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, - { 0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"}, - { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, - { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, - - //---------------------------------------------------------------------- - // Supervisor Call (previously Software Interrupt) - //---------------------------------------------------------------------- - { 0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"}, - - //---------------------------------------------------------------------- - // Branch instructions - //---------------------------------------------------------------------- - // To resolve ambiguity, "blx <label>" should come before "b #imm24" and "bl <label>". - { 0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, - { 0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"}, - { 0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, - { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, - // for example, "bx lr" - { 0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, - // bxj - { 0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, - - //---------------------------------------------------------------------- - // Data-processing instructions - //---------------------------------------------------------------------- - // adc (immediate) - { 0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"}, - // adc (register) - { 0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, - // add (immediate) - { 0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"}, - // add (register) - { 0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, - // add (register-shifted register) - { 0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"}, - // adr - { 0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, - { 0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, - // and (immediate) - { 0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"}, - // and (register) - { 0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, - // bic (immediate) - { 0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"}, - // bic (register) - { 0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, - // eor (immediate) - { 0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"}, - // eor (register) - { 0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, - // orr (immediate) - { 0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"}, - // orr (register) - { 0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, - // rsb (immediate) - { 0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"}, - // rsb (register) - { 0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, - // rsc (immediate) - { 0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"}, - // rsc (register) - { 0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, - // sbc (immediate) - { 0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, - // sbc (register) - { 0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, - // sub (immediate, ARM) - { 0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"}, - // sub (sp minus immediate) - { 0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"}, - // sub (register) - { 0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"}, - // teq (immediate) - { 0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"}, - // teq (register) - { 0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, - // tst (immediate) - { 0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"}, - // tst (register) - { 0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"}, - - // mov (immediate) - { 0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"}, - { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" }, - // mov (register) - { 0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"}, - // mvn (immediate) - { 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"}, - // mvn (register) - { 0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"}, - // cmn (immediate) - { 0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, - // cmn (register) - { 0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, - // cmp (immediate) - { 0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"}, - // cmp (register) - { 0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"}, - // asr (immediate) - { 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"}, - // asr (register) - { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"}, - // lsl (immediate) - { 0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"}, - // lsl (register) - { 0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"}, - // lsr (immediate) - { 0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"}, - // lsr (register) - { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"}, - // rrx is a special case encoding of ror (immediate) - { 0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"}, - // ror (immediate) - { 0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"}, - // ror (register) - { 0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"}, - // mul - { 0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" }, - - // subs pc, lr and related instructions - { 0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" }, - { 0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" }, - - //---------------------------------------------------------------------- - // Load instructions - //---------------------------------------------------------------------- - { 0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, - { 0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" }, - { 0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, - { 0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" }, - { 0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" }, - { 0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" }, - { 0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"}, - { 0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" }, - { 0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, - { 0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, - { 0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" }, - { 0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" }, - { 0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, - { 0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"}, - { 0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, - { 0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" }, - { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"}, - { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, - { 0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, - { 0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, - { 0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, - { 0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, - { 0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, - { 0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, - { 0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, - - //---------------------------------------------------------------------- - // Store instructions - //---------------------------------------------------------------------- - { 0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, - { 0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" }, - { 0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, - { 0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" }, - { 0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" }, - { 0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" }, - { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"}, - { 0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, - { 0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, - { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"}, - { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, - { 0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, - { 0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, - { 0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"}, - { 0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"}, - { 0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, - { 0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, - - //---------------------------------------------------------------------- - // Other instructions - //---------------------------------------------------------------------- - { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" }, - { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" }, - { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" }, - { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" }, - { 0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" } - - }; - static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_arm_opcodes); - - for (size_t i=0; i<k_num_arm_opcodes; ++i) - { - if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value && - (g_arm_opcodes[i].variants & arm_isa) != 0) - return &g_arm_opcodes[i]; - } - return NULL; -} + switch (encoding) { + case eEncodingT1: + // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE + // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = + // '0010'; // = SUB + n = 14; + imm32 = Bits32(opcode, 7, 0); + register_form = false; + code = 2; + + // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; + if (InITBlock() && !LastInITBlock()) + return false; - -EmulateInstructionARM::ARMOpcode* -EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa) -{ + break; - static ARMOpcode - g_thumb_opcodes[] = - { - //---------------------------------------------------------------------- - // Prologue instructions - //---------------------------------------------------------------------- - - // push register(s) - { 0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" }, - { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" }, - { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" }, - - // set r7 to point to a stack offset - { 0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" }, - // copy the stack pointer to r7 - { 0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" }, - // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity) - { 0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" }, - - // PC-relative load into register (see also EmulateADDSPRm) - { 0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"}, - - // adjust the stack pointer - { 0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"}, - { 0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"}, - { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"}, - { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"}, - { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, - - // vector push consecutive extension register(s) - { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, - { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, - - //---------------------------------------------------------------------- - // Epilogue instructions - //---------------------------------------------------------------------- - - { 0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"}, - { 0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"}, - { 0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, - { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" }, - { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" }, - { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, - { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, - - //---------------------------------------------------------------------- - // Supervisor Call (previously Software Interrupt) - //---------------------------------------------------------------------- - { 0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"}, - - //---------------------------------------------------------------------- - // If Then makes up to four following instructions conditional. - //---------------------------------------------------------------------- - // The next 5 opcode _must_ come before the if then instruction - { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"}, - { 0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"}, - { 0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"}, - { 0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"}, - { 0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"}, - { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, - - //---------------------------------------------------------------------- - // Branch instructions - //---------------------------------------------------------------------- - // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8". - { 0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"}, - { 0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"}, - { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"}, - { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"}, - // J1 == J2 == 1 - { 0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, - // J1 == J2 == 1 - { 0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, - { 0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, - // for example, "bx lr" - { 0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, - // bxj - { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, - // compare and branch - { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"}, - // table branch byte - { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"}, - // table branch halfword - { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"}, - - //---------------------------------------------------------------------- - // Data-processing instructions - //---------------------------------------------------------------------- - // adc (immediate) - { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"}, - // adc (register) - { 0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"}, - { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, - // add (register) - { 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"}, - // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two. - { 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"}, - // adr - { 0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, - { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, - { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, - // and (immediate) - { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"}, - // and (register) - { 0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"}, - { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, - // bic (immediate) - { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"}, - // bic (register) - { 0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"}, - { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, - // eor (immediate) - { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"}, - // eor (register) - { 0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"}, - { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, - // orr (immediate) - { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"}, - // orr (register) - { 0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"}, - { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, - // rsb (immediate) - { 0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"}, - { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"}, - // rsb (register) - { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, - // sbc (immediate) - { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, - // sbc (register) - { 0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"}, - { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, - // add (immediate, Thumb) - { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" }, - { 0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" }, - { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" }, - { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" }, - // sub (immediate, Thumb) - { 0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"}, - { 0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"}, - { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"}, - { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"}, - // sub (sp minus immediate) - { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"}, - { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"}, - // sub (register) - { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"}, - { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"}, - // teq (immediate) - { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"}, - // teq (register) - { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, - // tst (immediate) - { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"}, - // tst (register) - { 0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"}, - { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"}, - - - // move from high register to high register - { 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"}, - // move from low register to low register - { 0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"}, - // mov{s}<c>.w <Rd>, <Rm> - { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"}, - // move immediate - { 0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"}, - { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"}, - { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"}, - // mvn (immediate) - { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"}, - // mvn (register) - { 0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"}, - { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"}, - // cmn (immediate) - { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, - // cmn (register) - { 0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"}, - { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, - // cmp (immediate) - { 0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"}, - { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"}, - // cmp (register) (Rn and Rm both from r0-r7) - { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, - // cmp (register) (Rn and Rm not both from r0-r7) - { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, - { 0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c>.w <Rn>, <Rm> {, <shift>}"}, - // asr (immediate) - { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"}, - { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"}, - // asr (register) - { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"}, - { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"}, - // lsl (immediate) - { 0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"}, - { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"}, - // lsl (register) - { 0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"}, - { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"}, - // lsr (immediate) - { 0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"}, - { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"}, - // lsr (register) - { 0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"}, - { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"}, - // rrx is a special case encoding of ror (immediate) - { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"}, - // ror (immediate) - { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"}, - // ror (register) - { 0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"}, - { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"}, - // mul - { 0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" }, - // mul - { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" }, - - // subs pc, lr and related instructions - { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" }, - - //---------------------------------------------------------------------- - // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table; - // otherwise the wrong instructions will be selected. - //---------------------------------------------------------------------- - - { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" }, - { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" }, - - //---------------------------------------------------------------------- - // Load instructions - //---------------------------------------------------------------------- - { 0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" }, - { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" }, - { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" }, - { 0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}, - { 0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"}, - { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"}, - { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"}, - // Thumb2 PC-relative load into register - { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"}, - { 0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" }, - { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" }, - { 0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" }, - { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, - { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" }, - { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" }, - { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" }, - { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, - { 0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]" }, - { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" }, - { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}" }, - { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" }, - { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" }, - { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, - { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" }, - { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" }, - { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" }, - { 0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" }, - { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" }, - { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" }, - { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" }, - { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" }, - { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" }, - { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, - { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"}, - { 0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, - { 0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" }, - { 0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, - { 0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"}, - { 0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, - { 0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, - { 0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, - - //---------------------------------------------------------------------- - // Store instructions - //---------------------------------------------------------------------- - { 0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" }, - { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" }, - { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" }, - { 0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" }, - { 0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" }, - { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" }, - { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" }, - { 0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" }, - { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" }, - { 0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" }, - { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" }, - { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" }, - { 0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" }, - { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" }, - { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" }, - { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"}, - { 0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, - { 0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, - { 0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, - { 0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, - { 0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, - { 0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, - - //---------------------------------------------------------------------- - // Other instructions - //---------------------------------------------------------------------- - { 0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" }, - { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, - { 0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" }, - { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" }, - { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" }, - { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" }, - { 0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" }, - { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" }, - }; - - const size_t k_num_thumb_opcodes = llvm::array_lengthof(g_thumb_opcodes); - for (size_t i=0; i<k_num_thumb_opcodes; ++i) - { - if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value && - (g_thumb_opcodes[i].variants & arm_isa) != 0) - return &g_thumb_opcodes[i]; - } - return NULL; -} + case eEncodingA1: + // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE; + n = Bits32(opcode, 19, 16); + imm32 = ARMExpandImm(opcode); + register_form = false; + code = Bits32(opcode, 24, 21); -bool -EmulateInstructionARM::SetArchitecture (const ArchSpec &arch) -{ - m_arch = arch; - m_arm_isa = 0; - const char *arch_cstr = arch.GetArchitectureName (); - if (arch_cstr) - { - if (0 == ::strcasecmp(arch_cstr, "armv4t")) m_arm_isa = ARMv4T; - else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) m_arm_isa = ARMv5TEJ; - else if (0 == ::strcasecmp(arch_cstr, "armv5te")) m_arm_isa = ARMv5TE; - else if (0 == ::strcasecmp(arch_cstr, "armv5t")) m_arm_isa = ARMv5T; - else if (0 == ::strcasecmp(arch_cstr, "armv6k")) m_arm_isa = ARMv6K; - else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) m_arm_isa = ARMv6T2; - else if (0 == ::strcasecmp(arch_cstr, "armv7s")) m_arm_isa = ARMv7S; - else if (0 == ::strcasecmp(arch_cstr, "arm")) m_arm_isa = ARMvAll; - else if (0 == ::strcasecmp(arch_cstr, "thumb")) m_arm_isa = ARMvAll; - else if (0 == ::strncasecmp(arch_cstr,"armv4", 5)) m_arm_isa = ARMv4; - else if (0 == ::strncasecmp(arch_cstr,"armv6", 5)) m_arm_isa = ARMv6; - else if (0 == ::strncasecmp(arch_cstr,"armv7", 5)) m_arm_isa = ARMv7; - else if (0 == ::strncasecmp(arch_cstr,"armv8", 5)) m_arm_isa = ARMv8; - } - return m_arm_isa != 0; -} - -bool -EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target) -{ - if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target)) - { - if (m_arch.GetTriple().getArch() == llvm::Triple::thumb || m_arch.IsAlwaysThumbInstructions ()) - m_opcode_mode = eModeThumb; - else - { - AddressClass addr_class = inst_addr.GetAddressClass(); + break; - if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown)) - m_opcode_mode = eModeARM; - else if (addr_class == eAddressClassCodeAlternateISA) - m_opcode_mode = eModeThumb; - else - return false; - } - if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions ()) - m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T; - else - m_opcode_cpsr = CPSR_MODE_USR; - return true; + case eEncodingA2: + // n = UInt(Rn); m = UInt(Rm); register_form = TRUE; + n = Bits32(opcode, 19, 16); + m = Bits32(opcode, 3, 0); + register_form = true; + + // (shift_t, shift_n) = DecodeImmShift(type, imm5); + shift_n = DecodeImmShiftARM(opcode, shift_t); + + break; + + default: + return false; } - return false; -} -bool -EmulateInstructionARM::ReadInstruction () -{ - bool success = false; - m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success); - if (success) - { - addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); - if (success) - { - Context read_inst_context; - read_inst_context.type = eContextReadOpcode; - read_inst_context.SetNoArgs (); - - if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions ()) - { - m_opcode_mode = eModeThumb; - uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); - - if (success) - { - if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) - { - m_opcode.SetOpcode16 (thumb_opcode, GetByteOrder()); - } - else - { - m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success), GetByteOrder()); - } - } - } - else - { - m_opcode_mode = eModeARM; - m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success), GetByteOrder()); - } + // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) + // else imm32; + uint32_t operand2; + if (register_form) { + uint32_t Rm = ReadCoreReg(m, &success); + if (!success) + return false; - if (!m_ignore_conditions) - { - // If we are not ignoreing the conditions then init the it session from the current - // value of cpsr. - uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) | Bits32(m_opcode_cpsr, 26, 25); - if (it != 0) - m_it_session.InitIT(it); - } - } + operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success); + if (!success) + return false; + } else { + operand2 = imm32; } + + uint32_t Rn = ReadCoreReg(n, &success); if (!success) - { - m_opcode_mode = eModeInvalid; - m_addr = LLDB_INVALID_ADDRESS; + return false; + + AddWithCarryResult result; + + // case opcode of + switch (code) { + case 0: // when '0000' + // result = R[n] AND operand2; // AND + result.result = Rn & operand2; + break; + + case 1: // when '0001' + // result = R[n] EOR operand2; // EOR + result.result = Rn ^ operand2; + break; + + case 2: // when '0010' + // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB + result = AddWithCarry(Rn, ~(operand2), 1); + break; + + case 3: // when '0011' + // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB + result = AddWithCarry(~(Rn), operand2, 1); + break; + + case 4: // when '0100' + // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD + result = AddWithCarry(Rn, operand2, 0); + break; + + case 5: // when '0101' + // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC + result = AddWithCarry(Rn, operand2, APSR_C); + break; + + case 6: // when '0110' + // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC + result = AddWithCarry(Rn, ~(operand2), APSR_C); + break; + + case 7: // when '0111' + // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC + result = AddWithCarry(~(Rn), operand2, APSR_C); + break; + + case 10: // when '1100' + // result = R[n] OR operand2; // ORR + result.result = Rn | operand2; + break; + + case 11: // when '1101' + // result = operand2; // MOV + result.result = operand2; + break; + + case 12: // when '1110' + // result = R[n] AND NOT(operand2); // BIC + result.result = Rn & ~(operand2); + break; + + case 15: // when '1111' + // result = NOT(operand2); // MVN + result.result = ~(operand2); + break; + + default: + return false; } - return success; -} + // CPSRWriteByInstr(SPSR[], '1111', TRUE); -uint32_t -EmulateInstructionARM::ArchVersion () -{ - return m_arm_isa; -} + // For now, in emulation mode, we don't have access to the SPSR, so we will + // use the CPSR instead, and hope for + // the best. + uint32_t spsr = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success); + if (!success) + return false; -bool -EmulateInstructionARM::ConditionPassed (const uint32_t opcode) -{ - // If we are ignoring conditions, then always return true. - // this allows us to iterate over disassembly code and still - // emulate an instruction even if we don't have all the right - // bits set in the CPSR register... - if (m_ignore_conditions) - return true; + CPSRWriteByInstr(spsr, 15, true); - const uint32_t cond = CurrentCond (opcode); - if (cond == UINT32_MAX) + // BranchWritePC(result); + EmulateInstruction::Context context; + context.type = eContextAdjustPC; + context.SetImmediate(result.result); + + BranchWritePC(context, result.result); + } + return true; +} + +EmulateInstructionARM::ARMOpcode * +EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode, + uint32_t arm_isa) { + static ARMOpcode g_arm_opcodes[] = { + //---------------------------------------------------------------------- + // Prologue instructions + //---------------------------------------------------------------------- + + // push register(s) + {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulatePUSH, "push <registers>"}, + {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, + &EmulateInstructionARM::EmulatePUSH, "push <register>"}, + + // set r7 to point to a stack offset + {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"}, + {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"}, + // copy the stack pointer to ip + {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"}, + {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"}, + {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"}, + + // adjust the stack pointer + {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"}, + {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPReg, + "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"}, + + // push one register + // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH; + {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"}, + + // vector push consecutive extension register(s) + {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, + {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, + + //---------------------------------------------------------------------- + // Epilogue instructions + //---------------------------------------------------------------------- + + {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, + {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, + &EmulateInstructionARM::EmulatePOP, "pop <register>"}, + {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, + {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, + + //---------------------------------------------------------------------- + // Supervisor Call (previously Software Interrupt) + //---------------------------------------------------------------------- + {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSVC, "svc #imm24"}, + + //---------------------------------------------------------------------- + // Branch instructions + //---------------------------------------------------------------------- + // To resolve ambiguity, "blx <label>" should come before "b #imm24" and + // "bl <label>". + {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, + {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateB, "b #imm24"}, + {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, + {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, + // for example, "bx lr" + {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, + // bxj + {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, + + //---------------------------------------------------------------------- + // Data-processing instructions + //---------------------------------------------------------------------- + // adc (immediate) + {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"}, + // adc (register) + {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADCReg, + "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, + // add (immediate) + {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADDImmARM, + "add{s}<c> <Rd>, <Rn>, #const"}, + // add (register) + {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADDReg, + "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, + // add (register-shifted register) + {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADDRegShift, + "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"}, + // adr + {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, + {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, + // and (immediate) + {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"}, + // and (register) + {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateANDReg, + "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, + // bic (immediate) + {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"}, + // bic (register) + {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBICReg, + "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, + // eor (immediate) + {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"}, + // eor (register) + {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateEORReg, + "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, + // orr (immediate) + {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"}, + // orr (register) + {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateORRReg, + "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, + // rsb (immediate) + {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"}, + // rsb (register) + {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRSBReg, + "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, + // rsc (immediate) + {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"}, + // rsc (register) + {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRSCReg, + "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, + // sbc (immediate) + {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, + // sbc (register) + {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSBCReg, + "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, + // sub (immediate, ARM) + {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBImmARM, + "sub{s}<c> <Rd>, <Rn>, #<const>"}, + // sub (sp minus immediate) + {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"}, + // sub (register) + {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBReg, + "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"}, + // teq (immediate) + {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"}, + // teq (register) + {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, + // tst (immediate) + {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"}, + // tst (register) + {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"}, + + // mov (immediate) + {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"}, + {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"}, + // mov (register) + {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"}, + // mvn (immediate) + {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"}, + // mvn (register) + {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMVNReg, + "mvn{s}<c> <Rd>, <Rm> {,<shift>}"}, + // cmn (immediate) + {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, + // cmn (register) + {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, + // cmp (immediate) + {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"}, + // cmp (register) + {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"}, + // asr (immediate) + {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"}, + // asr (register) + {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"}, + // lsl (immediate) + {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"}, + // lsl (register) + {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"}, + // lsr (immediate) + {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"}, + // lsr (register) + {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"}, + // rrx is a special case encoding of ror (immediate) + {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"}, + // ror (immediate) + {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"}, + // ror (register) + {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"}, + // mul + {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"}, + + // subs pc, lr and related instructions + {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPcLrEtc, + "<opc>S<c> PC,#<const> | <Rn>,#<const>"}, + {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPcLrEtc, + "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"}, + + //---------------------------------------------------------------------- + // Load instructions + //---------------------------------------------------------------------- + {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"}, + {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"}, + {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"}, + {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"}, + {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRImmediateARM, + "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"}, + {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRRegister, + "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"}, + {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"}, + {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRBRegister, + "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"}, + {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"}, + {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRHRegister, + "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"}, + {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSBImmediate, + "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"}, + {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"}, + {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSBRegister, + "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"}, + {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSHImmediate, + "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"}, + {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"}, + {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSHRegister, + "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"}, + {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRDImmediate, + "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"}, + {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRDRegister, + "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, + {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, + &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, + {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, + &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, + {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, + &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, + {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, + &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, + {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, + &EmulateInstructionARM::EmulateVLD1Multiple, + "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, + {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, + &EmulateInstructionARM::EmulateVLD1Single, + "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, + {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, + &EmulateInstructionARM::EmulateVLD1SingleAll, + "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, + + //---------------------------------------------------------------------- + // Store instructions + //---------------------------------------------------------------------- + {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"}, + {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"}, + {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"}, + {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"}, + {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRRegister, + "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"}, + {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRHRegister, + "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"}, + {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"}, + {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRBImmARM, + "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, + {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRImmARM, + "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, + {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRDImm, + "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"}, + {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRDReg, + "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, + {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, + &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, + {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, + &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, + {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, + &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"}, + {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, + &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"}, + {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, + &EmulateInstructionARM::EmulateVST1Multiple, + "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, + {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, + &EmulateInstructionARM::EmulateVST1Single, + "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, + + //---------------------------------------------------------------------- + // Other instructions + //---------------------------------------------------------------------- + {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"}, + {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"}, + {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"}, + {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"}, + {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"} + + }; + static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_arm_opcodes); + + for (size_t i = 0; i < k_num_arm_opcodes; ++i) { + if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value && + (g_arm_opcodes[i].variants & arm_isa) != 0) + return &g_arm_opcodes[i]; + } + return NULL; +} + +EmulateInstructionARM::ARMOpcode * +EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode, + uint32_t arm_isa) { + + static ARMOpcode g_thumb_opcodes[] = { + //---------------------------------------------------------------------- + // Prologue instructions + //---------------------------------------------------------------------- + + // push register(s) + {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulatePUSH, "push <registers>"}, + {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"}, + {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulatePUSH, "push.w <register>"}, + + // set r7 to point to a stack offset + {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"}, + // copy the stack pointer to r7 + {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"}, + // move from high register to low register (comes after "mov r7, sp" to + // resolve ambiguity) + {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"}, + + // PC-relative load into register (see also EmulateADDSPRm) + {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"}, + + // adjust the stack pointer + {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, + &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"}, + {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"}, + {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"}, + {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"}, + {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPReg, + "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"}, + + // vector push consecutive extension register(s) + {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, + {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, + + //---------------------------------------------------------------------- + // Epilogue instructions + //---------------------------------------------------------------------- + + {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"}, + {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, + &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"}, + {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, + {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"}, + {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulatePOP, "pop.w <register>"}, + {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, + {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, + + //---------------------------------------------------------------------- + // Supervisor Call (previously Software Interrupt) + //---------------------------------------------------------------------- + {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSVC, "svc #imm8"}, + + //---------------------------------------------------------------------- + // If Then makes up to four following instructions conditional. + //---------------------------------------------------------------------- + // The next 5 opcode _must_ come before the if then instruction + {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateNop, "nop"}, + {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"}, + {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"}, + {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"}, + {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"}, + {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, + + //---------------------------------------------------------------------- + // Branch instructions + //---------------------------------------------------------------------- + // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8". + {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"}, + {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, + &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"}, + {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"}, + {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, + &EmulateInstructionARM::EmulateB, + "b<c>.w #imm8 (outside or last in IT)"}, + // J1 == J2 == 1 + {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, + // J1 == J2 == 1 + {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, + {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, + // for example, "bx lr" + {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, + // bxj + {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, + // compare and branch + {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"}, + // table branch byte + {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"}, + // table branch halfword + {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"}, + + //---------------------------------------------------------------------- + // Data-processing instructions + //---------------------------------------------------------------------- + // adc (immediate) + {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"}, + // adc (register) + {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"}, + {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADCReg, + "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, + // add (register) + {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"}, + // Make sure "add sp, <Rm>" comes before this instruction, so there's no + // ambiguity decoding the two. + {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, + &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"}, + // adr + {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, + {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, + {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, + // and (immediate) + {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"}, + // and (register) + {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"}, + {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateANDReg, + "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, + // bic (immediate) + {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"}, + // bic (register) + {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"}, + {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateBICReg, + "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, + // eor (immediate) + {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"}, + // eor (register) + {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"}, + {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateEORReg, + "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, + // orr (immediate) + {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"}, + // orr (register) + {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"}, + {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateORRReg, + "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, + // rsb (immediate) + {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"}, + {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRSBImm, + "rsb{s}<c>.w <Rd>, <Rn>, #<const>"}, + // rsb (register) + {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRSBReg, + "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, + // sbc (immediate) + {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, + // sbc (register) + {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"}, + {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSBCReg, + "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, + // add (immediate, Thumb) + {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateADDImmThumb, + "adds|add<c> <Rd>,<Rn>,#<imm3>"}, + {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, + &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"}, + {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADDImmThumb, + "add{s}<c>.w <Rd>,<Rn>,#<const>"}, + {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, + &EmulateInstructionARM::EmulateADDImmThumb, + "addw<c> <Rd>,<Rn>,#<imm12>"}, + // sub (immediate, Thumb) + {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSUBImmThumb, + "subs|sub<c> <Rd>, <Rn> #imm3"}, + {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"}, + {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBImmThumb, + "sub{s}<c>.w <Rd>, <Rn>, #<const>"}, + {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBImmThumb, + "subw<c> <Rd>, <Rn>, #imm12"}, + // sub (sp minus immediate) + {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"}, + {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"}, + // sub (register) + {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"}, + {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBReg, + "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"}, + // teq (immediate) + {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"}, + // teq (register) + {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, + // tst (immediate) + {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"}, + // tst (register) + {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"}, + {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"}, + + // move from high register to high register + {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"}, + // move from low register to low register + {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, + &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"}, + // mov{s}<c>.w <Rd>, <Rm> + {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"}, + // move immediate + {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"}, + {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"}, + {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"}, + // mvn (immediate) + {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"}, + // mvn (register) + {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"}, + {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMVNReg, + "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"}, + // cmn (immediate) + {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, + // cmn (register) + {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"}, + {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, + // cmp (immediate) + {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"}, + {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"}, + // cmp (register) (Rn and Rm both from r0-r7) + {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, + // cmp (register) (Rn and Rm not both from r0-r7) + {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, + &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, + {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16, + &EmulateInstructionARM::EmulateCMPReg, + "cmp<c>.w <Rn>, <Rm> {, <shift>}"}, + // asr (immediate) + {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"}, + {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"}, + // asr (register) + {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"}, + {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"}, + // lsl (immediate) + {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"}, + {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"}, + // lsl (register) + {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"}, + {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"}, + // lsr (immediate) + {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"}, + {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"}, + // lsr (register) + {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"}, + {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"}, + // rrx is a special case encoding of ror (immediate) + {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"}, + // ror (immediate) + {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"}, + // ror (register) + {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"}, + {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"}, + // mul + {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"}, + // mul + {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"}, + + // subs pc, lr and related instructions + {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"}, + + //---------------------------------------------------------------------- + // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE + // LDM.. Instructions in this table; + // otherwise the wrong instructions will be selected. + //---------------------------------------------------------------------- + + {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"}, + {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"}, + + //---------------------------------------------------------------------- + // Load instructions + //---------------------------------------------------------------------- + {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"}, + {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"}, + {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"}, + {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}, + {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"}, + {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRRtRnImm, + "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"}, + {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRRtRnImm, + "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"}, + // Thumb2 PC-relative load into register + {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRRtPCRelative, + "ldr<c>.w <Rt>, [PC, +/-#imm}]"}, + {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"}, + {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRRegister, + "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"}, + {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDRBImmediate, + "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"}, + {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRBImmediate, + "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"}, + {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRBImmediate, + "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"}, + {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"}, + {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"}, + {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRBRegister, + "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"}, + {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDRHImmediate, + "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"}, + {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRHImmediate, + "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"}, + {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRHImmediate, + "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"}, + {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"}, + {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDRHRegister, + "ldrh<c> <Rt>, [<Rn>,<Rm>]"}, + {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRHRegister, + "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"}, + {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSBImmediate, + "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"}, + {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSBImmediate, + "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"}, + {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"}, + {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDRSBRegister, + "ldrsb<c> <Rt>,[<Rn>,<Rm>]"}, + {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSBRegister, + "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"}, + {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSHImmediate, + "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"}, + {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSHImmediate, + "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"}, + {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"}, + {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateLDRSHRegister, + "ldrsh<c> <Rt>,[<Rn>,<Rm>]"}, + {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRSHRegister, + "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"}, + {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateLDRDImmediate, + "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"}, + {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, + &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, + {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, + &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, + {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, + &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, + {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, + &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"}, + {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, + &EmulateInstructionARM::EmulateVLD1Multiple, + "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, + {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, + &EmulateInstructionARM::EmulateVLD1Single, + "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, + {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, + &EmulateInstructionARM::EmulateVLD1SingleAll, + "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, + + //---------------------------------------------------------------------- + // Store instructions + //---------------------------------------------------------------------- + {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"}, + {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"}, + {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"}, + {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"}, + {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"}, + {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRThumb, + "str<c>.w <Rt>, [<Rn>,#<imm12>]"}, + {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRThumb, + "str<c> <Rt>, [<Rn>,#+/-<imm8>]"}, + {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"}, + {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRRegister, + "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"}, + {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSTRBThumb, + "strb<c> <Rt>, [<Rn>, #<imm5>]"}, + {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRBThumb, + "strb<c>.w <Rt>, [<Rn>, #<imm12>]"}, + {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRBThumb, + "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"}, + {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"}, + {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRHRegister, + "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"}, + {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTREX, + "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"}, + {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSTRDImm, + "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"}, + {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, + &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, + {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, + &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, + {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, + &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, + {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, + &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, + {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, + &EmulateInstructionARM::EmulateVST1Multiple, + "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, + {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, + &EmulateInstructionARM::EmulateVST1Single, + "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, + + //---------------------------------------------------------------------- + // Other instructions + //---------------------------------------------------------------------- + {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"}, + {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"}, + {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"}, + {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"}, + {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"}, + {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"}, + {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, + &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"}, + {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, + &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"}, + }; + + const size_t k_num_thumb_opcodes = llvm::array_lengthof(g_thumb_opcodes); + for (size_t i = 0; i < k_num_thumb_opcodes; ++i) { + if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value && + (g_thumb_opcodes[i].variants & arm_isa) != 0) + return &g_thumb_opcodes[i]; + } + return NULL; +} + +bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) { + m_arch = arch; + m_arm_isa = 0; + const char *arch_cstr = arch.GetArchitectureName(); + if (arch_cstr) { + if (0 == ::strcasecmp(arch_cstr, "armv4t")) + m_arm_isa = ARMv4T; + else if (0 == ::strcasecmp(arch_cstr, "armv5tej")) + m_arm_isa = ARMv5TEJ; + else if (0 == ::strcasecmp(arch_cstr, "armv5te")) + m_arm_isa = ARMv5TE; + else if (0 == ::strcasecmp(arch_cstr, "armv5t")) + m_arm_isa = ARMv5T; + else if (0 == ::strcasecmp(arch_cstr, "armv6k")) + m_arm_isa = ARMv6K; + else if (0 == ::strcasecmp(arch_cstr, "armv6t2")) + m_arm_isa = ARMv6T2; + else if (0 == ::strcasecmp(arch_cstr, "armv7s")) + m_arm_isa = ARMv7S; + else if (0 == ::strcasecmp(arch_cstr, "arm")) + m_arm_isa = ARMvAll; + else if (0 == ::strcasecmp(arch_cstr, "thumb")) + m_arm_isa = ARMvAll; + else if (0 == ::strncasecmp(arch_cstr, "armv4", 5)) + m_arm_isa = ARMv4; + else if (0 == ::strncasecmp(arch_cstr, "armv6", 5)) + m_arm_isa = ARMv6; + else if (0 == ::strncasecmp(arch_cstr, "armv7", 5)) + m_arm_isa = ARMv7; + else if (0 == ::strncasecmp(arch_cstr, "armv8", 5)) + m_arm_isa = ARMv8; + } + return m_arm_isa != 0; +} + +bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode, + const Address &inst_addr, + Target *target) { + if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) { + if (m_arch.GetTriple().getArch() == llvm::Triple::thumb || + m_arch.IsAlwaysThumbInstructions()) + m_opcode_mode = eModeThumb; + else { + AddressClass addr_class = inst_addr.GetAddressClass(); + + if ((addr_class == eAddressClassCode) || + (addr_class == eAddressClassUnknown)) + m_opcode_mode = eModeARM; + else if (addr_class == eAddressClassCodeAlternateISA) + m_opcode_mode = eModeThumb; + else return false; - - bool result = false; - switch (UnsignedBits(cond, 3, 1)) - { - case 0: - if (m_opcode_cpsr == 0) - result = true; - else - result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; - break; - case 1: - if (m_opcode_cpsr == 0) - result = true; - else - result = (m_opcode_cpsr & MASK_CPSR_C) != 0; - break; - case 2: - if (m_opcode_cpsr == 0) - result = true; - else - result = (m_opcode_cpsr & MASK_CPSR_N) != 0; - break; - case 3: - if (m_opcode_cpsr == 0) - result = true; - else - result = (m_opcode_cpsr & MASK_CPSR_V) != 0; - break; - case 4: - if (m_opcode_cpsr == 0) - result = true; - else - result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); - break; - case 5: - if (m_opcode_cpsr == 0) - result = true; - else - { - bool n = (m_opcode_cpsr & MASK_CPSR_N); - bool v = (m_opcode_cpsr & MASK_CPSR_V); - result = n == v; - } - break; - case 6: - if (m_opcode_cpsr == 0) - result = true; - else - { - bool n = (m_opcode_cpsr & MASK_CPSR_N); - bool v = (m_opcode_cpsr & MASK_CPSR_V); - result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); - } - break; - case 7: - // Always execute (cond == 0b1110, or the special 0b1111 which gives - // opcodes different meanings, but always means execution happens. - return true; } + if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions()) + m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T; + else + m_opcode_cpsr = CPSR_MODE_USR; + return true; + } + return false; +} + +bool EmulateInstructionARM::ReadInstruction() { + bool success = false; + m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FLAGS, 0, &success); + if (success) { + addr_t pc = + ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_ADDRESS, &success); + if (success) { + Context read_inst_context; + read_inst_context.type = eContextReadOpcode; + read_inst_context.SetNoArgs(); + + if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) { + m_opcode_mode = eModeThumb; + uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); + + if (success) { + if ((thumb_opcode & 0xe000) != 0xe000 || + ((thumb_opcode & 0x1800u) == 0)) { + m_opcode.SetOpcode16(thumb_opcode, GetByteOrder()); + } else { + m_opcode.SetOpcode32( + (thumb_opcode << 16) | + MemARead(read_inst_context, pc + 2, 2, 0, &success), + GetByteOrder()); + } + } + } else { + m_opcode_mode = eModeARM; + m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success), + GetByteOrder()); + } + + if (!m_ignore_conditions) { + // If we are not ignoreing the conditions then init the it session from + // the current + // value of cpsr. + uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) | + Bits32(m_opcode_cpsr, 26, 25); + if (it != 0) + m_it_session.InitIT(it); + } + } + } + if (!success) { + m_opcode_mode = eModeInvalid; + m_addr = LLDB_INVALID_ADDRESS; + } + return success; +} + +uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; } + +bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) { + // If we are ignoring conditions, then always return true. + // this allows us to iterate over disassembly code and still + // emulate an instruction even if we don't have all the right + // bits set in the CPSR register... + if (m_ignore_conditions) + return true; + + const uint32_t cond = CurrentCond(opcode); + if (cond == UINT32_MAX) + return false; - if (cond & 1) - result = !result; - return result; + bool result = false; + switch (UnsignedBits(cond, 3, 1)) { + case 0: + if (m_opcode_cpsr == 0) + result = true; + else + result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; + break; + case 1: + if (m_opcode_cpsr == 0) + result = true; + else + result = (m_opcode_cpsr & MASK_CPSR_C) != 0; + break; + case 2: + if (m_opcode_cpsr == 0) + result = true; + else + result = (m_opcode_cpsr & MASK_CPSR_N) != 0; + break; + case 3: + if (m_opcode_cpsr == 0) + result = true; + else + result = (m_opcode_cpsr & MASK_CPSR_V) != 0; + break; + case 4: + if (m_opcode_cpsr == 0) + result = true; + else + result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && + ((m_opcode_cpsr & MASK_CPSR_Z) == 0); + break; + case 5: + if (m_opcode_cpsr == 0) + result = true; + else { + bool n = (m_opcode_cpsr & MASK_CPSR_N); + bool v = (m_opcode_cpsr & MASK_CPSR_V); + result = n == v; + } + break; + case 6: + if (m_opcode_cpsr == 0) + result = true; + else { + bool n = (m_opcode_cpsr & MASK_CPSR_N); + bool v = (m_opcode_cpsr & MASK_CPSR_V); + result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); + } + break; + case 7: + // Always execute (cond == 0b1110, or the special 0b1111 which gives + // opcodes different meanings, but always means execution happens. + return true; + } + + if (cond & 1) + result = !result; + return result; } -uint32_t -EmulateInstructionARM::CurrentCond (const uint32_t opcode) -{ - switch (m_opcode_mode) +uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) { + switch (m_opcode_mode) { + case eModeInvalid: + break; + + case eModeARM: + return UnsignedBits(opcode, 31, 28); + + case eModeThumb: + // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit + // 'cond' field of the encoding. { - case eModeInvalid: + const uint32_t byte_size = m_opcode.GetByteSize(); + if (byte_size == 2) { + if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f) + return Bits32(opcode, 11, 8); + } else if (byte_size == 4) { + if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 && + Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) { + return Bits32(opcode, 25, 22); + } + } else + // We have an invalid thumb instruction, let's bail out. break; - case eModeARM: - return UnsignedBits(opcode, 31, 28); - - case eModeThumb: - // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit - // 'cond' field of the encoding. - { - const uint32_t byte_size = m_opcode.GetByteSize(); - if (byte_size == 2) - { - if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f) - return Bits32(opcode, 11, 8); - } - else if (byte_size == 4) - { - if (Bits32(opcode, 31, 27) == 0x1e && - Bits32(opcode, 15, 14) == 0x02 && - Bits32(opcode, 12, 12) == 0x00 && - Bits32(opcode, 25, 22) <= 0x0d) - { - return Bits32(opcode, 25, 22); - } - } - else - // We have an invalid thumb instruction, let's bail out. - break; - - return m_it_session.GetCond(); - } + return m_it_session.GetCond(); } - return UINT32_MAX; // Return invalid value + } + return UINT32_MAX; // Return invalid value } -bool -EmulateInstructionARM::InITBlock() -{ - return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock(); +bool EmulateInstructionARM::InITBlock() { + return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock(); } -bool -EmulateInstructionARM::LastInITBlock() -{ - return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock(); +bool EmulateInstructionARM::LastInITBlock() { + return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock(); } -bool -EmulateInstructionARM::BadMode (uint32_t mode) -{ - - switch (mode) - { - case 16: return false; // '10000' - case 17: return false; // '10001' - case 18: return false; // '10010' - case 19: return false; // '10011' - case 22: return false; // '10110' - case 23: return false; // '10111' - case 27: return false; // '11011' - case 31: return false; // '11111' - default: return true; - } - return true; -} - -bool -EmulateInstructionARM::CurrentModeIsPrivileged () -{ - uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0); - - if (BadMode (mode)) - return false; - - if (mode == 16) - return false; - +bool EmulateInstructionARM::BadMode(uint32_t mode) { + + switch (mode) { + case 16: + return false; // '10000' + case 17: + return false; // '10001' + case 18: + return false; // '10010' + case 19: + return false; // '10011' + case 22: + return false; // '10110' + case 23: + return false; // '10111' + case 27: + return false; // '11011' + case 31: + return false; // '11111' + default: return true; + } + return true; } -void -EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate) -{ - bool privileged = CurrentModeIsPrivileged(); +bool EmulateInstructionARM::CurrentModeIsPrivileged() { + uint32_t mode = Bits32(m_opcode_cpsr, 4, 0); - uint32_t tmp_cpsr = Bits32 (m_opcode_cpsr, 23, 20) << 20; - - if (BitIsSet (bytemask, 3)) - { - tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27); - if (affect_execstate) - tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24); - } - - if (BitIsSet (bytemask, 2)) - { - tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16); - } - - if (BitIsSet (bytemask, 1)) - { - if (affect_execstate) - tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10); - tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9); - if (privileged) - tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8); - } - - if (BitIsSet (bytemask, 0)) - { - if (privileged) - tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6); - if (affect_execstate) - tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5); - if (privileged) - tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0); - } - - m_opcode_cpsr = tmp_cpsr; + if (BadMode(mode)) + return false; + + if (mode == 16) + return false; + + return true; } - -bool -EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr) -{ - addr_t target; +void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask, + bool affect_execstate) { + bool privileged = CurrentModeIsPrivileged(); - // Check the current instruction set. - if (CurrentInstrSet() == eModeARM) - target = addr & 0xfffffffc; - else - target = addr & 0xfffffffe; + uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20; - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) - return false; + if (BitIsSet(bytemask, 3)) { + tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27); + if (affect_execstate) + tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24); + } - return true; + if (BitIsSet(bytemask, 2)) { + tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16); + } + + if (BitIsSet(bytemask, 1)) { + if (affect_execstate) + tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10); + tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9); + if (privileged) + tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8); + } + + if (BitIsSet(bytemask, 0)) { + if (privileged) + tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6); + if (affect_execstate) + tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5); + if (privileged) + tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0); + } + + m_opcode_cpsr = tmp_cpsr; } -// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr. -bool -EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr) -{ - addr_t target; - // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE, - // we want to record it and issue a WriteRegister callback so the clients - // can track the mode changes accordingly. - bool cpsr_changed = false; +bool EmulateInstructionARM::BranchWritePC(const Context &context, + uint32_t addr) { + addr_t target; - if (BitIsSet(addr, 0)) - { - if (CurrentInstrSet() != eModeThumb) - { - SelectInstrSet(eModeThumb); - cpsr_changed = true; - } - target = addr & 0xfffffffe; - context.SetISA (eModeThumb); - } - else if (BitIsClear(addr, 1)) - { - if (CurrentInstrSet() != eModeARM) - { - SelectInstrSet(eModeARM); - cpsr_changed = true; - } - target = addr & 0xfffffffc; - context.SetISA (eModeARM); - } - else - return false; // address<1:0> == '10' => UNPREDICTABLE + // Check the current instruction set. + if (CurrentInstrSet() == eModeARM) + target = addr & 0xfffffffc; + else + target = addr & 0xfffffffe; - if (cpsr_changed) - { - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) - return false; - } - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC, target)) + return false; - return true; + return true; +} + +// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by +// inspecting addr. +bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) { + addr_t target; + // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE, + // we want to record it and issue a WriteRegister callback so the clients + // can track the mode changes accordingly. + bool cpsr_changed = false; + + if (BitIsSet(addr, 0)) { + if (CurrentInstrSet() != eModeThumb) { + SelectInstrSet(eModeThumb); + cpsr_changed = true; + } + target = addr & 0xfffffffe; + context.SetISA(eModeThumb); + } else if (BitIsClear(addr, 1)) { + if (CurrentInstrSet() != eModeARM) { + SelectInstrSet(eModeARM); + cpsr_changed = true; + } + target = addr & 0xfffffffc; + context.SetISA(eModeARM); + } else + return false; // address<1:0> == '10' => UNPREDICTABLE + + if (cpsr_changed) { + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) + return false; + } + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC, target)) + return false; + + return true; } -// Dispatches to either BXWritePC or BranchWritePC based on architecture versions. -bool -EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr) -{ - if (ArchVersion() >= ARMv5T) - return BXWritePC(context, addr); - else - return BranchWritePC((const Context)context, addr); +// Dispatches to either BXWritePC or BranchWritePC based on architecture +// versions. +bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) { + if (ArchVersion() >= ARMv5T) + return BXWritePC(context, addr); + else + return BranchWritePC((const Context)context, addr); } -// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set. -bool -EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr) -{ - if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM) - return BXWritePC(context, addr); - else - return BranchWritePC((const Context)context, addr); +// Dispatches to either BXWritePC or BranchWritePC based on architecture +// versions and current instruction set. +bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) { + if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM) + return BXWritePC(context, addr); + else + return BranchWritePC((const Context)context, addr); } -EmulateInstructionARM::Mode -EmulateInstructionARM::CurrentInstrSet () -{ - return m_opcode_mode; +EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() { + return m_opcode_mode; } // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next // ReadInstruction() is performed. This function has a side effect of updating // the m_new_inst_cpsr member variable if necessary. -bool -EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb) -{ - m_new_inst_cpsr = m_opcode_cpsr; - switch (arm_or_thumb) - { - default: - return false; - case eModeARM: - // Clear the T bit. - m_new_inst_cpsr &= ~MASK_CPSR_T; - break; - case eModeThumb: - // Set the T bit. - m_new_inst_cpsr |= MASK_CPSR_T; - break; - } - return true; +bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) { + m_new_inst_cpsr = m_opcode_cpsr; + switch (arm_or_thumb) { + default: + return false; + case eModeARM: + // Clear the T bit. + m_new_inst_cpsr &= ~MASK_CPSR_T; + break; + case eModeThumb: + // Set the T bit. + m_new_inst_cpsr |= MASK_CPSR_T; + break; + } + return true; } // This function returns TRUE if the processor currently provides support for // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7, // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6. -bool -EmulateInstructionARM::UnalignedSupport() -{ - return (ArchVersion() >= ARMv7); +bool EmulateInstructionARM::UnalignedSupport() { + return (ArchVersion() >= ARMv7); } // The main addition and subtraction instructions can produce status information // about both unsigned carry and signed overflow conditions. This status // information can be used to synthesize multi-word additions and subtractions. EmulateInstructionARM::AddWithCarryResult -EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in) -{ - uint32_t result; - uint8_t carry_out; - uint8_t overflow; - - uint64_t unsigned_sum = x + y + carry_in; - int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; - - result = UnsignedBits(unsigned_sum, 31, 0); -// carry_out = (result == unsigned_sum ? 0 : 1); - overflow = ((int32_t)result == signed_sum ? 0 : 1); - - if (carry_in) - carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0; +EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) { + uint32_t result; + uint8_t carry_out; + uint8_t overflow; + + uint64_t unsigned_sum = x + y + carry_in; + int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; + + result = UnsignedBits(unsigned_sum, 31, 0); + // carry_out = (result == unsigned_sum ? 0 : 1); + overflow = ((int32_t)result == signed_sum ? 0 : 1); + + if (carry_in) + carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0; + else + carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0; + + AddWithCarryResult res = {result, carry_out, overflow}; + return res; +} + +uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) { + lldb::RegisterKind reg_kind; + uint32_t reg_num; + switch (num) { + case SP_REG: + reg_kind = eRegisterKindGeneric; + reg_num = LLDB_REGNUM_GENERIC_SP; + break; + case LR_REG: + reg_kind = eRegisterKindGeneric; + reg_num = LLDB_REGNUM_GENERIC_RA; + break; + case PC_REG: + reg_kind = eRegisterKindGeneric; + reg_num = LLDB_REGNUM_GENERIC_PC; + break; + default: + if (num < SP_REG) { + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_r0 + num; + } else { + // assert(0 && "Invalid register number"); + *success = false; + return UINT32_MAX; + } + break; + } + + // Read our register. + uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success); + + // When executing an ARM instruction , PC reads as the address of the current + // instruction plus 8. + // When executing a Thumb instruction , PC reads as the address of the current + // instruction plus 4. + if (num == 15) { + if (CurrentInstrSet() == eModeARM) + val += 8; else - carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0; - - AddWithCarryResult res = { result, carry_out, overflow }; - return res; -} + val += 4; + } -uint32_t -EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) -{ - lldb::RegisterKind reg_kind; - uint32_t reg_num; - switch (num) - { - case SP_REG: - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_SP; - break; - case LR_REG: - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_RA; - break; - case PC_REG: - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_PC; - break; - default: - if (num < SP_REG) - { - reg_kind = eRegisterKindDWARF; - reg_num = dwarf_r0 + num; - } - else - { - //assert(0 && "Invalid register number"); - *success = false; - return UINT32_MAX; - } - break; - } - - // Read our register. - uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success); - - // When executing an ARM instruction , PC reads as the address of the current - // instruction plus 8. - // When executing a Thumb instruction , PC reads as the address of the current - // instruction plus 4. - if (num == 15) - { - if (CurrentInstrSet() == eModeARM) - val += 8; - else - val += 4; - } - - return val; + return val; } // Write the result to the ARM core register Rd, and optionally update the @@ -13508,43 +13838,34 @@ EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) // // In the above case, the API client does not pass in the overflow arg, which // defaults to ~0u. -bool -EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context, - const uint32_t result, - const uint32_t Rd, - bool setflags, - const uint32_t carry, - const uint32_t overflow) -{ - if (Rd == 15) - { - if (!ALUWritePC (context, result)) - return false; - } - else - { - lldb::RegisterKind reg_kind; - uint32_t reg_num; - switch (Rd) - { - case SP_REG: - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_SP; - break; - case LR_REG: - reg_kind = eRegisterKindGeneric; - reg_num = LLDB_REGNUM_GENERIC_RA; - break; - default: - reg_kind = eRegisterKindDWARF; - reg_num = dwarf_r0 + Rd; - } - if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result)) - return false; - if (setflags) - return WriteFlags (context, result, carry, overflow); +bool EmulateInstructionARM::WriteCoreRegOptionalFlags( + Context &context, const uint32_t result, const uint32_t Rd, bool setflags, + const uint32_t carry, const uint32_t overflow) { + if (Rd == 15) { + if (!ALUWritePC(context, result)) + return false; + } else { + lldb::RegisterKind reg_kind; + uint32_t reg_num; + switch (Rd) { + case SP_REG: + reg_kind = eRegisterKindGeneric; + reg_num = LLDB_REGNUM_GENERIC_SP; + break; + case LR_REG: + reg_kind = eRegisterKindGeneric; + reg_num = LLDB_REGNUM_GENERIC_RA; + break; + default: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_r0 + Rd; } - return true; + if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result)) + return false; + if (setflags) + return WriteFlags(context, result, carry, overflow); + } + return true; } // This helper method tries to encapsulate the following pseudocode from the @@ -13555,203 +13876,192 @@ EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context, // APSR.C = carry; // APSR.V = overflow // -// Default arguments can be specified for carry and overflow parameters, which means +// Default arguments can be specified for carry and overflow parameters, which +// means // not to update the respective flags. -bool -EmulateInstructionARM::WriteFlags (Context &context, - const uint32_t result, - const uint32_t carry, - const uint32_t overflow) -{ - m_new_inst_cpsr = m_opcode_cpsr; - SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS)); - SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); - if (carry != ~0u) - SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry); - if (overflow != ~0u) - SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow); - if (m_new_inst_cpsr != m_opcode_cpsr) - { - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) - return false; - } - return true; -} +bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result, + const uint32_t carry, + const uint32_t overflow) { + m_new_inst_cpsr = m_opcode_cpsr; + SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS)); + SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); + if (carry != ~0u) + SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry); + if (overflow != ~0u) + SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow); + if (m_new_inst_cpsr != m_opcode_cpsr) { + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) + return false; + } + return true; +} + +bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) { + ARMOpcode *opcode_data = NULL; + + if (m_opcode_mode == eModeThumb) + opcode_data = + GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa); + else if (m_opcode_mode == eModeARM) + opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa); + + const bool auto_advance_pc = + evaluate_options & eEmulateInstructionOptionAutoAdvancePC; + m_ignore_conditions = + evaluate_options & eEmulateInstructionOptionIgnoreConditions; + + bool success = false; + if (m_opcode_cpsr == 0 || m_ignore_conditions == false) { + m_opcode_cpsr = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success); + } + + // Only return false if we are unable to read the CPSR if we care about + // conditions + if (success == false && m_ignore_conditions == false) + return false; -bool -EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options) -{ - ARMOpcode *opcode_data = NULL; - - if (m_opcode_mode == eModeThumb) - opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa); - else if (m_opcode_mode == eModeARM) - opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa); + uint32_t orig_pc_value = 0; + if (auto_advance_pc) { + orig_pc_value = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success); + if (!success) + return false; + } - const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; - m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions; - - bool success = false; - if (m_opcode_cpsr == 0 || m_ignore_conditions == false) - { - m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF, - dwarf_cpsr, - 0, - &success); - } + // Call the Emulate... function if we managed to decode the opcode. + if (opcode_data) { + success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(), + opcode_data->encoding); + if (!success) + return false; + } + + // Advance the ITSTATE bits to their values for the next instruction if we + // haven't just executed + // an IT instruction what initialized it. + if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() && + (opcode_data == nullptr || + opcode_data->callback != &EmulateInstructionARM::EmulateIT)) + m_it_session.ITAdvance(); + + if (auto_advance_pc) { + uint32_t after_pc_value = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success); + if (!success) + return false; - // Only return false if we are unable to read the CPSR if we care about conditions - if (success == false && m_ignore_conditions == false) + if (auto_advance_pc && (after_pc_value == orig_pc_value)) { + after_pc_value += m_opcode.GetByteSize(); + + EmulateInstruction::Context context; + context.type = eContextAdvancePC; + context.SetNoArgs(); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc, + after_pc_value)) return false; - - uint32_t orig_pc_value = 0; - if (auto_advance_pc) - { - orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); - if (!success) - return false; } + } + return true; +} - // Call the Emulate... function if we managed to decode the opcode. - if (opcode_data) - { - success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding); - if (!success) - return false; - } +EmulateInstruction::InstructionCondition +EmulateInstructionARM::GetInstructionCondition() { + const uint32_t cond = CurrentCond(m_opcode.GetOpcode32()); + if (cond == 0xe || cond == 0xf || cond == UINT32_MAX) + return EmulateInstruction::UnconditionalCondition; + return cond; +} - // Advance the ITSTATE bits to their values for the next instruction if we haven't just executed - // an IT instruction what initialized it. - if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() && - (opcode_data == nullptr || opcode_data->callback != &EmulateInstructionARM::EmulateIT)) - m_it_session.ITAdvance(); +bool EmulateInstructionARM::TestEmulation(Stream *out_stream, ArchSpec &arch, + OptionValueDictionary *test_data) { + if (!test_data) { + out_stream->Printf("TestEmulation: Missing test data.\n"); + return false; + } - if (auto_advance_pc) - { - uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success); - if (!success) - return false; + static ConstString opcode_key("opcode"); + static ConstString before_key("before_state"); + static ConstString after_key("after_state"); - if (auto_advance_pc && (after_pc_value == orig_pc_value)) - { - after_pc_value += m_opcode.GetByteSize(); + OptionValueSP value_sp = test_data->GetValueForKey(opcode_key); - EmulateInstruction::Context context; - context.type = eContextAdvancePC; - context.SetNoArgs(); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value)) - return false; - } - } - return true; -} + uint32_t test_opcode; + if ((value_sp.get() == NULL) || + (value_sp->GetType() != OptionValue::eTypeUInt64)) { + out_stream->Printf("TestEmulation: Error reading opcode from test file.\n"); + return false; + } + test_opcode = value_sp->GetUInt64Value(); + + if (arch.GetTriple().getArch() == llvm::Triple::thumb || + arch.IsAlwaysThumbInstructions()) { + m_opcode_mode = eModeThumb; + if (test_opcode < 0x10000) + m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder()); + else + m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder()); + } else if (arch.GetTriple().getArch() == llvm::Triple::arm) { + m_opcode_mode = eModeARM; + m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder()); + } else { + out_stream->Printf("TestEmulation: Invalid arch.\n"); + return false; + } -EmulateInstruction::InstructionCondition -EmulateInstructionARM::GetInstructionCondition() -{ - const uint32_t cond = CurrentCond (m_opcode.GetOpcode32()); - if (cond == 0xe || cond == 0xf || cond == UINT32_MAX) - return EmulateInstruction::UnconditionalCondition; - return cond; -} - -bool -EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) -{ - if (!test_data) - { - out_stream->Printf ("TestEmulation: Missing test data.\n"); - return false; - } - - static ConstString opcode_key ("opcode"); - static ConstString before_key ("before_state"); - static ConstString after_key ("after_state"); - - OptionValueSP value_sp = test_data->GetValueForKey (opcode_key); - - uint32_t test_opcode; - if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64)) - { - out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n"); - return false; - } - test_opcode = value_sp->GetUInt64Value (); + EmulationStateARM before_state; + EmulationStateARM after_state; + value_sp = test_data->GetValueForKey(before_key); + if ((value_sp.get() == NULL) || + (value_sp->GetType() != OptionValue::eTypeDictionary)) { + out_stream->Printf("TestEmulation: Failed to find 'before' state.\n"); + return false; + } - if (arch.GetTriple().getArch() == llvm::Triple::thumb || arch.IsAlwaysThumbInstructions ()) - { - m_opcode_mode = eModeThumb; - if (test_opcode < 0x10000) - m_opcode.SetOpcode16 (test_opcode, endian::InlHostByteOrder()); - else - m_opcode.SetOpcode32 (test_opcode, endian::InlHostByteOrder()); - } - else if (arch.GetTriple().getArch() == llvm::Triple::arm) - { - m_opcode_mode = eModeARM; - m_opcode.SetOpcode32 (test_opcode, endian::InlHostByteOrder()); - } - else - { - out_stream->Printf ("TestEmulation: Invalid arch.\n"); - return false; - } + OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary(); + if (!before_state.LoadStateFromDictionary(state_dictionary)) { + out_stream->Printf("TestEmulation: Failed loading 'before' state.\n"); + return false; + } - EmulationStateARM before_state; - EmulationStateARM after_state; - - value_sp = test_data->GetValueForKey (before_key); - if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary)) - { - out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n"); - return false; - } - - OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary (); - if (!before_state.LoadStateFromDictionary (state_dictionary)) - { - out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n"); - return false; - } + value_sp = test_data->GetValueForKey(after_key); + if ((value_sp.get() == NULL) || + (value_sp->GetType() != OptionValue::eTypeDictionary)) { + out_stream->Printf("TestEmulation: Failed to find 'after' state.\n"); + return false; + } - value_sp = test_data->GetValueForKey (after_key); - if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary)) - { - out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n"); - return false; - } + state_dictionary = value_sp->GetAsDictionary(); + if (!after_state.LoadStateFromDictionary(state_dictionary)) { + out_stream->Printf("TestEmulation: Failed loading 'after' state.\n"); + return false; + } - state_dictionary = value_sp->GetAsDictionary (); - if (!after_state.LoadStateFromDictionary (state_dictionary)) - { - out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n"); - return false; - } + SetBaton((void *)&before_state); + SetCallbacks(&EmulationStateARM::ReadPseudoMemory, + &EmulationStateARM::WritePseudoMemory, + &EmulationStateARM::ReadPseudoRegister, + &EmulationStateARM::WritePseudoRegister); - SetBaton ((void *) &before_state); - SetCallbacks (&EmulationStateARM::ReadPseudoMemory, - &EmulationStateARM::WritePseudoMemory, - &EmulationStateARM::ReadPseudoRegister, - &EmulationStateARM::WritePseudoRegister); - - bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC); - if (!success) - { - out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n"); - return false; - } - - success = before_state.CompareState (after_state); - if (!success) - out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n"); - - return success; + bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); + if (!success) { + out_stream->Printf("TestEmulation: EvaluateInstruction() failed.\n"); + return false; + } + + success = before_state.CompareState(after_state); + if (!success) + out_stream->Printf( + "TestEmulation: 'before' and 'after' states do not match.\n"); + + return success; } // -// -//const char * -//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num) +// +// const char * +// EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num) //{ // if (reg_kind == eRegisterKindGeneric) // { @@ -13772,21 +14082,19 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option // return NULL; //} // -bool -EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) -{ - unwind_plan.Clear(); - unwind_plan.SetRegisterKind (eRegisterKindDWARF); - - UnwindPlan::RowSP row(new UnwindPlan::Row); - - // Our previous Call Frame Address is the stack pointer - row->GetCFAValue().SetIsRegisterPlusOffset (dwarf_sp, 0); - - unwind_plan.AppendRow (row); - unwind_plan.SetSourceName ("EmulateInstructionARM"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); - unwind_plan.SetReturnAddressRegister (dwarf_lr); - return true; +bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Our previous Call Frame Address is the stack pointer + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0); + + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("EmulateInstructionARM"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetReturnAddressRegister(dwarf_lr); + return true; } diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index 6e75a3db2eb5..1bfc4cb398fb 100644 --- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -10,981 +10,778 @@ #ifndef lldb_EmulateInstructionARM_h_ #define lldb_EmulateInstructionARM_h_ -#include "lldb/Core/EmulateInstruction.h" +#include "Plugins/Process/Utility/ARMDefines.h" #include "lldb/Core/ConstString.h" +#include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Error.h" -#include "Plugins/Process/Utility/ARMDefines.h" namespace lldb_private { // ITSession - Keep track of the IT Block progression. -class ITSession -{ +class ITSession { public: - ITSession() : ITCounter(0), ITState(0) {} - ~ITSession() {} + ITSession() : ITCounter(0), ITState(0) {} + ~ITSession() {} - // InitIT - Initializes ITCounter/ITState. - bool InitIT(uint32_t bits7_0); + // InitIT - Initializes ITCounter/ITState. + bool InitIT(uint32_t bits7_0); - // ITAdvance - Updates ITCounter/ITState as IT Block progresses. - void ITAdvance(); + // ITAdvance - Updates ITCounter/ITState as IT Block progresses. + void ITAdvance(); - // InITBlock - Returns true if we're inside an IT Block. - bool InITBlock(); + // InITBlock - Returns true if we're inside an IT Block. + bool InITBlock(); - // LastInITBlock - Returns true if we're the last instruction inside an IT Block. - bool LastInITBlock(); + // LastInITBlock - Returns true if we're the last instruction inside an IT + // Block. + bool LastInITBlock(); - // GetCond - Gets condition bits for the current thumb instruction. - uint32_t GetCond(); + // GetCond - Gets condition bits for the current thumb instruction. + uint32_t GetCond(); private: - uint32_t ITCounter; // Possible values: 0, 1, 2, 3, 4. - uint32_t ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially. + uint32_t ITCounter; // Possible values: 0, 1, 2, 3, 4. + uint32_t ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially. }; -class EmulateInstructionARM : public EmulateInstruction -{ -public: - typedef enum - { - eEncodingA1, - eEncodingA2, - eEncodingA3, - eEncodingA4, - eEncodingA5, - eEncodingT1, - eEncodingT2, - eEncodingT3, - eEncodingT4, - eEncodingT5 - } ARMEncoding; - - - static void - Initialize (); - - static void - Terminate (); - - static lldb_private::ConstString - GetPluginNameStatic (); - - static const char * - GetPluginDescriptionStatic (); - - static lldb_private::EmulateInstruction * - CreateInstance (const lldb_private::ArchSpec &arch, - InstructionType inst_type); - - static bool - SupportsEmulatingInstructionsOfTypeStatic (InstructionType inst_type) - { - switch (inst_type) - { - case eInstructionTypeAny: - case eInstructionTypePrologueEpilogue: - case eInstructionTypePCModifying: - return true; - - case eInstructionTypeAll: - return false; - } - return false; +class EmulateInstructionARM : public EmulateInstruction { +public: + typedef enum { + eEncodingA1, + eEncodingA2, + eEncodingA3, + eEncodingA4, + eEncodingA5, + eEncodingT1, + eEncodingT2, + eEncodingT3, + eEncodingT4, + eEncodingT5 + } ARMEncoding; + + static void Initialize(); + + static void Terminate(); + + static lldb_private::ConstString GetPluginNameStatic(); + + static const char *GetPluginDescriptionStatic(); + + static lldb_private::EmulateInstruction * + CreateInstance(const lldb_private::ArchSpec &arch, InstructionType inst_type); + + static bool + SupportsEmulatingInstructionsOfTypeStatic(InstructionType inst_type) { + switch (inst_type) { + case eInstructionTypeAny: + case eInstructionTypePrologueEpilogue: + case eInstructionTypePCModifying: + return true; + + case eInstructionTypeAll: + return false; } + return false; + } - lldb_private::ConstString - GetPluginName() override - { - return GetPluginNameStatic(); - } + lldb_private::ConstString GetPluginName() override { + return GetPluginNameStatic(); + } - uint32_t - GetPluginVersion() override - { - return 1; - } + uint32_t GetPluginVersion() override { return 1; } - bool - SetTargetTriple (const ArchSpec &arch) override; - - enum Mode - { - eModeInvalid = -1, - eModeARM, - eModeThumb - }; - - EmulateInstructionARM (const ArchSpec &arch) : - EmulateInstruction (arch), - m_arm_isa (0), - m_opcode_mode (eModeInvalid), - m_opcode_cpsr (0), - m_it_session (), - m_ignore_conditions (false) - { - SetArchitecture (arch); - } + bool SetTargetTriple(const ArchSpec &arch) override; -// EmulateInstructionARM (const ArchSpec &arch, -// bool ignore_conditions, -// void *baton, -// ReadMemory read_mem_callback, -// WriteMemory write_mem_callback, -// ReadRegister read_reg_callback, -// WriteRegister write_reg_callback) : -// EmulateInstruction (arch, -// ignore_conditions, -// baton, -// read_mem_callback, -// write_mem_callback, -// read_reg_callback, -// write_reg_callback), -// m_arm_isa (0), -// m_opcode_mode (eModeInvalid), -// m_opcode_cpsr (0), -// m_it_session () -// { -// } - - bool - SupportsEmulatingInstructionsOfType (InstructionType inst_type) override - { - return SupportsEmulatingInstructionsOfTypeStatic (inst_type); - } + enum Mode { eModeInvalid = -1, eModeARM, eModeThumb }; - virtual bool - SetArchitecture (const ArchSpec &arch); - - bool - ReadInstruction () override; - - bool - SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target) override; - - bool - EvaluateInstruction (uint32_t evaluate_options) override; - - InstructionCondition - GetInstructionCondition() override; - - bool - TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) override; - - bool - GetRegisterInfo (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) override; - - bool - CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) override; - - uint32_t - ArchVersion(); - - bool - ConditionPassed (const uint32_t opcode); - - uint32_t - CurrentCond (const uint32_t opcode); - - // InITBlock - Returns true if we're in Thumb mode and inside an IT Block. - bool InITBlock(); - - // LastInITBlock - Returns true if we're in Thumb mode and the last instruction inside an IT Block. - bool LastInITBlock(); - - bool - BadMode (uint32_t mode); - - bool - CurrentModeIsPrivileged (); - - void - CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate); - - bool - BranchWritePC(const Context &context, uint32_t addr); - - bool - BXWritePC(Context &context, uint32_t addr); - - bool - LoadWritePC(Context &context, uint32_t addr); - - bool - ALUWritePC(Context &context, uint32_t addr); - - Mode - CurrentInstrSet(); - - bool - SelectInstrSet(Mode arm_or_thumb); - - bool - WriteBits32Unknown (int n); - - bool - WriteBits32UnknownToMemory (lldb::addr_t address); - - bool - UnalignedSupport(); - - typedef struct - { - uint32_t result; - uint8_t carry_out; - uint8_t overflow; - } AddWithCarryResult; - - AddWithCarryResult - AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in); - - // Helper method to read the content of an ARM core register. - uint32_t - ReadCoreReg (uint32_t regnum, bool *success); - - // See A8.6.96 MOV (immediate) Operation. - // Default arguments are specified for carry and overflow parameters, which means - // not to update the respective flags even if setflags is true. - bool - WriteCoreRegOptionalFlags (Context &context, - const uint32_t result, - const uint32_t Rd, - bool setflags, - const uint32_t carry = ~0u, - const uint32_t overflow = ~0u); - - bool - WriteCoreReg (Context &context, - const uint32_t result, - const uint32_t Rd) - { - // Don't set the flags. - return WriteCoreRegOptionalFlags(context, result, Rd, false); - } + EmulateInstructionARM(const ArchSpec &arch) + : EmulateInstruction(arch), m_arm_isa(0), m_opcode_mode(eModeInvalid), + m_opcode_cpsr(0), m_it_session(), m_ignore_conditions(false) { + SetArchitecture(arch); + } - // See A8.6.35 CMP (immediate) Operation. - // Default arguments are specified for carry and overflow parameters, which means - // not to update the respective flags. - bool - WriteFlags (Context &context, - const uint32_t result, - const uint32_t carry = ~0u, - const uint32_t overflow = ~0u); - - inline uint64_t - MemARead (EmulateInstruction::Context &context, - lldb::addr_t address, - uint32_t size, - uint64_t fail_value, - bool *success_ptr) - { - // This is a stub function corresponding to "MemA[]" in the ARM manual pseudocode, for - // aligned reads from memory. Since we are not trying to write a full hardware simulator, and since - // we are running in User mode (rather than Kernel mode) and therefore won't have access to many of the - // system registers we would need in order to fully implement this function, we will just call - // ReadMemoryUnsigned from here. In the future, if we decide we do need to do more faithful emulation of - // the hardware, we can update this function appropriately. - - return ReadMemoryUnsigned (context, address, size, fail_value, success_ptr); - } - - inline bool - MemAWrite (EmulateInstruction::Context &context, - lldb::addr_t address, - uint64_t data_val, - uint32_t size) - - { - // This is a stub function corresponding to "MemA[]" in the ARM manual pseudocode, for - // aligned writes to memory. Since we are not trying to write a full hardware simulator, and since - // we are running in User mode (rather than Kernel mode) and therefore won't have access to many of the - // system registers we would need in order to fully implement this function, we will just call - // WriteMemoryUnsigned from here. In the future, if we decide we do need to do more faithful emulation of - // the hardware, we can update this function appropriately. - - return WriteMemoryUnsigned (context, address, data_val, size); - } - - - inline uint64_t - MemURead (EmulateInstruction::Context &context, - lldb::addr_t address, - uint32_t size, - uint64_t fail_value, - bool *success_ptr) - { - // This is a stub function corresponding to "MemU[]" in the ARM manual pseudocode, for - // unaligned reads from memory. Since we are not trying to write a full hardware simulator, and since - // we are running in User mode (rather than Kernel mode) and therefore won't have access to many of the - // system registers we would need in order to fully implement this function, we will just call - // ReadMemoryUnsigned from here. In the future, if we decide we do need to do more faithful emulation of - // the hardware, we can update this function appropriately. - - return ReadMemoryUnsigned (context, address, size, fail_value, success_ptr); - } - - inline bool - MemUWrite (EmulateInstruction::Context &context, - lldb::addr_t address, - uint64_t data_val, - uint32_t size) - - { - // This is a stub function corresponding to "MemU[]" in the ARM manual pseudocode, for - // unaligned writes to memory. Since we are not trying to write a full hardware simulator, and since - // we are running in User mode (rather than Kernel mode) and therefore won't have access to many of the - // system registers we would need in order to fully implement this function, we will just call - // WriteMemoryUnsigned from here. In the future, if we decide we do need to do more faithful emulation of - // the hardware, we can update this function appropriately. - - return WriteMemoryUnsigned (context, address, data_val, size); - } + // EmulateInstructionARM (const ArchSpec &arch, + // bool ignore_conditions, + // void *baton, + // ReadMemory read_mem_callback, + // WriteMemory write_mem_callback, + // ReadRegister read_reg_callback, + // WriteRegister write_reg_callback) : + // EmulateInstruction (arch, + // ignore_conditions, + // baton, + // read_mem_callback, + // write_mem_callback, + // read_reg_callback, + // write_reg_callback), + // m_arm_isa (0), + // m_opcode_mode (eModeInvalid), + // m_opcode_cpsr (0), + // m_it_session () + // { + // } + + bool SupportsEmulatingInstructionsOfType(InstructionType inst_type) override { + return SupportsEmulatingInstructionsOfTypeStatic(inst_type); + } + + virtual bool SetArchitecture(const ArchSpec &arch); + + bool ReadInstruction() override; + + bool SetInstruction(const Opcode &insn_opcode, const Address &inst_addr, + Target *target) override; + + bool EvaluateInstruction(uint32_t evaluate_options) override; + + InstructionCondition GetInstructionCondition() override; + + bool TestEmulation(Stream *out_stream, ArchSpec &arch, + OptionValueDictionary *test_data) override; + + bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, + RegisterInfo ®_info) override; + + bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) override; + + uint32_t ArchVersion(); + + bool ConditionPassed(const uint32_t opcode); + + uint32_t CurrentCond(const uint32_t opcode); + + // InITBlock - Returns true if we're in Thumb mode and inside an IT Block. + bool InITBlock(); + + // LastInITBlock - Returns true if we're in Thumb mode and the last + // instruction inside an IT Block. + bool LastInITBlock(); + + bool BadMode(uint32_t mode); + + bool CurrentModeIsPrivileged(); + + void CPSRWriteByInstr(uint32_t value, uint32_t bytemask, + bool affect_execstate); + + bool BranchWritePC(const Context &context, uint32_t addr); + + bool BXWritePC(Context &context, uint32_t addr); + + bool LoadWritePC(Context &context, uint32_t addr); + + bool ALUWritePC(Context &context, uint32_t addr); + + Mode CurrentInstrSet(); + + bool SelectInstrSet(Mode arm_or_thumb); + + bool WriteBits32Unknown(int n); + + bool WriteBits32UnknownToMemory(lldb::addr_t address); + + bool UnalignedSupport(); + + typedef struct { + uint32_t result; + uint8_t carry_out; + uint8_t overflow; + } AddWithCarryResult; + + AddWithCarryResult AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in); + + // Helper method to read the content of an ARM core register. + uint32_t ReadCoreReg(uint32_t regnum, bool *success); + + // See A8.6.96 MOV (immediate) Operation. + // Default arguments are specified for carry and overflow parameters, which + // means + // not to update the respective flags even if setflags is true. + bool WriteCoreRegOptionalFlags(Context &context, const uint32_t result, + const uint32_t Rd, bool setflags, + const uint32_t carry = ~0u, + const uint32_t overflow = ~0u); + + bool WriteCoreReg(Context &context, const uint32_t result, + const uint32_t Rd) { + // Don't set the flags. + return WriteCoreRegOptionalFlags(context, result, Rd, false); + } + + // See A8.6.35 CMP (immediate) Operation. + // Default arguments are specified for carry and overflow parameters, which + // means + // not to update the respective flags. + bool WriteFlags(Context &context, const uint32_t result, + const uint32_t carry = ~0u, const uint32_t overflow = ~0u); + + inline uint64_t MemARead(EmulateInstruction::Context &context, + lldb::addr_t address, uint32_t size, + uint64_t fail_value, bool *success_ptr) { + // This is a stub function corresponding to "MemA[]" in the ARM manual + // pseudocode, for + // aligned reads from memory. Since we are not trying to write a full + // hardware simulator, and since + // we are running in User mode (rather than Kernel mode) and therefore won't + // have access to many of the + // system registers we would need in order to fully implement this function, + // we will just call + // ReadMemoryUnsigned from here. In the future, if we decide we do need to + // do more faithful emulation of + // the hardware, we can update this function appropriately. + + return ReadMemoryUnsigned(context, address, size, fail_value, success_ptr); + } + + inline bool MemAWrite(EmulateInstruction::Context &context, + lldb::addr_t address, uint64_t data_val, uint32_t size) + + { + // This is a stub function corresponding to "MemA[]" in the ARM manual + // pseudocode, for + // aligned writes to memory. Since we are not trying to write a full + // hardware simulator, and since + // we are running in User mode (rather than Kernel mode) and therefore won't + // have access to many of the + // system registers we would need in order to fully implement this function, + // we will just call + // WriteMemoryUnsigned from here. In the future, if we decide we do need to + // do more faithful emulation of + // the hardware, we can update this function appropriately. + + return WriteMemoryUnsigned(context, address, data_val, size); + } + + inline uint64_t MemURead(EmulateInstruction::Context &context, + lldb::addr_t address, uint32_t size, + uint64_t fail_value, bool *success_ptr) { + // This is a stub function corresponding to "MemU[]" in the ARM manual + // pseudocode, for + // unaligned reads from memory. Since we are not trying to write a full + // hardware simulator, and since + // we are running in User mode (rather than Kernel mode) and therefore won't + // have access to many of the + // system registers we would need in order to fully implement this function, + // we will just call + // ReadMemoryUnsigned from here. In the future, if we decide we do need to + // do more faithful emulation of + // the hardware, we can update this function appropriately. + + return ReadMemoryUnsigned(context, address, size, fail_value, success_ptr); + } + + inline bool MemUWrite(EmulateInstruction::Context &context, + lldb::addr_t address, uint64_t data_val, uint32_t size) + + { + // This is a stub function corresponding to "MemU[]" in the ARM manual + // pseudocode, for + // unaligned writes to memory. Since we are not trying to write a full + // hardware simulator, and since + // we are running in User mode (rather than Kernel mode) and therefore won't + // have access to many of the + // system registers we would need in order to fully implement this function, + // we will just call + // WriteMemoryUnsigned from here. In the future, if we decide we do need to + // do more faithful emulation of + // the hardware, we can update this function appropriately. + + return WriteMemoryUnsigned(context, address, data_val, size); + } protected: + // Typedef for the callback function used during the emulation. + // Pass along (ARMEncoding)encoding as the callback data. + typedef enum { eSize16, eSize32 } ARMInstrSize; + + typedef struct { + uint32_t mask; + uint32_t value; + uint32_t variants; + EmulateInstructionARM::ARMEncoding encoding; + uint32_t vfp_variants; + ARMInstrSize size; + bool (EmulateInstructionARM::*callback)( + const uint32_t opcode, + const EmulateInstructionARM::ARMEncoding encoding); + const char *name; + } ARMOpcode; + + uint32_t GetFramePointerRegisterNumber() const; + + uint32_t GetFramePointerDWARFRegisterNumber() const; + + static ARMOpcode *GetARMOpcodeForInstruction(const uint32_t opcode, + uint32_t isa_mask); + + static ARMOpcode *GetThumbOpcodeForInstruction(const uint32_t opcode, + uint32_t isa_mask); + + // A8.6.123 PUSH + bool EmulatePUSH(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.122 POP + bool EmulatePOP(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.8 ADD (SP plus immediate) + bool EmulateADDRdSPImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.97 MOV (register) -- Rd == r7|ip and Rm == sp + bool EmulateMOVRdSP(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.97 MOV (register) -- move from r8-r15 to r0-r7 + bool EmulateMOVLowHigh(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.59 LDR (literal) + bool EmulateLDRRtPCRelative(const uint32_t opcode, + const ARMEncoding encoding); + + // A8.6.8 ADD (SP plus immediate) + bool EmulateADDSPImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.9 ADD (SP plus register) + bool EmulateADDSPRm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.23 BL, BLX (immediate) + bool EmulateBLXImmediate(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.24 BLX (register) + bool EmulateBLXRm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.25 BX + bool EmulateBXRm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.26 BXJ + bool EmulateBXJRm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.212 SUB (immediate, ARM) -- Rd == r7 and Rm == ip + bool EmulateSUBR7IPImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.215 SUB (SP minus immediate) -- Rd == ip + bool EmulateSUBIPSPImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.215 SUB (SP minus immediate) + bool EmulateSUBSPImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.216 SUB (SP minus register) + bool EmulateSUBSPReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.194 STR (immediate, ARM) -- Rn == sp + bool EmulateSTRRtSP(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.355 VPUSH + bool EmulateVPUSH(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.354 VPOP + bool EmulateVPOP(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.218 SVC (previously SWI) + bool EmulateSVC(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.50 IT + bool EmulateIT(const uint32_t opcode, const ARMEncoding encoding); + + // NOP + bool EmulateNop(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.16 B + bool EmulateB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.27 CBNZ, CBZ + bool EmulateCB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.226 TBB, TBH + bool EmulateTB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.4 ADD (immediate, Thumb) + bool EmulateADDImmThumb(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.5 ADD (immediate, ARM) + bool EmulateADDImmARM(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.6 ADD (register) + bool EmulateADDReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.7 ADD (register-shifted register) + bool EmulateADDRegShift(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.97 MOV (register) + bool EmulateMOVRdRm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.96 MOV (immediate) + bool EmulateMOVRdImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.35 CMP (immediate) + bool EmulateCMPImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.36 CMP (register) + bool EmulateCMPReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.14 ASR (immediate) + bool EmulateASRImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.15 ASR (register) + bool EmulateASRReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.88 LSL (immediate) + bool EmulateLSLImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.89 LSL (register) + bool EmulateLSLReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.90 LSR (immediate) + bool EmulateLSRImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.91 LSR (register) + bool EmulateLSRReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.139 ROR (immediate) + bool EmulateRORImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.140 ROR (register) + bool EmulateRORReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.141 RRX + bool EmulateRRX(const uint32_t opcode, const ARMEncoding encoding); + + // Helper method for ASR, LSL, LSR, ROR (immediate), and RRX + bool EmulateShiftImm(const uint32_t opcode, const ARMEncoding encoding, + ARM_ShifterType shift_type); + + // Helper method for ASR, LSL, LSR, and ROR (register) + bool EmulateShiftReg(const uint32_t opcode, const ARMEncoding encoding, + ARM_ShifterType shift_type); + + // LOAD FUNCTIONS + + // A8.6.53 LDM/LDMIA/LDMFD + bool EmulateLDM(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.54 LDMDA/LDMFA + bool EmulateLDMDA(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.55 LDMDB/LDMEA + bool EmulateLDMDB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.56 LDMIB/LDMED + bool EmulateLDMIB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.57 LDR (immediate, Thumb) -- Encoding T1 + bool EmulateLDRRtRnImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.58 LDR (immediate, ARM) - Encoding A1 + bool EmulateLDRImmediateARM(const uint32_t opcode, + const ARMEncoding encoding); + + // A8.6.59 LDR (literal) + bool EmulateLDRLiteral(const uint32_t, const ARMEncoding encoding); + + // A8.6.60 LDR (register) - Encoding T1, T2, A1 + bool EmulateLDRRegister(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.61 LDRB (immediate, Thumb) - Encoding T1, T2, T3 + bool EmulateLDRBImmediate(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.62 LDRB (immediate, ARM) + bool EmulateLDRBImmediateARM(const uint32_t opcode, + const ARMEncoding encoding); + + // A8.6.63 LDRB (literal) - Encoding T1, A1 + bool EmulateLDRBLiteral(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.64 LDRB (register) - Encoding T1, T2, A1 + bool EmulateLDRBRegister(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.65 LDRBT + bool EmulateLDRBT(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.66 LDRD (immediate) + bool EmulateLDRDImmediate(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.67 + bool EmulateLDRDLiteral(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.68 LDRD (register) + bool EmulateLDRDRegister(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.69 LDREX + bool EmulateLDREX(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.70 LDREXB + bool EmulateLDREXB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.71 LDREXD + bool EmulateLDREXD(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.72 LDREXH + bool EmulateLDREXH(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.73 LDRH (immediate, Thumb) - Encoding T1, T2, T3 + bool EmulateLDRHImmediate(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.74 LDRS (immediate, ARM) + bool EmulateLDRHImmediateARM(const uint32_t opcode, + const ARMEncoding encoding); + + // A8.6.75 LDRH (literal) - Encoding T1, A1 + bool EmulateLDRHLiteral(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.76 LDRH (register) - Encoding T1, T2, A1 + bool EmulateLDRHRegister(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.77 LDRHT + bool EmulateLDRHT(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.78 LDRSB (immediate) - Encoding T1, T2, A1 + bool EmulateLDRSBImmediate(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.79 LDRSB (literal) - Encoding T1, A1 + bool EmulateLDRSBLiteral(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.80 LDRSB (register) - Encoding T1, T2, A1 + bool EmulateLDRSBRegister(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.81 LDRSBT + bool EmulateLDRSBT(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.82 LDRSH (immediate) - Encoding T1, T2, A1 + bool EmulateLDRSHImmediate(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.83 LDRSH (literal) - Encoding T1, A1 + bool EmulateLDRSHLiteral(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.84 LDRSH (register) - Encoding T1, T2, A1 + bool EmulateLDRSHRegister(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.85 LDRSHT + bool EmulateLDRSHT(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.86 + bool EmulateLDRT(const uint32_t opcode, const ARMEncoding encoding); + + // STORE FUNCTIONS + + // A8.6.189 STM/STMIA/STMEA + bool EmulateSTM(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.190 STMDA/STMED + bool EmulateSTMDA(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.191 STMDB/STMFD + bool EmulateSTMDB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.192 STMIB/STMFA + bool EmulateSTMIB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.193 STR (immediate, Thumb) + bool EmulateSTRThumb(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.194 STR (immediate, ARM) + bool EmulateSTRImmARM(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.195 STR (register) + bool EmulateSTRRegister(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.196 STRB (immediate, Thumb) + bool EmulateSTRBThumb(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.197 STRB (immediate, ARM) + bool EmulateSTRBImmARM(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.198 STRB (register) + bool EmulateSTRBReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.199 STRBT + bool EmulateSTRBT(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.200 STRD (immediate) + bool EmulateSTRDImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.201 STRD (register) + bool EmulateSTRDReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.202 STREX + bool EmulateSTREX(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.203 STREXB + bool EmulateSTREXB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.204 STREXD + bool EmulateSTREXD(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.205 STREXH + bool EmulateSTREXH(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.206 STRH (immediate, Thumb) + bool EmulateSTRHImmThumb(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.207 STRH (immediate, ARM) + bool EmulateSTRHImmARM(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.208 STRH (register) + bool EmulateSTRHRegister(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.209 STRHT + bool EmulateSTRHT(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.210 STRT + bool EmulateSTRT(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.1 ADC (immediate) + bool EmulateADCImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.2 ADC (Register) + bool EmulateADCReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.10 ADR + bool EmulateADR(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.11 AND (immediate) + bool EmulateANDImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.12 AND (register) + bool EmulateANDReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.19 BIC (immediate) + bool EmulateBICImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.20 BIC (register) + bool EmulateBICReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.26 BXJ + bool EmulateBXJ(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.32 CMN (immediate) + bool EmulateCMNImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.33 CMN (register) + bool EmulateCMNReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.44 EOR (immediate) + bool EmulateEORImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.45 EOR (register) + bool EmulateEORReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.105 MUL + bool EmulateMUL(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.106 MVN (immediate) + bool EmulateMVNImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.107 MVN (register) + bool EmulateMVNReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.113 ORR (immediate) + bool EmulateORRImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.114 ORR (register) + bool EmulateORRReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.117 PLD (immediate, literal) - Encoding T1, T2, T3, A1 + bool EmulatePLDImmediate(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.119 PLI (immediate,literal) - Encoding T3, A1 + bool EmulatePLIImmediate(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.120 PLI (register) - Encoding T1, A1 + bool EmulatePLIRegister(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.141 RSB (immediate) + bool EmulateRSBImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.142 RSB (register) + bool EmulateRSBReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.144 RSC (immediate) + bool EmulateRSCImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.145 RSC (register) + bool EmulateRSCReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.150 SBC (immediate) + bool EmulateSBCImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.151 SBC (register) + bool EmulateSBCReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.211 SUB (immediate, Thumb) + bool EmulateSUBImmThumb(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.212 SUB (immediate, ARM) + bool EmulateSUBImmARM(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.213 SUB (register) + bool EmulateSUBReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.214 SUB (register-shifted register) + bool EmulateSUBRegShift(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.222 SXTB - Encoding T1 + bool EmulateSXTB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.224 SXTH - EncodingT1 + bool EmulateSXTH(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.227 TEQ (immediate) - Encoding A1 + bool EmulateTEQImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.228 TEQ (register) - Encoding A1 + bool EmulateTEQReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.230 TST (immediate) - Encoding A1 + bool EmulateTSTImm(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.231 TST (register) - Encoding T1, A1 + bool EmulateTSTReg(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.262 UXTB - Encoding T1 + bool EmulateUXTB(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.264 UXTH - Encoding T1 + bool EmulateUXTH(const uint32_t opcode, const ARMEncoding encoding); + + // B6.1.8 RFE + bool EmulateRFE(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.319 VLDM + bool EmulateVLDM(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.399 VSTM + bool EmulateVSTM(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.307 VLD1 (multiple single elements) + bool EmulateVLD1Multiple(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.308 VLD1 (single element to one lane) + bool EmulateVLD1Single(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.309 VLD1 (single element to all lanes) + bool EmulateVLD1SingleAll(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.391 VST1 (multiple single elements) + bool EmulateVST1Multiple(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.392 VST1 (single element from one lane) + bool EmulateVST1Single(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.317 VLDR + bool EmulateVLDR(const uint32_t opcode, const ARMEncoding encoding); + + // A8.6.400 VSTR + bool EmulateVSTR(const uint32_t opcode, const ARMEncoding encoding); + + // B6.2.13 SUBS PC, LR and related instructions + bool EmulateSUBSPcLrEtc(const uint32_t opcode, const ARMEncoding encoding); - // Typedef for the callback function used during the emulation. - // Pass along (ARMEncoding)encoding as the callback data. - typedef enum - { - eSize16, - eSize32 - } ARMInstrSize; - - typedef struct - { - uint32_t mask; - uint32_t value; - uint32_t variants; - EmulateInstructionARM::ARMEncoding encoding; - uint32_t vfp_variants; - ARMInstrSize size; - bool (EmulateInstructionARM::*callback) (const uint32_t opcode, const EmulateInstructionARM::ARMEncoding encoding); - const char *name; - } ARMOpcode; - - uint32_t - GetFramePointerRegisterNumber () const; - - uint32_t - GetFramePointerDWARFRegisterNumber () const; - - static ARMOpcode* - GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t isa_mask); - - static ARMOpcode* - GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t isa_mask); - - // A8.6.123 PUSH - bool - EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.122 POP - bool - EmulatePOP (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.8 ADD (SP plus immediate) - bool - EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.97 MOV (register) -- Rd == r7|ip and Rm == sp - bool - EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.97 MOV (register) -- move from r8-r15 to r0-r7 - bool - EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.59 LDR (literal) - bool - EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.8 ADD (SP plus immediate) - bool - EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.9 ADD (SP plus register) - bool - EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.23 BL, BLX (immediate) - bool - EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.24 BLX (register) - bool - EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.25 BX - bool - EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.26 BXJ - bool - EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.212 SUB (immediate, ARM) -- Rd == r7 and Rm == ip - bool - EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.215 SUB (SP minus immediate) -- Rd == ip - bool - EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.215 SUB (SP minus immediate) - bool - EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.216 SUB (SP minus register) - bool - EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.194 STR (immediate, ARM) -- Rn == sp - bool - EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.355 VPUSH - bool - EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.354 VPOP - bool - EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.218 SVC (previously SWI) - bool - EmulateSVC (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.50 IT - bool - EmulateIT (const uint32_t opcode, const ARMEncoding encoding); - - // NOP - bool - EmulateNop (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.16 B - bool - EmulateB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.27 CBNZ, CBZ - bool - EmulateCB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.226 TBB, TBH - bool - EmulateTB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.4 ADD (immediate, Thumb) - bool - EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.5 ADD (immediate, ARM) - bool - EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.6 ADD (register) - bool - EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.7 ADD (register-shifted register) - bool - EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.97 MOV (register) - bool - EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.96 MOV (immediate) - bool - EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.35 CMP (immediate) - bool - EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.36 CMP (register) - bool - EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.14 ASR (immediate) - bool - EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.15 ASR (register) - bool - EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.88 LSL (immediate) - bool - EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.89 LSL (register) - bool - EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.90 LSR (immediate) - bool - EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.91 LSR (register) - bool - EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.139 ROR (immediate) - bool - EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.140 ROR (register) - bool - EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.141 RRX - bool - EmulateRRX (const uint32_t opcode, const ARMEncoding encoding); - - // Helper method for ASR, LSL, LSR, ROR (immediate), and RRX - bool - EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type); - - // Helper method for ASR, LSL, LSR, and ROR (register) - bool - EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type); - - // LOAD FUNCTIONS - - // A8.6.53 LDM/LDMIA/LDMFD - bool - EmulateLDM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.54 LDMDA/LDMFA - bool - EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.55 LDMDB/LDMEA - bool - EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.56 LDMIB/LDMED - bool - EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.57 LDR (immediate, Thumb) -- Encoding T1 - bool - EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.58 LDR (immediate, ARM) - Encoding A1 - bool - EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.59 LDR (literal) - bool - EmulateLDRLiteral (const uint32_t, const ARMEncoding encoding); - - // A8.6.60 LDR (register) - Encoding T1, T2, A1 - bool - EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.61 LDRB (immediate, Thumb) - Encoding T1, T2, T3 - bool - EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.62 LDRB (immediate, ARM) - bool - EmulateLDRBImmediateARM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.63 LDRB (literal) - Encoding T1, A1 - bool - EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.64 LDRB (register) - Encoding T1, T2, A1 - bool - EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.65 LDRBT - bool - EmulateLDRBT (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.66 LDRD (immediate) - bool - EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.67 - bool - EmulateLDRDLiteral (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.68 LDRD (register) - bool - EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.69 LDREX - bool - EmulateLDREX (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.70 LDREXB - bool - EmulateLDREXB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.71 LDREXD - bool - EmulateLDREXD (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.72 LDREXH - bool - EmulateLDREXH (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.73 LDRH (immediate, Thumb) - Encoding T1, T2, T3 - bool - EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.74 LDRS (immediate, ARM) - bool - EmulateLDRHImmediateARM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.75 LDRH (literal) - Encoding T1, A1 - bool - EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.76 LDRH (register) - Encoding T1, T2, A1 - bool - EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.77 LDRHT - bool - EmulateLDRHT (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.78 LDRSB (immediate) - Encoding T1, T2, A1 - bool - EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.79 LDRSB (literal) - Encoding T1, A1 - bool - EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.80 LDRSB (register) - Encoding T1, T2, A1 - bool - EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.81 LDRSBT - bool - EmulateLDRSBT (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.82 LDRSH (immediate) - Encoding T1, T2, A1 - bool - EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.83 LDRSH (literal) - Encoding T1, A1 - bool - EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.84 LDRSH (register) - Encoding T1, T2, A1 - bool - EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.85 LDRSHT - bool - EmulateLDRSHT (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.86 - bool - EmulateLDRT (const uint32_t opcode, const ARMEncoding encoding); - - - // STORE FUNCTIONS - - // A8.6.189 STM/STMIA/STMEA - bool - EmulateSTM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.190 STMDA/STMED - bool - EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.191 STMDB/STMFD - bool - EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.192 STMIB/STMFA - bool - EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.193 STR (immediate, Thumb) - bool - EmulateSTRThumb(const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.194 STR (immediate, ARM) - bool - EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.195 STR (register) - bool - EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.196 STRB (immediate, Thumb) - bool - EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.197 STRB (immediate, ARM) - bool - EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.198 STRB (register) - bool - EmulateSTRBReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.199 STRBT - bool - EmulateSTRBT (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.200 STRD (immediate) - bool - EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.201 STRD (register) - bool - EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.202 STREX - bool - EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.203 STREXB - bool - EmulateSTREXB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.204 STREXD - bool - EmulateSTREXD (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.205 STREXH - bool - EmulateSTREXH (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.206 STRH (immediate, Thumb) - bool - EmulateSTRHImmThumb (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.207 STRH (immediate, ARM) - bool - EmulateSTRHImmARM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.208 STRH (register) - bool - EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.209 STRHT - bool - EmulateSTRHT (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.210 STRT - bool - EmulateSTRT (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.1 ADC (immediate) - bool - EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.2 ADC (Register) - bool - EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.10 ADR - bool - EmulateADR (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.11 AND (immediate) - bool - EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.12 AND (register) - bool - EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.19 BIC (immediate) - bool - EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.20 BIC (register) - bool - EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.26 BXJ - bool - EmulateBXJ (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.32 CMN (immediate) - bool - EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.33 CMN (register) - bool - EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.44 EOR (immediate) - bool - EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.45 EOR (register) - bool - EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.105 MUL - bool - EmulateMUL (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.106 MVN (immediate) - bool - EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.107 MVN (register) - bool - EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.113 ORR (immediate) - bool - EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.114 ORR (register) - bool - EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.117 PLD (immediate, literal) - Encoding T1, T2, T3, A1 - bool - EmulatePLDImmediate (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.119 PLI (immediate,literal) - Encoding T3, A1 - bool - EmulatePLIImmediate (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.120 PLI (register) - Encoding T1, A1 - bool - EmulatePLIRegister (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.141 RSB (immediate) - bool - EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.142 RSB (register) - bool - EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.144 RSC (immediate) - bool - EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.145 RSC (register) - bool - EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.150 SBC (immediate) - bool - EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.151 SBC (register) - bool - EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.211 SUB (immediate, Thumb) - bool - EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.212 SUB (immediate, ARM) - bool - EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.213 SUB (register) - bool - EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.214 SUB (register-shifted register) - bool - EmulateSUBRegShift (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.222 SXTB - Encoding T1 - bool - EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.224 SXTH - EncodingT1 - bool - EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.227 TEQ (immediate) - Encoding A1 - bool - EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.228 TEQ (register) - Encoding A1 - bool - EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.230 TST (immediate) - Encoding A1 - bool - EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.231 TST (register) - Encoding T1, A1 - bool - EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.262 UXTB - Encoding T1 - bool - EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.264 UXTH - Encoding T1 - bool - EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding); - - // B6.1.8 RFE - bool - EmulateRFE (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.319 VLDM - bool - EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.399 VSTM - bool - EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.307 VLD1 (multiple single elements) - bool - EmulateVLD1Multiple (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.308 VLD1 (single element to one lane) - bool - EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.309 VLD1 (single element to all lanes) - bool - EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.391 VST1 (multiple single elements) - bool - EmulateVST1Multiple (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.392 VST1 (single element from one lane) - bool - EmulateVST1Single (const uint32_t opcode, const ARMEncoding encoding); - - // A8.6.317 VLDR - bool - EmulateVLDR (const uint32_t opcode, const ARMEncoding encoding); - - - // A8.6.400 VSTR - bool - EmulateVSTR (const uint32_t opcode, const ARMEncoding encoding); - - // B6.2.13 SUBS PC, LR and related instructions - bool - EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding); - - uint32_t m_arm_isa; - Mode m_opcode_mode; - uint32_t m_opcode_cpsr; - uint32_t m_new_inst_cpsr; // This can get updated by the opcode. - ITSession m_it_session; - bool m_ignore_conditions; + uint32_t m_arm_isa; + Mode m_opcode_mode; + uint32_t m_opcode_cpsr; + uint32_t m_new_inst_cpsr; // This can get updated by the opcode. + ITSession m_it_session; + bool m_ignore_conditions; }; -} // namespace lldb_private +} // namespace lldb_private -#endif // lldb_EmulateInstructionARM_h_ +#endif // lldb_EmulateInstructionARM_h_ diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp index 547db44ebfb2..9ceeb76c6f5e 100644 --- a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp +++ b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -13,406 +13,341 @@ #include "lldb/Core/Scalar.h" #include "lldb/Interpreter/OptionValueArray.h" #include "lldb/Interpreter/OptionValueDictionary.h" -#include "lldb/Target/StackFrame.h" #include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" #include "Utility/ARM_DWARF_Registers.h" using namespace lldb; using namespace lldb_private; -EmulationStateARM::EmulationStateARM () : - m_gpr (), - m_vfp_regs (), - m_memory () -{ - ClearPseudoRegisters(); +EmulationStateARM::EmulationStateARM() : m_gpr(), m_vfp_regs(), m_memory() { + ClearPseudoRegisters(); } -EmulationStateARM::~EmulationStateARM () -{ -} +EmulationStateARM::~EmulationStateARM() {} -bool -EmulationStateARM::LoadPseudoRegistersFromFrame (StackFrame &frame) -{ - RegisterContext *reg_ctx = frame.GetRegisterContext().get(); - bool success = true; - uint32_t reg_num; - - for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i) - { - reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindDWARF, i); - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); - RegisterValue reg_value; - if (reg_ctx->ReadRegister (reg_info, reg_value)) - { - m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32(); - } - else - success = false; - } - - for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i) - { - reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindDWARF, i); - RegisterValue reg_value; - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num); - - if (reg_ctx->ReadRegister (reg_info, reg_value)) - { - uint64_t value = reg_value.GetAsUInt64(); - uint32_t idx = i - dwarf_d0; - if (i < 16) - { - m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; - m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); - } - else - m_vfp_regs.d_regs[idx - 16] = value; - } - else - success = false; - } - - return success; +bool EmulationStateARM::LoadPseudoRegistersFromFrame(StackFrame &frame) { + RegisterContext *reg_ctx = frame.GetRegisterContext().get(); + bool success = true; + uint32_t reg_num; + + for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i) { + reg_num = + reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i); + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); + RegisterValue reg_value; + if (reg_ctx->ReadRegister(reg_info, reg_value)) { + m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32(); + } else + success = false; + } + + for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i) { + reg_num = + reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i); + RegisterValue reg_value; + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); + + if (reg_ctx->ReadRegister(reg_info, reg_value)) { + uint64_t value = reg_value.GetAsUInt64(); + uint32_t idx = i - dwarf_d0; + if (i < 16) { + m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; + m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); + } else + m_vfp_regs.d_regs[idx - 16] = value; + } else + success = false; + } + + return success; } - -bool -EmulationStateARM::StorePseudoRegisterValue (uint32_t reg_num, uint64_t value) -{ - if ((dwarf_r0 <= reg_num) && (reg_num <= dwarf_cpsr)) - m_gpr[reg_num - dwarf_r0] = (uint32_t) value; - else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) - { - uint32_t idx = reg_num - dwarf_s0; - m_vfp_regs.s_regs[idx] = (uint32_t)value; - } - else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) - { - uint32_t idx = reg_num - dwarf_d0; - if (idx < 16) - { - m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; - m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); - } - else - m_vfp_regs.d_regs[idx - 16] = value; - } - else - return false; - - return true; + +bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num, + uint64_t value) { + if ((dwarf_r0 <= reg_num) && (reg_num <= dwarf_cpsr)) + m_gpr[reg_num - dwarf_r0] = (uint32_t)value; + else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) { + uint32_t idx = reg_num - dwarf_s0; + m_vfp_regs.s_regs[idx] = (uint32_t)value; + } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) { + uint32_t idx = reg_num - dwarf_d0; + if (idx < 16) { + m_vfp_regs.s_regs[idx * 2] = (uint32_t)value; + m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32); + } else + m_vfp_regs.d_regs[idx - 16] = value; + } else + return false; + + return true; } - -uint64_t -EmulationStateARM::ReadPseudoRegisterValue (uint32_t reg_num, bool &success) -{ - uint64_t value = 0; - success = true; - - if ((dwarf_r0 <= reg_num) && (reg_num <= dwarf_cpsr)) - value = m_gpr[reg_num - dwarf_r0]; - else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) - { - uint32_t idx = reg_num - dwarf_s0; - value = m_vfp_regs.d_regs[idx]; - } - else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) - { - uint32_t idx = reg_num - dwarf_d0; - if (idx < 16) - value = (uint64_t)m_vfp_regs.s_regs[idx * 2] | ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] >> 32); - else - value = m_vfp_regs.d_regs[idx - 16]; - } + +uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num, + bool &success) { + uint64_t value = 0; + success = true; + + if ((dwarf_r0 <= reg_num) && (reg_num <= dwarf_cpsr)) + value = m_gpr[reg_num - dwarf_r0]; + else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) { + uint32_t idx = reg_num - dwarf_s0; + value = m_vfp_regs.d_regs[idx]; + } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) { + uint32_t idx = reg_num - dwarf_d0; + if (idx < 16) + value = (uint64_t)m_vfp_regs.s_regs[idx * 2] | + ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] >> 32); else - success = false; - - return value; -} - -void -EmulationStateARM::ClearPseudoRegisters () -{ - for (int i = 0; i < 17; ++i) - m_gpr[i] = 0; - - for (int i = 0; i < 32; ++i) - m_vfp_regs.s_regs[i] = 0; - - for (int i = 0; i < 16; ++i) - m_vfp_regs.d_regs[i] = 0; + value = m_vfp_regs.d_regs[idx - 16]; + } else + success = false; + + return value; } -void -EmulationStateARM::ClearPseudoMemory () -{ - m_memory.clear(); +void EmulationStateARM::ClearPseudoRegisters() { + for (int i = 0; i < 17; ++i) + m_gpr[i] = 0; + + for (int i = 0; i < 32; ++i) + m_vfp_regs.s_regs[i] = 0; + + for (int i = 0; i < 16; ++i) + m_vfp_regs.d_regs[i] = 0; } - -bool -EmulationStateARM::StoreToPseudoAddress (lldb::addr_t p_address, uint32_t value) -{ - m_memory[p_address] = value; - return true; + +void EmulationStateARM::ClearPseudoMemory() { m_memory.clear(); } + +bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address, + uint32_t value) { + m_memory[p_address] = value; + return true; } - -uint32_t -EmulationStateARM::ReadFromPseudoAddress (lldb::addr_t p_address, bool &success) -{ - std::map<lldb::addr_t,uint32_t>::iterator pos; - uint32_t ret_val = 0; - - success = true; - pos = m_memory.find(p_address); - if (pos != m_memory.end()) - ret_val = pos->second; - else - success = false; - - return ret_val; + +uint32_t EmulationStateARM::ReadFromPseudoAddress(lldb::addr_t p_address, + bool &success) { + std::map<lldb::addr_t, uint32_t>::iterator pos; + uint32_t ret_val = 0; + + success = true; + pos = m_memory.find(p_address); + if (pos != m_memory.end()) + ret_val = pos->second; + else + success = false; + + return ret_val; } -size_t -EmulationStateARM::ReadPseudoMemory (EmulateInstruction *instruction, - void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, - void *dst, - size_t length) -{ - if (!baton) - return 0; - - bool success = true; - EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; - if (length <= 4) - { - uint32_t value = pseudo_state->ReadFromPseudoAddress (addr, success); - if (!success) - return 0; - - if (endian::InlHostByteOrder() == lldb::eByteOrderBig) - value = llvm::ByteSwap_32 (value); - *((uint32_t *) dst) = value; - } - else if (length == 8) - { - uint32_t value1 = pseudo_state->ReadFromPseudoAddress (addr, success); - if (!success) - return 0; - - uint32_t value2 = pseudo_state->ReadFromPseudoAddress (addr + 4, success); - if (!success) - return 0; - - if (endian::InlHostByteOrder() == lldb::eByteOrderBig) - { - value1 = llvm::ByteSwap_32 (value1); - value2 = llvm::ByteSwap_32 (value2); - } - ((uint32_t *) dst)[0] = value1; - ((uint32_t *) dst)[1] = value2; - } - else - success = false; - - if (success) - return length; - +size_t EmulationStateARM::ReadPseudoMemory( + EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst, + size_t length) { + if (!baton) return 0; -} - -size_t -EmulationStateARM::WritePseudoMemory (EmulateInstruction *instruction, - void *baton, - const EmulateInstruction::Context &context, - lldb::addr_t addr, - const void *dst, - size_t length) -{ - if (!baton) - return 0; - - EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; - - if (length <= 4) - { - uint32_t value = *((const uint32_t *) dst); - if (endian::InlHostByteOrder() == lldb::eByteOrderBig) - value = llvm::ByteSwap_32 (value); - - pseudo_state->StoreToPseudoAddress (addr, value); - return length; - } - else if (length == 8) - { - uint32_t value1 = ((const uint32_t *) dst)[0]; - uint32_t value2 = ((const uint32_t *) dst)[1]; - if (endian::InlHostByteOrder() == lldb::eByteOrderBig) - { - value1 = llvm::ByteSwap_32 (value1); - value2 = llvm::ByteSwap_32 (value2); - } - - pseudo_state->StoreToPseudoAddress (addr, value1); - pseudo_state->StoreToPseudoAddress (addr + 4, value2); - return length; + + bool success = true; + EmulationStateARM *pseudo_state = (EmulationStateARM *)baton; + if (length <= 4) { + uint32_t value = pseudo_state->ReadFromPseudoAddress(addr, success); + if (!success) + return 0; + + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) + value = llvm::ByteSwap_32(value); + *((uint32_t *)dst) = value; + } else if (length == 8) { + uint32_t value1 = pseudo_state->ReadFromPseudoAddress(addr, success); + if (!success) + return 0; + + uint32_t value2 = pseudo_state->ReadFromPseudoAddress(addr + 4, success); + if (!success) + return 0; + + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) { + value1 = llvm::ByteSwap_32(value1); + value2 = llvm::ByteSwap_32(value2); } + ((uint32_t *)dst)[0] = value1; + ((uint32_t *)dst)[1] = value2; + } else + success = false; + + if (success) + return length; + + return 0; +} +size_t EmulationStateARM::WritePseudoMemory( + EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, lldb::addr_t addr, + const void *dst, size_t length) { + if (!baton) return 0; + + EmulationStateARM *pseudo_state = (EmulationStateARM *)baton; + + if (length <= 4) { + uint32_t value = *((const uint32_t *)dst); + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) + value = llvm::ByteSwap_32(value); + + pseudo_state->StoreToPseudoAddress(addr, value); + return length; + } else if (length == 8) { + uint32_t value1 = ((const uint32_t *)dst)[0]; + uint32_t value2 = ((const uint32_t *)dst)[1]; + if (endian::InlHostByteOrder() == lldb::eByteOrderBig) { + value1 = llvm::ByteSwap_32(value1); + value2 = llvm::ByteSwap_32(value2); + } + + pseudo_state->StoreToPseudoAddress(addr, value1); + pseudo_state->StoreToPseudoAddress(addr + 4, value2); + return length; + } + + return 0; } - -bool -EmulationStateARM::ReadPseudoRegister (EmulateInstruction *instruction, - void *baton, - const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue ®_value) -{ - if (!baton || !reg_info) - return false; - - bool success = true; - EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; - const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF]; - assert (dwarf_reg_num != LLDB_INVALID_REGNUM); - uint64_t reg_uval = pseudo_state->ReadPseudoRegisterValue (dwarf_reg_num, success); - - if (success) - success = reg_value.SetUInt(reg_uval, reg_info->byte_size); - return success; - + +bool EmulationStateARM::ReadPseudoRegister( + EmulateInstruction *instruction, void *baton, + const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue ®_value) { + if (!baton || !reg_info) + return false; + + bool success = true; + EmulationStateARM *pseudo_state = (EmulationStateARM *)baton; + const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF]; + assert(dwarf_reg_num != LLDB_INVALID_REGNUM); + uint64_t reg_uval = + pseudo_state->ReadPseudoRegisterValue(dwarf_reg_num, success); + + if (success) + success = reg_value.SetUInt(reg_uval, reg_info->byte_size); + return success; } - -bool -EmulationStateARM::WritePseudoRegister (EmulateInstruction *instruction, - void *baton, - const EmulateInstruction::Context &context, - const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue ®_value) -{ - if (!baton || !reg_info) - return false; - EmulationStateARM *pseudo_state = (EmulationStateARM *) baton; - const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF]; - assert (dwarf_reg_num != LLDB_INVALID_REGNUM); - return pseudo_state->StorePseudoRegisterValue (dwarf_reg_num, reg_value.GetAsUInt64()); +bool EmulationStateARM::WritePseudoRegister( + EmulateInstruction *instruction, void *baton, + const EmulateInstruction::Context &context, + const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue ®_value) { + if (!baton || !reg_info) + return false; + + EmulationStateARM *pseudo_state = (EmulationStateARM *)baton; + const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF]; + assert(dwarf_reg_num != LLDB_INVALID_REGNUM); + return pseudo_state->StorePseudoRegisterValue(dwarf_reg_num, + reg_value.GetAsUInt64()); } - -bool -EmulationStateARM::CompareState (EmulationStateARM &other_state) -{ - bool match = true; - - for (int i = 0; match && i < 17; ++i) - { - if (m_gpr[i] != other_state.m_gpr[i]) - match = false; - } - - for (int i = 0; match && i < 32; ++i) - { - if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i]) - match = false; - } - - for (int i = 0; match && i < 16; ++i) - { - if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i]) - match = false; - } - - return match; + +bool EmulationStateARM::CompareState(EmulationStateARM &other_state) { + bool match = true; + + for (int i = 0; match && i < 17; ++i) { + if (m_gpr[i] != other_state.m_gpr[i]) + match = false; + } + + for (int i = 0; match && i < 32; ++i) { + if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i]) + match = false; + } + + for (int i = 0; match && i < 16; ++i) { + if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i]) + match = false; + } + + return match; } -bool -EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data) -{ - static ConstString memory_key ("memory"); - static ConstString registers_key ("registers"); - - if (!test_data) +bool EmulationStateARM::LoadStateFromDictionary( + OptionValueDictionary *test_data) { + static ConstString memory_key("memory"); + static ConstString registers_key("registers"); + + if (!test_data) + return false; + + OptionValueSP value_sp = test_data->GetValueForKey(memory_key); + + // Load memory, if present. + + if (value_sp.get() != NULL) { + static ConstString address_key("address"); + static ConstString data_key("data"); + uint64_t start_address = 0; + + OptionValueDictionary *mem_dict = value_sp->GetAsDictionary(); + value_sp = mem_dict->GetValueForKey(address_key); + if (value_sp.get() == NULL) + return false; + else + start_address = value_sp->GetUInt64Value(); + + value_sp = mem_dict->GetValueForKey(data_key); + OptionValueArray *mem_array = value_sp->GetAsArray(); + if (!mem_array) + return false; + + uint32_t num_elts = mem_array->GetSize(); + uint32_t address = (uint32_t)start_address; + + for (uint32_t i = 0; i < num_elts; ++i) { + value_sp = mem_array->GetValueAtIndex(i); + if (value_sp.get() == NULL) return false; - - OptionValueSP value_sp = test_data->GetValueForKey (memory_key); - - // Load memory, if present. - - if (value_sp.get() != NULL) - { - static ConstString address_key ("address"); - static ConstString data_key ("data"); - uint64_t start_address = 0; - - OptionValueDictionary *mem_dict = value_sp->GetAsDictionary(); - value_sp = mem_dict->GetValueForKey (address_key); - if (value_sp.get() == NULL) - return false; - else - start_address = value_sp->GetUInt64Value (); - - value_sp = mem_dict->GetValueForKey (data_key); - OptionValueArray *mem_array = value_sp->GetAsArray(); - if (!mem_array) - return false; - - uint32_t num_elts = mem_array->GetSize(); - uint32_t address = (uint32_t) start_address; - - for (uint32_t i = 0; i < num_elts; ++i) - { - value_sp = mem_array->GetValueAtIndex (i); - if (value_sp.get() == NULL) - return false; - uint64_t value = value_sp->GetUInt64Value(); - StoreToPseudoAddress (address, value); - address = address + 4; - } + uint64_t value = value_sp->GetUInt64Value(); + StoreToPseudoAddress(address, value); + address = address + 4; } - - value_sp = test_data->GetValueForKey (registers_key); + } + + value_sp = test_data->GetValueForKey(registers_key); + if (value_sp.get() == NULL) + return false; + + // Load General Registers + + OptionValueDictionary *reg_dict = value_sp->GetAsDictionary(); + + StreamString sstr; + for (int i = 0; i < 16; ++i) { + sstr.Clear(); + sstr.Printf("r%d", i); + ConstString reg_name(sstr.GetString()); + value_sp = reg_dict->GetValueForKey(reg_name); if (value_sp.get() == NULL) - return false; + return false; + uint64_t reg_value = value_sp->GetUInt64Value(); + StorePseudoRegisterValue(dwarf_r0 + i, reg_value); + } - - // Load General Registers - - OptionValueDictionary *reg_dict = value_sp->GetAsDictionary (); - - StreamString sstr; - for (int i = 0; i < 16; ++i) - { - sstr.Clear(); - sstr.Printf ("r%d", i); - ConstString reg_name (sstr.GetData()); - value_sp = reg_dict->GetValueForKey (reg_name); - if (value_sp.get() == NULL) - return false; - uint64_t reg_value = value_sp->GetUInt64Value(); - StorePseudoRegisterValue (dwarf_r0 + i, reg_value); - } - - static ConstString cpsr_name ("cpsr"); - value_sp = reg_dict->GetValueForKey (cpsr_name); + static ConstString cpsr_name("cpsr"); + value_sp = reg_dict->GetValueForKey(cpsr_name); + if (value_sp.get() == NULL) + return false; + StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value()); + + // Load s/d Registers + for (int i = 0; i < 32; ++i) { + sstr.Clear(); + sstr.Printf("s%d", i); + ConstString reg_name(sstr.GetString()); + value_sp = reg_dict->GetValueForKey(reg_name); if (value_sp.get() == NULL) - return false; - StorePseudoRegisterValue (dwarf_cpsr, value_sp->GetUInt64Value()); - - // Load s/d Registers - for (int i = 0; i < 32; ++i) - { - sstr.Clear(); - sstr.Printf ("s%d", i); - ConstString reg_name (sstr.GetData()); - value_sp = reg_dict->GetValueForKey (reg_name); - if (value_sp.get() == NULL) - return false; - uint64_t reg_value = value_sp->GetUInt64Value(); - StorePseudoRegisterValue (dwarf_s0 + i, reg_value); - } + return false; + uint64_t reg_value = value_sp->GetUInt64Value(); + StorePseudoRegisterValue(dwarf_s0 + i, reg_value); + } - return true; + return true; } - diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.h b/source/Plugins/Instruction/ARM/EmulationStateARM.h index e82ef94b5a01..f27f4755a177 100644 --- a/source/Plugins/Instruction/ARM/EmulationStateARM.h +++ b/source/Plugins/Instruction/ARM/EmulationStateARM.h @@ -16,81 +16,65 @@ #include "lldb/Core/Opcode.h" class EmulationStateARM { -public: - - EmulationStateARM (); - - virtual - ~EmulationStateARM (); - - bool - StorePseudoRegisterValue (uint32_t reg_num, uint64_t value); - - uint64_t - ReadPseudoRegisterValue (uint32_t reg_num, bool &success); - - bool - StoreToPseudoAddress (lldb::addr_t p_address, uint32_t value); - - uint32_t - ReadFromPseudoAddress (lldb::addr_t p_address, bool &success); - - void - ClearPseudoRegisters (); - - void - ClearPseudoMemory (); - - bool - LoadPseudoRegistersFromFrame (lldb_private::StackFrame &frame); - - bool - LoadStateFromDictionary (lldb_private::OptionValueDictionary *test_data); - - bool - CompareState (EmulationStateARM &other_state); - - static size_t - ReadPseudoMemory (lldb_private::EmulateInstruction *instruction, +public: + EmulationStateARM(); + + virtual ~EmulationStateARM(); + + bool StorePseudoRegisterValue(uint32_t reg_num, uint64_t value); + + uint64_t ReadPseudoRegisterValue(uint32_t reg_num, bool &success); + + bool StoreToPseudoAddress(lldb::addr_t p_address, uint32_t value); + + uint32_t ReadFromPseudoAddress(lldb::addr_t p_address, bool &success); + + void ClearPseudoRegisters(); + + void ClearPseudoMemory(); + + bool LoadPseudoRegistersFromFrame(lldb_private::StackFrame &frame); + + bool LoadStateFromDictionary(lldb_private::OptionValueDictionary *test_data); + + bool CompareState(EmulationStateARM &other_state); + + static size_t + ReadPseudoMemory(lldb_private::EmulateInstruction *instruction, void *baton, + const lldb_private::EmulateInstruction::Context &context, + lldb::addr_t addr, void *dst, size_t length); + + static size_t + WritePseudoMemory(lldb_private::EmulateInstruction *instruction, void *baton, + const lldb_private::EmulateInstruction::Context &context, + lldb::addr_t addr, const void *dst, size_t length); + + static bool ReadPseudoRegister(lldb_private::EmulateInstruction *instruction, + void *baton, + const lldb_private::RegisterInfo *reg_info, + lldb_private::RegisterValue ®_value); + + static bool + WritePseudoRegister(lldb_private::EmulateInstruction *instruction, void *baton, const lldb_private::EmulateInstruction::Context &context, - lldb::addr_t addr, - void *dst, - size_t length); - - static size_t - WritePseudoMemory (lldb_private::EmulateInstruction *instruction, - void *baton, - const lldb_private::EmulateInstruction::Context &context, - lldb::addr_t addr, - const void *dst, - size_t length); - - static bool - ReadPseudoRegister (lldb_private::EmulateInstruction *instruction, - void *baton, - const lldb_private::RegisterInfo *reg_info, - lldb_private::RegisterValue ®_value); - - static bool - WritePseudoRegister (lldb_private::EmulateInstruction *instruction, - void *baton, - const lldb_private::EmulateInstruction::Context &context, - const lldb_private::RegisterInfo *reg_info, - const lldb_private::RegisterValue ®_value); + const lldb_private::RegisterInfo *reg_info, + const lldb_private::RegisterValue ®_value); + private: - uint32_t m_gpr[17]; - struct _sd_regs - { - uint32_t s_regs[32]; // sregs 0 - 31 & dregs 0 - 15 - - uint64_t d_regs[16]; // dregs 16-31 - - } m_vfp_regs; - - std::map<lldb::addr_t, uint32_t> m_memory; // Eventually will want to change uint32_t to a data buffer heap type. - - DISALLOW_COPY_AND_ASSIGN (EmulationStateARM); + uint32_t m_gpr[17]; + struct _sd_regs { + uint32_t s_regs[32]; // sregs 0 - 31 & dregs 0 - 15 + + uint64_t d_regs[16]; // dregs 16-31 + + } m_vfp_regs; + + std::map<lldb::addr_t, uint32_t> m_memory; // Eventually will want to change + // uint32_t to a data buffer heap + // type. + + DISALLOW_COPY_AND_ASSIGN(EmulationStateARM); }; -#endif // lldb_EmulationStateARM_h_ +#endif // lldb_EmulationStateARM_h_ diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp index ea67928280d3..43f23097c0d9 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -1,4 +1,4 @@ -//===-- EmulateInstructionARM64.cpp -------------------------------*- C++ -*-===// +//===-- EmulateInstructionARM64.cpp ------------------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -11,8 +11,8 @@ #include <stdlib.h> -#include "lldb/Core/ArchSpec.h" #include "lldb/Core/Address.h" +#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Stream.h" @@ -20,7 +20,24 @@ #include "Plugins/Process/Utility/ARMDefines.h" #include "Plugins/Process/Utility/ARMUtils.h" -#include "Utility/ARM64_DWARF_Registers.h" +#include "Plugins/Process/Utility/lldb-arm64-register-enums.h" + +#define GPR_OFFSET(idx) ((idx)*8) +#define GPR_OFFSET_NAME(reg) 0 +#define FPU_OFFSET(idx) ((idx)*16) +#define FPU_OFFSET_NAME(reg) 0 +#define EXC_OFFSET_NAME(reg) 0 +#define DBG_OFFSET_NAME(reg) 0 +#define DBG_OFFSET_NAME(reg) 0 +#define DEFINE_DBG(re, y) \ + "na", nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex, \ + {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM}, \ + nullptr, nullptr, nullptr, 0 + +#define DECLARE_REGISTER_INFOS_ARM64_STRUCT + +#include "Plugins/Process/Utility/RegisterInfos_arm64.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/MathExtras.h" // for SignExtend32 template function @@ -31,15 +48,22 @@ using namespace lldb; using namespace lldb_private; -#define No_VFP 0 -#define VFPv1 (1u << 1) -#define VFPv2 (1u << 2) -#define VFPv3 (1u << 3) +static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo ®_info) { + if (reg_num >= llvm::array_lengthof(g_register_infos_arm64_le)) + return false; + reg_info = g_register_infos_arm64_le[reg_num]; + return true; +} + +#define No_VFP 0 +#define VFPv1 (1u << 1) +#define VFPv2 (1u << 2) +#define VFPv3 (1u << 3) #define AdvancedSIMD (1u << 4) #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD) #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD) -#define VFPv2v3 (VFPv2 | VFPv3) +#define VFPv2v3 (VFPv2 | VFPv3) #define UInt(x) ((uint64_t)x) #define SInt(x) ((int64_t)x) @@ -47,17 +71,9 @@ using namespace lldb_private; #define boolean bool #define integer int64_t -static inline bool -IsZero(uint64_t x) -{ - return x == 0; -} +static inline bool IsZero(uint64_t x) { return x == 0; } -static inline uint64_t -NOT(uint64_t x) -{ - return ~x; -} +static inline uint64_t NOT(uint64_t x) { return ~x; } #if 0 // LSL_C() @@ -75,354 +91,435 @@ LSL_C (uint64_t x, integer shift, bool &carry_out) // LSL() // ===== -static inline uint64_t -LSL(uint64_t x, integer shift) -{ - if (shift == 0) - return x; - return x << shift; +static inline uint64_t LSL(uint64_t x, integer shift) { + if (shift == 0) + return x; + return x << shift; } // AddWithCarry() // =============== static inline uint64_t -AddWithCarry (uint32_t N, uint64_t x, uint64_t y, bit carry_in, EmulateInstructionARM64::ProcState &proc_state) -{ - uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in); - int64_t signed_sum = SInt(x) + SInt(y) + UInt(carry_in); - uint64_t result = unsigned_sum; - if (N < 64) - result = Bits64 (result, N-1, 0); - proc_state.N = Bit64(result, N-1); - proc_state.Z = IsZero(result); - proc_state.C = UInt(result) == unsigned_sum; - proc_state.V = SInt(result) == signed_sum; - return result; +AddWithCarry(uint32_t N, uint64_t x, uint64_t y, bit carry_in, + EmulateInstructionARM64::ProcState &proc_state) { + uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in); + int64_t signed_sum = SInt(x) + SInt(y) + UInt(carry_in); + uint64_t result = unsigned_sum; + if (N < 64) + result = Bits64(result, N - 1, 0); + proc_state.N = Bit64(result, N - 1); + proc_state.Z = IsZero(result); + proc_state.C = UInt(result) == unsigned_sum; + proc_state.V = SInt(result) == signed_sum; + return result; } // ConstrainUnpredictable() // ======================== EmulateInstructionARM64::ConstraintType -ConstrainUnpredictable (EmulateInstructionARM64::Unpredictable which) -{ - EmulateInstructionARM64::ConstraintType result = EmulateInstructionARM64::Constraint_UNKNOWN; - switch (which) - { - case EmulateInstructionARM64::Unpredictable_WBOVERLAP: - case EmulateInstructionARM64::Unpredictable_LDPOVERLAP: - // TODO: don't know what to really do here? Pseudo code says: - // set result to one of above Constraint behaviours or UNDEFINED - break; - } - return result; +ConstrainUnpredictable(EmulateInstructionARM64::Unpredictable which) { + EmulateInstructionARM64::ConstraintType result = + EmulateInstructionARM64::Constraint_UNKNOWN; + switch (which) { + case EmulateInstructionARM64::Unpredictable_WBOVERLAP: + case EmulateInstructionARM64::Unpredictable_LDPOVERLAP: + // TODO: don't know what to really do here? Pseudo code says: + // set result to one of above Constraint behaviours or UNDEFINED + break; + } + return result; } - - //---------------------------------------------------------------------- // // EmulateInstructionARM implementation // //---------------------------------------------------------------------- -void -EmulateInstructionARM64::Initialize () -{ - PluginManager::RegisterPlugin (GetPluginNameStatic (), - GetPluginDescriptionStatic (), - CreateInstance); +void EmulateInstructionARM64::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); } -void -EmulateInstructionARM64::Terminate () -{ - PluginManager::UnregisterPlugin (CreateInstance); +void EmulateInstructionARM64::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); } -ConstString -EmulateInstructionARM64::GetPluginNameStatic () -{ - ConstString g_plugin_name ("lldb.emulate-instruction.arm64"); - return g_plugin_name; +ConstString EmulateInstructionARM64::GetPluginNameStatic() { + ConstString g_plugin_name("lldb.emulate-instruction.arm64"); + return g_plugin_name; } -lldb_private::ConstString -EmulateInstructionARM64::GetPluginName() -{ - static ConstString g_plugin_name ("EmulateInstructionARM64"); - return g_plugin_name; +lldb_private::ConstString EmulateInstructionARM64::GetPluginName() { + static ConstString g_plugin_name("EmulateInstructionARM64"); + return g_plugin_name; } -const char * -EmulateInstructionARM64::GetPluginDescriptionStatic () -{ - return "Emulate instructions for the ARM64 architecture."; +const char *EmulateInstructionARM64::GetPluginDescriptionStatic() { + return "Emulate instructions for the ARM64 architecture."; } EmulateInstruction * -EmulateInstructionARM64::CreateInstance (const ArchSpec &arch, InstructionType inst_type) -{ - if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic(inst_type)) - { - if (arch.GetTriple().getArch() == llvm::Triple::aarch64) - { - std::auto_ptr<EmulateInstructionARM64> emulate_insn_ap (new EmulateInstructionARM64 (arch)); - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); - } +EmulateInstructionARM64::CreateInstance(const ArchSpec &arch, + InstructionType inst_type) { + if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic( + inst_type)) { + if (arch.GetTriple().getArch() == llvm::Triple::aarch64) { + std::auto_ptr<EmulateInstructionARM64> emulate_insn_ap( + new EmulateInstructionARM64(arch)); + if (emulate_insn_ap.get()) + return emulate_insn_ap.release(); } - - return NULL; + } + + return NULL; } -bool -EmulateInstructionARM64::SetTargetTriple (const ArchSpec &arch) -{ - if (arch.GetTriple().getArch () == llvm::Triple::arm) - return true; - else if (arch.GetTriple().getArch () == llvm::Triple::thumb) - return true; +bool EmulateInstructionARM64::SetTargetTriple(const ArchSpec &arch) { + if (arch.GetTriple().getArch() == llvm::Triple::arm) + return true; + else if (arch.GetTriple().getArch() == llvm::Triple::thumb) + return true; - return false; + return false; } -bool -EmulateInstructionARM64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) -{ - if (reg_kind == eRegisterKindGeneric) - { - switch (reg_num) - { - case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::pc; break; - case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::sp; break; - case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::fp; break; - case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::lr; break; - case LLDB_REGNUM_GENERIC_FLAGS: - // There is no DWARF register number for the CPSR right now... - reg_info.name = "cpsr"; - reg_info.alt_name = NULL; - reg_info.byte_size = 4; - reg_info.byte_offset = 0; - reg_info.encoding = eEncodingUint; - reg_info.format = eFormatHex; - for (uint32_t i=0; i<lldb::kNumRegisterKinds; ++i) - reg_info.kinds[reg_kind] = LLDB_INVALID_REGNUM; - reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; - return true; - - default: return false; - } +bool EmulateInstructionARM64::GetRegisterInfo(RegisterKind reg_kind, + uint32_t reg_num, + RegisterInfo ®_info) { + if (reg_kind == eRegisterKindGeneric) { + switch (reg_num) { + case LLDB_REGNUM_GENERIC_PC: + reg_kind = eRegisterKindLLDB; + reg_num = gpr_pc_arm64; + break; + case LLDB_REGNUM_GENERIC_SP: + reg_kind = eRegisterKindLLDB; + reg_num = gpr_sp_arm64; + break; + case LLDB_REGNUM_GENERIC_FP: + reg_kind = eRegisterKindLLDB; + reg_num = gpr_fp_arm64; + break; + case LLDB_REGNUM_GENERIC_RA: + reg_kind = eRegisterKindLLDB; + reg_num = gpr_lr_arm64; + break; + case LLDB_REGNUM_GENERIC_FLAGS: + reg_kind = eRegisterKindLLDB; + reg_num = gpr_cpsr_arm64; + break; + + default: + return false; } - - if (reg_kind == eRegisterKindDWARF) - return arm64_dwarf::GetRegisterInfo(reg_num, reg_info); - return false; + } + + if (reg_kind == eRegisterKindLLDB) + return LLDBTableGetRegisterInfo(reg_num, reg_info); + return false; } -EmulateInstructionARM64::Opcode* -EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode) -{ - static EmulateInstructionARM64::Opcode - g_opcodes[] = - { - //---------------------------------------------------------------------- - // Prologue instructions - //---------------------------------------------------------------------- - - // push register(s) - { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" }, - { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}" }, - { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" }, - { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}" }, - - { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" }, - { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" }, - { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" }, - { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::EmulateADDSUBImm, "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" }, - - { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" }, - - { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - - { 0xffc00000, 0x28800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xa8800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x2c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x6c800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xac800000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - - { 0xffc00000, 0x29400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0xa9400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0x2d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <St>, <St2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0x6d400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" }, - { 0xffc00000, 0xad400000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, "LDP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" }, - - { 0xffc00000, 0x29c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xa9c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x2dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x6dc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xadc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - - { 0xffc00000, 0x28c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xa8c00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x2cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0x6cc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, - { 0xffc00000, 0xacc00000, No_VFP, &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, - - { 0xffe00c00, 0xb8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "STR <Wt>, [<Xn|SP>], #<simm>" }, - { 0xffe00c00, 0xf8000400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "STR <Xt>, [<Xn|SP>], #<simm>" }, - { 0xffe00c00, 0xb8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "STR <Wt>, [<Xn|SP>, #<simm>]!" }, - { 0xffe00c00, 0xf8000c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "STR <Xt>, [<Xn|SP>, #<simm>]!" }, - { 0xffc00000, 0xb9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "STR <Wt>, [<Xn|SP>{, #<pimm>}]" }, - { 0xffc00000, 0xf9000000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "STR <Xt>, [<Xn|SP>{, #<pimm>}]" }, - - { 0xffe00c00, 0xb8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "LDR <Wt>, [<Xn|SP>], #<simm>" }, - { 0xffe00c00, 0xf8400400, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, "LDR <Xt>, [<Xn|SP>], #<simm>" }, - { 0xffe00c00, 0xb8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "LDR <Wt>, [<Xn|SP>, #<simm>]!" }, - { 0xffe00c00, 0xf8400c00, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, "LDR <Xt>, [<Xn|SP>, #<simm>]!" }, - { 0xffc00000, 0xb9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "LDR <Wt>, [<Xn|SP>{, #<pimm>}]" }, - { 0xffc00000, 0xf9400000, No_VFP, &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, "LDR <Xt>, [<Xn|SP>{, #<pimm>}]" }, - - { 0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, "B <label>" }, - { 0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond, "B.<cond> <label>" }, - { 0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBZ <Wt>, <label>" }, - { 0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, "CBNZ <Wt>, <label>" }, - { 0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBZ <R><t>, #<imm>, <label>" }, - { 0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, "TBNZ <R><t>, #<imm>, <label>" }, - - }; - static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes); - - for (size_t i=0; i<k_num_arm_opcodes; ++i) - { - if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value) - return &g_opcodes[i]; - } - return nullptr; +EmulateInstructionARM64::Opcode * +EmulateInstructionARM64::GetOpcodeForInstruction(const uint32_t opcode) { + static EmulateInstructionARM64::Opcode g_opcodes[] = { + //---------------------------------------------------------------------- + // Prologue instructions + //---------------------------------------------------------------------- + + // push register(s) + {0xff000000, 0xd1000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}"}, + {0xff000000, 0xf1000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}"}, + {0xff000000, 0x91000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}"}, + {0xff000000, 0xb1000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}"}, + + {0xff000000, 0x51000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}"}, + {0xff000000, 0x71000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}"}, + {0xff000000, 0x11000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}"}, + {0xff000000, 0x31000000, No_VFP, + &EmulateInstructionARM64::EmulateADDSUBImm, + "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}"}, + + {0xffc00000, 0x29000000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0xa9000000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0x2d000000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0x6d000000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0xad000000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]"}, + + {0xffc00000, 0x29800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xa9800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x2d800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "STP <St>, <St2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x6d800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xad800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"}, + + {0xffc00000, 0x28800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xa8800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x2c800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "STP <St>, <St2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x6c800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xac800000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"}, + + {0xffc00000, 0x29400000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "LDP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0xa9400000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "LDP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0x2d400000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "LDP <St>, <St2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0x6d400000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "LDP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]"}, + {0xffc00000, 0xad400000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_OFF>, + "LDP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]"}, + + {0xffc00000, 0x29c00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xa9c00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x2dc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x6dc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xadc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_PRE>, + "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"}, + + {0xffc00000, 0x28c00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "LDP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xa8c00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "LDP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x2cc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "LDP <St>, <St2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0x6cc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "LDP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!"}, + {0xffc00000, 0xacc00000, No_VFP, + &EmulateInstructionARM64::EmulateLDPSTP<AddrMode_POST>, + "LDP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!"}, + + {0xffe00c00, 0xb8000400, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, + "STR <Wt>, [<Xn|SP>], #<simm>"}, + {0xffe00c00, 0xf8000400, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, + "STR <Xt>, [<Xn|SP>], #<simm>"}, + {0xffe00c00, 0xb8000c00, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, + "STR <Wt>, [<Xn|SP>, #<simm>]!"}, + {0xffe00c00, 0xf8000c00, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, + "STR <Xt>, [<Xn|SP>, #<simm>]!"}, + {0xffc00000, 0xb9000000, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, + "STR <Wt>, [<Xn|SP>{, #<pimm>}]"}, + {0xffc00000, 0xf9000000, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, + "STR <Xt>, [<Xn|SP>{, #<pimm>}]"}, + + {0xffe00c00, 0xb8400400, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, + "LDR <Wt>, [<Xn|SP>], #<simm>"}, + {0xffe00c00, 0xf8400400, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_POST>, + "LDR <Xt>, [<Xn|SP>], #<simm>"}, + {0xffe00c00, 0xb8400c00, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, + "LDR <Wt>, [<Xn|SP>, #<simm>]!"}, + {0xffe00c00, 0xf8400c00, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_PRE>, + "LDR <Xt>, [<Xn|SP>, #<simm>]!"}, + {0xffc00000, 0xb9400000, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, + "LDR <Wt>, [<Xn|SP>{, #<pimm>}]"}, + {0xffc00000, 0xf9400000, No_VFP, + &EmulateInstructionARM64::EmulateLDRSTRImm<AddrMode_OFF>, + "LDR <Xt>, [<Xn|SP>{, #<pimm>}]"}, + + {0xfc000000, 0x14000000, No_VFP, &EmulateInstructionARM64::EmulateB, + "B <label>"}, + {0xff000010, 0x54000000, No_VFP, &EmulateInstructionARM64::EmulateBcond, + "B.<cond> <label>"}, + {0x7f000000, 0x34000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, + "CBZ <Wt>, <label>"}, + {0x7f000000, 0x35000000, No_VFP, &EmulateInstructionARM64::EmulateCBZ, + "CBNZ <Wt>, <label>"}, + {0x7f000000, 0x36000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, + "TBZ <R><t>, #<imm>, <label>"}, + {0x7f000000, 0x37000000, No_VFP, &EmulateInstructionARM64::EmulateTBZ, + "TBNZ <R><t>, #<imm>, <label>"}, + + }; + static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes); + + for (size_t i = 0; i < k_num_arm_opcodes; ++i) { + if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value) + return &g_opcodes[i]; + } + return nullptr; } -bool -EmulateInstructionARM64::ReadInstruction () -{ - bool success = false; - m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); - if (success) - { - Context read_inst_context; - read_inst_context.type = eContextReadOpcode; - read_inst_context.SetNoArgs (); - m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder()); - } - if (!success) - m_addr = LLDB_INVALID_ADDRESS; - return success; +bool EmulateInstructionARM64::ReadInstruction() { + bool success = false; + m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_ADDRESS, &success); + if (success) { + Context read_inst_context; + read_inst_context.type = eContextReadOpcode; + read_inst_context.SetNoArgs(); + m_opcode.SetOpcode32( + ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success), + GetByteOrder()); + } + if (!success) + m_addr = LLDB_INVALID_ADDRESS; + return success; } +bool EmulateInstructionARM64::EvaluateInstruction(uint32_t evaluate_options) { + const uint32_t opcode = m_opcode.GetOpcode32(); + Opcode *opcode_data = GetOpcodeForInstruction(opcode); + if (opcode_data == NULL) + return false; -bool -EmulateInstructionARM64::EvaluateInstruction (uint32_t evaluate_options) -{ - const uint32_t opcode = m_opcode.GetOpcode32(); - Opcode *opcode_data = GetOpcodeForInstruction(opcode); - if (opcode_data == NULL) - return false; - - //printf ("opcode template for 0x%8.8x: %s\n", opcode, opcode_data->name); - const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; - m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions; - - bool success = false; -// if (m_opcode_cpsr == 0 || m_ignore_conditions == false) -// { -// m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, // use eRegisterKindDWARF is we ever get a cpsr DWARF register number -// LLDB_REGNUM_GENERIC_FLAGS, // use arm64_dwarf::cpsr if we ever get one -// 0, -// &success); -// } - - // Only return false if we are unable to read the CPSR if we care about conditions - if (success == false && m_ignore_conditions == false) - return false; - - uint32_t orig_pc_value = 0; - if (auto_advance_pc) - { - orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::pc, 0, &success); - if (!success) - return false; - } - - // Call the Emulate... function. - success = (this->*opcode_data->callback) (opcode); + // printf ("opcode template for 0x%8.8x: %s\n", opcode, opcode_data->name); + const bool auto_advance_pc = + evaluate_options & eEmulateInstructionOptionAutoAdvancePC; + m_ignore_conditions = + evaluate_options & eEmulateInstructionOptionIgnoreConditions; + + bool success = false; + // if (m_opcode_cpsr == 0 || m_ignore_conditions == false) + // { + // m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindLLDB, + // gpr_cpsr_arm64, + // 0, + // &success); + // } + + // Only return false if we are unable to read the CPSR if we care about + // conditions + if (success == false && m_ignore_conditions == false) + return false; + + uint32_t orig_pc_value = 0; + if (auto_advance_pc) { + orig_pc_value = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success); if (!success) + return false; + } + + // Call the Emulate... function. + success = (this->*opcode_data->callback)(opcode); + if (!success) + return false; + + if (auto_advance_pc) { + uint32_t new_pc_value = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_arm64, 0, &success); + if (!success) + return false; + + if (auto_advance_pc && (new_pc_value == orig_pc_value)) { + EmulateInstruction::Context context; + context.type = eContextAdvancePC; + context.SetNoArgs(); + if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_arm64, + orig_pc_value + 4)) return false; - - if (auto_advance_pc) - { - uint32_t new_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::pc, 0, &success); - if (!success) - return false; - - if (auto_advance_pc && (new_pc_value == orig_pc_value)) - { - EmulateInstruction::Context context; - context.type = eContextAdvancePC; - context.SetNoArgs(); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::pc, orig_pc_value + 4)) - return false; - } } - return true; + } + return true; } -bool -EmulateInstructionARM64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) -{ - unwind_plan.Clear(); - unwind_plan.SetRegisterKind (eRegisterKindDWARF); +bool EmulateInstructionARM64::CreateFunctionEntryUnwind( + UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindLLDB); - UnwindPlan::RowSP row(new UnwindPlan::Row); + UnwindPlan::RowSP row(new UnwindPlan::Row); - // Our previous Call Frame Address is the stack pointer - row->GetCFAValue().SetIsRegisterPlusOffset(arm64_dwarf::sp, 0); + // Our previous Call Frame Address is the stack pointer + row->GetCFAValue().SetIsRegisterPlusOffset(gpr_sp_arm64, 0); - unwind_plan.AppendRow (row); - unwind_plan.SetSourceName ("EmulateInstructionARM64"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); - unwind_plan.SetReturnAddressRegister (arm64_dwarf::lr); - return true; + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("EmulateInstructionARM64"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetReturnAddressRegister(gpr_lr_arm64); + return true; } -uint32_t -EmulateInstructionARM64::GetFramePointerRegisterNumber () const -{ - if (m_arch.GetTriple().isAndroid()) - return LLDB_INVALID_REGNUM; // Don't use frame pointer on android +uint32_t EmulateInstructionARM64::GetFramePointerRegisterNumber() const { + if (m_arch.GetTriple().isAndroid()) + return LLDB_INVALID_REGNUM; // Don't use frame pointer on android - return arm64_dwarf::sp; + return gpr_fp_arm64; } -bool -EmulateInstructionARM64::UsingAArch32() -{ - bool aarch32 = m_opcode_pstate.RW == 1; - // if !HaveAnyAArch32() then assert !aarch32; - // if HighestELUsingAArch32() then assert aarch32; - return aarch32; +bool EmulateInstructionARM64::UsingAArch32() { + bool aarch32 = m_opcode_pstate.RW == 1; + // if !HaveAnyAArch32() then assert !aarch32; + // if HighestELUsingAArch32() then assert aarch32; + return aarch32; } -bool -EmulateInstructionARM64::BranchTo (const Context &context, uint32_t N, addr_t target) -{ +bool EmulateInstructionARM64::BranchTo(const Context &context, uint32_t N, + addr_t target) { #if 0 // Set program counter to a new address, with a branch reason hint // for possible use by hardware fetching the next instruction. @@ -450,603 +547,578 @@ EmulateInstructionARM64::BranchTo (const Context &context, uint32_t N, addr_t ta return; #endif - addr_t addr; + addr_t addr; + + // Hint_Branch(branch_type); + if (N == 32) { + if (!UsingAArch32()) + return false; + addr = target; + } else if (N == 64) { + if (UsingAArch32()) + return false; + // TODO: Remove the tag bits from a tagged target + addr = target; + } else + return false; - //Hint_Branch(branch_type); - if (N == 32) - { - if (!UsingAArch32()) - return false; - addr = target; - } - else if (N == 64) - { - if (UsingAArch32()) - return false; - // TODO: Remove the tag bits from a tagged target - addr = target; - } - else - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC, addr)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, addr)) - return false; + return true; +} +bool EmulateInstructionARM64::ConditionHolds(const uint32_t cond) { + // If we are ignoring conditions, then always return true. + // this allows us to iterate over disassembly code and still + // emulate an instruction even if we don't have all the right + // bits set in the CPSR register... + if (m_ignore_conditions) return true; -} -bool -EmulateInstructionARM64::ConditionHolds (const uint32_t cond) -{ - // If we are ignoring conditions, then always return true. - // this allows us to iterate over disassembly code and still - // emulate an instruction even if we don't have all the right - // bits set in the CPSR register... - if (m_ignore_conditions) - return true; - - bool result = false; - switch (UnsignedBits(cond, 3, 1)) - { - case 0: - result = (m_opcode_pstate.Z == 1); - break; - case 1: - result = (m_opcode_pstate.C == 1); - break; - case 2: - result = (m_opcode_pstate.N == 1); - break; - case 3: - result = (m_opcode_pstate.V == 1); - break; - case 4: - result = (m_opcode_pstate.C == 1 && m_opcode_pstate.Z == 0); - break; - case 5: - result = (m_opcode_pstate.N == m_opcode_pstate.V); - break; - case 6: - result = (m_opcode_pstate.N == m_opcode_pstate.V && m_opcode_pstate.Z == 0); - break; - case 7: - // Always execute (cond == 0b1110, or the special 0b1111 which gives - // opcodes different meanings, but always means execution happens. - return true; - } + bool result = false; + switch (UnsignedBits(cond, 3, 1)) { + case 0: + result = (m_opcode_pstate.Z == 1); + break; + case 1: + result = (m_opcode_pstate.C == 1); + break; + case 2: + result = (m_opcode_pstate.N == 1); + break; + case 3: + result = (m_opcode_pstate.V == 1); + break; + case 4: + result = (m_opcode_pstate.C == 1 && m_opcode_pstate.Z == 0); + break; + case 5: + result = (m_opcode_pstate.N == m_opcode_pstate.V); + break; + case 6: + result = (m_opcode_pstate.N == m_opcode_pstate.V && m_opcode_pstate.Z == 0); + break; + case 7: + // Always execute (cond == 0b1110, or the special 0b1111 which gives + // opcodes different meanings, but always means execution happens. + return true; + } - if (cond & 1) - result = !result; - return result; + if (cond & 1) + result = !result; + return result; } -bool -EmulateInstructionARM64::EmulateADDSUBImm (const uint32_t opcode) -{ - // integer d = UInt(Rd); - // integer n = UInt(Rn); - // integer datasize = if sf == 1 then 64 else 32; - // boolean sub_op = (op == 1); - // boolean setflags = (S == 1); - // bits(datasize) imm; - // - // case shift of - // when '00' imm = ZeroExtend(imm12, datasize); - // when '01' imm = ZeroExtend(imm12 : Zeros(12), datasize); - // when '1x' UNDEFINED; - // - // - // bits(datasize) result; - // bits(datasize) operand1 = if n == 31 then SP[] else X[n]; - // bits(datasize) operand2 = imm; - // bits(4) nzcv; - // bit carry_in; - // - // if sub_op then - // operand2 = NOT(operand2); - // carry_in = 1; - // else - // carry_in = 0; - // - // (result, nzcv) = AddWithCarry(operand1, operand2, carry_in); - // - // if setflags then - // PSTATE.NZCV = nzcv; - // - // if d == 31 && !setflags then - // SP[] = result; - // else - // X[d] = result; - - const uint32_t sf = Bit32(opcode, 31); - const uint32_t op = Bit32(opcode, 30); - const uint32_t S = Bit32(opcode, 29); - const uint32_t shift = Bits32(opcode, 23, 22); - const uint32_t imm12 = Bits32(opcode, 21, 10); - const uint32_t Rn = Bits32(opcode, 9, 5); - const uint32_t Rd = Bits32(opcode, 4, 0); - - bool success = false; - - const uint32_t d = UInt(Rd); - const uint32_t n = UInt(Rn); - const uint32_t datasize = (sf == 1) ? 64 : 32; - boolean sub_op = op == 1; - boolean setflags = S == 1; - uint64_t imm; - - switch (shift) - { - case 0: imm = imm12; break; - case 1: imm = imm12 << 12; break; - default: return false; // UNDEFINED; - } - uint64_t result; - uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success); - uint64_t operand2 = imm; - bit carry_in; - - if (sub_op) - { - operand2 = NOT(operand2); - carry_in = 1; - imm = -imm; // For the Register plug offset context below - } - else - { - carry_in = 0; - } - - ProcState proc_state; - - result = AddWithCarry (datasize, operand1, operand2, carry_in, proc_state); +bool EmulateInstructionARM64::EmulateADDSUBImm(const uint32_t opcode) { + // integer d = UInt(Rd); + // integer n = UInt(Rn); + // integer datasize = if sf == 1 then 64 else 32; + // boolean sub_op = (op == 1); + // boolean setflags = (S == 1); + // bits(datasize) imm; + // + // case shift of + // when '00' imm = ZeroExtend(imm12, datasize); + // when '01' imm = ZeroExtend(imm12 : Zeros(12), datasize); + // when '1x' UNDEFINED; + // + // + // bits(datasize) result; + // bits(datasize) operand1 = if n == 31 then SP[] else X[n]; + // bits(datasize) operand2 = imm; + // bits(4) nzcv; + // bit carry_in; + // + // if sub_op then + // operand2 = NOT(operand2); + // carry_in = 1; + // else + // carry_in = 0; + // + // (result, nzcv) = AddWithCarry(operand1, operand2, carry_in); + // + // if setflags then + // PSTATE.NZCV = nzcv; + // + // if d == 31 && !setflags then + // SP[] = result; + // else + // X[d] = result; + + const uint32_t sf = Bit32(opcode, 31); + const uint32_t op = Bit32(opcode, 30); + const uint32_t S = Bit32(opcode, 29); + const uint32_t shift = Bits32(opcode, 23, 22); + const uint32_t imm12 = Bits32(opcode, 21, 10); + const uint32_t Rn = Bits32(opcode, 9, 5); + const uint32_t Rd = Bits32(opcode, 4, 0); + + bool success = false; + + const uint32_t d = UInt(Rd); + const uint32_t n = UInt(Rn); + const uint32_t datasize = (sf == 1) ? 64 : 32; + boolean sub_op = op == 1; + boolean setflags = S == 1; + uint64_t imm; + + switch (shift) { + case 0: + imm = imm12; + break; + case 1: + imm = imm12 << 12; + break; + default: + return false; // UNDEFINED; + } + uint64_t result; + uint64_t operand1 = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success); + uint64_t operand2 = imm; + bit carry_in; + + if (sub_op) { + operand2 = NOT(operand2); + carry_in = 1; + imm = -imm; // For the Register plug offset context below + } else { + carry_in = 0; + } + + ProcState proc_state; + + result = AddWithCarry(datasize, operand1, operand2, carry_in, proc_state); + + if (setflags) { + m_emulated_pstate.N = proc_state.N; + m_emulated_pstate.Z = proc_state.Z; + m_emulated_pstate.C = proc_state.C; + m_emulated_pstate.V = proc_state.V; + } + + Context context; + RegisterInfo reg_info_Rn; + if (GetRegisterInfo(eRegisterKindLLDB, n, reg_info_Rn)) + context.SetRegisterPlusOffset(reg_info_Rn, imm); + + if (n == GetFramePointerRegisterNumber() && d == gpr_sp_arm64 && !setflags) { + // 'mov sp, fp' - common epilogue instruction, CFA is now in terms + // of the stack pointer, instead of frame pointer. + context.type = EmulateInstruction::eContextRestoreStackPointer; + } else if ((n == gpr_sp_arm64 || n == GetFramePointerRegisterNumber()) && + d == gpr_sp_arm64 && !setflags) { + context.type = EmulateInstruction::eContextAdjustStackPointer; + } else if (d == GetFramePointerRegisterNumber() && n == gpr_sp_arm64 && + !setflags) { + context.type = EmulateInstruction::eContextSetFramePointer; + } else { + context.type = EmulateInstruction::eContextImmediate; + } + + // If setflags && d == gpr_sp_arm64 then d = WZR/XZR. See CMN, CMP + if (!setflags || d != gpr_sp_arm64) + WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_x0_arm64 + d, result); + + return false; +} - if (setflags) - { - m_emulated_pstate.N = proc_state.N; - m_emulated_pstate.Z = proc_state.Z; - m_emulated_pstate.C = proc_state.C; - m_emulated_pstate.V = proc_state.V; +template <EmulateInstructionARM64::AddrMode a_mode> +bool EmulateInstructionARM64::EmulateLDPSTP(const uint32_t opcode) { + uint32_t opc = Bits32(opcode, 31, 30); + uint32_t V = Bit32(opcode, 26); + uint32_t L = Bit32(opcode, 22); + uint32_t imm7 = Bits32(opcode, 21, 15); + uint32_t Rt2 = Bits32(opcode, 14, 10); + uint32_t Rn = Bits32(opcode, 9, 5); + uint32_t Rt = Bits32(opcode, 4, 0); + + integer n = UInt(Rn); + integer t = UInt(Rt); + integer t2 = UInt(Rt2); + uint64_t idx; + + MemOp memop = L == 1 ? MemOp_LOAD : MemOp_STORE; + boolean vector = (V == 1); + // AccType acctype = AccType_NORMAL; + boolean is_signed = false; + boolean wback = a_mode != AddrMode_OFF; + boolean wb_unknown = false; + boolean rt_unknown = false; + integer scale; + integer size; + + if (opc == 3) + return false; // UNDEFINED + + if (vector) { + scale = 2 + UInt(opc); + } else { + scale = (opc & 2) ? 3 : 2; + is_signed = (opc & 1) != 0; + if (is_signed && memop == MemOp_STORE) + return false; // UNDEFINED + } + + if (!vector && wback && ((t == n) || (t2 == n))) { + switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) { + case Constraint_UNKNOWN: + wb_unknown = true; // writeback is UNKNOWN + break; + + case Constraint_SUPPRESSWB: + wback = false; // writeback is suppressed + break; + + case Constraint_NOP: + memop = MemOp_NOP; // do nothing + wback = false; + break; + + case Constraint_NONE: + break; } - - Context context; - RegisterInfo reg_info_Rn; - if (arm64_dwarf::GetRegisterInfo (n, reg_info_Rn)) - context.SetRegisterPlusOffset (reg_info_Rn, imm); + } - if ((n == arm64_dwarf::sp || n == GetFramePointerRegisterNumber()) && - d == arm64_dwarf::sp && - !setflags) - { - context.type = EmulateInstruction::eContextAdjustStackPointer; - } - else if (d == GetFramePointerRegisterNumber() && - n == arm64_dwarf::sp && - !setflags) - { - context.type = EmulateInstruction::eContextSetFramePointer; - } - else - { - context.type = EmulateInstruction::eContextImmediate; + if (memop == MemOp_LOAD && t == t2) { + switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) { + case Constraint_UNKNOWN: + rt_unknown = true; // result is UNKNOWN + break; + + case Constraint_NOP: + memop = MemOp_NOP; // do nothing + wback = false; + break; + + default: + break; } + } + + idx = LSL(llvm::SignExtend64<7>(imm7), scale); + size = (integer)1 << scale; + uint64_t datasize = size * 8; + uint64_t address; + uint64_t wb_address; - // If setflags && d == arm64_dwarf::sp then d = WZR/XZR. See CMN, CMP - if (!setflags || d != arm64_dwarf::sp) - WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::x0 + d, result); + RegisterValue data_Rt; + RegisterValue data_Rt2; + // if (vector) + // CheckFPEnabled(false); + + RegisterInfo reg_info_base; + RegisterInfo reg_info_Rt; + RegisterInfo reg_info_Rt2; + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base)) return false; -} -template <EmulateInstructionARM64::AddrMode a_mode> bool -EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode) -{ - uint32_t opc = Bits32(opcode, 31, 30); - uint32_t V = Bit32(opcode, 26); - uint32_t L = Bit32(opcode, 22); - uint32_t imm7 = Bits32(opcode, 21, 15); - uint32_t Rt2 = Bits32(opcode, 14, 10); - uint32_t Rn = Bits32(opcode, 9, 5); - uint32_t Rt = Bits32(opcode, 4, 0); - - integer n = UInt(Rn); - integer t = UInt(Rt); - integer t2 = UInt(Rt2); - uint64_t idx; - - MemOp memop = L == 1 ? MemOp_LOAD : MemOp_STORE; - boolean vector = (V == 1); - //AccType acctype = AccType_NORMAL; - boolean is_signed = false; - boolean wback = a_mode != AddrMode_OFF; - boolean wb_unknown = false; - boolean rt_unknown = false; - integer scale; - integer size; - - if (opc == 3) - return false; // UNDEFINED - - if (vector) - { - scale = 2 + UInt(opc); - } - else + if (vector) { + if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t, reg_info_Rt)) + return false; + if (!GetRegisterInfo(eRegisterKindLLDB, fpu_d0_arm64 + t2, reg_info_Rt2)) + return false; + } else { + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt)) + return false; + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t2, reg_info_Rt2)) + return false; + } + + bool success = false; + if (n == 31) { + // CheckSPAlignment(); + address = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success); + } else + address = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success); + + wb_address = address + idx; + if (a_mode != AddrMode_POST) + address = wb_address; + + Context context_t; + Context context_t2; + + uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; + Error error; + + switch (memop) { + case MemOp_STORE: { + if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is + // based off of the sp + // or fp register { - scale = (opc & 2) ? 3 : 2; - is_signed = (opc & 1) != 0; - if (is_signed && memop == MemOp_STORE) - return false; // UNDEFINED - } - - if (!vector && wback && ((t == n) || (t2 == n))) - { - switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) - { - case Constraint_UNKNOWN: - wb_unknown = true; // writeback is UNKNOWN - break; - - case Constraint_SUPPRESSWB: - wback = false; // writeback is suppressed - break; - - case Constraint_NOP: - memop = MemOp_NOP; // do nothing - wback = false; - break; - - case Constraint_NONE: - break; - } + context_t.type = eContextPushRegisterOnStack; + context_t2.type = eContextPushRegisterOnStack; + } else { + context_t.type = eContextRegisterStore; + context_t2.type = eContextRegisterStore; } + context_t.SetRegisterToRegisterPlusOffset(reg_info_Rt, reg_info_base, 0); + context_t2.SetRegisterToRegisterPlusOffset(reg_info_Rt2, reg_info_base, + size); + + if (!ReadRegister(®_info_Rt, data_Rt)) + return false; + + if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, + eByteOrderLittle, error) == 0) + return false; + + if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size)) + return false; + + if (!ReadRegister(®_info_Rt2, data_Rt2)) + return false; + + if (data_Rt2.GetAsMemoryData(®_info_Rt2, buffer, reg_info_Rt2.byte_size, + eByteOrderLittle, error) == 0) + return false; - if (memop == MemOp_LOAD && t == t2) + if (!WriteMemory(context_t2, address + size, buffer, + reg_info_Rt2.byte_size)) + return false; + } break; + + case MemOp_LOAD: { + if (n == 31 || n == GetFramePointerRegisterNumber()) // if this load is + // based off of the sp + // or fp register { - switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) - { - case Constraint_UNKNOWN: - rt_unknown = true; // result is UNKNOWN - break; - - case Constraint_NOP: - memop = MemOp_NOP; // do nothing - wback = false; - break; - - default: - break; - } + context_t.type = eContextPopRegisterOffStack; + context_t2.type = eContextPopRegisterOffStack; + } else { + context_t.type = eContextRegisterLoad; + context_t2.type = eContextRegisterLoad; } - - idx = LSL(llvm::SignExtend64<7>(imm7), scale); - size = (integer)1 << scale; - uint64_t datasize = size * 8; - uint64_t address; - uint64_t wb_address; - - RegisterValue data_Rt; - RegisterValue data_Rt2; - - // if (vector) - // CheckFPEnabled(false); - - RegisterInfo reg_info_base; - RegisterInfo reg_info_Rt; - RegisterInfo reg_info_Rt2; - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base)) + context_t.SetAddress(address); + context_t2.SetAddress(address + size); + + if (rt_unknown) + memset(buffer, 'U', reg_info_Rt.byte_size); + else { + if (!ReadMemory(context_t, address, buffer, reg_info_Rt.byte_size)) return false; - - if (vector) - { - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt)) - return false; - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt2)) - return false; - } - else - { - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt)) - return false; - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t2, reg_info_Rt2)) - return false; - } - - bool success = false; - if (n == 31) - { - //CheckSPAlignment(); - address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::sp, 0, &success); } - else - address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success); - - wb_address = address + idx; - if (a_mode != AddrMode_POST) - address = wb_address; - - Context context_t; - Context context_t2; - - uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; - Error error; - - switch (memop) - { - case MemOp_STORE: - { - if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register - { - context_t.type = eContextPushRegisterOnStack; - context_t2.type = eContextPushRegisterOnStack; - } - else - { - context_t.type = eContextRegisterStore; - context_t2.type = eContextRegisterStore; - } - context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0); - context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size); - - if (!ReadRegister (®_info_Rt, data_Rt)) - return false; - - if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size)) - return false; - - if (!ReadRegister (®_info_Rt2, data_Rt2)) - return false; - - if (data_Rt2.GetAsMemoryData(®_info_Rt2, buffer, reg_info_Rt2.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!WriteMemory(context_t2, address + size, buffer, reg_info_Rt2.byte_size)) - return false; - } - break; - - case MemOp_LOAD: - { - if (n == 31 || n == GetFramePointerRegisterNumber()) // if this load is based off of the sp or fp register - { - context_t.type = eContextPopRegisterOffStack; - context_t2.type = eContextPopRegisterOffStack; - } - else - { - context_t.type = eContextRegisterLoad; - context_t2.type = eContextRegisterLoad; - } - context_t.SetAddress(address); - context_t2.SetAddress(address + size); - - if (rt_unknown) - memset (buffer, 'U', reg_info_Rt.byte_size); - else - { - if (!ReadMemory (context_t, address, buffer, reg_info_Rt.byte_size)) - return false; - } - - if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!vector && is_signed && !data_Rt.SignExtend (datasize)) - return false; - - if (!WriteRegister (context_t, ®_info_Rt, data_Rt)) - return false; - - if (!rt_unknown) - { - if (!ReadMemory (context_t2, address + size, buffer, reg_info_Rt2.byte_size)) - return false; - } - - if (data_Rt2.SetFromMemoryData(®_info_Rt2, buffer, reg_info_Rt2.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!vector && is_signed && !data_Rt2.SignExtend (datasize)) - return false; - - if (!WriteRegister (context_t2, ®_info_Rt2, data_Rt2)) - return false; - } - break; - - default: - break; - } - - if (wback) - { - if (wb_unknown) - wb_address = LLDB_INVALID_ADDRESS; - Context context; - context.SetImmediateSigned (idx); - if (n == 31) - context.type = eContextAdjustStackPointer; - else - context.type = eContextAdjustBaseRegister; - WriteRegisterUnsigned (context, ®_info_base, wb_address); - } - return true; -} -template <EmulateInstructionARM64::AddrMode a_mode> bool -EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode) -{ - uint32_t size = Bits32(opcode, 31, 30); - uint32_t opc = Bits32(opcode, 23, 22); - uint32_t n = Bits32(opcode, 9, 5); - uint32_t t = Bits32(opcode, 4, 0); + if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, + eByteOrderLittle, error) == 0) + return false; - bool wback; - bool postindex; - uint64_t offset; + if (!vector && is_signed && !data_Rt.SignExtend(datasize)) + return false; - switch (a_mode) - { - case AddrMode_POST: - wback = true; - postindex = true; - offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12)); - break; - case AddrMode_PRE: - wback = true; - postindex = false; - offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12)); - break; - case AddrMode_OFF: - wback = false; - postindex = false; - offset = LSL(Bits32(opcode, 21, 10), size); - break; + if (!WriteRegister(context_t, ®_info_Rt, data_Rt)) + return false; + + if (!rt_unknown) { + if (!ReadMemory(context_t2, address + size, buffer, + reg_info_Rt2.byte_size)) + return false; } - MemOp memop; + if (data_Rt2.SetFromMemoryData(®_info_Rt2, buffer, + reg_info_Rt2.byte_size, eByteOrderLittle, + error) == 0) + return false; - if (Bit32(opc, 1) == 0) - { - memop = Bit32(opc, 0) == 1 ? MemOp_LOAD : MemOp_STORE; - } - else - { - memop = MemOp_LOAD; - if (size == 2 && Bit32(opc, 0) == 1) - return false; - } + if (!vector && is_signed && !data_Rt2.SignExtend(datasize)) + return false; - Error error; - bool success = false; - uint64_t address; - uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; - RegisterValue data_Rt; + if (!WriteRegister(context_t2, ®_info_Rt2, data_Rt2)) + return false; + } break; + + default: + break; + } + if (wback) { + if (wb_unknown) + wb_address = LLDB_INVALID_ADDRESS; + Context context; + context.SetImmediateSigned(idx); if (n == 31) - address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::sp, 0, &success); + context.type = eContextAdjustStackPointer; else - address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success); + context.type = eContextAdjustBaseRegister; + WriteRegisterUnsigned(context, ®_info_base, wb_address); + } + return true; +} - if (!success) - return false; +template <EmulateInstructionARM64::AddrMode a_mode> +bool EmulateInstructionARM64::EmulateLDRSTRImm(const uint32_t opcode) { + uint32_t size = Bits32(opcode, 31, 30); + uint32_t opc = Bits32(opcode, 23, 22); + uint32_t n = Bits32(opcode, 9, 5); + uint32_t t = Bits32(opcode, 4, 0); + + bool wback; + bool postindex; + uint64_t offset; + + switch (a_mode) { + case AddrMode_POST: + wback = true; + postindex = true; + offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12)); + break; + case AddrMode_PRE: + wback = true; + postindex = false; + offset = llvm::SignExtend64<9>(Bits32(opcode, 20, 12)); + break; + case AddrMode_OFF: + wback = false; + postindex = false; + offset = LSL(Bits32(opcode, 21, 10), size); + break; + } + + MemOp memop; + + if (Bit32(opc, 1) == 0) { + memop = Bit32(opc, 0) == 1 ? MemOp_LOAD : MemOp_STORE; + } else { + memop = MemOp_LOAD; + if (size == 2 && Bit32(opc, 0) == 1) + return false; + } + + Error error; + bool success = false; + uint64_t address; + uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; + RegisterValue data_Rt; + + if (n == 31) + address = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_sp_arm64, 0, &success); + else + address = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + n, 0, &success); + + if (!success) + return false; - if (!postindex) - address += offset; + if (!postindex) + address += offset; - RegisterInfo reg_info_base; - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base)) - return false; + RegisterInfo reg_info_base; + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + n, reg_info_base)) + return false; - RegisterInfo reg_info_Rt; - if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt)) - return false; + RegisterInfo reg_info_Rt; + if (!GetRegisterInfo(eRegisterKindLLDB, gpr_x0_arm64 + t, reg_info_Rt)) + return false; - Context context; - switch (memop) - { - case MemOp_STORE: - if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register - context.type = eContextPushRegisterOnStack; - else - context.type = eContextRegisterStore; - context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset); - - if (!ReadRegister (®_info_Rt, data_Rt)) - return false; - - if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!WriteMemory(context, address, buffer, reg_info_Rt.byte_size)) - return false; - break; - - case MemOp_LOAD: - if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is based off of the sp or fp register - context.type = eContextPopRegisterOffStack; - else - context.type = eContextRegisterLoad; - context.SetAddress(address); - - if (!ReadMemory (context, address, buffer, reg_info_Rt.byte_size)) - return false; - - if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) - return false; - - if (!WriteRegister (context, ®_info_Rt, data_Rt)) - return false; - break; - default: - return false; - } + Context context; + switch (memop) { + case MemOp_STORE: + if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is + // based off of the sp + // or fp register + context.type = eContextPushRegisterOnStack; + else + context.type = eContextRegisterStore; + context.SetRegisterToRegisterPlusOffset(reg_info_Rt, reg_info_base, + postindex ? 0 : offset); + + if (!ReadRegister(®_info_Rt, data_Rt)) + return false; + + if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, + eByteOrderLittle, error) == 0) + return false; + + if (!WriteMemory(context, address, buffer, reg_info_Rt.byte_size)) + return false; + break; + + case MemOp_LOAD: + if (n == 31 || n == GetFramePointerRegisterNumber()) // if this store is + // based off of the sp + // or fp register + context.type = eContextPopRegisterOffStack; + else + context.type = eContextRegisterLoad; + context.SetAddress(address); - if (wback) - { - if (postindex) - address += offset; + if (!ReadMemory(context, address, buffer, reg_info_Rt.byte_size)) + return false; - if (n == 31) - context.type = eContextAdjustStackPointer; - else - context.type = eContextAdjustBaseRegister; - context.SetImmediateSigned (offset); + if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, + eByteOrderLittle, error) == 0) + return false; - if (!WriteRegisterUnsigned (context, ®_info_base, address)) - return false; - } - return true; + if (!WriteRegister(context, ®_info_Rt, data_Rt)) + return false; + break; + default: + return false; + } + + if (wback) { + if (postindex) + address += offset; + + if (n == 31) + context.type = eContextAdjustStackPointer; + else + context.type = eContextAdjustBaseRegister; + context.SetImmediateSigned(offset); + + if (!WriteRegisterUnsigned(context, ®_info_base, address)) + return false; + } + return true; } -bool -EmulateInstructionARM64::EmulateB (const uint32_t opcode) -{ +bool EmulateInstructionARM64::EmulateB(const uint32_t opcode) { #if 0 // ARM64 pseudo code... if branch_type == BranchType_CALL then X[30] = PC[] + 4; BranchTo(PC[] + offset, branch_type); #endif - bool success = false; + bool success = false; - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); - if (!success) - return false; - - int64_t offset = llvm::SignExtend64<28>(Bits32(opcode, 25, 0) << 2); - BranchType branch_type = Bit32(opcode, 31) ? BranchType_CALL : BranchType_JMP; - addr_t target = pc + offset; - context.SetImmediateSigned(offset); + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_PC, 0, &success); + if (!success) + return false; - switch (branch_type) - { - case BranchType_CALL: - { - addr_t x30 = pc + 4; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::x30, x30)) - return false; - } - break; - case BranchType_JMP: - break; - default: - return false; - } + int64_t offset = llvm::SignExtend64<28>(Bits32(opcode, 25, 0) << 2); + BranchType branch_type = Bit32(opcode, 31) ? BranchType_CALL : BranchType_JMP; + addr_t target = pc + offset; + context.SetImmediateSigned(offset); + + switch (branch_type) { + case BranchType_CALL: { + addr_t x30 = pc + 4; + if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_lr_arm64, x30)) + return false; + } break; + case BranchType_JMP: + break; + default: + return false; + } - if (!BranchTo(context, 64, target)) - return false; - return true; + if (!BranchTo(context, 64, target)) + return false; + return true; } -bool -EmulateInstructionARM64::EmulateBcond (const uint32_t opcode) -{ +bool EmulateInstructionARM64::EmulateBcond(const uint32_t opcode) { #if 0 // ARM64 pseudo code... bits(64) offset = SignExtend(imm19:'00', 64); @@ -1055,29 +1127,27 @@ EmulateInstructionARM64::EmulateBcond (const uint32_t opcode) BranchTo(PC[] + offset, BranchType_JMP); #endif - if (ConditionHolds(Bits32(opcode, 3, 0))) - { - bool success = false; - - const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); - if (!success) - return false; - - int64_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2); - addr_t target = pc + offset; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - context.SetImmediateSigned(offset); - if (!BranchTo(context, 64, target)) - return false; - } - return true; + if (ConditionHolds(Bits32(opcode, 3, 0))) { + bool success = false; + + const uint64_t pc = ReadRegisterUnsigned( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); + if (!success) + return false; + + int64_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2); + addr_t target = pc + offset; + + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + context.SetImmediateSigned(offset); + if (!BranchTo(context, 64, target)) + return false; + } + return true; } -bool -EmulateInstructionARM64::EmulateCBZ (const uint32_t opcode) -{ +bool EmulateInstructionARM64::EmulateCBZ(const uint32_t opcode) { #if 0 integer t = UInt(Rt); integer datasize = if sf == '1' then 64 else 32; @@ -1089,34 +1159,33 @@ EmulateInstructionARM64::EmulateCBZ (const uint32_t opcode) BranchTo(PC[] + offset, BranchType_JMP); #endif - bool success = false; + bool success = false; + + uint32_t t = Bits32(opcode, 4, 0); + bool is_zero = Bit32(opcode, 24) == 0; + int32_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2); - uint32_t t = Bits32(opcode, 4, 0); - bool is_zero = Bit32(opcode, 24) == 0; - int32_t offset = llvm::SignExtend64<21>(Bits32(opcode, 23, 5) << 2); + const uint64_t operand = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success); + if (!success) + return false; - const uint64_t operand = ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::x0 + t, 0, &success); + if (m_ignore_conditions || ((operand == 0) == is_zero)) { + const uint64_t pc = ReadRegisterUnsigned( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); if (!success) - return false; + return false; - if (m_ignore_conditions || ((operand == 0) == is_zero)) - { - const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); - if (!success) - return false; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - context.SetImmediateSigned(offset); - if (!BranchTo(context, 64, pc + offset)) - return false; - } - return true; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + context.SetImmediateSigned(offset); + if (!BranchTo(context, 64, pc + offset)) + return false; + } + return true; } -bool -EmulateInstructionARM64::EmulateTBZ (const uint32_t opcode) -{ +bool EmulateInstructionARM64::EmulateTBZ(const uint32_t opcode) { #if 0 integer t = UInt(Rt); integer datasize = if b5 == '1' then 64 else 32; @@ -1125,28 +1194,29 @@ EmulateInstructionARM64::EmulateTBZ (const uint32_t opcode) bits(64) offset = SignExtend(imm14:'00', 64); #endif - bool success = false; + bool success = false; + + uint32_t t = Bits32(opcode, 4, 0); + uint32_t bit_pos = (Bit32(opcode, 31) << 6) | (Bits32(opcode, 23, 19)); + uint32_t bit_val = Bit32(opcode, 24); + int64_t offset = llvm::SignExtend64<16>(Bits32(opcode, 18, 5) << 2); - uint32_t t = Bits32(opcode, 4, 0); - uint32_t bit_pos = (Bit32(opcode, 31) << 6) | (Bits32(opcode, 23, 19)); - uint32_t bit_val = Bit32(opcode, 24); - int64_t offset = llvm::SignExtend64<16>(Bits32(opcode, 18, 5) << 2); + const uint64_t operand = + ReadRegisterUnsigned(eRegisterKindLLDB, gpr_x0_arm64 + t, 0, &success); + if (!success) + return false; - const uint64_t operand = ReadRegisterUnsigned(eRegisterKindDWARF, arm64_dwarf::x0 + t, 0, &success); + if (m_ignore_conditions || Bit32(operand, bit_pos) == bit_val) { + const uint64_t pc = ReadRegisterUnsigned( + eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); if (!success) - return false; + return false; - if (m_ignore_conditions || Bit32(operand, bit_pos) == bit_val) - { - const uint64_t pc = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success); - if (!success) - return false; - - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - context.SetImmediateSigned(offset); - if (!BranchTo(context, 64, pc + offset)) - return false; - } - return true; + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + context.SetImmediateSigned(offset); + if (!BranchTo(context, 64, pc + offset)) + return false; + } + return true; } diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h index d9333c2824d2..1da330497b33 100644 --- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h +++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h @@ -14,288 +14,192 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "Plugins/Process/Utility/ARMDefines.h" #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Error.h" #include "lldb/Interpreter/OptionValue.h" -#include "Plugins/Process/Utility/ARMDefines.h" -class EmulateInstructionARM64 : public lldb_private::EmulateInstruction -{ -public: - EmulateInstructionARM64 (const lldb_private::ArchSpec &arch) : - EmulateInstruction (arch), - m_opcode_pstate (), - m_emulated_pstate (), - m_ignore_conditions (false) - { - } +class EmulateInstructionARM64 : public lldb_private::EmulateInstruction { +public: + EmulateInstructionARM64(const lldb_private::ArchSpec &arch) + : EmulateInstruction(arch), m_opcode_pstate(), m_emulated_pstate(), + m_ignore_conditions(false) {} - static void - Initialize (); - - static void - Terminate (); - - static lldb_private::ConstString - GetPluginNameStatic (); - - static const char * - GetPluginDescriptionStatic (); - - static lldb_private::EmulateInstruction * - CreateInstance (const lldb_private::ArchSpec &arch, - lldb_private::InstructionType inst_type); - - static bool - SupportsEmulatingInstructionsOfTypeStatic (lldb_private::InstructionType inst_type) - { - switch (inst_type) - { - case lldb_private::eInstructionTypeAny: - case lldb_private::eInstructionTypePrologueEpilogue: - return true; - - case lldb_private::eInstructionTypePCModifying: - case lldb_private::eInstructionTypeAll: - return false; - } - return false; - } + static void Initialize(); - lldb_private::ConstString - GetPluginName() override; + static void Terminate(); - uint32_t - GetPluginVersion() override - { - return 1; - } + static lldb_private::ConstString GetPluginNameStatic(); - bool - SetTargetTriple(const lldb_private::ArchSpec &arch) override; - - bool - SupportsEmulatingInstructionsOfType(lldb_private::InstructionType inst_type) override - { - return SupportsEmulatingInstructionsOfTypeStatic (inst_type); - } + static const char *GetPluginDescriptionStatic(); - bool - ReadInstruction() override; - - bool - EvaluateInstruction(uint32_t evaluate_options) override; - - bool - TestEmulation(lldb_private::Stream *out_stream, - lldb_private::ArchSpec &arch, - lldb_private::OptionValueDictionary *test_data) override - { - return false; + static lldb_private::EmulateInstruction * + CreateInstance(const lldb_private::ArchSpec &arch, + lldb_private::InstructionType inst_type); + + static bool SupportsEmulatingInstructionsOfTypeStatic( + lldb_private::InstructionType inst_type) { + switch (inst_type) { + case lldb_private::eInstructionTypeAny: + case lldb_private::eInstructionTypePrologueEpilogue: + return true; + + case lldb_private::eInstructionTypePCModifying: + case lldb_private::eInstructionTypeAll: + return false; } + return false; + } + + lldb_private::ConstString GetPluginName() override; - bool - GetRegisterInfo(lldb::RegisterKind reg_kind, - uint32_t reg_num, - lldb_private::RegisterInfo ®_info) override; - - bool - CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override; - - typedef enum - { - AddrMode_OFF, - AddrMode_PRE, - AddrMode_POST - } AddrMode; - - typedef enum - { - BranchType_CALL, - BranchType_ERET, - BranchType_DRET, - BranchType_RET, - BranchType_JMP - } BranchType; - - typedef enum - { - CountOp_CLZ, - CountOp_CLS, - CountOp_CNT - } CountOp; - - typedef enum - { - RevOp_RBIT, - RevOp_REV16, - RevOp_REV32, - RevOp_REV64 - } RevOp; - - typedef enum - { - BitwiseOp_NOT, - BitwiseOp_RBIT - } BitwiseOp; - - typedef enum - { - EL0 = 0, - EL1 = 1, - EL2 = 2, - EL3 = 3 - } ExceptionLevel; - - typedef enum - { - ExtendType_SXTB, - ExtendType_SXTH, - ExtendType_SXTW, - ExtendType_SXTX, - ExtendType_UXTB, - ExtendType_UXTH, - ExtendType_UXTW, - ExtendType_UXTX - } ExtendType; - - typedef enum - { - ExtractType_LEFT, - ExtractType_RIGHT - } ExtractType; - - typedef enum - { - LogicalOp_AND, - LogicalOp_EOR, - LogicalOp_ORR - } LogicalOp; - - typedef enum - { - MemOp_LOAD, - MemOp_STORE, - MemOp_PREFETCH, - MemOp_NOP - } MemOp; - - typedef enum - { - MoveWideOp_N, - MoveWideOp_Z, - MoveWideOp_K - } MoveWideOp; - - typedef enum { - ShiftType_LSL, - ShiftType_LSR, - ShiftType_ASR, - ShiftType_ROR - } ShiftType; - - typedef enum - { - SP0 = 0, - SPx = 1 - } StackPointerSelection; - - typedef enum - { - Unpredictable_WBOVERLAP, - Unpredictable_LDPOVERLAP - } Unpredictable; - - typedef enum - { - Constraint_NONE, - Constraint_UNKNOWN, - Constraint_SUPPRESSWB, - Constraint_NOP - } ConstraintType; - - typedef enum - { - AccType_NORMAL, - AccType_UNPRIV, - AccType_STREAM, - AccType_ALIGNED, - AccType_ORDERED - } AccType; - - typedef struct - { - uint32_t - N:1, - V:1, - C:1, - Z:1, // condition code flags – can also be accessed as PSTATE.[N,Z,C,V] - Q:1, // AArch32 only – CSPR.Q bit - IT:8, // AArch32 only – CPSR.IT bits - J:1, // AArch32 only – CSPR.J bit - T:1, // AArch32 only – CPSR.T bit - SS:1, // Single step process state bit - IL:1, // Illegal state bit - D:1, - A:1, - I:1, - F:1, // Interrupt masks – can also be accessed as PSTATE.[D,A,I,F] - E:1, // AArch32 only – CSPR.E bit - M:5, // AArch32 only – mode encodings - RW:1, // Current register width – 0 is AArch64, 1 is AArch32 - EL:2, // Current exception level (see ExceptionLevel enum) - SP:1; // AArch64 only - Stack Pointer selection (see StackPointerSelection enum) - } ProcState; + uint32_t GetPluginVersion() override { return 1; } + + bool SetTargetTriple(const lldb_private::ArchSpec &arch) override; + + bool SupportsEmulatingInstructionsOfType( + lldb_private::InstructionType inst_type) override { + return SupportsEmulatingInstructionsOfTypeStatic(inst_type); + } + + bool ReadInstruction() override; + + bool EvaluateInstruction(uint32_t evaluate_options) override; + + bool TestEmulation(lldb_private::Stream *out_stream, + lldb_private::ArchSpec &arch, + lldb_private::OptionValueDictionary *test_data) override { + return false; + } + + bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, + lldb_private::RegisterInfo ®_info) override; + + bool + CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override; + + typedef enum { AddrMode_OFF, AddrMode_PRE, AddrMode_POST } AddrMode; + + typedef enum { + BranchType_CALL, + BranchType_ERET, + BranchType_DRET, + BranchType_RET, + BranchType_JMP + } BranchType; + + typedef enum { CountOp_CLZ, CountOp_CLS, CountOp_CNT } CountOp; + + typedef enum { RevOp_RBIT, RevOp_REV16, RevOp_REV32, RevOp_REV64 } RevOp; + + typedef enum { BitwiseOp_NOT, BitwiseOp_RBIT } BitwiseOp; + + typedef enum { EL0 = 0, EL1 = 1, EL2 = 2, EL3 = 3 } ExceptionLevel; + + typedef enum { + ExtendType_SXTB, + ExtendType_SXTH, + ExtendType_SXTW, + ExtendType_SXTX, + ExtendType_UXTB, + ExtendType_UXTH, + ExtendType_UXTW, + ExtendType_UXTX + } ExtendType; + + typedef enum { ExtractType_LEFT, ExtractType_RIGHT } ExtractType; + + typedef enum { LogicalOp_AND, LogicalOp_EOR, LogicalOp_ORR } LogicalOp; + + typedef enum { MemOp_LOAD, MemOp_STORE, MemOp_PREFETCH, MemOp_NOP } MemOp; + + typedef enum { MoveWideOp_N, MoveWideOp_Z, MoveWideOp_K } MoveWideOp; + + typedef enum { + ShiftType_LSL, + ShiftType_LSR, + ShiftType_ASR, + ShiftType_ROR + } ShiftType; + + typedef enum { SP0 = 0, SPx = 1 } StackPointerSelection; + + typedef enum { + Unpredictable_WBOVERLAP, + Unpredictable_LDPOVERLAP + } Unpredictable; + + typedef enum { + Constraint_NONE, + Constraint_UNKNOWN, + Constraint_SUPPRESSWB, + Constraint_NOP + } ConstraintType; + + typedef enum { + AccType_NORMAL, + AccType_UNPRIV, + AccType_STREAM, + AccType_ALIGNED, + AccType_ORDERED + } AccType; + + typedef struct { + uint32_t N : 1, V : 1, C : 1, + Z : 1, // condition code flags – can also be accessed as + // PSTATE.[N,Z,C,V] + Q : 1, // AArch32 only – CSPR.Q bit + IT : 8, // AArch32 only – CPSR.IT bits + J : 1, // AArch32 only – CSPR.J bit + T : 1, // AArch32 only – CPSR.T bit + SS : 1, // Single step process state bit + IL : 1, // Illegal state bit + D : 1, A : 1, I : 1, + F : 1, // Interrupt masks – can also be accessed as PSTATE.[D,A,I,F] + E : 1, // AArch32 only – CSPR.E bit + M : 5, // AArch32 only – mode encodings + RW : 1, // Current register width – 0 is AArch64, 1 is AArch32 + EL : 2, // Current exception level (see ExceptionLevel enum) + SP : 1; // AArch64 only - Stack Pointer selection (see + // StackPointerSelection enum) + } ProcState; protected: - typedef struct - { - uint32_t mask; - uint32_t value; - uint32_t vfp_variants; - bool (EmulateInstructionARM64::*callback) (const uint32_t opcode); - const char *name; - } Opcode; - - static Opcode* - GetOpcodeForInstruction (const uint32_t opcode); + typedef struct { + uint32_t mask; + uint32_t value; + uint32_t vfp_variants; + bool (EmulateInstructionARM64::*callback)(const uint32_t opcode); + const char *name; + } Opcode; + + static Opcode *GetOpcodeForInstruction(const uint32_t opcode); - uint32_t - GetFramePointerRegisterNumber() const; + uint32_t GetFramePointerRegisterNumber() const; - bool - BranchTo (const Context &context, uint32_t N, lldb::addr_t target); + bool BranchTo(const Context &context, uint32_t N, lldb::addr_t target); - bool - ConditionHolds (const uint32_t cond); + bool ConditionHolds(const uint32_t cond); - bool - UsingAArch32 (); + bool UsingAArch32(); - bool - EmulateADDSUBImm (const uint32_t opcode); + bool EmulateADDSUBImm(const uint32_t opcode); - template <AddrMode a_mode> bool - EmulateLDPSTP (const uint32_t opcode); + template <AddrMode a_mode> bool EmulateLDPSTP(const uint32_t opcode); - template <AddrMode a_mode> bool - EmulateLDRSTRImm (const uint32_t opcode); + template <AddrMode a_mode> bool EmulateLDRSTRImm(const uint32_t opcode); - bool - EmulateB (const uint32_t opcode); + bool EmulateB(const uint32_t opcode); - bool - EmulateBcond (const uint32_t opcode); + bool EmulateBcond(const uint32_t opcode); - bool - EmulateCBZ (const uint32_t opcode); + bool EmulateCBZ(const uint32_t opcode); - bool - EmulateTBZ (const uint32_t opcode); + bool EmulateTBZ(const uint32_t opcode); - ProcState m_opcode_pstate; - ProcState m_emulated_pstate; // This can get updated by the opcode. - bool m_ignore_conditions; + ProcState m_opcode_pstate; + ProcState m_emulated_pstate; // This can get updated by the opcode. + bool m_ignore_conditions; }; #endif // EmulateInstructionARM64_h_ diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp index 47b98ca85b78..8cc34c171c72 100644 --- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp +++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp @@ -1,4 +1,5 @@ -//===-- EmulateInstructionMIPS.cpp -------------------------------*- C++ -*-===// +//===-- EmulateInstructionMIPS.cpp -------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -11,30 +12,30 @@ #include <stdlib.h> -#include "llvm-c/Disassembler.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCDisassembler/MCDisassembler.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCContext.h" #include "lldb/Core/Address.h" -#include "lldb/Core/Opcode.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ConstString.h" -#include "lldb/Core/PluginManager.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Opcode.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/Stream.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Target/Target.h" +#include "llvm-c/Disassembler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/ADT/STLExtras.h" #include "Plugins/Process/Utility/InstructionUtils.h" -#include "Plugins/Process/Utility/RegisterContext_mips.h" //mips32 has same registers nos as mips64 +#include "Plugins/Process/Utility/RegisterContext_mips.h" //mips32 has same registers nos as mips64 using namespace lldb; using namespace lldb_private; @@ -42,7 +43,6 @@ using namespace lldb_private; #define UInt(x) ((uint64_t)x) #define integer int64_t - //---------------------------------------------------------------------- // // EmulateInstructionMIPS implementation @@ -51,1926 +51,2180 @@ using namespace lldb_private; #ifdef __mips__ extern "C" { - void LLVMInitializeMipsTargetInfo (); - void LLVMInitializeMipsTarget (); - void LLVMInitializeMipsAsmPrinter (); - void LLVMInitializeMipsTargetMC (); - void LLVMInitializeMipsDisassembler (); +void LLVMInitializeMipsTargetInfo(); +void LLVMInitializeMipsTarget(); +void LLVMInitializeMipsAsmPrinter(); +void LLVMInitializeMipsTargetMC(); +void LLVMInitializeMipsDisassembler(); } #endif -EmulateInstructionMIPS::EmulateInstructionMIPS (const lldb_private::ArchSpec &arch) : - EmulateInstruction (arch) -{ - /* Create instance of llvm::MCDisassembler */ - std::string Error; - llvm::Triple triple = arch.GetTriple(); - const llvm::Target *target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error); +EmulateInstructionMIPS::EmulateInstructionMIPS( + const lldb_private::ArchSpec &arch) + : EmulateInstruction(arch) { + /* Create instance of llvm::MCDisassembler */ + std::string Error; + llvm::Triple triple = arch.GetTriple(); + const llvm::Target *target = + llvm::TargetRegistry::lookupTarget(triple.getTriple(), Error); - /* - * If we fail to get the target then we haven't registered it. The SystemInitializerCommon - * does not initialize targets, MCs and disassemblers. However we need the MCDisassembler - * to decode the instructions so that the decoding complexity stays with LLVM. - * Initialize the MIPS targets and disassemblers. - */ +/* + * If we fail to get the target then we haven't registered it. The + * SystemInitializerCommon + * does not initialize targets, MCs and disassemblers. However we need the + * MCDisassembler + * to decode the instructions so that the decoding complexity stays with LLVM. + * Initialize the MIPS targets and disassemblers. +*/ #ifdef __mips__ - if (!target) - { - LLVMInitializeMipsTargetInfo (); - LLVMInitializeMipsTarget (); - LLVMInitializeMipsAsmPrinter (); - LLVMInitializeMipsTargetMC (); - LLVMInitializeMipsDisassembler (); - target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error); - } + if (!target) { + LLVMInitializeMipsTargetInfo(); + LLVMInitializeMipsTarget(); + LLVMInitializeMipsAsmPrinter(); + LLVMInitializeMipsTargetMC(); + LLVMInitializeMipsDisassembler(); + target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), Error); + } #endif - assert (target); - - llvm::StringRef cpu; - - switch (arch.GetCore()) - { - case ArchSpec::eCore_mips32: - case ArchSpec::eCore_mips32el: - cpu = "mips32"; break; - case ArchSpec::eCore_mips32r2: - case ArchSpec::eCore_mips32r2el: - cpu = "mips32r2"; break; - case ArchSpec::eCore_mips32r3: - case ArchSpec::eCore_mips32r3el: - cpu = "mips32r3"; break; - case ArchSpec::eCore_mips32r5: - case ArchSpec::eCore_mips32r5el: - cpu = "mips32r5"; break; - case ArchSpec::eCore_mips32r6: - case ArchSpec::eCore_mips32r6el: - cpu = "mips32r6"; break; - case ArchSpec::eCore_mips64: - case ArchSpec::eCore_mips64el: - cpu = "mips64"; break; - case ArchSpec::eCore_mips64r2: - case ArchSpec::eCore_mips64r2el: - cpu = "mips64r2"; break; - case ArchSpec::eCore_mips64r3: - case ArchSpec::eCore_mips64r3el: - cpu = "mips64r3"; break; - case ArchSpec::eCore_mips64r5: - case ArchSpec::eCore_mips64r5el: - cpu = "mips64r5"; break; - case ArchSpec::eCore_mips64r6: - case ArchSpec::eCore_mips64r6el: - cpu = "mips64r6"; break; - default: - cpu = "generic"; break; - } - - std::string features = ""; - uint32_t arch_flags = arch.GetFlags (); - if (arch_flags & ArchSpec::eMIPSAse_msa) - features += "+msa,"; - if (arch_flags & ArchSpec::eMIPSAse_dsp) - features += "+dsp,"; - if (arch_flags & ArchSpec::eMIPSAse_dspr2) - features += "+dspr2,"; - - m_reg_info.reset (target->createMCRegInfo (triple.getTriple())); - assert (m_reg_info.get()); - - m_insn_info.reset (target->createMCInstrInfo()); - assert (m_insn_info.get()); - - m_asm_info.reset (target->createMCAsmInfo (*m_reg_info, triple.getTriple())); - m_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, features)); - assert (m_asm_info.get() && m_subtype_info.get()); - - m_context.reset (new llvm::MCContext (m_asm_info.get(), m_reg_info.get(), nullptr)); - assert (m_context.get()); - - m_disasm.reset (target->createMCDisassembler (*m_subtype_info, *m_context)); - assert (m_disasm.get()); - - /* Create alternate disassembler for microMIPS */ - if (arch_flags & ArchSpec::eMIPSAse_mips16) - features += "+mips16,"; - else if (arch_flags & ArchSpec::eMIPSAse_micromips) - features += "+micromips,"; - - m_alt_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, features)); - assert (m_alt_subtype_info.get()); - - m_alt_disasm.reset (target->createMCDisassembler (*m_alt_subtype_info, *m_context)); - assert (m_alt_disasm.get()); - - m_next_inst_size = 0; - m_use_alt_disaasm = false; + assert(target); + + llvm::StringRef cpu; + + switch (arch.GetCore()) { + case ArchSpec::eCore_mips32: + case ArchSpec::eCore_mips32el: + cpu = "mips32"; + break; + case ArchSpec::eCore_mips32r2: + case ArchSpec::eCore_mips32r2el: + cpu = "mips32r2"; + break; + case ArchSpec::eCore_mips32r3: + case ArchSpec::eCore_mips32r3el: + cpu = "mips32r3"; + break; + case ArchSpec::eCore_mips32r5: + case ArchSpec::eCore_mips32r5el: + cpu = "mips32r5"; + break; + case ArchSpec::eCore_mips32r6: + case ArchSpec::eCore_mips32r6el: + cpu = "mips32r6"; + break; + case ArchSpec::eCore_mips64: + case ArchSpec::eCore_mips64el: + cpu = "mips64"; + break; + case ArchSpec::eCore_mips64r2: + case ArchSpec::eCore_mips64r2el: + cpu = "mips64r2"; + break; + case ArchSpec::eCore_mips64r3: + case ArchSpec::eCore_mips64r3el: + cpu = "mips64r3"; + break; + case ArchSpec::eCore_mips64r5: + case ArchSpec::eCore_mips64r5el: + cpu = "mips64r5"; + break; + case ArchSpec::eCore_mips64r6: + case ArchSpec::eCore_mips64r6el: + cpu = "mips64r6"; + break; + default: + cpu = "generic"; + break; + } + + std::string features = ""; + uint32_t arch_flags = arch.GetFlags(); + if (arch_flags & ArchSpec::eMIPSAse_msa) + features += "+msa,"; + if (arch_flags & ArchSpec::eMIPSAse_dsp) + features += "+dsp,"; + if (arch_flags & ArchSpec::eMIPSAse_dspr2) + features += "+dspr2,"; + + m_reg_info.reset(target->createMCRegInfo(triple.getTriple())); + assert(m_reg_info.get()); + + m_insn_info.reset(target->createMCInstrInfo()); + assert(m_insn_info.get()); + + m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple.getTriple())); + m_subtype_info.reset( + target->createMCSubtargetInfo(triple.getTriple(), cpu, features)); + assert(m_asm_info.get() && m_subtype_info.get()); + + m_context.reset( + new llvm::MCContext(m_asm_info.get(), m_reg_info.get(), nullptr)); + assert(m_context.get()); + + m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context)); + assert(m_disasm.get()); + + /* Create alternate disassembler for microMIPS */ + if (arch_flags & ArchSpec::eMIPSAse_mips16) + features += "+mips16,"; + else if (arch_flags & ArchSpec::eMIPSAse_micromips) + features += "+micromips,"; + + m_alt_subtype_info.reset( + target->createMCSubtargetInfo(triple.getTriple(), cpu, features)); + assert(m_alt_subtype_info.get()); + + m_alt_disasm.reset( + target->createMCDisassembler(*m_alt_subtype_info, *m_context)); + assert(m_alt_disasm.get()); + + m_next_inst_size = 0; + m_use_alt_disaasm = false; +} + +void EmulateInstructionMIPS::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); +} + +void EmulateInstructionMIPS::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +ConstString EmulateInstructionMIPS::GetPluginNameStatic() { + ConstString g_plugin_name("lldb.emulate-instruction.mips32"); + return g_plugin_name; +} + +lldb_private::ConstString EmulateInstructionMIPS::GetPluginName() { + static ConstString g_plugin_name("EmulateInstructionMIPS"); + return g_plugin_name; +} + +const char *EmulateInstructionMIPS::GetPluginDescriptionStatic() { + return "Emulate instructions for the MIPS32 architecture."; } -void -EmulateInstructionMIPS::Initialize () -{ - PluginManager::RegisterPlugin (GetPluginNameStatic (), - GetPluginDescriptionStatic (), - CreateInstance); -} - -void -EmulateInstructionMIPS::Terminate () -{ - PluginManager::UnregisterPlugin (CreateInstance); -} - -ConstString -EmulateInstructionMIPS::GetPluginNameStatic () -{ - ConstString g_plugin_name ("lldb.emulate-instruction.mips32"); - return g_plugin_name; -} - -lldb_private::ConstString -EmulateInstructionMIPS::GetPluginName() -{ - static ConstString g_plugin_name ("EmulateInstructionMIPS"); - return g_plugin_name; -} +EmulateInstruction * +EmulateInstructionMIPS::CreateInstance(const ArchSpec &arch, + InstructionType inst_type) { + if (EmulateInstructionMIPS::SupportsEmulatingInstructionsOfTypeStatic( + inst_type)) { + if (arch.GetTriple().getArch() == llvm::Triple::mips || + arch.GetTriple().getArch() == llvm::Triple::mipsel) { + std::auto_ptr<EmulateInstructionMIPS> emulate_insn_ap( + new EmulateInstructionMIPS(arch)); + if (emulate_insn_ap.get()) + return emulate_insn_ap.release(); + } + } -const char * -EmulateInstructionMIPS::GetPluginDescriptionStatic () -{ - return "Emulate instructions for the MIPS32 architecture."; + return NULL; } -EmulateInstruction * -EmulateInstructionMIPS::CreateInstance (const ArchSpec &arch, InstructionType inst_type) -{ - if (EmulateInstructionMIPS::SupportsEmulatingInstructionsOfTypeStatic(inst_type)) - { - if (arch.GetTriple().getArch() == llvm::Triple::mips - || arch.GetTriple().getArch() == llvm::Triple::mipsel) - { - std::auto_ptr<EmulateInstructionMIPS> emulate_insn_ap (new EmulateInstructionMIPS (arch)); - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); - } +bool EmulateInstructionMIPS::SetTargetTriple(const ArchSpec &arch) { + if (arch.GetTriple().getArch() == llvm::Triple::mips || + arch.GetTriple().getArch() == llvm::Triple::mipsel) + return true; + return false; +} + +const char *EmulateInstructionMIPS::GetRegisterName(unsigned reg_num, + bool alternate_name) { + if (alternate_name) { + switch (reg_num) { + case dwarf_sp_mips: + return "r29"; + case dwarf_r30_mips: + return "r30"; + case dwarf_ra_mips: + return "r31"; + case dwarf_f0_mips: + return "f0"; + case dwarf_f1_mips: + return "f1"; + case dwarf_f2_mips: + return "f2"; + case dwarf_f3_mips: + return "f3"; + case dwarf_f4_mips: + return "f4"; + case dwarf_f5_mips: + return "f5"; + case dwarf_f6_mips: + return "f6"; + case dwarf_f7_mips: + return "f7"; + case dwarf_f8_mips: + return "f8"; + case dwarf_f9_mips: + return "f9"; + case dwarf_f10_mips: + return "f10"; + case dwarf_f11_mips: + return "f11"; + case dwarf_f12_mips: + return "f12"; + case dwarf_f13_mips: + return "f13"; + case dwarf_f14_mips: + return "f14"; + case dwarf_f15_mips: + return "f15"; + case dwarf_f16_mips: + return "f16"; + case dwarf_f17_mips: + return "f17"; + case dwarf_f18_mips: + return "f18"; + case dwarf_f19_mips: + return "f19"; + case dwarf_f20_mips: + return "f20"; + case dwarf_f21_mips: + return "f21"; + case dwarf_f22_mips: + return "f22"; + case dwarf_f23_mips: + return "f23"; + case dwarf_f24_mips: + return "f24"; + case dwarf_f25_mips: + return "f25"; + case dwarf_f26_mips: + return "f26"; + case dwarf_f27_mips: + return "f27"; + case dwarf_f28_mips: + return "f28"; + case dwarf_f29_mips: + return "f29"; + case dwarf_f30_mips: + return "f30"; + case dwarf_f31_mips: + return "f31"; + case dwarf_w0_mips: + return "w0"; + case dwarf_w1_mips: + return "w1"; + case dwarf_w2_mips: + return "w2"; + case dwarf_w3_mips: + return "w3"; + case dwarf_w4_mips: + return "w4"; + case dwarf_w5_mips: + return "w5"; + case dwarf_w6_mips: + return "w6"; + case dwarf_w7_mips: + return "w7"; + case dwarf_w8_mips: + return "w8"; + case dwarf_w9_mips: + return "w9"; + case dwarf_w10_mips: + return "w10"; + case dwarf_w11_mips: + return "w11"; + case dwarf_w12_mips: + return "w12"; + case dwarf_w13_mips: + return "w13"; + case dwarf_w14_mips: + return "w14"; + case dwarf_w15_mips: + return "w15"; + case dwarf_w16_mips: + return "w16"; + case dwarf_w17_mips: + return "w17"; + case dwarf_w18_mips: + return "w18"; + case dwarf_w19_mips: + return "w19"; + case dwarf_w20_mips: + return "w20"; + case dwarf_w21_mips: + return "w21"; + case dwarf_w22_mips: + return "w22"; + case dwarf_w23_mips: + return "w23"; + case dwarf_w24_mips: + return "w24"; + case dwarf_w25_mips: + return "w25"; + case dwarf_w26_mips: + return "w26"; + case dwarf_w27_mips: + return "w27"; + case dwarf_w28_mips: + return "w28"; + case dwarf_w29_mips: + return "w29"; + case dwarf_w30_mips: + return "w30"; + case dwarf_w31_mips: + return "w31"; + case dwarf_mir_mips: + return "mir"; + case dwarf_mcsr_mips: + return "mcsr"; + case dwarf_config5_mips: + return "config5"; + default: + break; + } + return nullptr; + } + + switch (reg_num) { + case dwarf_zero_mips: + return "r0"; + case dwarf_r1_mips: + return "r1"; + case dwarf_r2_mips: + return "r2"; + case dwarf_r3_mips: + return "r3"; + case dwarf_r4_mips: + return "r4"; + case dwarf_r5_mips: + return "r5"; + case dwarf_r6_mips: + return "r6"; + case dwarf_r7_mips: + return "r7"; + case dwarf_r8_mips: + return "r8"; + case dwarf_r9_mips: + return "r9"; + case dwarf_r10_mips: + return "r10"; + case dwarf_r11_mips: + return "r11"; + case dwarf_r12_mips: + return "r12"; + case dwarf_r13_mips: + return "r13"; + case dwarf_r14_mips: + return "r14"; + case dwarf_r15_mips: + return "r15"; + case dwarf_r16_mips: + return "r16"; + case dwarf_r17_mips: + return "r17"; + case dwarf_r18_mips: + return "r18"; + case dwarf_r19_mips: + return "r19"; + case dwarf_r20_mips: + return "r20"; + case dwarf_r21_mips: + return "r21"; + case dwarf_r22_mips: + return "r22"; + case dwarf_r23_mips: + return "r23"; + case dwarf_r24_mips: + return "r24"; + case dwarf_r25_mips: + return "r25"; + case dwarf_r26_mips: + return "r26"; + case dwarf_r27_mips: + return "r27"; + case dwarf_gp_mips: + return "gp"; + case dwarf_sp_mips: + return "sp"; + case dwarf_r30_mips: + return "fp"; + case dwarf_ra_mips: + return "ra"; + case dwarf_sr_mips: + return "sr"; + case dwarf_lo_mips: + return "lo"; + case dwarf_hi_mips: + return "hi"; + case dwarf_bad_mips: + return "bad"; + case dwarf_cause_mips: + return "cause"; + case dwarf_pc_mips: + return "pc"; + case dwarf_f0_mips: + return "f0"; + case dwarf_f1_mips: + return "f1"; + case dwarf_f2_mips: + return "f2"; + case dwarf_f3_mips: + return "f3"; + case dwarf_f4_mips: + return "f4"; + case dwarf_f5_mips: + return "f5"; + case dwarf_f6_mips: + return "f6"; + case dwarf_f7_mips: + return "f7"; + case dwarf_f8_mips: + return "f8"; + case dwarf_f9_mips: + return "f9"; + case dwarf_f10_mips: + return "f10"; + case dwarf_f11_mips: + return "f11"; + case dwarf_f12_mips: + return "f12"; + case dwarf_f13_mips: + return "f13"; + case dwarf_f14_mips: + return "f14"; + case dwarf_f15_mips: + return "f15"; + case dwarf_f16_mips: + return "f16"; + case dwarf_f17_mips: + return "f17"; + case dwarf_f18_mips: + return "f18"; + case dwarf_f19_mips: + return "f19"; + case dwarf_f20_mips: + return "f20"; + case dwarf_f21_mips: + return "f21"; + case dwarf_f22_mips: + return "f22"; + case dwarf_f23_mips: + return "f23"; + case dwarf_f24_mips: + return "f24"; + case dwarf_f25_mips: + return "f25"; + case dwarf_f26_mips: + return "f26"; + case dwarf_f27_mips: + return "f27"; + case dwarf_f28_mips: + return "f28"; + case dwarf_f29_mips: + return "f29"; + case dwarf_f30_mips: + return "f30"; + case dwarf_f31_mips: + return "f31"; + case dwarf_fcsr_mips: + return "fcsr"; + case dwarf_fir_mips: + return "fir"; + case dwarf_w0_mips: + return "w0"; + case dwarf_w1_mips: + return "w1"; + case dwarf_w2_mips: + return "w2"; + case dwarf_w3_mips: + return "w3"; + case dwarf_w4_mips: + return "w4"; + case dwarf_w5_mips: + return "w5"; + case dwarf_w6_mips: + return "w6"; + case dwarf_w7_mips: + return "w7"; + case dwarf_w8_mips: + return "w8"; + case dwarf_w9_mips: + return "w9"; + case dwarf_w10_mips: + return "w10"; + case dwarf_w11_mips: + return "w11"; + case dwarf_w12_mips: + return "w12"; + case dwarf_w13_mips: + return "w13"; + case dwarf_w14_mips: + return "w14"; + case dwarf_w15_mips: + return "w15"; + case dwarf_w16_mips: + return "w16"; + case dwarf_w17_mips: + return "w17"; + case dwarf_w18_mips: + return "w18"; + case dwarf_w19_mips: + return "w19"; + case dwarf_w20_mips: + return "w20"; + case dwarf_w21_mips: + return "w21"; + case dwarf_w22_mips: + return "w22"; + case dwarf_w23_mips: + return "w23"; + case dwarf_w24_mips: + return "w24"; + case dwarf_w25_mips: + return "w25"; + case dwarf_w26_mips: + return "w26"; + case dwarf_w27_mips: + return "w27"; + case dwarf_w28_mips: + return "w28"; + case dwarf_w29_mips: + return "w29"; + case dwarf_w30_mips: + return "w30"; + case dwarf_w31_mips: + return "w31"; + case dwarf_mcsr_mips: + return "mcsr"; + case dwarf_mir_mips: + return "mir"; + case dwarf_config5_mips: + return "config5"; + } + return nullptr; +} + +bool EmulateInstructionMIPS::GetRegisterInfo(RegisterKind reg_kind, + uint32_t reg_num, + RegisterInfo ®_info) { + if (reg_kind == eRegisterKindGeneric) { + switch (reg_num) { + case LLDB_REGNUM_GENERIC_PC: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_pc_mips; + break; + case LLDB_REGNUM_GENERIC_SP: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_sp_mips; + break; + case LLDB_REGNUM_GENERIC_FP: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_r30_mips; + break; + case LLDB_REGNUM_GENERIC_RA: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_ra_mips; + break; + case LLDB_REGNUM_GENERIC_FLAGS: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_sr_mips; + break; + default: + return false; + } + } + + if (reg_kind == eRegisterKindDWARF) { + ::memset(®_info, 0, sizeof(RegisterInfo)); + ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); + + if (reg_num == dwarf_sr_mips || reg_num == dwarf_fcsr_mips || + reg_num == dwarf_fir_mips || reg_num == dwarf_mcsr_mips || + reg_num == dwarf_mir_mips || reg_num == dwarf_config5_mips) { + reg_info.byte_size = 4; + reg_info.format = eFormatHex; + reg_info.encoding = eEncodingUint; + } else if ((int)reg_num >= dwarf_zero_mips && + (int)reg_num <= dwarf_f31_mips) { + reg_info.byte_size = 4; + reg_info.format = eFormatHex; + reg_info.encoding = eEncodingUint; + } else if ((int)reg_num >= dwarf_w0_mips && + (int)reg_num <= dwarf_w31_mips) { + reg_info.byte_size = 16; + reg_info.format = eFormatVectorOfUInt8; + reg_info.encoding = eEncodingVector; + } else { + return false; + } + + reg_info.name = GetRegisterName(reg_num, false); + reg_info.alt_name = GetRegisterName(reg_num, true); + reg_info.kinds[eRegisterKindDWARF] = reg_num; + + switch (reg_num) { + case dwarf_r30_mips: + reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; + break; + case dwarf_ra_mips: + reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; + break; + case dwarf_sp_mips: + reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; + break; + case dwarf_pc_mips: + reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; + break; + case dwarf_sr_mips: + reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; + break; + default: + break; } - - return NULL; + return true; + } + return false; +} + +EmulateInstructionMIPS::MipsOpcode * +EmulateInstructionMIPS::GetOpcodeForInstruction(const char *op_name) { + static EmulateInstructionMIPS::MipsOpcode g_opcodes[] = { + //---------------------------------------------------------------------- + // Prologue/Epilogue instructions + //---------------------------------------------------------------------- + {"ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu, + "ADDIU rt, rs, immediate"}, + {"SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt, offset(rs)"}, + {"LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt, offset(base)"}, + {"SUBU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "SUBU rd, rs, rt"}, + {"ADDU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "ADDU rd, rs, rt"}, + {"LUI", &EmulateInstructionMIPS::Emulate_LUI, "LUI rt, immediate"}, + + //---------------------------------------------------------------------- + // MicroMIPS Prologue/Epilogue instructions + //---------------------------------------------------------------------- + {"ADDIUSP_MM", &EmulateInstructionMIPS::Emulate_ADDIUSP, + "ADDIU immediate"}, + {"ADDIUS5_MM", &EmulateInstructionMIPS::Emulate_ADDIUS5, + "ADDIUS5 rd,immediate"}, + {"SWSP_MM", &EmulateInstructionMIPS::Emulate_SWSP, "SWSP rt,offset(sp)"}, + {"SWM16_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, + "SWM16 reglist,offset(sp)"}, + {"SWM32_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, + "SWM32 reglist,offset(base)"}, + {"SWP_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, + "SWP rs1,offset(base)"}, + {"LWSP_MM", &EmulateInstructionMIPS::Emulate_LWSP, "LWSP rt,offset(sp)"}, + {"LWM16_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, + "LWM16 reglist,offset(sp)"}, + {"LWM32_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, + "LWM32 reglist,offset(base)"}, + {"LWP_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, + "LWP rd,offset(base)"}, + {"JRADDIUSP", &EmulateInstructionMIPS::Emulate_JRADDIUSP, + "JRADDIUSP immediate"}, + //---------------------------------------------------------------------- + + // Load/Store instructions + //---------------------------------------------------------------------- + /* Following list of emulated instructions are required by implementation + of hardware watchpoint + for MIPS in lldb. As we just need the address accessed by instructions, + we have generalised + all these instructions in 2 functions depending on their addressing + modes */ + + {"LB", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LB rt, offset(base)"}, + {"LBE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LBE rt, offset(base)"}, + {"LBU", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LBU rt, offset(base)"}, + {"LBUE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LBUE rt, offset(base)"}, + {"LDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LDC1 ft, offset(base)"}, + {"LD", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LD rt, offset(base)"}, + {"LDL", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LDL rt, offset(base)"}, + {"LDR", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LDR rt, offset(base)"}, + {"LLD", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LLD rt, offset(base)"}, + {"LDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LDC2 rt, offset(base)"}, + {"LDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, + "LDXC1 fd, index (base)"}, + {"LH", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LH rt, offset(base)"}, + {"LHE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LHE rt, offset(base)"}, + {"LHU", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LHU rt, offset(base)"}, + {"LHUE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LHUE rt, offset(base)"}, + {"LL", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LL rt, offset(base)"}, + {"LLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LLE rt, offset(base)"}, + {"LUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, + "LUXC1 fd, index (base)"}, + {"LW", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LW rt, offset(base)"}, + {"LWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LWC1 ft, offset(base)"}, + {"LWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LWC2 rt, offset(base)"}, + {"LWE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LWE rt, offset(base)"}, + {"LWL", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LWL rt, offset(base)"}, + {"LWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LWLE rt, offset(base)"}, + {"LWR", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LWR rt, offset(base)"}, + {"LWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LWRE rt, offset(base)"}, + {"LWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, + "LWXC1 fd, index (base)"}, + {"LLX", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LLX rt, offset(base)"}, + {"LLXE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LLXE rt, offset(base)"}, + {"LLDX", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LLDX rt, offset(base)"}, + + {"SB", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SB rt, offset(base)"}, + {"SBE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SBE rt, offset(base)"}, + {"SC", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SC rt, offset(base)"}, + {"SCE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SCE rt, offset(base)"}, + {"SCD", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SCD rt, offset(base)"}, + {"SD", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SD rt, offset(base)"}, + {"SDL", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SDL rt, offset(base)"}, + {"SDR", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SDR rt, offset(base)"}, + {"SDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SDC1 ft, offset(base)"}, + {"SDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SDC2 rt, offset(base)"}, + {"SDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, + "SDXC1 fs, index(base)"}, + {"SH", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SH rt, offset(base)"}, + {"SHE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SHE rt, offset(base)"}, + {"SUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, + "SUXC1 fs, index (base)"}, + {"SWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SWC1 ft, offset(base)"}, + {"SWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SWC2 rt, offset(base)"}, + {"SWE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SWE rt, offset(base)"}, + {"SWL", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SWL rt, offset(base)"}, + {"SWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SWLE rt, offset(base)"}, + {"SWR", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SWR rt, offset(base)"}, + {"SWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SWRE rt, offset(base)"}, + {"SWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, + "SWXC1 fs, index (base)"}, + {"SCX", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SCX rt, offset(base)"}, + {"SCXE", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SCXE rt, offset(base)"}, + {"SCDX", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SCDX rt, offset(base)"}, + + //---------------------------------------------------------------------- + // MicroMIPS Load/Store instructions + //---------------------------------------------------------------------- + {"LBU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LBU16 rt, decoded_offset(base)"}, + {"LHU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LHU16 rt, left_shifted_offset(base)"}, + {"LW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LW16 rt, left_shifted_offset(base)"}, + {"LWGP_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "LWGP rt, left_shifted_offset(gp)"}, + {"SH16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SH16 rt, left_shifted_offset(base)"}, + {"SW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SW16 rt, left_shifted_offset(base)"}, + {"SW_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SWSP rt, left_shifted_offset(base)"}, + {"SB16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, + "SB16 rt, offset(base)"}, + + //---------------------------------------------------------------------- + // Branch instructions + //---------------------------------------------------------------------- + {"BEQ", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQ rs,rt,offset"}, + {"BNE", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNE rs,rt,offset"}, + {"BEQL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQL rs,rt,offset"}, + {"BNEL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNEL rs,rt,offset"}, + {"BGEZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link, + "BGEZALL rt,offset"}, + {"BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset"}, + {"BGEZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link, + "BGEZAL rs,offset"}, + {"BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset"}, + {"BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset"}, + {"BGEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZ rs,offset"}, + {"BLEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C, + "BLEZALC rs,offset"}, + {"BGEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C, + "BGEZALC rs,offset"}, + {"BLTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C, + "BLTZALC rs,offset"}, + {"BGTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C, + "BGTZALC rs,offset"}, + {"BEQZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C, + "BEQZALC rs,offset"}, + {"BNEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C, + "BNEZALC rs,offset"}, + {"BEQC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, + "BEQC rs,rt,offset"}, + {"BNEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, + "BNEC rs,rt,offset"}, + {"BLTC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, + "BLTC rs,rt,offset"}, + {"BGEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, + "BGEC rs,rt,offset"}, + {"BLTUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, + "BLTUC rs,rt,offset"}, + {"BGEUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, + "BGEUC rs,rt,offset"}, + {"BLTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLTZC rt,offset"}, + {"BLEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLEZC rt,offset"}, + {"BGEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGEZC rt,offset"}, + {"BGTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGTZC rt,offset"}, + {"BEQZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BEQZC rt,offset"}, + {"BNEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BNEZC rt,offset"}, + {"BGEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZL rt,offset"}, + {"BGTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZ rt,offset"}, + {"BGTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZL rt,offset"}, + {"BLEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZ rt,offset"}, + {"BLEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZL rt,offset"}, + {"BLTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZ rt,offset"}, + {"BLTZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link, + "BLTZAL rt,offset"}, + {"BLTZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link, + "BLTZALL rt,offset"}, + {"BLTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZL rt,offset"}, + {"BOVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, + "BOVC rs,rt,offset"}, + {"BNVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, + "BNVC rs,rt,offset"}, + {"J", &EmulateInstructionMIPS::Emulate_J, "J target"}, + {"JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target"}, + {"JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target"}, + {"JALR", &EmulateInstructionMIPS::Emulate_JALR, "JALR target"}, + {"JALR_HB", &EmulateInstructionMIPS::Emulate_JALR, "JALR.HB target"}, + {"JIALC", &EmulateInstructionMIPS::Emulate_JIALC, "JIALC rt,offset"}, + {"JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset"}, + {"JR", &EmulateInstructionMIPS::Emulate_JR, "JR target"}, + {"JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target"}, + {"BC1F", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1F cc, offset"}, + {"BC1T", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1T cc, offset"}, + {"BC1FL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1FL cc, offset"}, + {"BC1TL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1TL cc, offset"}, + {"BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset"}, + {"BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset"}, + {"BC1ANY2F", &EmulateInstructionMIPS::Emulate_3D_branch, + "BC1ANY2F cc, offset"}, + {"BC1ANY2T", &EmulateInstructionMIPS::Emulate_3D_branch, + "BC1ANY2T cc, offset"}, + {"BC1ANY4F", &EmulateInstructionMIPS::Emulate_3D_branch, + "BC1ANY4F cc, offset"}, + {"BC1ANY4T", &EmulateInstructionMIPS::Emulate_3D_branch, + "BC1ANY4T cc, offset"}, + {"BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16"}, + {"BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16"}, + {"BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16"}, + {"BNZ_D", &EmulateInstructionMIPS::Emulate_BNZD, "BNZ.d wt,s16"}, + {"BZ_B", &EmulateInstructionMIPS::Emulate_BZB, "BZ.b wt,s16"}, + {"BZ_H", &EmulateInstructionMIPS::Emulate_BZH, "BZ.h wt,s16"}, + {"BZ_W", &EmulateInstructionMIPS::Emulate_BZW, "BZ.w wt,s16"}, + {"BZ_D", &EmulateInstructionMIPS::Emulate_BZD, "BZ.d wt,s16"}, + {"BNZ_V", &EmulateInstructionMIPS::Emulate_BNZV, "BNZ.V wt,s16"}, + {"BZ_V", &EmulateInstructionMIPS::Emulate_BZV, "BZ.V wt,s16"}, + + //---------------------------------------------------------------------- + // MicroMIPS Branch instructions + //---------------------------------------------------------------------- + {"B16_MM", &EmulateInstructionMIPS::Emulate_B16_MM, "B16 offset"}, + {"BEQZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, + "BEQZ16 rs, offset"}, + {"BNEZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, + "BNEZ16 rs, offset"}, + {"BEQZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, + "BEQZC rs, offset"}, + {"BNEZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, + "BNEZC rs, offset"}, + {"BGEZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, + "BGEZALS rs, offset"}, + {"BLTZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, + "BLTZALS rs, offset"}, + {"JALR16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALR16 rs"}, + {"JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALRS16 rs"}, + {"JR16_MM", &EmulateInstructionMIPS::Emulate_JR, "JR16 rs rs"}, + {"JRC16_MM", &EmulateInstructionMIPS::Emulate_JR, "JRC16 rs rs"}, + {"JALS_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALS target"}, + {"JALX_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALX target"}, + {"JALRS_MM", &EmulateInstructionMIPS::Emulate_JALRS, "JALRS rt, rs"}, + }; + + static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); + + for (size_t i = 0; i < k_num_mips_opcodes; ++i) { + if (!strcasecmp(g_opcodes[i].op_name, op_name)) + return &g_opcodes[i]; + } + + return NULL; } -bool -EmulateInstructionMIPS::SetTargetTriple (const ArchSpec &arch) -{ - if (arch.GetTriple().getArch () == llvm::Triple::mips - || arch.GetTriple().getArch () == llvm::Triple::mipsel) - return true; +uint32_t +EmulateInstructionMIPS::GetSizeOfInstruction(lldb_private::DataExtractor &data, + uint64_t inst_addr) { + uint64_t next_inst_size = 0; + llvm::MCInst mc_insn; + llvm::MCDisassembler::DecodeStatus decode_status; + llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize()); + + if (m_use_alt_disaasm) + decode_status = + m_alt_disasm->getInstruction(mc_insn, next_inst_size, raw_insn, + inst_addr, llvm::nulls(), llvm::nulls()); + else + decode_status = + m_disasm->getInstruction(mc_insn, next_inst_size, raw_insn, inst_addr, + llvm::nulls(), llvm::nulls()); + + if (decode_status != llvm::MCDisassembler::Success) return false; + + return m_insn_info->get(mc_insn.getOpcode()).getSize(); } -const char * -EmulateInstructionMIPS::GetRegisterName (unsigned reg_num, bool alternate_name) -{ - if (alternate_name) - { - switch (reg_num) - { - case dwarf_sp_mips: return "r29"; - case dwarf_r30_mips: return "r30"; - case dwarf_ra_mips: return "r31"; - case dwarf_f0_mips: return "f0"; - case dwarf_f1_mips: return "f1"; - case dwarf_f2_mips: return "f2"; - case dwarf_f3_mips: return "f3"; - case dwarf_f4_mips: return "f4"; - case dwarf_f5_mips: return "f5"; - case dwarf_f6_mips: return "f6"; - case dwarf_f7_mips: return "f7"; - case dwarf_f8_mips: return "f8"; - case dwarf_f9_mips: return "f9"; - case dwarf_f10_mips: return "f10"; - case dwarf_f11_mips: return "f11"; - case dwarf_f12_mips: return "f12"; - case dwarf_f13_mips: return "f13"; - case dwarf_f14_mips: return "f14"; - case dwarf_f15_mips: return "f15"; - case dwarf_f16_mips: return "f16"; - case dwarf_f17_mips: return "f17"; - case dwarf_f18_mips: return "f18"; - case dwarf_f19_mips: return "f19"; - case dwarf_f20_mips: return "f20"; - case dwarf_f21_mips: return "f21"; - case dwarf_f22_mips: return "f22"; - case dwarf_f23_mips: return "f23"; - case dwarf_f24_mips: return "f24"; - case dwarf_f25_mips: return "f25"; - case dwarf_f26_mips: return "f26"; - case dwarf_f27_mips: return "f27"; - case dwarf_f28_mips: return "f28"; - case dwarf_f29_mips: return "f29"; - case dwarf_f30_mips: return "f30"; - case dwarf_f31_mips: return "f31"; - case dwarf_w0_mips: return "w0"; - case dwarf_w1_mips: return "w1"; - case dwarf_w2_mips: return "w2"; - case dwarf_w3_mips: return "w3"; - case dwarf_w4_mips: return "w4"; - case dwarf_w5_mips: return "w5"; - case dwarf_w6_mips: return "w6"; - case dwarf_w7_mips: return "w7"; - case dwarf_w8_mips: return "w8"; - case dwarf_w9_mips: return "w9"; - case dwarf_w10_mips: return "w10"; - case dwarf_w11_mips: return "w11"; - case dwarf_w12_mips: return "w12"; - case dwarf_w13_mips: return "w13"; - case dwarf_w14_mips: return "w14"; - case dwarf_w15_mips: return "w15"; - case dwarf_w16_mips: return "w16"; - case dwarf_w17_mips: return "w17"; - case dwarf_w18_mips: return "w18"; - case dwarf_w19_mips: return "w19"; - case dwarf_w20_mips: return "w20"; - case dwarf_w21_mips: return "w21"; - case dwarf_w22_mips: return "w22"; - case dwarf_w23_mips: return "w23"; - case dwarf_w24_mips: return "w24"; - case dwarf_w25_mips: return "w25"; - case dwarf_w26_mips: return "w26"; - case dwarf_w27_mips: return "w27"; - case dwarf_w28_mips: return "w28"; - case dwarf_w29_mips: return "w29"; - case dwarf_w30_mips: return "w30"; - case dwarf_w31_mips: return "w31"; - case dwarf_mir_mips: return "mir"; - case dwarf_mcsr_mips: return "mcsr"; - case dwarf_config5_mips: return "config5"; - default: - break; - } - return nullptr; - } +bool EmulateInstructionMIPS::SetInstruction(const Opcode &insn_opcode, + const Address &inst_addr, + Target *target) { + m_use_alt_disaasm = false; - switch (reg_num) - { - case dwarf_zero_mips: return "r0"; - case dwarf_r1_mips: return "r1"; - case dwarf_r2_mips: return "r2"; - case dwarf_r3_mips: return "r3"; - case dwarf_r4_mips: return "r4"; - case dwarf_r5_mips: return "r5"; - case dwarf_r6_mips: return "r6"; - case dwarf_r7_mips: return "r7"; - case dwarf_r8_mips: return "r8"; - case dwarf_r9_mips: return "r9"; - case dwarf_r10_mips: return "r10"; - case dwarf_r11_mips: return "r11"; - case dwarf_r12_mips: return "r12"; - case dwarf_r13_mips: return "r13"; - case dwarf_r14_mips: return "r14"; - case dwarf_r15_mips: return "r15"; - case dwarf_r16_mips: return "r16"; - case dwarf_r17_mips: return "r17"; - case dwarf_r18_mips: return "r18"; - case dwarf_r19_mips: return "r19"; - case dwarf_r20_mips: return "r20"; - case dwarf_r21_mips: return "r21"; - case dwarf_r22_mips: return "r22"; - case dwarf_r23_mips: return "r23"; - case dwarf_r24_mips: return "r24"; - case dwarf_r25_mips: return "r25"; - case dwarf_r26_mips: return "r26"; - case dwarf_r27_mips: return "r27"; - case dwarf_gp_mips: return "gp"; - case dwarf_sp_mips: return "sp"; - case dwarf_r30_mips: return "fp"; - case dwarf_ra_mips: return "ra"; - case dwarf_sr_mips: return "sr"; - case dwarf_lo_mips: return "lo"; - case dwarf_hi_mips: return "hi"; - case dwarf_bad_mips: return "bad"; - case dwarf_cause_mips: return "cause"; - case dwarf_pc_mips: return "pc"; - case dwarf_f0_mips: return "f0"; - case dwarf_f1_mips: return "f1"; - case dwarf_f2_mips: return "f2"; - case dwarf_f3_mips: return "f3"; - case dwarf_f4_mips: return "f4"; - case dwarf_f5_mips: return "f5"; - case dwarf_f6_mips: return "f6"; - case dwarf_f7_mips: return "f7"; - case dwarf_f8_mips: return "f8"; - case dwarf_f9_mips: return "f9"; - case dwarf_f10_mips: return "f10"; - case dwarf_f11_mips: return "f11"; - case dwarf_f12_mips: return "f12"; - case dwarf_f13_mips: return "f13"; - case dwarf_f14_mips: return "f14"; - case dwarf_f15_mips: return "f15"; - case dwarf_f16_mips: return "f16"; - case dwarf_f17_mips: return "f17"; - case dwarf_f18_mips: return "f18"; - case dwarf_f19_mips: return "f19"; - case dwarf_f20_mips: return "f20"; - case dwarf_f21_mips: return "f21"; - case dwarf_f22_mips: return "f22"; - case dwarf_f23_mips: return "f23"; - case dwarf_f24_mips: return "f24"; - case dwarf_f25_mips: return "f25"; - case dwarf_f26_mips: return "f26"; - case dwarf_f27_mips: return "f27"; - case dwarf_f28_mips: return "f28"; - case dwarf_f29_mips: return "f29"; - case dwarf_f30_mips: return "f30"; - case dwarf_f31_mips: return "f31"; - case dwarf_fcsr_mips: return "fcsr"; - case dwarf_fir_mips: return "fir"; - case dwarf_w0_mips: return "w0"; - case dwarf_w1_mips: return "w1"; - case dwarf_w2_mips: return "w2"; - case dwarf_w3_mips: return "w3"; - case dwarf_w4_mips: return "w4"; - case dwarf_w5_mips: return "w5"; - case dwarf_w6_mips: return "w6"; - case dwarf_w7_mips: return "w7"; - case dwarf_w8_mips: return "w8"; - case dwarf_w9_mips: return "w9"; - case dwarf_w10_mips: return "w10"; - case dwarf_w11_mips: return "w11"; - case dwarf_w12_mips: return "w12"; - case dwarf_w13_mips: return "w13"; - case dwarf_w14_mips: return "w14"; - case dwarf_w15_mips: return "w15"; - case dwarf_w16_mips: return "w16"; - case dwarf_w17_mips: return "w17"; - case dwarf_w18_mips: return "w18"; - case dwarf_w19_mips: return "w19"; - case dwarf_w20_mips: return "w20"; - case dwarf_w21_mips: return "w21"; - case dwarf_w22_mips: return "w22"; - case dwarf_w23_mips: return "w23"; - case dwarf_w24_mips: return "w24"; - case dwarf_w25_mips: return "w25"; - case dwarf_w26_mips: return "w26"; - case dwarf_w27_mips: return "w27"; - case dwarf_w28_mips: return "w28"; - case dwarf_w29_mips: return "w29"; - case dwarf_w30_mips: return "w30"; - case dwarf_w31_mips: return "w31"; - case dwarf_mcsr_mips: return "mcsr"; - case dwarf_mir_mips: return "mir"; - case dwarf_config5_mips: return "config5"; - } - return nullptr; -} + if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) { + if (inst_addr.GetAddressClass() == eAddressClassCodeAlternateISA) { + Error error; + lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; -bool -EmulateInstructionMIPS::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) -{ - if (reg_kind == eRegisterKindGeneric) - { - switch (reg_num) - { - case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc_mips; break; - case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp_mips; break; - case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r30_mips; break; - case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_ra_mips; break; - case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sr_mips; break; - default: - return false; - } - } + /* + * The address belongs to microMIPS function. To find the size of + * next instruction use microMIPS disassembler. + */ + m_use_alt_disaasm = true; - if (reg_kind == eRegisterKindDWARF) - { - ::memset (®_info, 0, sizeof(RegisterInfo)); - ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); - - if (reg_num == dwarf_sr_mips || reg_num == dwarf_fcsr_mips || reg_num == dwarf_fir_mips || reg_num == dwarf_mcsr_mips || reg_num == dwarf_mir_mips || reg_num == dwarf_config5_mips) - { - reg_info.byte_size = 4; - reg_info.format = eFormatHex; - reg_info.encoding = eEncodingUint; - } - else if ((int)reg_num >= dwarf_zero_mips && (int)reg_num <= dwarf_f31_mips) - { - reg_info.byte_size = 4; - reg_info.format = eFormatHex; - reg_info.encoding = eEncodingUint; - } - else if ((int)reg_num >= dwarf_w0_mips && (int)reg_num <= dwarf_w31_mips) - { - reg_info.byte_size = 16; - reg_info.format = eFormatVectorOfUInt8; - reg_info.encoding = eEncodingVector; - } - else - { - return false; - } - - reg_info.name = GetRegisterName (reg_num, false); - reg_info.alt_name = GetRegisterName (reg_num, true); - reg_info.kinds[eRegisterKindDWARF] = reg_num; - - switch (reg_num) - { - case dwarf_r30_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break; - case dwarf_ra_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break; - case dwarf_sp_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break; - case dwarf_pc_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break; - case dwarf_sr_mips: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break; - default: break; - } - return true; - } - return false; -} + uint32_t current_inst_size = insn_opcode.GetByteSize(); + uint8_t buf[sizeof(uint32_t)]; + uint64_t next_inst_addr = (m_addr & (~1ull)) + current_inst_size; + Address next_addr(next_inst_addr); -EmulateInstructionMIPS::MipsOpcode* -EmulateInstructionMIPS::GetOpcodeForInstruction (const char *op_name) -{ - static EmulateInstructionMIPS::MipsOpcode - g_opcodes[] = - { - //---------------------------------------------------------------------- - // Prologue/Epilogue instructions - //---------------------------------------------------------------------- - { "ADDiu", &EmulateInstructionMIPS::Emulate_ADDiu, "ADDIU rt, rs, immediate" }, - { "SW", &EmulateInstructionMIPS::Emulate_SW, "SW rt, offset(rs)" }, - { "LW", &EmulateInstructionMIPS::Emulate_LW, "LW rt, offset(base)" }, - { "SUBU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "SUBU rd, rs, rt" }, - { "ADDU", &EmulateInstructionMIPS::Emulate_SUBU_ADDU, "ADDU rd, rs, rt" }, - { "LUI", &EmulateInstructionMIPS::Emulate_LUI, "LUI rt, immediate" }, - - //---------------------------------------------------------------------- - // MicroMIPS Prologue/Epilogue instructions - //---------------------------------------------------------------------- - { "ADDIUSP_MM", &EmulateInstructionMIPS::Emulate_ADDIUSP, "ADDIU immediate" }, - { "ADDIUS5_MM", &EmulateInstructionMIPS::Emulate_ADDIUS5, "ADDIUS5 rd,immediate" }, - { "SWSP_MM", &EmulateInstructionMIPS::Emulate_SWSP, "SWSP rt,offset(sp)" }, - { "SWM16_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, "SWM16 reglist,offset(sp)" }, - { "SWM32_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, "SWM32 reglist,offset(base)" }, - { "SWP_MM", &EmulateInstructionMIPS::Emulate_SWM16_32, "SWP rs1,offset(base)" }, - { "LWSP_MM", &EmulateInstructionMIPS::Emulate_LWSP, "LWSP rt,offset(sp)" }, - { "LWM16_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, "LWM16 reglist,offset(sp)" }, - { "LWM32_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, "LWM32 reglist,offset(base)" }, - { "LWP_MM", &EmulateInstructionMIPS::Emulate_LWM16_32, "LWP rd,offset(base)" }, - { "JRADDIUSP", &EmulateInstructionMIPS::Emulate_JRADDIUSP, "JRADDIUSP immediate" }, - //---------------------------------------------------------------------- - - // Load/Store instructions - //---------------------------------------------------------------------- - /* Following list of emulated instructions are required by implementation of hardware watchpoint - for MIPS in lldb. As we just need the address accessed by instructions, we have generalised - all these instructions in 2 functions depending on their addressing modes */ - - { "LB", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LB rt, offset(base)" }, - { "LBE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBE rt, offset(base)" }, - { "LBU", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBU rt, offset(base)" }, - { "LBUE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBUE rt, offset(base)" }, - { "LDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDC1 ft, offset(base)" }, - { "LD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LD rt, offset(base)" }, - { "LDL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDL rt, offset(base)" }, - { "LDR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDR rt, offset(base)" }, - { "LLD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLD rt, offset(base)" }, - { "LDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LDC2 rt, offset(base)" }, - { "LDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "LDXC1 fd, index (base)" }, - { "LH", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LH rt, offset(base)" }, - { "LHE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHE rt, offset(base)" }, - { "LHU", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHU rt, offset(base)" }, - { "LHUE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHUE rt, offset(base)" }, - { "LL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LL rt, offset(base)" }, - { "LLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLE rt, offset(base)" }, - { "LUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "LUXC1 fd, index (base)" }, - { "LW", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LW rt, offset(base)" }, - { "LWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWC1 ft, offset(base)" }, - { "LWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWC2 rt, offset(base)" }, - { "LWE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWE rt, offset(base)" }, - { "LWL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWL rt, offset(base)" }, - { "LWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWLE rt, offset(base)" }, - { "LWR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWR rt, offset(base)" }, - { "LWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWRE rt, offset(base)" }, - { "LWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "LWXC1 fd, index (base)" }, - { "LLX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLX rt, offset(base)" }, - { "LLXE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLXE rt, offset(base)" }, - { "LLDX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LLDX rt, offset(base)" }, - - { "SB", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SB rt, offset(base)" }, - { "SBE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SBE rt, offset(base)" }, - { "SC", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SC rt, offset(base)" }, - { "SCE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCE rt, offset(base)" }, - { "SCD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCD rt, offset(base)" }, - { "SD", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SD rt, offset(base)" }, - { "SDL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDL rt, offset(base)" }, - { "SDR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDR rt, offset(base)" }, - { "SDC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDC1 ft, offset(base)" }, - { "SDC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SDC2 rt, offset(base)" }, - { "SDXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "SDXC1 fs, index(base)" }, - { "SH", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SH rt, offset(base)" }, - { "SHE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SHE rt, offset(base)" }, - { "SUXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "SUXC1 fs, index (base)" }, - { "SWC1", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWC1 ft, offset(base)" }, - { "SWC2", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWC2 rt, offset(base)" }, - { "SWE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWE rt, offset(base)" }, - { "SWL", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWL rt, offset(base)" }, - { "SWLE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWLE rt, offset(base)" }, - { "SWR", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWR rt, offset(base)" }, - { "SWRE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWRE rt, offset(base)" }, - { "SWXC1", &EmulateInstructionMIPS::Emulate_LDST_Reg, "SWXC1 fs, index (base)" }, - { "SCX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCX rt, offset(base)" }, - { "SCXE", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCXE rt, offset(base)" }, - { "SCDX", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SCDX rt, offset(base)" }, - - //---------------------------------------------------------------------- - // MicroMIPS Load/Store instructions - //---------------------------------------------------------------------- - { "LBU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LBU16 rt, decoded_offset(base)" }, - { "LHU16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LHU16 rt, left_shifted_offset(base)" }, - { "LW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LW16 rt, left_shifted_offset(base)" }, - { "LWGP_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "LWGP rt, left_shifted_offset(gp)" }, - { "SH16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SH16 rt, left_shifted_offset(base)" }, - { "SW16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SW16 rt, left_shifted_offset(base)" }, - { "SW_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SWSP rt, left_shifted_offset(base)" }, - { "SB16_MM", &EmulateInstructionMIPS::Emulate_LDST_Imm, "SB16 rt, offset(base)" }, - - //---------------------------------------------------------------------- - // Branch instructions - //---------------------------------------------------------------------- - { "BEQ", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQ rs,rt,offset" }, - { "BNE", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNE rs,rt,offset" }, - { "BEQL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BEQL rs,rt,offset" }, - { "BNEL", &EmulateInstructionMIPS::Emulate_BXX_3ops, "BNEL rs,rt,offset" }, - { "BGEZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BGEZALL rt,offset" }, - { "BAL", &EmulateInstructionMIPS::Emulate_BAL, "BAL offset" }, - { "BGEZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BGEZAL rs,offset" }, - { "BALC", &EmulateInstructionMIPS::Emulate_BALC, "BALC offset" }, - { "BC", &EmulateInstructionMIPS::Emulate_BC, "BC offset" }, - { "BGEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZ rs,offset" }, - { "BLEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BLEZALC rs,offset" }, - { "BGEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BGEZALC rs,offset" }, - { "BLTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BLTZALC rs,offset" }, - { "BGTZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BGTZALC rs,offset" }, - { "BEQZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BEQZALC rs,offset" }, - { "BNEZALC", &EmulateInstructionMIPS::Emulate_Bcond_Link_C,"BNEZALC rs,offset" }, - { "BEQC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BEQC rs,rt,offset" }, - { "BNEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BNEC rs,rt,offset" }, - { "BLTC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BLTC rs,rt,offset" }, - { "BGEC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BGEC rs,rt,offset" }, - { "BLTUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BLTUC rs,rt,offset" }, - { "BGEUC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BGEUC rs,rt,offset" }, - { "BLTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLTZC rt,offset" }, - { "BLEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BLEZC rt,offset" }, - { "BGEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGEZC rt,offset" }, - { "BGTZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BGTZC rt,offset" }, - { "BEQZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BEQZC rt,offset" }, - { "BNEZC", &EmulateInstructionMIPS::Emulate_BXX_2ops_C, "BNEZC rt,offset" }, - { "BGEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGEZL rt,offset" }, - { "BGTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZ rt,offset" }, - { "BGTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BGTZL rt,offset" }, - { "BLEZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZ rt,offset" }, - { "BLEZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLEZL rt,offset" }, - { "BLTZ", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZ rt,offset" }, - { "BLTZAL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BLTZAL rt,offset" }, - { "BLTZALL", &EmulateInstructionMIPS::Emulate_Bcond_Link, "BLTZALL rt,offset" }, - { "BLTZL", &EmulateInstructionMIPS::Emulate_BXX_2ops, "BLTZL rt,offset" }, - { "BOVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BOVC rs,rt,offset" }, - { "BNVC", &EmulateInstructionMIPS::Emulate_BXX_3ops_C, "BNVC rs,rt,offset" }, - { "J", &EmulateInstructionMIPS::Emulate_J, "J target" }, - { "JAL", &EmulateInstructionMIPS::Emulate_JAL, "JAL target" }, - { "JALX", &EmulateInstructionMIPS::Emulate_JAL, "JALX target" }, - { "JALR", &EmulateInstructionMIPS::Emulate_JALR, "JALR target" }, - { "JALR_HB", &EmulateInstructionMIPS::Emulate_JALR, "JALR.HB target" }, - { "JIALC", &EmulateInstructionMIPS::Emulate_JIALC, "JIALC rt,offset" }, - { "JIC", &EmulateInstructionMIPS::Emulate_JIC, "JIC rt,offset" }, - { "JR", &EmulateInstructionMIPS::Emulate_JR, "JR target" }, - { "JR_HB", &EmulateInstructionMIPS::Emulate_JR, "JR.HB target" }, - { "BC1F", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1F cc, offset" }, - { "BC1T", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1T cc, offset" }, - { "BC1FL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1FL cc, offset" }, - { "BC1TL", &EmulateInstructionMIPS::Emulate_FP_branch, "BC1TL cc, offset" }, - { "BC1EQZ", &EmulateInstructionMIPS::Emulate_BC1EQZ, "BC1EQZ ft, offset" }, - { "BC1NEZ", &EmulateInstructionMIPS::Emulate_BC1NEZ, "BC1NEZ ft, offset" }, - { "BC1ANY2F", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY2F cc, offset" }, - { "BC1ANY2T", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY2T cc, offset" }, - { "BC1ANY4F", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY4F cc, offset" }, - { "BC1ANY4T", &EmulateInstructionMIPS::Emulate_3D_branch, "BC1ANY4T cc, offset" }, - { "BNZ_B", &EmulateInstructionMIPS::Emulate_BNZB, "BNZ.b wt,s16" }, - { "BNZ_H", &EmulateInstructionMIPS::Emulate_BNZH, "BNZ.h wt,s16" }, - { "BNZ_W", &EmulateInstructionMIPS::Emulate_BNZW, "BNZ.w wt,s16" }, - { "BNZ_D", &EmulateInstructionMIPS::Emulate_BNZD, "BNZ.d wt,s16" }, - { "BZ_B", &EmulateInstructionMIPS::Emulate_BZB, "BZ.b wt,s16" }, - { "BZ_H", &EmulateInstructionMIPS::Emulate_BZH, "BZ.h wt,s16" }, - { "BZ_W", &EmulateInstructionMIPS::Emulate_BZW, "BZ.w wt,s16" }, - { "BZ_D", &EmulateInstructionMIPS::Emulate_BZD, "BZ.d wt,s16" }, - { "BNZ_V", &EmulateInstructionMIPS::Emulate_BNZV, "BNZ.V wt,s16" }, - { "BZ_V", &EmulateInstructionMIPS::Emulate_BZV, "BZ.V wt,s16" }, - - //---------------------------------------------------------------------- - // MicroMIPS Branch instructions - //---------------------------------------------------------------------- - { "B16_MM", &EmulateInstructionMIPS::Emulate_B16_MM, "B16 offset" }, - { "BEQZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BEQZ16 rs, offset" }, - { "BNEZ16_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BNEZ16 rs, offset" }, - { "BEQZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BEQZC rs, offset" }, - { "BNEZC_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BNEZC rs, offset" }, - { "BGEZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BGEZALS rs, offset" }, - { "BLTZALS_MM", &EmulateInstructionMIPS::Emulate_Branch_MM, "BLTZALS rs, offset" }, - { "JALR16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALR16 rs" }, - { "JALRS16_MM", &EmulateInstructionMIPS::Emulate_JALRx16_MM, "JALRS16 rs" }, - { "JR16_MM", &EmulateInstructionMIPS::Emulate_JR, "JR16 rs rs" }, - { "JRC16_MM", &EmulateInstructionMIPS::Emulate_JR, "JRC16 rs rs" }, - { "JALS_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALS target" }, - { "JALX_MM", &EmulateInstructionMIPS::Emulate_JALx, "JALX target" }, - { "JALRS_MM", &EmulateInstructionMIPS::Emulate_JALRS, "JALRS rt, rs" }, - }; - - static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); - - for (size_t i = 0; i < k_num_mips_opcodes; ++i) - { - if (! strcasecmp (g_opcodes[i].op_name, op_name)) - return &g_opcodes[i]; - } + const size_t bytes_read = + target->ReadMemory(next_addr, /* Address of next instruction */ + true, /* prefer_file_cache */ + buf, sizeof(uint32_t), error, &load_addr); - return NULL; -} + if (bytes_read == 0) + return true; -uint32_t -EmulateInstructionMIPS::GetSizeOfInstruction (lldb_private::DataExtractor& data, uint64_t inst_addr) -{ - uint64_t next_inst_size = 0; - llvm::MCInst mc_insn; + DataExtractor data(buf, sizeof(uint32_t), GetByteOrder(), + GetAddressByteSize()); + m_next_inst_size = GetSizeOfInstruction(data, next_inst_addr); + return true; + } else { + /* + * If the address class is not eAddressClassCodeAlternateISA then + * the function is not microMIPS. In this case instruction size is + * always 4 bytes. + */ + m_next_inst_size = 4; + return true; + } + } + return false; +} + +bool EmulateInstructionMIPS::ReadInstruction() { + bool success = false; + m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_ADDRESS, &success); + if (success) { + Context read_inst_context; + read_inst_context.type = eContextReadOpcode; + read_inst_context.SetNoArgs(); + m_opcode.SetOpcode32( + ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success), + GetByteOrder()); + } + if (!success) + m_addr = LLDB_INVALID_ADDRESS; + return success; +} + +bool EmulateInstructionMIPS::EvaluateInstruction(uint32_t evaluate_options) { + bool success = false; + llvm::MCInst mc_insn; + uint64_t insn_size; + DataExtractor data; + + /* Keep the complexity of the decode logic with the llvm::MCDisassembler + * class. */ + if (m_opcode.GetData(data)) { llvm::MCDisassembler::DecodeStatus decode_status; - llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize()); - + llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize()); if (m_use_alt_disaasm) - decode_status = m_alt_disasm->getInstruction (mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls(), llvm::nulls()); + decode_status = m_alt_disasm->getInstruction( + mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); else - decode_status = m_disasm->getInstruction (mc_insn, next_inst_size, raw_insn, inst_addr, llvm::nulls(), llvm::nulls()); + decode_status = m_disasm->getInstruction( + mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); if (decode_status != llvm::MCDisassembler::Success) - return false; - - return m_insn_info->get(mc_insn.getOpcode()).getSize(); -} - -bool -EmulateInstructionMIPS::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target) -{ - m_use_alt_disaasm = false; - - if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target)) - { - if (inst_addr.GetAddressClass() == eAddressClassCodeAlternateISA) - { - Error error; - lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; - - /* - * The address belongs to microMIPS function. To find the size of - * next instruction use microMIPS disassembler. - */ - m_use_alt_disaasm = true; - - uint32_t current_inst_size = insn_opcode.GetByteSize(); - uint8_t buf[sizeof(uint32_t)]; - uint64_t next_inst_addr = (m_addr & (~1ull)) + current_inst_size; - Address next_addr (next_inst_addr); - - const size_t bytes_read = target->ReadMemory (next_addr, /* Address of next instruction */ - true, /* prefer_file_cache */ - buf, - sizeof(uint32_t), - error, - &load_addr); - - if (bytes_read == 0) - return true; - - DataExtractor data (buf, sizeof(uint32_t), GetByteOrder(), GetAddressByteSize()); - m_next_inst_size = GetSizeOfInstruction (data, next_inst_addr); - return true; - } - else - { - /* - * If the address class is not eAddressClassCodeAlternateISA then - * the function is not microMIPS. In this case instruction size is - * always 4 bytes. - */ - m_next_inst_size = 4; - return true; - } - } - return false; -} + return false; + } -bool -EmulateInstructionMIPS::ReadInstruction () -{ - bool success = false; - m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); - if (success) - { - Context read_inst_context; - read_inst_context.type = eContextReadOpcode; - read_inst_context.SetNoArgs (); - m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder()); - } - if (!success) - m_addr = LLDB_INVALID_ADDRESS; - return success; -} - -bool -EmulateInstructionMIPS::EvaluateInstruction (uint32_t evaluate_options) -{ - bool success = false; - llvm::MCInst mc_insn; - uint64_t insn_size; - DataExtractor data; - - /* Keep the complexity of the decode logic with the llvm::MCDisassembler class. */ - if (m_opcode.GetData (data)) - { - llvm::MCDisassembler::DecodeStatus decode_status; - llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize()); - if (m_use_alt_disaasm) - decode_status = m_alt_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); - else - decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); - - if (decode_status != llvm::MCDisassembler::Success) - return false; - } + /* + * mc_insn.getOpcode() returns decoded opcode. However to make use + * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc". + */ + const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data(); - /* - * mc_insn.getOpcode() returns decoded opcode. However to make use - * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc". - */ - const char *op_name = m_insn_info->getName (mc_insn.getOpcode ()); + if (op_name == NULL) + return false; - if (op_name == NULL) - return false; + /* + * Decoding has been done already. Just get the call-back function + * and emulate the instruction. + */ + MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name); - /* - * Decoding has been done already. Just get the call-back function - * and emulate the instruction. - */ - MipsOpcode *opcode_data = GetOpcodeForInstruction (op_name); + if (opcode_data == NULL) + return false; - if (opcode_data == NULL) - return false; + uint64_t old_pc = 0, new_pc = 0; + const bool auto_advance_pc = + evaluate_options & eEmulateInstructionOptionAutoAdvancePC; - uint64_t old_pc = 0, new_pc = 0; - const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; + if (auto_advance_pc) { + old_pc = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; + } - if (auto_advance_pc) - { - old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; - } + /* emulate instruction */ + success = (this->*opcode_data->callback)(mc_insn); + if (!success) + return false; - /* emulate instruction */ - success = (this->*opcode_data->callback) (mc_insn); + if (auto_advance_pc) { + new_pc = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); if (!success) - return false; + return false; - if (auto_advance_pc) - { - new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - /* If we haven't changed the PC, change it here */ - if (old_pc == new_pc) - { - new_pc += 4; - Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, new_pc)) - return false; - } + /* If we haven't changed the PC, change it here */ + if (old_pc == new_pc) { + new_pc += 4; + Context context; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + new_pc)) + return false; } + } - return true; + return true; } -bool -EmulateInstructionMIPS::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) -{ - unwind_plan.Clear(); - unwind_plan.SetRegisterKind (eRegisterKindDWARF); +bool EmulateInstructionMIPS::CreateFunctionEntryUnwind( + UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); - UnwindPlan::RowSP row(new UnwindPlan::Row); - const bool can_replace = false; + UnwindPlan::RowSP row(new UnwindPlan::Row); + const bool can_replace = false; - // Our previous Call Frame Address is the stack pointer - row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips, 0); + // Our previous Call Frame Address is the stack pointer + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips, 0); - // Our previous PC is in the RA - row->SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace); + // Our previous PC is in the RA + row->SetRegisterLocationToRegister(dwarf_pc_mips, dwarf_ra_mips, can_replace); - unwind_plan.AppendRow (row); + unwind_plan.AppendRow(row); - // All other registers are the same. - unwind_plan.SetSourceName ("EmulateInstructionMIPS"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); - unwind_plan.SetReturnAddressRegister (dwarf_ra_mips); + // All other registers are the same. + unwind_plan.SetSourceName("EmulateInstructionMIPS"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetReturnAddressRegister(dwarf_ra_mips); - return true; + return true; } -bool -EmulateInstructionMIPS::nonvolatile_reg_p (uint32_t regnum) -{ - switch (regnum) - { - case dwarf_r16_mips: - case dwarf_r17_mips: - case dwarf_r18_mips: - case dwarf_r19_mips: - case dwarf_r20_mips: - case dwarf_r21_mips: - case dwarf_r22_mips: - case dwarf_r23_mips: - case dwarf_gp_mips: - case dwarf_sp_mips: - case dwarf_r30_mips: - case dwarf_ra_mips: - return true; - default: - return false; - } +bool EmulateInstructionMIPS::nonvolatile_reg_p(uint32_t regnum) { + switch (regnum) { + case dwarf_r16_mips: + case dwarf_r17_mips: + case dwarf_r18_mips: + case dwarf_r19_mips: + case dwarf_r20_mips: + case dwarf_r21_mips: + case dwarf_r22_mips: + case dwarf_r23_mips: + case dwarf_gp_mips: + case dwarf_sp_mips: + case dwarf_r30_mips: + case dwarf_ra_mips: + return true; + default: return false; -} - -bool -EmulateInstructionMIPS::Emulate_ADDiu (llvm::MCInst& insn) -{ - // ADDIU rt, rs, immediate - // GPR[rt] <- GPR[rs] + sign_extend(immediate) - - uint8_t dst, src; - bool success = false; - const uint32_t imm16 = insn.getOperand(2).getImm(); - int64_t imm = SignedBits(imm16, 15, 0); - - dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - - // If immediate value is greater then 2^16 - 1 then clang generate - // LUI, ADDIU, SUBU instructions in prolog. - // Example - // lui $1, 0x2 - // addiu $1, $1, -0x5920 - // subu $sp, $sp, $1 - // In this case, ADDIU dst and src will be same and not equal to sp - if (dst == src) - { - Context context; + } + return false; +} + +bool EmulateInstructionMIPS::Emulate_ADDiu(llvm::MCInst &insn) { + // ADDIU rt, rs, immediate + // GPR[rt] <- GPR[rs] + sign_extend(immediate) + + uint8_t dst, src; + bool success = false; + const uint32_t imm16 = insn.getOperand(2).getImm(); + int64_t imm = SignedBits(imm16, 15, 0); + + dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + + // If immediate value is greater then 2^16 - 1 then clang generate + // LUI, ADDIU, SUBU instructions in prolog. + // Example + // lui $1, 0x2 + // addiu $1, $1, -0x5920 + // subu $sp, $sp, $1 + // In this case, ADDIU dst and src will be same and not equal to sp + if (dst == src) { + Context context; - /* read <src> register */ - const int64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success); - if (!success) - return false; + /* read <src> register */ + const int64_t src_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success); + if (!success) + return false; - /* Check if this is daddiu sp, sp, imm16 */ - if (dst == dwarf_sp_mips) - { - uint64_t result = src_opd_val + imm; - RegisterInfo reg_info_sp; + /* Check if this is daddiu sp, sp, imm16 */ + if (dst == dwarf_sp_mips) { + uint64_t result = src_opd_val + imm; + RegisterInfo reg_info_sp; - if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset (reg_info_sp, imm); + if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) + context.SetRegisterPlusOffset(reg_info_sp, imm); - /* We are allocating bytes on stack */ - context.type = eContextAdjustStackPointer; + /* We are allocating bytes on stack */ + context.type = eContextAdjustStackPointer; - WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result); - return true; - } + WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result); + return true; + } - imm += src_opd_val; - context.SetImmediateSigned (imm); - context.type = eContextImmediate; + imm += src_opd_val; + context.SetImmediateSigned(imm); + context.type = eContextImmediate; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + dst, imm)) - return false; - } + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, + dwarf_zero_mips + dst, imm)) + return false; + } - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_SW (llvm::MCInst& insn) -{ - bool success = false; - uint32_t imm16 = insn.getOperand(2).getImm(); - uint32_t imm = SignedBits(imm16, 15, 0); - uint32_t src, base; - int32_t address; - Context bad_vaddr_context; +bool EmulateInstructionMIPS::Emulate_SW(llvm::MCInst &insn) { + bool success = false; + uint32_t imm16 = insn.getOperand(2).getImm(); + uint32_t imm = SignedBits(imm16, 15, 0); + uint32_t src, base; + int32_t address; + Context bad_vaddr_context; - RegisterInfo reg_info_base; + RegisterInfo reg_info_base; - src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) - return false; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, + reg_info_base)) + return false; - /* read base register */ - address = (int32_t)ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + /* read base register */ + address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + base, 0, &success); + if (!success) + return false; - /* destination address */ - address = address + imm; + /* destination address */ + address = address + imm; - /* Set the bad_vaddr register with base address used in the instruction */ - bad_vaddr_context.type = eContextInvalid; - WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + /* Set the bad_vaddr register with base address used in the instruction */ + bad_vaddr_context.type = eContextInvalid; + WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, + address); - /* We look for sp based non-volatile register stores */ - if (nonvolatile_reg_p (src)) - { + /* We look for sp based non-volatile register stores */ + if (nonvolatile_reg_p(src)) { - RegisterInfo reg_info_src; + RegisterInfo reg_info_src; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src)) - return false; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src, + reg_info_src)) + return false; - Context context; - RegisterValue data_src; - context.type = eContextPushRegisterOnStack; - context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0); + Context context; + RegisterValue data_src; + context.type = eContextPushRegisterOnStack; + context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0); - uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; - Error error; + uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; + Error error; - if (!ReadRegister (®_info_base, data_src)) - return false; + if (!ReadRegister(®_info_base, data_src)) + return false; - if (data_src.GetAsMemoryData (®_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0) - return false; + if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size, + eByteOrderLittle, error) == 0) + return false; - if (!WriteMemory (context, address, buffer, reg_info_src.byte_size)) - return false; + if (!WriteMemory(context, address, buffer, reg_info_src.byte_size)) + return false; - return true; - } + return true; + } - return false; + return false; } -bool -EmulateInstructionMIPS::Emulate_LW (llvm::MCInst& insn) -{ - bool success =false; - uint32_t src, base; - int32_t imm, address; - Context bad_vaddr_context; +bool EmulateInstructionMIPS::Emulate_LW(llvm::MCInst &insn) { + bool success = false; + uint32_t src, base; + int32_t imm, address; + Context bad_vaddr_context; - src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - imm = insn.getOperand(2).getImm(); + src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + imm = insn.getOperand(2).getImm(); - RegisterInfo reg_info_base; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) - return false; + RegisterInfo reg_info_base; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, + reg_info_base)) + return false; - /* read base register */ - address = (int32_t)ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + /* read base register */ + address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + base, 0, &success); + if (!success) + return false; - /* destination address */ - address = address + imm; + /* destination address */ + address = address + imm; - /* Set the bad_vaddr register with base address used in the instruction */ - bad_vaddr_context.type = eContextInvalid; - WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + /* Set the bad_vaddr register with base address used in the instruction */ + bad_vaddr_context.type = eContextInvalid; + WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, + address); - if (nonvolatile_reg_p (src)) - { - RegisterValue data_src; - RegisterInfo reg_info_src; + if (nonvolatile_reg_p(src)) { + RegisterValue data_src; + RegisterInfo reg_info_src; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src)) - return false; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src, + reg_info_src)) + return false; - Context context; - context.type = eContextPopRegisterOffStack; - context.SetAddress (address); + Context context; + context.type = eContextPopRegisterOffStack; + context.SetAddress(address); - if (!WriteRegister (context, ®_info_src, data_src)) - return false; + if (!WriteRegister(context, ®_info_src, data_src)) + return false; - return true; - } + return true; + } - return false; + return false; } -bool -EmulateInstructionMIPS::Emulate_SUBU_ADDU (llvm::MCInst& insn) -{ - // SUBU sp, <src>, <rt> - // ADDU sp, <src>, <rt> - // ADDU dst, sp, <rt> +bool EmulateInstructionMIPS::Emulate_SUBU_ADDU(llvm::MCInst &insn) { + // SUBU sp, <src>, <rt> + // ADDU sp, <src>, <rt> + // ADDU dst, sp, <rt> - bool success = false; - uint64_t result; - uint8_t src, dst, rt; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + bool success = false; + uint64_t result; + uint8_t src, dst, rt; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); - /* Check if sp is destination register */ - if (dst == dwarf_sp_mips) - { - rt = m_reg_info->getEncodingValue (insn.getOperand(2).getReg()); + dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); - /* read <src> register */ - uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success); - if (!success) - return false; + /* Check if sp is destination register */ + if (dst == dwarf_sp_mips) { + rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg()); - /* read <rt > register */ - uint64_t rt_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); - if (!success) - return false; + /* read <src> register */ + uint64_t src_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "SUBU")) - result = src_opd_val - rt_opd_val; - else - result = src_opd_val + rt_opd_val; + /* read <rt > register */ + uint64_t rt_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; - Context context; - RegisterInfo reg_info_sp; - if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset (reg_info_sp, rt_opd_val); + if (!strcasecmp(op_name, "SUBU")) + result = src_opd_val - rt_opd_val; + else + result = src_opd_val + rt_opd_val; - /* We are allocating bytes on stack */ - context.type = eContextAdjustStackPointer; + Context context; + RegisterInfo reg_info_sp; + if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) + context.SetRegisterPlusOffset(reg_info_sp, rt_opd_val); - WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result); + /* We are allocating bytes on stack */ + context.type = eContextAdjustStackPointer; - return true; - } - else if (src == dwarf_sp_mips) - { - rt = m_reg_info->getEncodingValue (insn.getOperand(2).getReg()); + WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result); - /* read <src> register */ - uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success); - if (!success) - return false; + return true; + } else if (src == dwarf_sp_mips) { + rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg()); - /* read <rt> register */ - uint64_t rt_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); - if (!success) - return false; + /* read <src> register */ + uint64_t src_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + src, 0, &success); + if (!success) + return false; - Context context; + /* read <rt> register */ + uint64_t rt_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "SUBU")) - result = src_opd_val - rt_opd_val; - else - result = src_opd_val + rt_opd_val; + Context context; - context.SetImmediateSigned (result); - context.type = eContextImmediate; + if (!strcasecmp(op_name, "SUBU")) + result = src_opd_val - rt_opd_val; + else + result = src_opd_val + rt_opd_val; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + dst, result)) - return false; - } + context.SetImmediateSigned(result); + context.type = eContextImmediate; - return true; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, + dwarf_zero_mips + dst, result)) + return false; + } + + return true; } -bool -EmulateInstructionMIPS::Emulate_LUI (llvm::MCInst& insn) -{ - // LUI rt, immediate - // GPR[rt] <- sign_extend(immediate << 16) +bool EmulateInstructionMIPS::Emulate_LUI(llvm::MCInst &insn) { + // LUI rt, immediate + // GPR[rt] <- sign_extend(immediate << 16) - const uint32_t imm32 = insn.getOperand(1).getImm() << 16; - int64_t imm = SignedBits(imm32, 31, 0); - uint8_t rt; - Context context; - - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - context.SetImmediateSigned (imm); - context.type = eContextImmediate; + const uint32_t imm32 = insn.getOperand(1).getImm() << 16; + int64_t imm = SignedBits(imm32, 31, 0); + uint8_t rt; + Context context; - if (WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, imm)) - return true; + rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + context.SetImmediateSigned(imm); + context.type = eContextImmediate; - return false; + if (WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt, + imm)) + return true; + + return false; } -bool -EmulateInstructionMIPS::Emulate_ADDIUSP (llvm::MCInst& insn) -{ - bool success = false; - const uint32_t imm9 = insn.getOperand(0).getImm(); - uint64_t result; +bool EmulateInstructionMIPS::Emulate_ADDIUSP(llvm::MCInst &insn) { + bool success = false; + const uint32_t imm9 = insn.getOperand(0).getImm(); + uint64_t result; - // This instruction operates implicitly on stack pointer, so read <sp> register. - uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_sp_mips, 0, &success); - if (!success) - return false; + // This instruction operates implicitly on stack pointer, so read <sp> + // register. + uint64_t src_opd_val = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success); + if (!success) + return false; - result = src_opd_val + imm9; + result = src_opd_val + imm9; - Context context; - RegisterInfo reg_info_sp; - if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset (reg_info_sp, imm9); + Context context; + RegisterInfo reg_info_sp; + if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) + context.SetRegisterPlusOffset(reg_info_sp, imm9); - // We are adjusting the stack. - context.type = eContextAdjustStackPointer; + // We are adjusting the stack. + context.type = eContextAdjustStackPointer; - WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result); - return true; + WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result); + return true; } -bool -EmulateInstructionMIPS::Emulate_ADDIUS5 (llvm::MCInst& insn) -{ - bool success = false; - uint32_t base; - const uint32_t imm4 = insn.getOperand(2).getImm(); - uint64_t result; +bool EmulateInstructionMIPS::Emulate_ADDIUS5(llvm::MCInst &insn) { + bool success = false; + uint32_t base; + const uint32_t imm4 = insn.getOperand(2).getImm(); + uint64_t result; - // The source and destination register is same for this instruction. - base = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + // The source and destination register is same for this instruction. + base = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); - // We are looking for stack adjustment only - if (base == dwarf_sp_mips) - { - // Read stack pointer register - uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + // We are looking for stack adjustment only + if (base == dwarf_sp_mips) { + // Read stack pointer register + uint64_t src_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); + if (!success) + return false; - result = src_opd_val + imm4; + result = src_opd_val + imm4; - Context context; - RegisterInfo reg_info_sp; - if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset (reg_info_sp, imm4); + Context context; + RegisterInfo reg_info_sp; + if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) + context.SetRegisterPlusOffset(reg_info_sp, imm4); - // We are adjusting the stack. - context.type = eContextAdjustStackPointer; + // We are adjusting the stack. + context.type = eContextAdjustStackPointer; - WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result); - } + WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, result); + } - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_SWSP (llvm::MCInst& insn) -{ - bool success = false; - uint32_t imm5 = insn.getOperand(2).getImm(); - uint32_t src, base; - Context bad_vaddr_context; - uint32_t address; +bool EmulateInstructionMIPS::Emulate_SWSP(llvm::MCInst &insn) { + bool success = false; + uint32_t imm5 = insn.getOperand(2).getImm(); + uint32_t src, base; + Context bad_vaddr_context; + uint32_t address; - src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); - RegisterInfo reg_info_base; + RegisterInfo reg_info_base; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) - return false; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, + reg_info_base)) + return false; - // read base register - address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + // read base register + address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0, + &success); + if (!success) + return false; - // destination address - address = address + imm5; + // destination address + address = address + imm5; - // We use bad_vaddr_context to store base address which is used by H/W watchpoint - // Set the bad_vaddr register with base address used in the instruction - bad_vaddr_context.type = eContextInvalid; - WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + // We use bad_vaddr_context to store base address which is used by H/W + // watchpoint + // Set the bad_vaddr register with base address used in the instruction + bad_vaddr_context.type = eContextInvalid; + WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, + address); - // We look for sp based non-volatile register stores. - if (base == dwarf_sp_mips && nonvolatile_reg_p (src)) - { - RegisterInfo reg_info_src = {}; - Context context; - RegisterValue data_src; - context.type = eContextPushRegisterOnStack; - context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0); + // We look for sp based non-volatile register stores. + if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) { + RegisterInfo reg_info_src = {}; + Context context; + RegisterValue data_src; + context.type = eContextPushRegisterOnStack; + context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0); - uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; - Error error; + uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; + Error error; - if (!ReadRegister (®_info_base, data_src)) - return false; + if (!ReadRegister(®_info_base, data_src)) + return false; - if (data_src.GetAsMemoryData (®_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0) - return false; + if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size, + eByteOrderLittle, error) == 0) + return false; - if (!WriteMemory (context, address, buffer, reg_info_src.byte_size)) - return false; + if (!WriteMemory(context, address, buffer, reg_info_src.byte_size)) + return false; - return true; - } + return true; + } - return false; + return false; } /* Emulate SWM16,SWM32 and SWP instruction. - SWM16 always has stack pointer as a base register (but it is still available in MCInst as an operand). + SWM16 always has stack pointer as a base register (but it is still available + in MCInst as an operand). SWM32 and SWP can have base register other than stack pointer. */ -bool -EmulateInstructionMIPS::Emulate_SWM16_32 (llvm::MCInst& insn) -{ - bool success = false; - uint32_t src, base; - uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on no of regs to store. - - // Base register is second last operand of the instruction. - base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); - - // We are looking for sp based stores so if base is not a stack pointer then don't proceed. - if (base != dwarf_sp_mips) - return false; +bool EmulateInstructionMIPS::Emulate_SWM16_32(llvm::MCInst &insn) { + bool success = false; + uint32_t src, base; + uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on + // no of regs to store. + + // Base register is second last operand of the instruction. + base = + m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); + + // We are looking for sp based stores so if base is not a stack pointer then + // don't proceed. + if (base != dwarf_sp_mips) + return false; - // offset is always the last operand. - uint32_t offset = insn.getOperand(num_operands-1).getImm(); + // offset is always the last operand. + uint32_t offset = insn.getOperand(num_operands - 1).getImm(); - RegisterInfo reg_info_base; - RegisterInfo reg_info_src; - - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) - return false; + RegisterInfo reg_info_base; + RegisterInfo reg_info_src; - // read SP - uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, + reg_info_base)) + return false; - // Resulting base addrss - base_address = base_address + offset; + // read SP + uint32_t base_address = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); + if (!success) + return false; - // Total no of registers to be stored are num_operands-2. - for (uint32_t i = 0; i < num_operands - 2; i++) - { - // Get the register number to be stored. - src = m_reg_info->getEncodingValue (insn.getOperand(i).getReg()); + // Resulting base addrss + base_address = base_address + offset; - /* - Record only non-volatile stores. - This check is required for SWP instruction because source operand could be any register. - SWM16 and SWM32 instruction always has saved registers as source operands. - */ - if (!nonvolatile_reg_p (src)) - return false; + // Total no of registers to be stored are num_operands-2. + for (uint32_t i = 0; i < num_operands - 2; i++) { + // Get the register number to be stored. + src = m_reg_info->getEncodingValue(insn.getOperand(i).getReg()); - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src)) - return false; + /* + Record only non-volatile stores. + This check is required for SWP instruction because source operand could + be any register. + SWM16 and SWM32 instruction always has saved registers as source + operands. + */ + if (!nonvolatile_reg_p(src)) + return false; - Context context; - RegisterValue data_src; - context.type = eContextPushRegisterOnStack; - context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0); + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src, + reg_info_src)) + return false; - uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; - Error error; + Context context; + RegisterValue data_src; + context.type = eContextPushRegisterOnStack; + context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0); - if (!ReadRegister (®_info_base, data_src)) - return false; + uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; + Error error; - if (data_src.GetAsMemoryData (®_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0) - return false; + if (!ReadRegister(®_info_base, data_src)) + return false; - if (!WriteMemory (context, base_address, buffer, reg_info_src.byte_size)) - return false; + if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size, + eByteOrderLittle, error) == 0) + return false; - // Stack address for next register - base_address = base_address + reg_info_src.byte_size; - } - return true; + if (!WriteMemory(context, base_address, buffer, reg_info_src.byte_size)) + return false; + + // Stack address for next register + base_address = base_address + reg_info_src.byte_size; + } + return true; } -bool -EmulateInstructionMIPS::Emulate_LWSP (llvm::MCInst& insn) -{ - bool success = false; - uint32_t src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - uint32_t base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - uint32_t imm5 = insn.getOperand(2).getImm(); - Context bad_vaddr_context; +bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) { + bool success = false; + uint32_t src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + uint32_t base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + uint32_t imm5 = insn.getOperand(2).getImm(); + Context bad_vaddr_context; - RegisterInfo reg_info_base; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) - return false; + RegisterInfo reg_info_base; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, + reg_info_base)) + return false; - // read base register - uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + // read base register + uint32_t base_address = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); + if (!success) + return false; - base_address = base_address + imm5; + base_address = base_address + imm5; - // We use bad_vaddr_context to store base address which is used by H/W watchpoint - // Set the bad_vaddr register with base address used in the instruction - bad_vaddr_context.type = eContextInvalid; - WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, base_address); + // We use bad_vaddr_context to store base address which is used by H/W + // watchpoint + // Set the bad_vaddr register with base address used in the instruction + bad_vaddr_context.type = eContextInvalid; + WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, + base_address); - if (base == dwarf_sp_mips && nonvolatile_reg_p (src)) - { - RegisterValue data_src; - RegisterInfo reg_info_src; + if (base == dwarf_sp_mips && nonvolatile_reg_p(src)) { + RegisterValue data_src; + RegisterInfo reg_info_src; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + src, reg_info_src)) - return false; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + src, + reg_info_src)) + return false; - Context context; - context.type = eContextPopRegisterOffStack; - context.SetAddress (base_address); + Context context; + context.type = eContextPopRegisterOffStack; + context.SetAddress(base_address); - if (!WriteRegister (context, ®_info_src, data_src)) - return false; + if (!WriteRegister(context, ®_info_src, data_src)) + return false; - return true; - } + return true; + } - return false; + return false; } /* Emulate LWM16, LWM32 and LWP instructions. - LWM16 always has stack pointer as a base register (but it is still available in MCInst as an operand). + LWM16 always has stack pointer as a base register (but it is still available + in MCInst as an operand). LWM32 and LWP can have base register other than stack pointer. */ -bool -EmulateInstructionMIPS::Emulate_LWM16_32 (llvm::MCInst& insn) -{ - bool success = false; - uint32_t dst, base; - uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on no of regs to store. - uint32_t imm = insn.getOperand(num_operands-1).getImm(); // imm is the last operand in the instruction. - - // Base register is second last operand of the instruction. - base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); - - // We are looking for sp based loads so if base is not a stack pointer then don't proceed. - if (base != dwarf_sp_mips) - return false; +bool EmulateInstructionMIPS::Emulate_LWM16_32(llvm::MCInst &insn) { + bool success = false; + uint32_t dst, base; + uint32_t num_operands = insn.getNumOperands(); // No of operands vary based on + // no of regs to store. + uint32_t imm = insn.getOperand(num_operands - 1) + .getImm(); // imm is the last operand in the instruction. + + // Base register is second last operand of the instruction. + base = + m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); + + // We are looking for sp based loads so if base is not a stack pointer then + // don't proceed. + if (base != dwarf_sp_mips) + return false; - uint32_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + uint32_t base_address = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); + if (!success) + return false; - base_address = base_address + imm; - - RegisterValue data_dst; - RegisterInfo reg_info_dst; - - // Total no of registers to be re-stored are num_operands-2. - for (uint32_t i = 0; i < num_operands - 2; i++) - { - // Get the register number to be re-stored. - dst = m_reg_info->getEncodingValue (insn.getOperand(i).getReg()); - - /* - Record only non-volatile loads. - This check is required for LWP instruction because destination operand could be any register. - LWM16 and LWM32 instruction always has saved registers as destination operands. - */ - if (!nonvolatile_reg_p (dst)) - return false; - - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + dst, reg_info_dst)) - return false; - - Context context; - context.type = eContextPopRegisterOffStack; - context.SetAddress (base_address + (i*4)); - - if (!WriteRegister (context, ®_info_dst, data_dst)) - return false; - } + base_address = base_address + imm; - return true; -} + RegisterValue data_dst; + RegisterInfo reg_info_dst; -bool -EmulateInstructionMIPS::Emulate_JRADDIUSP (llvm::MCInst& insn) -{ - bool success = false; - int32_t imm5 = insn.getOperand(0).getImm(); + // Total no of registers to be re-stored are num_operands-2. + for (uint32_t i = 0; i < num_operands - 2; i++) { + // Get the register number to be re-stored. + dst = m_reg_info->getEncodingValue(insn.getOperand(i).getReg()); - /* JRADDIUSP immediate - * PC <- RA - * SP <- SP + zero_extend(Immediate << 2) + /* + Record only non-volatile loads. + This check is required for LWP instruction because destination operand + could be any register. + LWM16 and LWM32 instruction always has saved registers as destination + operands. */ - - // This instruction operates implicitly on stack pointer, so read <sp> register. - int32_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_sp_mips, 0, &success); - if (!success) - return false; + if (!nonvolatile_reg_p(dst)) + return false; - int32_t ra_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_ra_mips, 0, &success); - if (!success) - return false; - - int32_t result = src_opd_val + imm5; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + dst, + reg_info_dst)) + return false; Context context; + context.type = eContextPopRegisterOffStack; + context.SetAddress(base_address + (i * 4)); - // Update the PC - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, ra_val)) - return false; - - RegisterInfo reg_info_sp; - if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) - context.SetRegisterPlusOffset (reg_info_sp, imm5); + if (!WriteRegister(context, ®_info_dst, data_dst)) + return false; + } - // We are adjusting stack - context.type = eContextAdjustStackPointer; + return true; +} - // update SP - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips, result)) - return false; +bool EmulateInstructionMIPS::Emulate_JRADDIUSP(llvm::MCInst &insn) { + bool success = false; + int32_t imm5 = insn.getOperand(0).getImm(); - return true; + /* JRADDIUSP immediate + * PC <- RA + * SP <- SP + zero_extend(Immediate << 2) + */ + + // This instruction operates implicitly on stack pointer, so read <sp> + // register. + int32_t src_opd_val = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_sp_mips, 0, &success); + if (!success) + return false; + + int32_t ra_val = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_ra_mips, 0, &success); + if (!success) + return false; + + int32_t result = src_opd_val + imm5; + + Context context; + + // Update the PC + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + ra_val)) + return false; + + RegisterInfo reg_info_sp; + if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips, reg_info_sp)) + context.SetRegisterPlusOffset(reg_info_sp, imm5); + + // We are adjusting stack + context.type = eContextAdjustStackPointer; + + // update SP + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips, + result)) + return false; + + return true; } -static int -IsAdd64bitOverflow (int32_t a, int32_t b) -{ - int32_t r = (uint32_t) a + (uint32_t) b; +static int IsAdd64bitOverflow(int32_t a, int32_t b) { + int32_t r = (uint32_t)a + (uint32_t)b; return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0); } -/* +/* Emulate below MIPS branch instructions. BEQ, BNE : Branch on condition BEQL, BNEL : Branch likely */ -bool -EmulateInstructionMIPS::Emulate_BXX_3ops (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs, rt; - int32_t offset, pc, target = 0, rs_val, rt_val; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - offset = insn.getOperand(2).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_BXX_3ops(llvm::MCInst &insn) { + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target = 0, rs_val, rt_val; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); - if (!success) - return false; + rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BEQ") || - !strcasecmp (op_name, "BEQL")) - { - if (rs_val == rt_val) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BNE") || - !strcasecmp (op_name, "BNEL")) - { - if (rs_val != rt_val) - target = pc + offset; - else - target = pc + 8; - } + if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")) { + if (rs_val == rt_val) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL")) { + if (rs_val != rt_val) + target = pc + offset; + else + target = pc + 8; + } - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (offset); + Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(offset); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; - - return true; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; + + return true; } -/* +/* Emulate below MIPS branch instructions. - BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch instructions with no delay slot + BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch + instructions with no delay slot */ -bool -EmulateInstructionMIPS::Emulate_BXX_3ops_C (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs, rt; - int32_t offset, pc, target = 0, rs_val, rt_val; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - offset = insn.getOperand(2).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_BXX_3ops_C(llvm::MCInst &insn) { + bool success = false; + uint32_t rs, rt; + int32_t offset, pc, target = 0, rs_val, rt_val; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); + + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); - if (!success) - return false; + rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BEQC")) - { - if (rs_val == rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BNEC")) - { - if (rs_val != rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BLTC")) - { - if (rs_val < rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGEC")) - { - if (rs_val >= rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BLTUC")) - { - if (rs_val < rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGEUC")) - { - if ((uint32_t)rs_val >= (uint32_t)rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BOVC")) - { - if (IsAdd64bitOverflow (rs_val, rt_val)) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BNVC")) - { - if (!IsAdd64bitOverflow (rs_val, rt_val)) - target = pc + offset; - else - target = pc + 4; - } + if (!strcasecmp(op_name, "BEQC")) { + if (rs_val == rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BNEC")) { + if (rs_val != rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BLTC")) { + if (rs_val < rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGEC")) { + if (rs_val >= rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BLTUC")) { + if (rs_val < rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGEUC")) { + if ((uint32_t)rs_val >= (uint32_t)rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BOVC")) { + if (IsAdd64bitOverflow(rs_val, rt_val)) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BNVC")) { + if (!IsAdd64bitOverflow(rs_val, rt_val)) + target = pc + offset; + else + target = pc + 4; + } - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (current_inst_size + offset); + Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(current_inst_size + offset); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; - - return true; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; + + return true; } -/* +/* Emulate below MIPS conditional branch and link instructions. BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches */ -bool -EmulateInstructionMIPS::Emulate_Bcond_Link_C (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs; - int32_t offset, pc, target = 0; - int32_t rs_val; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_Bcond_Link_C(llvm::MCInst &insn) { + bool success = false; + uint32_t rs; + int32_t offset, pc, target = 0; + int32_t rs_val; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BLEZALC")) - { - if (rs_val <= 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGEZALC")) - { - if (rs_val >= 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BLTZALC")) - { - if (rs_val < 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGTZALC")) - { - if (rs_val > 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BEQZALC")) - { - if (rs_val == 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BNEZALC")) - { - if (rs_val != 0) - target = pc + offset; - else - target = pc + 4; - } + if (!strcasecmp(op_name, "BLEZALC")) { + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGEZALC")) { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BLTZALC")) { + if (rs_val < 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGTZALC")) { + if (rs_val > 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BEQZALC")) { + if (rs_val == 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BNEZALC")) { + if (rs_val != 0) + target = pc + offset; + else + target = pc + 4; + } - Context context; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - return true; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips, + pc + 4)) + return false; + + return true; } -/* +/* Emulate below MIPS Non-Compact conditional branch and link instructions. BLTZAL, BGEZAL : BLTZALL, BGEZALL : Branch likely */ -bool -EmulateInstructionMIPS::Emulate_Bcond_Link (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs; - int32_t offset, pc, target = 0; - int32_t rs_val; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_Bcond_Link(llvm::MCInst &insn) { + bool success = false; + uint32_t rs; + int32_t offset, pc, target = 0; + int32_t rs_val; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BLTZAL") || - !strcasecmp (op_name, "BLTZALL")) - { - if ((int32_t) rs_val < 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BGEZAL") || - !strcasecmp (op_name, "BGEZALL")) - { - if ((int32_t) rs_val >= 0) - target = pc + offset; - else - target = pc + 8; - } + if (!strcasecmp(op_name, "BLTZAL") || !strcasecmp(op_name, "BLTZALL")) { + if ((int32_t)rs_val < 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BGEZAL") || + !strcasecmp(op_name, "BGEZALL")) { + if ((int32_t)rs_val >= 0) + target = pc + offset; + else + target = pc + 8; + } - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips, + pc + 8)) + return false; - return true; + return true; } -/* +/* Emulate below MIPS branch instructions. BLTZL, BGEZL, BGTZL, BLEZL : Branch likely BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches */ -bool -EmulateInstructionMIPS::Emulate_BXX_2ops (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs; - int32_t offset, pc, target = 0; - int32_t rs_val; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_BXX_2ops(llvm::MCInst &insn) { + bool success = false; + uint32_t rs; + int32_t offset, pc, target = 0; + int32_t rs_val; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BLTZL") || - !strcasecmp (op_name, "BLTZ")) - { - if (rs_val < 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BGEZL") || - !strcasecmp (op_name, "BGEZ")) - { - if (rs_val >= 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BGTZL") || - !strcasecmp (op_name, "BGTZ")) - { - if (rs_val > 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BLEZL") || - !strcasecmp (op_name, "BLEZ")) - { - if (rs_val <= 0) - target = pc + offset; - else - target = pc + 8; - } + if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ")) { + if (rs_val < 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ")) { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ")) { + if (rs_val > 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")) { + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 8; + } - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (offset); + Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(offset); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - return true; + return true; } -/* +/* Emulate below MIPS branch instructions. BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches */ -bool -EmulateInstructionMIPS::Emulate_BXX_2ops_C (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs; - int32_t offset, pc, target = 0; - int32_t rs_val; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_BXX_2ops_C(llvm::MCInst &insn) { + bool success = false; + uint32_t rs; + int32_t offset, pc, target = 0; + int32_t rs_val; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); + + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BLTZC")) - { - if (rs_val < 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BLEZC")) - { - if (rs_val <= 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGEZC")) - { - if (rs_val >= 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGTZC")) - { - if (rs_val > 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BEQZC")) - { - if (rs_val == 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BNEZC")) - { - if (rs_val != 0) - target = pc + offset; - else - target = pc + 4; - } + if (!strcasecmp(op_name, "BLTZC")) { + if (rs_val < 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BLEZC")) { + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGEZC")) { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGTZC")) { + if (rs_val > 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BEQZC")) { + if (rs_val == 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BNEZC")) { + if (rs_val != 0) + target = pc + offset; + else + target = pc + 4; + } - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (current_inst_size + offset); + Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(current_inst_size + offset); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_B16_MM (llvm::MCInst& insn) -{ - bool success = false; - int32_t offset, pc, target; - uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); +bool EmulateInstructionMIPS::Emulate_B16_MM(llvm::MCInst &insn) { + bool success = false; + int32_t offset, pc, target; + uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); - offset = insn.getOperand(0).getImm(); + offset = insn.getOperand(0).getImm(); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - // unconditional branch - target = pc + offset; + // unconditional branch + target = pc + offset; - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (current_inst_size + offset); + Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(current_inst_size + offset); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - return true; + return true; } /* @@ -1978,503 +2232,498 @@ EmulateInstructionMIPS::Emulate_B16_MM (llvm::MCInst& insn) BEQZ16, BNEZ16 are 16 bit instructions with delay slot. BGEZALS, BLTZALS are 16 bit instructions with short (2-byte) delay slot. */ -bool -EmulateInstructionMIPS::Emulate_Branch_MM (llvm::MCInst& insn) -{ - bool success = false; - int32_t target = 0; - uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - bool update_ra = false; - uint32_t ra_offset = 0; - - /* - * BEQZ16 rs, offset - * condition <- (GPR[rs] = 0) - * if condition then - * PC = PC + sign_ext (offset || 0) - * - * BNEZ16 rs, offset - * condition <- (GPR[rs] != 0) - * if condition then - * PC = PC + sign_ext (offset || 0) - * - * BEQZC rs, offset (compact instruction: No delay slot) - * condition <- (GPR[rs] == 0) - * if condition then - * PC = PC + 4 + sign_ext (offset || 0) - */ +bool EmulateInstructionMIPS::Emulate_Branch_MM(llvm::MCInst &insn) { + bool success = false; + int32_t target = 0; + uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + bool update_ra = false; + uint32_t ra_offset = 0; + + /* + * BEQZ16 rs, offset + * condition <- (GPR[rs] = 0) + * if condition then + * PC = PC + sign_ext (offset || 0) + * + * BNEZ16 rs, offset + * condition <- (GPR[rs] != 0) + * if condition then + * PC = PC + sign_ext (offset || 0) + * + * BEQZC rs, offset (compact instruction: No delay slot) + * condition <- (GPR[rs] == 0) + * if condition then + * PC = PC + 4 + sign_ext (offset || 0) + */ + + uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + int32_t offset = insn.getOperand(1).getImm(); + + int32_t pc = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - int32_t offset = insn.getOperand(1).getImm(); + int32_t rs_val = (int32_t)ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; - int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + if (!strcasecmp(op_name, "BEQZ16_MM")) { + if (rs_val == 0) + target = pc + offset; + else + target = pc + current_inst_size + + m_next_inst_size; // Skip delay slot instruction. + } else if (!strcasecmp(op_name, "BNEZ16_MM")) { + if (rs_val != 0) + target = pc + offset; + else + target = pc + current_inst_size + + m_next_inst_size; // Skip delay slot instruction. + } else if (!strcasecmp(op_name, "BEQZC_MM")) { + if (rs_val == 0) + target = pc + 4 + offset; + else + target = + pc + + 4; // 32 bit instruction and does not have delay slot instruction. + } else if (!strcasecmp(op_name, "BNEZC_MM")) { + if (rs_val != 0) + target = pc + 4 + offset; + else + target = + pc + + 4; // 32 bit instruction and does not have delay slot instruction. + } else if (!strcasecmp(op_name, "BGEZALS_MM")) { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 6; // 32 bit instruction with short (2-byte) delay slot - int32_t rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + update_ra = true; + ra_offset = 6; + } else if (!strcasecmp(op_name, "BLTZALS_MM")) { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 6; // 32 bit instruction with short (2-byte) delay slot - if (!strcasecmp (op_name, "BEQZ16_MM")) - { - if (rs_val == 0) - target = pc + offset; - else - target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction. - } - else if (!strcasecmp (op_name, "BNEZ16_MM")) - { - if (rs_val != 0) - target = pc + offset; - else - target = pc + current_inst_size + m_next_inst_size; // Skip delay slot instruction. - } - else if (!strcasecmp (op_name, "BEQZC_MM")) - { - if (rs_val == 0) - target = pc + 4 + offset; - else - target = pc + 4; // 32 bit instruction and does not have delay slot instruction. - } - else if (!strcasecmp (op_name, "BNEZC_MM")) - { - if (rs_val != 0) - target = pc + 4 + offset; - else - target = pc + 4; // 32 bit instruction and does not have delay slot instruction. - } - else if (!strcasecmp (op_name, "BGEZALS_MM")) - { - if (rs_val >= 0) - target = pc + offset; - else - target = pc + 6; // 32 bit instruction with short (2-byte) delay slot - - update_ra = true; - ra_offset = 6; - } - else if (!strcasecmp (op_name, "BLTZALS_MM")) - { - if (rs_val >= 0) - target = pc + offset; - else - target = pc + 6; // 32 bit instruction with short (2-byte) delay slot - - update_ra = true; - ra_offset = 6; - } + update_ra = true; + ra_offset = 6; + } - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (current_inst_size + offset); + Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(current_inst_size + offset); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - if (update_ra) - { - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) - return false; - } - return true; + if (update_ra) { + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips, + pc + ra_offset)) + return false; + } + return true; } /* Emulate micromips jump instructions. JALR16,JALRS16 */ -bool -EmulateInstructionMIPS::Emulate_JALRx16_MM (llvm::MCInst& insn) -{ - bool success = false; - uint32_t ra_offset = 0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); +bool EmulateInstructionMIPS::Emulate_JALRx16_MM(llvm::MCInst &insn) { + bool success = false; + uint32_t ra_offset = 0; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); - uint32_t rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + uint32_t rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); - uint32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + uint32_t pc = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - uint32_t rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + uint32_t rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "JALR16_MM")) - ra_offset = 6; // 2-byte instruction with 4-byte delay slot. - else if (!strcasecmp (op_name, "JALRS16_MM")) - ra_offset = 4; // 2-byte instruction with 2-byte delay slot. + if (!strcasecmp(op_name, "JALR16_MM")) + ra_offset = 6; // 2-byte instruction with 4-byte delay slot. + else if (!strcasecmp(op_name, "JALRS16_MM")) + ra_offset = 4; // 2-byte instruction with 2-byte delay slot. - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + rs_val)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips, + pc + ra_offset)) + return false; - return true; + return true; } /* Emulate JALS and JALX instructions. JALS 32 bit instruction with short (2-byte) delay slot. JALX 32 bit instruction with 4-byte delay slot. */ -bool -EmulateInstructionMIPS::Emulate_JALx (llvm::MCInst& insn) -{ - bool success = false; - uint32_t offset=0, target=0, pc=0, ra_offset=0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - /* - * JALS target - * RA = PC + 6 - * offset = sign_ext (offset << 1) - * PC = PC[31-27] | offset - * JALX target - * RA = PC + 8 - * offset = sign_ext (offset << 2) - * PC = PC[31-28] | offset - */ - offset = insn.getOperand(0).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_JALx(llvm::MCInst &insn) { + bool success = false; + uint32_t offset = 0, target = 0, pc = 0, ra_offset = 0; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + + /* + * JALS target + * RA = PC + 6 + * offset = sign_ext (offset << 1) + * PC = PC[31-27] | offset + * JALX target + * RA = PC + 8 + * offset = sign_ext (offset << 2) + * PC = PC[31-28] | offset + */ + offset = insn.getOperand(0).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - // These are PC-region branches and not PC-relative. - if (!strcasecmp (op_name, "JALS_MM")) - { - // target address is in the “current” 128 MB-aligned region - target = (pc & 0xF8000000UL) | offset; - ra_offset = 6; - } - else if (!strcasecmp (op_name, "JALX_MM")) - { - // target address is in the “current” 256 MB-aligned region - target = (pc & 0xF0000000UL) | offset; - ra_offset = 8; - } + // These are PC-region branches and not PC-relative. + if (!strcasecmp(op_name, "JALS_MM")) { + // target address is in the “current” 128 MB-aligned region + target = (pc & 0xF8000000UL) | offset; + ra_offset = 6; + } else if (!strcasecmp(op_name, "JALX_MM")) { + // target address is in the “current” 256 MB-aligned region + target = (pc & 0xF0000000UL) | offset; + ra_offset = 8; + } - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + ra_offset)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips, + pc + ra_offset)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_JALRS (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs=0, rt=0; - int32_t pc=0, rs_val=0; - - /* - JALRS rt, rs - GPR[rt] <- PC + 6 - PC <- GPR[rs] - */ +bool EmulateInstructionMIPS::Emulate_JALRS(llvm::MCInst &insn) { + bool success = false; + uint32_t rs = 0, rt = 0; + int32_t pc = 0, rs_val = 0; - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + /* + JALRS rt, rs + GPR[rt] <- PC + 6 + PC <- GPR[rs] + */ - rs_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; - - Context context; + rs_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rs, 0, &success); + if (!success) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - // This is 4-byte instruction with 2-byte delay slot. - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 6)) - return false; - - return true; + Context context; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + rs_val)) + return false; + + // This is 4-byte instruction with 2-byte delay slot. + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt, + pc + 6)) + return false; + + return true; } -bool -EmulateInstructionMIPS::Emulate_BAL (llvm::MCInst& insn) -{ - bool success = false; - int32_t offset, pc, target; +bool EmulateInstructionMIPS::Emulate_BAL(llvm::MCInst &insn) { + bool success = false; + int32_t offset, pc, target; - /* - * BAL offset - * offset = sign_ext (offset << 2) - * RA = PC + 8 - * PC = PC + offset - */ - offset = insn.getOperand(0).getImm(); + /* + * BAL offset + * offset = sign_ext (offset << 2) + * RA = PC + 8 + * PC = PC + offset + */ + offset = insn.getOperand(0).getImm(); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - target = pc + offset; + target = pc + offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips, + pc + 8)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_BALC (llvm::MCInst& insn) -{ - bool success = false; - int32_t offset, pc, target; +bool EmulateInstructionMIPS::Emulate_BALC(llvm::MCInst &insn) { + bool success = false; + int32_t offset, pc, target; - /* - * BALC offset - * offset = sign_ext (offset << 2) - * RA = PC + 4 - * PC = PC + 4 + offset - */ - offset = insn.getOperand(0).getImm(); + /* + * BALC offset + * offset = sign_ext (offset << 2) + * RA = PC + 4 + * PC = PC + 4 + offset + */ + offset = insn.getOperand(0).getImm(); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - target = pc + offset; + target = pc + offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips, + pc + 4)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_BC (llvm::MCInst& insn) -{ - bool success = false; - int32_t offset, pc, target; +bool EmulateInstructionMIPS::Emulate_BC(llvm::MCInst &insn) { + bool success = false; + int32_t offset, pc, target; - /* - * BC offset - * offset = sign_ext (offset << 2) - * PC = PC + 4 + offset - */ - offset = insn.getOperand(0).getImm(); + /* + * BC offset + * offset = sign_ext (offset << 2) + * PC = PC + 4 + offset + */ + offset = insn.getOperand(0).getImm(); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - target = pc + offset; + target = pc + offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_J (llvm::MCInst& insn) -{ - bool success = false; - uint32_t offset, pc; +bool EmulateInstructionMIPS::Emulate_J(llvm::MCInst &insn) { + bool success = false; + uint32_t offset, pc; - /* - * J offset - * offset = sign_ext (offset << 2) - * PC = PC[63-28] | offset - */ - offset = insn.getOperand(0).getImm(); + /* + * J offset + * offset = sign_ext (offset << 2) + * PC = PC[63-28] | offset + */ + offset = insn.getOperand(0).getImm(); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - /* This is a PC-region branch and not PC-relative */ - pc = (pc & 0xF0000000UL) | offset; + /* This is a PC-region branch and not PC-relative */ + pc = (pc & 0xF0000000UL) | offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, pc)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, pc)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_JAL (llvm::MCInst& insn) -{ - bool success = false; - uint32_t offset, target, pc; +bool EmulateInstructionMIPS::Emulate_JAL(llvm::MCInst &insn) { + bool success = false; + uint32_t offset, target, pc; - /* - * JAL offset - * offset = sign_ext (offset << 2) - * PC = PC[63-28] | offset - */ - offset = insn.getOperand(0).getImm(); + /* + * JAL offset + * offset = sign_ext (offset << 2) + * PC = PC[63-28] | offset + */ + offset = insn.getOperand(0).getImm(); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - /* This is a PC-region branch and not PC-relative */ - target = (pc & 0xF0000000UL) | offset; + /* This is a PC-region branch and not PC-relative */ + target = (pc & 0xF0000000UL) | offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 8)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips, + pc + 8)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_JALR (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs, rt; - uint32_t pc, rs_val; +bool EmulateInstructionMIPS::Emulate_JALR(llvm::MCInst &insn) { + bool success = false; + uint32_t rs, rt; + uint32_t pc, rs_val; - /* - * JALR rt, rs - * GPR[rt] = PC + 8 - * PC = GPR[rs] - */ - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + /* + * JALR rt, rs + * GPR[rt] = PC + 8 + * PC = GPR[rs] + */ + rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0, + &success); + if (!success) + return false; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + rs_val)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips + rt, pc + 8)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt, + pc + 8)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_JIALC (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rt; - int32_t target, offset, pc, rt_val; +bool EmulateInstructionMIPS::Emulate_JIALC(llvm::MCInst &insn) { + bool success = false; + uint32_t rt; + int32_t target, offset, pc, rt_val; - /* - * JIALC rt, offset - * offset = sign_ext (offset) - * PC = GPR[rt] + offset - * RA = PC + 4 - */ - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); + /* + * JIALC rt, offset + * offset = sign_ext (offset) + * PC = GPR[rt] + offset + * RA = PC + 4 + */ + rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); - if (!success) - return false; + rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; - target = rt_val + offset; + target = rt_val + offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips, pc + 4)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips, + pc + 4)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_JIC (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rt; - int32_t target, offset, rt_val; +bool EmulateInstructionMIPS::Emulate_JIC(llvm::MCInst &insn) { + bool success = false; + uint32_t rt; + int32_t target, offset, rt_val; - /* - * JIC rt, offset - * offset = sign_ext (offset) - * PC = GPR[rt] + offset - */ - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); + /* + * JIC rt, offset + * offset = sign_ext (offset) + * PC = GPR[rt] + offset + */ + rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); - rt_val = (int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rt, 0, &success); - if (!success) - return false; + rt_val = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + rt, 0, &success); + if (!success) + return false; - target = rt_val + offset; + target = rt_val + offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_JR (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs; - uint32_t rs_val; +bool EmulateInstructionMIPS::Emulate_JR(llvm::MCInst &insn) { + bool success = false; + uint32_t rs; + uint32_t rs_val; - /* - * JR rs - * PC = GPR[rs] - */ - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + /* + * JR rs + * PC = GPR[rs] + */ + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + rs, 0, &success); - if (!success) - return false; + rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + rs, 0, + &success); + if (!success) + return false; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, rs_val)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + rs_val)) + return false; - return true; + return true; } /* @@ -2482,419 +2731,400 @@ EmulateInstructionMIPS::Emulate_JR (llvm::MCInst& insn) BC1F, BC1FL : Branch on FP False (L stands for branch likely) BC1T, BC1TL : Branch on FP True (L stands for branch likely) */ -bool -EmulateInstructionMIPS::Emulate_FP_branch (llvm::MCInst& insn) -{ - bool success = false; - uint32_t cc, fcsr; - int32_t pc, offset, target = 0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_FP_branch(llvm::MCInst &insn) { + bool success = false; + uint32_t cc, fcsr; + int32_t pc, offset, target = 0; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); - fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success); - if (!success) - return false; + cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); - /* fcsr[23], fcsr[25-31] are vaild condition bits */ - fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BC1F") || - !strcasecmp (op_name, "BC1FL")) - { - if ((fcsr & (1 << cc)) == 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BC1T") || - !strcasecmp (op_name, "BC1TL")) - { - if ((fcsr & (1 << cc)) != 0) - target = pc + offset; - else - target = pc + 8; - } - Context context; + fcsr = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success); + if (!success) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); - return true; + if (!strcasecmp(op_name, "BC1F") || !strcasecmp(op_name, "BC1FL")) { + if ((fcsr & (1 << cc)) == 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BC1T") || !strcasecmp(op_name, "BC1TL")) { + if ((fcsr & (1 << cc)) != 0) + target = pc + offset; + else + target = pc + 8; + } + Context context; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; + + return true; } -bool -EmulateInstructionMIPS::Emulate_BC1EQZ (llvm::MCInst& insn) -{ - bool success = false; - uint32_t ft; - uint32_t ft_val; - int32_t target, pc, offset; - - /* - * BC1EQZ ft, offset - * condition <- (FPR[ft].bit0 == 0) - * if condition then - * offset = sign_ext (offset) - * PC = PC + 4 + offset - */ - ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_BC1EQZ(llvm::MCInst &insn) { + bool success = false; + uint32_t ft; + uint32_t ft_val; + int32_t target, pc, offset; - ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 0, &success); - if (!success) - return false; + /* + * BC1EQZ ft, offset + * condition <- (FPR[ft].bit0 == 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + 4 + offset + */ + ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); - if ((ft_val & 1) == 0) - target = pc + 4 + offset; - else - target = pc + 8; - - Context context; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0, + &success); + if (!success) + return false; - return true; + if ((ft_val & 1) == 0) + target = pc + 4 + offset; + else + target = pc + 8; + + Context context; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; + + return true; } -bool -EmulateInstructionMIPS::Emulate_BC1NEZ (llvm::MCInst& insn) -{ - bool success = false; - uint32_t ft; - uint32_t ft_val; - int32_t target, pc, offset; - - /* - * BC1NEZ ft, offset - * condition <- (FPR[ft].bit0 != 0) - * if condition then - * offset = sign_ext (offset) - * PC = PC + 4 + offset - */ - ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_BC1NEZ(llvm::MCInst &insn) { + bool success = false; + uint32_t ft; + uint32_t ft_val; + int32_t target, pc, offset; - ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + ft, 0, &success); - if (!success) - return false; + /* + * BC1NEZ ft, offset + * condition <- (FPR[ft].bit0 != 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + 4 + offset + */ + ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); - if ((ft_val & 1) != 0) - target = pc + 4 + offset; - else - target = pc + 8; - - Context context; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + ft, 0, + &success); + if (!success) + return false; - return true; + if ((ft_val & 1) != 0) + target = pc + 4 + offset; + else + target = pc + 8; + + Context context; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; + + return true; } /* Emulate MIPS-3D Branch instructions - BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes False/True - BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes False/True + BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes + False/True + BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes + False/True */ -bool -EmulateInstructionMIPS::Emulate_3D_branch (llvm::MCInst& insn) -{ - bool success = false; - uint32_t cc, fcsr; - int32_t pc, offset, target = 0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS::Emulate_3D_branch(llvm::MCInst &insn) { + bool success = false; + uint32_t cc, fcsr; + int32_t pc, offset, target = 0; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); - fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips, 0, &success); - if (!success) - return false; + cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); - /* fcsr[23], fcsr[25-31] are vaild condition bits */ - fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BC1ANY2F")) - { - /* if any one bit is 0 */ - if (((fcsr >> cc) & 3) != 3) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BC1ANY2T")) - { - /* if any one bit is 1 */ - if (((fcsr >> cc) & 3) != 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BC1ANY4F")) - { - /* if any one bit is 0 */ - if (((fcsr >> cc) & 0xf) != 0xf) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BC1ANY4T")) - { - /* if any one bit is 1 */ - if (((fcsr >> cc) & 0xf) != 0) - target = pc + offset; - else - target = pc + 8; - } - Context context; + fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips, 0, + &success); + if (!success) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); - return true; -} + if (!strcasecmp(op_name, "BC1ANY2F")) { + /* if any one bit is 0 */ + if (((fcsr >> cc) & 3) != 3) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BC1ANY2T")) { + /* if any one bit is 1 */ + if (((fcsr >> cc) & 3) != 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BC1ANY4F")) { + /* if any one bit is 0 */ + if (((fcsr >> cc) & 0xf) != 0xf) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BC1ANY4T")) { + /* if any one bit is 1 */ + if (((fcsr >> cc) & 0xf) != 0) + target = pc + offset; + else + target = pc + 8; + } + Context context; -bool -EmulateInstructionMIPS::Emulate_BNZB (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 1, true); + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; + + return true; } -bool -EmulateInstructionMIPS::Emulate_BNZH (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 2, true); +bool EmulateInstructionMIPS::Emulate_BNZB(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 1, true); } -bool -EmulateInstructionMIPS::Emulate_BNZW (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 4, true); +bool EmulateInstructionMIPS::Emulate_BNZH(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 2, true); } -bool -EmulateInstructionMIPS::Emulate_BNZD (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 8, true); +bool EmulateInstructionMIPS::Emulate_BNZW(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 4, true); } -bool -EmulateInstructionMIPS::Emulate_BZB (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 1, false); +bool EmulateInstructionMIPS::Emulate_BNZD(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 8, true); } -bool -EmulateInstructionMIPS::Emulate_BZH (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 2, false); +bool EmulateInstructionMIPS::Emulate_BZB(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 1, false); } -bool -EmulateInstructionMIPS::Emulate_BZW (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 4, false); +bool EmulateInstructionMIPS::Emulate_BZH(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 2, false); } -bool -EmulateInstructionMIPS::Emulate_BZD (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 8, false); +bool EmulateInstructionMIPS::Emulate_BZW(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 4, false); } -bool -EmulateInstructionMIPS::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz) -{ - bool success = false, branch_hit = true; - int32_t target = 0; - RegisterValue reg_value; - const uint8_t *ptr = NULL; +bool EmulateInstructionMIPS::Emulate_BZD(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 8, false); +} - uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - int32_t offset = insn.getOperand(1).getImm(); +bool EmulateInstructionMIPS::Emulate_MSA_Branch_DF(llvm::MCInst &insn, + int element_byte_size, + bool bnz) { + bool success = false, branch_hit = true; + int32_t target = 0; + RegisterValue reg_value; + const uint8_t *ptr = NULL; - int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + int32_t offset = insn.getOperand(1).getImm(); - if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value)) - ptr = (const uint8_t *)reg_value.GetBytes(); - else - return false; + int32_t pc = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - for(int i = 0; i < 16 / element_byte_size; i++) - { - switch(element_byte_size) - { - case 1: - if((*ptr == 0 && bnz) || (*ptr != 0 && !bnz) ) - branch_hit = false; - break; - case 2: - if ((*(const uint16_t *)ptr == 0 && bnz) || (*(const uint16_t *)ptr != 0 && !bnz)) - branch_hit = false; - break; - case 4: - if ((*(const uint32_t *)ptr == 0 && bnz) || (*(const uint32_t *)ptr != 0 && !bnz)) - branch_hit = false; - break; - case 8: - if ((*(const uint64_t *)ptr == 0 && bnz) || (*(const uint64_t *)ptr != 0 && !bnz)) - branch_hit = false; - break; - } - if(!branch_hit) - break; - ptr = ptr + element_byte_size; - } + if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value)) + ptr = (const uint8_t *)reg_value.GetBytes(); + else + return false; - if(branch_hit) - target = pc + offset; - else - target = pc + 8; + for (int i = 0; i < 16 / element_byte_size; i++) { + switch (element_byte_size) { + case 1: + if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz)) + branch_hit = false; + break; + case 2: + if ((*(const uint16_t *)ptr == 0 && bnz) || + (*(const uint16_t *)ptr != 0 && !bnz)) + branch_hit = false; + break; + case 4: + if ((*(const uint32_t *)ptr == 0 && bnz) || + (*(const uint32_t *)ptr != 0 && !bnz)) + branch_hit = false; + break; + case 8: + if ((*(const uint64_t *)ptr == 0 && bnz) || + (*(const uint64_t *)ptr != 0 && !bnz)) + branch_hit = false; + break; + } + if (!branch_hit) + break; + ptr = ptr + element_byte_size; + } + + if (branch_hit) + target = pc + offset; + else + target = pc + 8; - Context context; - context.type = eContextRelativeBranchImmediate; + Context context; + context.type = eContextRelativeBranchImmediate; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_BNZV (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_V (insn, true); +bool EmulateInstructionMIPS::Emulate_BNZV(llvm::MCInst &insn) { + return Emulate_MSA_Branch_V(insn, true); } -bool -EmulateInstructionMIPS::Emulate_BZV (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_V (insn, false); +bool EmulateInstructionMIPS::Emulate_BZV(llvm::MCInst &insn) { + return Emulate_MSA_Branch_V(insn, false); } -bool -EmulateInstructionMIPS::Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz) -{ - bool success = false; - int32_t target = 0; - llvm::APInt wr_val = llvm::APInt::getNullValue(128); - llvm::APInt fail_value = llvm::APInt::getMaxValue(128); - llvm::APInt zero_value = llvm::APInt::getNullValue(128); - RegisterValue reg_value; +bool EmulateInstructionMIPS::Emulate_MSA_Branch_V(llvm::MCInst &insn, + bool bnz) { + bool success = false; + int32_t target = 0; + llvm::APInt wr_val = llvm::APInt::getNullValue(128); + llvm::APInt fail_value = llvm::APInt::getMaxValue(128); + llvm::APInt zero_value = llvm::APInt::getNullValue(128); + RegisterValue reg_value; - uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - int32_t offset = insn.getOperand(1).getImm(); + uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + int32_t offset = insn.getOperand(1).getImm(); - int32_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips, 0, &success); - if (!success) - return false; + int32_t pc = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips, 0, &success); + if (!success) + return false; - if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value)) - wr_val = reg_value.GetAsUInt128(fail_value); - else - return false; + if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips + wt, reg_value)) + wr_val = reg_value.GetAsUInt128(fail_value); + else + return false; - if((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz)) - target = pc + offset; - else - target = pc + 8; + if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || + (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz)) + target = pc + offset; + else + target = pc + 8; - Context context; - context.type = eContextRelativeBranchImmediate; + Context context; + context.type = eContextRelativeBranchImmediate; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, + target)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_LDST_Imm (llvm::MCInst& insn) -{ - bool success = false; - uint32_t base; - int32_t imm, address; - Context bad_vaddr_context; +bool EmulateInstructionMIPS::Emulate_LDST_Imm(llvm::MCInst &insn) { + bool success = false; + uint32_t base; + int32_t imm, address; + Context bad_vaddr_context; - uint32_t num_operands = insn.getNumOperands(); - base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); - imm = insn.getOperand(num_operands-1).getImm(); + uint32_t num_operands = insn.getNumOperands(); + base = + m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); + imm = insn.getOperand(num_operands - 1).getImm(); - RegisterInfo reg_info_base; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) - return false; + RegisterInfo reg_info_base; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, + reg_info_base)) + return false; - /* read base register */ - address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + /* read base register */ + address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + base, 0, &success); + if (!success) + return false; - /* destination address */ - address = address + imm; + /* destination address */ + address = address + imm; - /* Set the bad_vaddr register with base address used in the instruction */ - bad_vaddr_context.type = eContextInvalid; - WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + /* Set the bad_vaddr register with base address used in the instruction */ + bad_vaddr_context.type = eContextInvalid; + WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, + address); - return true; + return true; } -bool -EmulateInstructionMIPS::Emulate_LDST_Reg (llvm::MCInst& insn) -{ - bool success = false; - uint32_t base, index; - int32_t address, index_address; - Context bad_vaddr_context; +bool EmulateInstructionMIPS::Emulate_LDST_Reg(llvm::MCInst &insn) { + bool success = false; + uint32_t base, index; + int32_t address, index_address; + Context bad_vaddr_context; - uint32_t num_operands = insn.getNumOperands(); - base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); - index = m_reg_info->getEncodingValue (insn.getOperand(num_operands-1).getReg()); + uint32_t num_operands = insn.getNumOperands(); + base = + m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); + index = + m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg()); - RegisterInfo reg_info_base, reg_info_index; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) - return false; + RegisterInfo reg_info_base, reg_info_index; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, + reg_info_base)) + return false; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + index, reg_info_index)) - return false; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index, + reg_info_index)) + return false; - /* read base register */ - address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + /* read base register */ + address = (int32_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + base, 0, &success); + if (!success) + return false; - /* read index register */ - index_address =(int32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success); - if (!success) - return false; + /* read index register */ + index_address = (int32_t)ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success); + if (!success) + return false; - /* destination address */ - address = address + index_address; + /* destination address */ + address = address + index_address; - /* Set the bad_vaddr register with base address used in the instruction */ - bad_vaddr_context.type = eContextInvalid; - WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + /* Set the bad_vaddr register with base address used in the instruction */ + bad_vaddr_context.type = eContextInvalid; + WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, + address); - return true; + return true; } diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h index f1f92a065956..82c6a0a31e81 100644 --- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h +++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.h @@ -1,4 +1,5 @@ -//===-- EmulateInstructionMIPS.h ------------------------------------*- C++ -*-===// +//===-- EmulateInstructionMIPS.h ------------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -10,286 +11,209 @@ #ifndef EmulateInstructionMIPS_h_ #define EmulateInstructionMIPS_h_ -namespace llvm -{ - class MCDisassembler; - class MCSubtargetInfo; - class MCRegisterInfo; - class MCAsmInfo; - class MCContext; - class MCInstrInfo; - class MCInst; +namespace llvm { +class MCDisassembler; +class MCSubtargetInfo; +class MCRegisterInfo; +class MCAsmInfo; +class MCContext; +class MCInstrInfo; +class MCInst; } #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Error.h" #include "lldb/Interpreter/OptionValue.h" -class EmulateInstructionMIPS : public lldb_private::EmulateInstruction -{ -public: - static void - Initialize (); - - static void - Terminate (); - - static lldb_private::ConstString - GetPluginNameStatic (); - - static const char * - GetPluginDescriptionStatic (); - - static lldb_private::EmulateInstruction * - CreateInstance (const lldb_private::ArchSpec &arch, - lldb_private::InstructionType inst_type); - - static bool - SupportsEmulatingInstructionsOfTypeStatic (lldb_private::InstructionType inst_type) - { - switch (inst_type) - { - case lldb_private::eInstructionTypeAny: - case lldb_private::eInstructionTypePrologueEpilogue: - case lldb_private::eInstructionTypePCModifying: - return true; - - case lldb_private::eInstructionTypeAll: - return false; - } - return false; - } +class EmulateInstructionMIPS : public lldb_private::EmulateInstruction { +public: + static void Initialize(); - lldb_private::ConstString - GetPluginName() override; + static void Terminate(); - uint32_t - GetPluginVersion() override - { - return 1; - } + static lldb_private::ConstString GetPluginNameStatic(); - bool - SetTargetTriple (const lldb_private::ArchSpec &arch) override; - - EmulateInstructionMIPS (const lldb_private::ArchSpec &arch); + static const char *GetPluginDescriptionStatic(); - bool - SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type) override - { - return SupportsEmulatingInstructionsOfTypeStatic (inst_type); - } + static lldb_private::EmulateInstruction * + CreateInstance(const lldb_private::ArchSpec &arch, + lldb_private::InstructionType inst_type); - bool - ReadInstruction () override; - - bool - EvaluateInstruction (uint32_t evaluate_options) override; - - bool - SetInstruction (const lldb_private::Opcode &insn_opcode, - const lldb_private::Address &inst_addr, - lldb_private::Target *target) override; - - bool - TestEmulation (lldb_private::Stream *out_stream, - lldb_private::ArchSpec &arch, - lldb_private::OptionValueDictionary *test_data) override - { - return false; + static bool SupportsEmulatingInstructionsOfTypeStatic( + lldb_private::InstructionType inst_type) { + switch (inst_type) { + case lldb_private::eInstructionTypeAny: + case lldb_private::eInstructionTypePrologueEpilogue: + case lldb_private::eInstructionTypePCModifying: + return true; + + case lldb_private::eInstructionTypeAll: + return false; } + return false; + } + + lldb_private::ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override { return 1; } + + bool SetTargetTriple(const lldb_private::ArchSpec &arch) override; + + EmulateInstructionMIPS(const lldb_private::ArchSpec &arch); + + bool SupportsEmulatingInstructionsOfType( + lldb_private::InstructionType inst_type) override { + return SupportsEmulatingInstructionsOfTypeStatic(inst_type); + } + + bool ReadInstruction() override; + + bool EvaluateInstruction(uint32_t evaluate_options) override; + + bool SetInstruction(const lldb_private::Opcode &insn_opcode, + const lldb_private::Address &inst_addr, + lldb_private::Target *target) override; - bool - GetRegisterInfo (lldb::RegisterKind reg_kind, - uint32_t reg_num, - lldb_private::RegisterInfo ®_info) override; + bool TestEmulation(lldb_private::Stream *out_stream, + lldb_private::ArchSpec &arch, + lldb_private::OptionValueDictionary *test_data) override { + return false; + } - bool - CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan) override; + bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, + lldb_private::RegisterInfo ®_info) override; + bool + CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override; protected: + typedef struct { + const char *op_name; + bool (EmulateInstructionMIPS::*callback)(llvm::MCInst &insn); + const char *insn_name; + } MipsOpcode; - typedef struct - { - const char *op_name; - bool (EmulateInstructionMIPS::*callback) (llvm::MCInst& insn); - const char *insn_name; - } MipsOpcode; - - static MipsOpcode* - GetOpcodeForInstruction (const char *op_name); + static MipsOpcode *GetOpcodeForInstruction(const char *op_name); - uint32_t - GetSizeOfInstruction (lldb_private::DataExtractor& data, uint64_t inst_addr); + uint32_t GetSizeOfInstruction(lldb_private::DataExtractor &data, + uint64_t inst_addr); - bool - Emulate_ADDiu (llvm::MCInst& insn); + bool Emulate_ADDiu(llvm::MCInst &insn); - bool - Emulate_SUBU_ADDU (llvm::MCInst& insn); + bool Emulate_SUBU_ADDU(llvm::MCInst &insn); - bool - Emulate_LUI (llvm::MCInst& insn); + bool Emulate_LUI(llvm::MCInst &insn); - bool - Emulate_SW (llvm::MCInst& insn); + bool Emulate_SW(llvm::MCInst &insn); - bool - Emulate_LW (llvm::MCInst& insn); + bool Emulate_LW(llvm::MCInst &insn); - bool - Emulate_ADDIUSP (llvm::MCInst& insn); + bool Emulate_ADDIUSP(llvm::MCInst &insn); - bool - Emulate_ADDIUS5 (llvm::MCInst& insn); + bool Emulate_ADDIUS5(llvm::MCInst &insn); - bool - Emulate_SWSP (llvm::MCInst& insn); + bool Emulate_SWSP(llvm::MCInst &insn); - bool - Emulate_SWM16_32 (llvm::MCInst& insn); + bool Emulate_SWM16_32(llvm::MCInst &insn); - bool - Emulate_LWSP (llvm::MCInst& insn); + bool Emulate_LWSP(llvm::MCInst &insn); - bool - Emulate_LWM16_32 (llvm::MCInst& insn); + bool Emulate_LWM16_32(llvm::MCInst &insn); - bool - Emulate_JRADDIUSP (llvm::MCInst& insn); + bool Emulate_JRADDIUSP(llvm::MCInst &insn); - bool - Emulate_LDST_Imm (llvm::MCInst& insn); + bool Emulate_LDST_Imm(llvm::MCInst &insn); - bool - Emulate_LDST_Reg (llvm::MCInst& insn); + bool Emulate_LDST_Reg(llvm::MCInst &insn); - bool - Emulate_BXX_3ops (llvm::MCInst& insn); + bool Emulate_BXX_3ops(llvm::MCInst &insn); - bool - Emulate_BXX_3ops_C (llvm::MCInst& insn); + bool Emulate_BXX_3ops_C(llvm::MCInst &insn); - bool - Emulate_BXX_2ops (llvm::MCInst& insn); + bool Emulate_BXX_2ops(llvm::MCInst &insn); - bool - Emulate_BXX_2ops_C (llvm::MCInst& insn); + bool Emulate_BXX_2ops_C(llvm::MCInst &insn); - bool - Emulate_Bcond_Link_C (llvm::MCInst& insn); + bool Emulate_Bcond_Link_C(llvm::MCInst &insn); - bool - Emulate_Bcond_Link (llvm::MCInst& insn); + bool Emulate_Bcond_Link(llvm::MCInst &insn); - bool - Emulate_FP_branch (llvm::MCInst& insn); + bool Emulate_FP_branch(llvm::MCInst &insn); - bool - Emulate_3D_branch (llvm::MCInst& insn); + bool Emulate_3D_branch(llvm::MCInst &insn); - bool - Emulate_BAL (llvm::MCInst& insn); + bool Emulate_BAL(llvm::MCInst &insn); - bool - Emulate_BALC (llvm::MCInst& insn); + bool Emulate_BALC(llvm::MCInst &insn); - bool - Emulate_BC (llvm::MCInst& insn); + bool Emulate_BC(llvm::MCInst &insn); - bool - Emulate_J (llvm::MCInst& insn); + bool Emulate_J(llvm::MCInst &insn); - bool - Emulate_JAL (llvm::MCInst& insn); + bool Emulate_JAL(llvm::MCInst &insn); - bool - Emulate_JALR (llvm::MCInst& insn); + bool Emulate_JALR(llvm::MCInst &insn); - bool - Emulate_JIALC (llvm::MCInst& insn); + bool Emulate_JIALC(llvm::MCInst &insn); - bool - Emulate_JIC (llvm::MCInst& insn); + bool Emulate_JIC(llvm::MCInst &insn); - bool - Emulate_JR (llvm::MCInst& insn); + bool Emulate_JR(llvm::MCInst &insn); - bool - Emulate_BC1EQZ (llvm::MCInst& insn); + bool Emulate_BC1EQZ(llvm::MCInst &insn); - bool - Emulate_BC1NEZ (llvm::MCInst& insn); + bool Emulate_BC1NEZ(llvm::MCInst &insn); - bool - Emulate_BNZB (llvm::MCInst& insn); + bool Emulate_BNZB(llvm::MCInst &insn); - bool - Emulate_BNZH (llvm::MCInst& insn); + bool Emulate_BNZH(llvm::MCInst &insn); - bool - Emulate_BNZW (llvm::MCInst& insn); + bool Emulate_BNZW(llvm::MCInst &insn); - bool - Emulate_BNZD (llvm::MCInst& insn); + bool Emulate_BNZD(llvm::MCInst &insn); - bool - Emulate_BZB (llvm::MCInst& insn); + bool Emulate_BZB(llvm::MCInst &insn); - bool - Emulate_BZH (llvm::MCInst& insn); + bool Emulate_BZH(llvm::MCInst &insn); - bool - Emulate_BZW (llvm::MCInst& insn); + bool Emulate_BZW(llvm::MCInst &insn); - bool - Emulate_BZD (llvm::MCInst& insn); + bool Emulate_BZD(llvm::MCInst &insn); - bool - Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz); + bool Emulate_MSA_Branch_DF(llvm::MCInst &insn, int element_byte_size, + bool bnz); - bool - Emulate_BNZV (llvm::MCInst& insn); + bool Emulate_BNZV(llvm::MCInst &insn); - bool - Emulate_BZV (llvm::MCInst& insn); + bool Emulate_BZV(llvm::MCInst &insn); - bool - Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz); + bool Emulate_MSA_Branch_V(llvm::MCInst &insn, bool bnz); - bool - Emulate_B16_MM (llvm::MCInst& insn); + bool Emulate_B16_MM(llvm::MCInst &insn); - bool - Emulate_Branch_MM (llvm::MCInst& insn); + bool Emulate_Branch_MM(llvm::MCInst &insn); - bool - Emulate_JALRx16_MM (llvm::MCInst& insn); + bool Emulate_JALRx16_MM(llvm::MCInst &insn); - bool - Emulate_JALx (llvm::MCInst& insn); + bool Emulate_JALx(llvm::MCInst &insn); - bool - Emulate_JALRS (llvm::MCInst& insn); + bool Emulate_JALRS(llvm::MCInst &insn); - bool - nonvolatile_reg_p (uint32_t regnum); + bool nonvolatile_reg_p(uint32_t regnum); - const char * - GetRegisterName (unsigned reg_num, bool altnernate_name); + const char *GetRegisterName(unsigned reg_num, bool altnernate_name); private: - std::unique_ptr<llvm::MCDisassembler> m_disasm; - std::unique_ptr<llvm::MCDisassembler> m_alt_disasm; - std::unique_ptr<llvm::MCSubtargetInfo> m_subtype_info; - std::unique_ptr<llvm::MCSubtargetInfo> m_alt_subtype_info; - std::unique_ptr<llvm::MCRegisterInfo> m_reg_info; - std::unique_ptr<llvm::MCAsmInfo> m_asm_info; - std::unique_ptr<llvm::MCContext> m_context; - std::unique_ptr<llvm::MCInstrInfo> m_insn_info; - uint32_t m_next_inst_size; - bool m_use_alt_disaasm; + std::unique_ptr<llvm::MCDisassembler> m_disasm; + std::unique_ptr<llvm::MCDisassembler> m_alt_disasm; + std::unique_ptr<llvm::MCSubtargetInfo> m_subtype_info; + std::unique_ptr<llvm::MCSubtargetInfo> m_alt_subtype_info; + std::unique_ptr<llvm::MCRegisterInfo> m_reg_info; + std::unique_ptr<llvm::MCAsmInfo> m_asm_info; + std::unique_ptr<llvm::MCContext> m_context; + std::unique_ptr<llvm::MCInstrInfo> m_insn_info; + uint32_t m_next_inst_size; + bool m_use_alt_disaasm; }; -#endif // EmulateInstructionMIPS_h_ +#endif // EmulateInstructionMIPS_h_ diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp index 7b4b6aa0100e..c054760be8a0 100644 --- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp +++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp @@ -1,4 +1,5 @@ -//===-- EmulateInstructionMIPS64.cpp -------------------------------*- C++ -*-===// +//===-- EmulateInstructionMIPS64.cpp -------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -11,24 +12,25 @@ #include <stdlib.h> -#include "llvm-c/Disassembler.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCDisassembler/MCDisassembler.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCContext.h" #include "lldb/Core/Address.h" -#include "lldb/Core/Opcode.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ConstString.h" -#include "lldb/Core/PluginManager.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Opcode.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/Stream.h" +#include "lldb/Host/PosixApi.h" #include "lldb/Symbol/UnwindPlan.h" +#include "llvm-c/Disassembler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/ADT/STLExtras.h" @@ -41,7 +43,6 @@ using namespace lldb_private; #define UInt(x) ((uint64_t)x) #define integer int64_t - //---------------------------------------------------------------------- // // EmulateInstructionMIPS64 implementation @@ -50,987 +51,1262 @@ using namespace lldb_private; #ifdef __mips__ extern "C" { - void LLVMInitializeMipsTargetInfo (); - void LLVMInitializeMipsTarget (); - void LLVMInitializeMipsAsmPrinter (); - void LLVMInitializeMipsTargetMC (); - void LLVMInitializeMipsDisassembler (); +void LLVMInitializeMipsTargetInfo(); +void LLVMInitializeMipsTarget(); +void LLVMInitializeMipsAsmPrinter(); +void LLVMInitializeMipsTargetMC(); +void LLVMInitializeMipsDisassembler(); } #endif -EmulateInstructionMIPS64::EmulateInstructionMIPS64 (const lldb_private::ArchSpec &arch) : - EmulateInstruction (arch) -{ - /* Create instance of llvm::MCDisassembler */ - std::string Error; - llvm::Triple triple = arch.GetTriple(); - const llvm::Target *target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error); - - /* - * If we fail to get the target then we haven't registered it. The SystemInitializerCommon - * does not initialize targets, MCs and disassemblers. However we need the MCDisassembler - * to decode the instructions so that the decoding complexity stays with LLVM. - * Initialize the MIPS targets and disassemblers. - */ +EmulateInstructionMIPS64::EmulateInstructionMIPS64( + const lldb_private::ArchSpec &arch) + : EmulateInstruction(arch) { + /* Create instance of llvm::MCDisassembler */ + std::string Error; + llvm::Triple triple = arch.GetTriple(); + const llvm::Target *target = + llvm::TargetRegistry::lookupTarget(triple.getTriple(), Error); + +/* + * If we fail to get the target then we haven't registered it. The + * SystemInitializerCommon + * does not initialize targets, MCs and disassemblers. However we need the + * MCDisassembler + * to decode the instructions so that the decoding complexity stays with LLVM. + * Initialize the MIPS targets and disassemblers. +*/ #ifdef __mips__ - if (!target) - { - LLVMInitializeMipsTargetInfo (); - LLVMInitializeMipsTarget (); - LLVMInitializeMipsAsmPrinter (); - LLVMInitializeMipsTargetMC (); - LLVMInitializeMipsDisassembler (); - target = llvm::TargetRegistry::lookupTarget (triple.getTriple(), Error); - } + if (!target) { + LLVMInitializeMipsTargetInfo(); + LLVMInitializeMipsTarget(); + LLVMInitializeMipsAsmPrinter(); + LLVMInitializeMipsTargetMC(); + LLVMInitializeMipsDisassembler(); + target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), Error); + } #endif - assert (target); - - llvm::StringRef cpu; - - switch (arch.GetCore()) - { - case ArchSpec::eCore_mips32: - case ArchSpec::eCore_mips32el: - cpu = "mips32"; break; - case ArchSpec::eCore_mips32r2: - case ArchSpec::eCore_mips32r2el: - cpu = "mips32r2"; break; - case ArchSpec::eCore_mips32r3: - case ArchSpec::eCore_mips32r3el: - cpu = "mips32r3"; break; - case ArchSpec::eCore_mips32r5: - case ArchSpec::eCore_mips32r5el: - cpu = "mips32r5"; break; - case ArchSpec::eCore_mips32r6: - case ArchSpec::eCore_mips32r6el: - cpu = "mips32r6"; break; - case ArchSpec::eCore_mips64: - case ArchSpec::eCore_mips64el: - cpu = "mips64"; break; - case ArchSpec::eCore_mips64r2: - case ArchSpec::eCore_mips64r2el: - cpu = "mips64r2"; break; - case ArchSpec::eCore_mips64r3: - case ArchSpec::eCore_mips64r3el: - cpu = "mips64r3"; break; - case ArchSpec::eCore_mips64r5: - case ArchSpec::eCore_mips64r5el: - cpu = "mips64r5"; break; - case ArchSpec::eCore_mips64r6: - case ArchSpec::eCore_mips64r6el: - cpu = "mips64r6"; break; - default: - cpu = "generic"; break; - } - - std::string features = ""; - uint32_t arch_flags = arch.GetFlags (); - if (arch_flags & ArchSpec::eMIPSAse_msa) - features += "+msa,"; - if (arch_flags & ArchSpec::eMIPSAse_dsp) - features += "+dsp,"; - if (arch_flags & ArchSpec::eMIPSAse_dspr2) - features += "+dspr2,"; - if (arch_flags & ArchSpec::eMIPSAse_mips16) - features += "+mips16,"; - if (arch_flags & ArchSpec::eMIPSAse_micromips) - features += "+micromips,"; - - m_reg_info.reset (target->createMCRegInfo (triple.getTriple())); - assert (m_reg_info.get()); - - m_insn_info.reset (target->createMCInstrInfo()); - assert (m_insn_info.get()); - - m_asm_info.reset (target->createMCAsmInfo (*m_reg_info, triple.getTriple())); - m_subtype_info.reset (target->createMCSubtargetInfo (triple.getTriple(), cpu, features)); - assert (m_asm_info.get() && m_subtype_info.get()); - - m_context.reset (new llvm::MCContext (m_asm_info.get(), m_reg_info.get(), nullptr)); - assert (m_context.get()); - - m_disasm.reset (target->createMCDisassembler (*m_subtype_info, *m_context)); - assert (m_disasm.get()); + assert(target); + + llvm::StringRef cpu; + + switch (arch.GetCore()) { + case ArchSpec::eCore_mips32: + case ArchSpec::eCore_mips32el: + cpu = "mips32"; + break; + case ArchSpec::eCore_mips32r2: + case ArchSpec::eCore_mips32r2el: + cpu = "mips32r2"; + break; + case ArchSpec::eCore_mips32r3: + case ArchSpec::eCore_mips32r3el: + cpu = "mips32r3"; + break; + case ArchSpec::eCore_mips32r5: + case ArchSpec::eCore_mips32r5el: + cpu = "mips32r5"; + break; + case ArchSpec::eCore_mips32r6: + case ArchSpec::eCore_mips32r6el: + cpu = "mips32r6"; + break; + case ArchSpec::eCore_mips64: + case ArchSpec::eCore_mips64el: + cpu = "mips64"; + break; + case ArchSpec::eCore_mips64r2: + case ArchSpec::eCore_mips64r2el: + cpu = "mips64r2"; + break; + case ArchSpec::eCore_mips64r3: + case ArchSpec::eCore_mips64r3el: + cpu = "mips64r3"; + break; + case ArchSpec::eCore_mips64r5: + case ArchSpec::eCore_mips64r5el: + cpu = "mips64r5"; + break; + case ArchSpec::eCore_mips64r6: + case ArchSpec::eCore_mips64r6el: + cpu = "mips64r6"; + break; + default: + cpu = "generic"; + break; + } + + std::string features = ""; + uint32_t arch_flags = arch.GetFlags(); + if (arch_flags & ArchSpec::eMIPSAse_msa) + features += "+msa,"; + if (arch_flags & ArchSpec::eMIPSAse_dsp) + features += "+dsp,"; + if (arch_flags & ArchSpec::eMIPSAse_dspr2) + features += "+dspr2,"; + if (arch_flags & ArchSpec::eMIPSAse_mips16) + features += "+mips16,"; + if (arch_flags & ArchSpec::eMIPSAse_micromips) + features += "+micromips,"; + + m_reg_info.reset(target->createMCRegInfo(triple.getTriple())); + assert(m_reg_info.get()); + + m_insn_info.reset(target->createMCInstrInfo()); + assert(m_insn_info.get()); + + m_asm_info.reset(target->createMCAsmInfo(*m_reg_info, triple.getTriple())); + m_subtype_info.reset( + target->createMCSubtargetInfo(triple.getTriple(), cpu, features)); + assert(m_asm_info.get() && m_subtype_info.get()); + + m_context.reset( + new llvm::MCContext(m_asm_info.get(), m_reg_info.get(), nullptr)); + assert(m_context.get()); + + m_disasm.reset(target->createMCDisassembler(*m_subtype_info, *m_context)); + assert(m_disasm.get()); } -void -EmulateInstructionMIPS64::Initialize () -{ - PluginManager::RegisterPlugin (GetPluginNameStatic (), - GetPluginDescriptionStatic (), - CreateInstance); +void EmulateInstructionMIPS64::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance); } -void -EmulateInstructionMIPS64::Terminate () -{ - PluginManager::UnregisterPlugin (CreateInstance); +void EmulateInstructionMIPS64::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); } -ConstString -EmulateInstructionMIPS64::GetPluginNameStatic () -{ - ConstString g_plugin_name ("lldb.emulate-instruction.mips64"); - return g_plugin_name; +ConstString EmulateInstructionMIPS64::GetPluginNameStatic() { + ConstString g_plugin_name("lldb.emulate-instruction.mips64"); + return g_plugin_name; } -lldb_private::ConstString -EmulateInstructionMIPS64::GetPluginName() -{ - static ConstString g_plugin_name ("EmulateInstructionMIPS64"); - return g_plugin_name; +lldb_private::ConstString EmulateInstructionMIPS64::GetPluginName() { + static ConstString g_plugin_name("EmulateInstructionMIPS64"); + return g_plugin_name; } -const char * -EmulateInstructionMIPS64::GetPluginDescriptionStatic () -{ - return "Emulate instructions for the MIPS64 architecture."; +const char *EmulateInstructionMIPS64::GetPluginDescriptionStatic() { + return "Emulate instructions for the MIPS64 architecture."; } EmulateInstruction * -EmulateInstructionMIPS64::CreateInstance (const ArchSpec &arch, InstructionType inst_type) -{ - if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic(inst_type)) - { - if (arch.GetTriple().getArch() == llvm::Triple::mips64 - || arch.GetTriple().getArch() == llvm::Triple::mips64el) - { - std::auto_ptr<EmulateInstructionMIPS64> emulate_insn_ap (new EmulateInstructionMIPS64 (arch)); - if (emulate_insn_ap.get()) - return emulate_insn_ap.release(); - } +EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch, + InstructionType inst_type) { + if (EmulateInstructionMIPS64::SupportsEmulatingInstructionsOfTypeStatic( + inst_type)) { + if (arch.GetTriple().getArch() == llvm::Triple::mips64 || + arch.GetTriple().getArch() == llvm::Triple::mips64el) { + std::auto_ptr<EmulateInstructionMIPS64> emulate_insn_ap( + new EmulateInstructionMIPS64(arch)); + if (emulate_insn_ap.get()) + return emulate_insn_ap.release(); } - - return NULL; -} + } -bool -EmulateInstructionMIPS64::SetTargetTriple (const ArchSpec &arch) -{ - if (arch.GetTriple().getArch () == llvm::Triple::mips64 - || arch.GetTriple().getArch () == llvm::Triple::mips64el) - return true; - return false; + return NULL; } -const char * -EmulateInstructionMIPS64::GetRegisterName (unsigned reg_num, bool alternate_name) -{ - if (alternate_name) - { - switch (reg_num) - { - case dwarf_sp_mips64: return "r29"; - case dwarf_r30_mips64: return "r30"; - case dwarf_ra_mips64: return "r31"; - case dwarf_f0_mips64: return "f0"; - case dwarf_f1_mips64: return "f1"; - case dwarf_f2_mips64: return "f2"; - case dwarf_f3_mips64: return "f3"; - case dwarf_f4_mips64: return "f4"; - case dwarf_f5_mips64: return "f5"; - case dwarf_f6_mips64: return "f6"; - case dwarf_f7_mips64: return "f7"; - case dwarf_f8_mips64: return "f8"; - case dwarf_f9_mips64: return "f9"; - case dwarf_f10_mips64: return "f10"; - case dwarf_f11_mips64: return "f11"; - case dwarf_f12_mips64: return "f12"; - case dwarf_f13_mips64: return "f13"; - case dwarf_f14_mips64: return "f14"; - case dwarf_f15_mips64: return "f15"; - case dwarf_f16_mips64: return "f16"; - case dwarf_f17_mips64: return "f17"; - case dwarf_f18_mips64: return "f18"; - case dwarf_f19_mips64: return "f19"; - case dwarf_f20_mips64: return "f20"; - case dwarf_f21_mips64: return "f21"; - case dwarf_f22_mips64: return "f22"; - case dwarf_f23_mips64: return "f23"; - case dwarf_f24_mips64: return "f24"; - case dwarf_f25_mips64: return "f25"; - case dwarf_f26_mips64: return "f26"; - case dwarf_f27_mips64: return "f27"; - case dwarf_f28_mips64: return "f28"; - case dwarf_f29_mips64: return "f29"; - case dwarf_f30_mips64: return "f30"; - case dwarf_f31_mips64: return "f31"; - case dwarf_w0_mips64: return "w0"; - case dwarf_w1_mips64: return "w1"; - case dwarf_w2_mips64: return "w2"; - case dwarf_w3_mips64: return "w3"; - case dwarf_w4_mips64: return "w4"; - case dwarf_w5_mips64: return "w5"; - case dwarf_w6_mips64: return "w6"; - case dwarf_w7_mips64: return "w7"; - case dwarf_w8_mips64: return "w8"; - case dwarf_w9_mips64: return "w9"; - case dwarf_w10_mips64: return "w10"; - case dwarf_w11_mips64: return "w11"; - case dwarf_w12_mips64: return "w12"; - case dwarf_w13_mips64: return "w13"; - case dwarf_w14_mips64: return "w14"; - case dwarf_w15_mips64: return "w15"; - case dwarf_w16_mips64: return "w16"; - case dwarf_w17_mips64: return "w17"; - case dwarf_w18_mips64: return "w18"; - case dwarf_w19_mips64: return "w19"; - case dwarf_w20_mips64: return "w20"; - case dwarf_w21_mips64: return "w21"; - case dwarf_w22_mips64: return "w22"; - case dwarf_w23_mips64: return "w23"; - case dwarf_w24_mips64: return "w24"; - case dwarf_w25_mips64: return "w25"; - case dwarf_w26_mips64: return "w26"; - case dwarf_w27_mips64: return "w27"; - case dwarf_w28_mips64: return "w28"; - case dwarf_w29_mips64: return "w29"; - case dwarf_w30_mips64: return "w30"; - case dwarf_w31_mips64: return "w31"; - case dwarf_mir_mips64: return "mir"; - case dwarf_mcsr_mips64: return "mcsr"; - case dwarf_config5_mips64: return "config5"; - default: - break; - } - return nullptr; - } +bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) { + if (arch.GetTriple().getArch() == llvm::Triple::mips64 || + arch.GetTriple().getArch() == llvm::Triple::mips64el) + return true; + return false; +} - switch (reg_num) - { - case dwarf_zero_mips64: return "r0"; - case dwarf_r1_mips64: return "r1"; - case dwarf_r2_mips64: return "r2"; - case dwarf_r3_mips64: return "r3"; - case dwarf_r4_mips64: return "r4"; - case dwarf_r5_mips64: return "r5"; - case dwarf_r6_mips64: return "r6"; - case dwarf_r7_mips64: return "r7"; - case dwarf_r8_mips64: return "r8"; - case dwarf_r9_mips64: return "r9"; - case dwarf_r10_mips64: return "r10"; - case dwarf_r11_mips64: return "r11"; - case dwarf_r12_mips64: return "r12"; - case dwarf_r13_mips64: return "r13"; - case dwarf_r14_mips64: return "r14"; - case dwarf_r15_mips64: return "r15"; - case dwarf_r16_mips64: return "r16"; - case dwarf_r17_mips64: return "r17"; - case dwarf_r18_mips64: return "r18"; - case dwarf_r19_mips64: return "r19"; - case dwarf_r20_mips64: return "r20"; - case dwarf_r21_mips64: return "r21"; - case dwarf_r22_mips64: return "r22"; - case dwarf_r23_mips64: return "r23"; - case dwarf_r24_mips64: return "r24"; - case dwarf_r25_mips64: return "r25"; - case dwarf_r26_mips64: return "r26"; - case dwarf_r27_mips64: return "r27"; - case dwarf_gp_mips64: return "gp"; - case dwarf_sp_mips64: return "sp"; - case dwarf_r30_mips64: return "fp"; - case dwarf_ra_mips64: return "ra"; - case dwarf_sr_mips64: return "sr"; - case dwarf_lo_mips64: return "lo"; - case dwarf_hi_mips64: return "hi"; - case dwarf_bad_mips64: return "bad"; - case dwarf_cause_mips64: return "cause"; - case dwarf_pc_mips64: return "pc"; - case dwarf_f0_mips64: return "f0"; - case dwarf_f1_mips64: return "f1"; - case dwarf_f2_mips64: return "f2"; - case dwarf_f3_mips64: return "f3"; - case dwarf_f4_mips64: return "f4"; - case dwarf_f5_mips64: return "f5"; - case dwarf_f6_mips64: return "f6"; - case dwarf_f7_mips64: return "f7"; - case dwarf_f8_mips64: return "f8"; - case dwarf_f9_mips64: return "f9"; - case dwarf_f10_mips64: return "f10"; - case dwarf_f11_mips64: return "f11"; - case dwarf_f12_mips64: return "f12"; - case dwarf_f13_mips64: return "f13"; - case dwarf_f14_mips64: return "f14"; - case dwarf_f15_mips64: return "f15"; - case dwarf_f16_mips64: return "f16"; - case dwarf_f17_mips64: return "f17"; - case dwarf_f18_mips64: return "f18"; - case dwarf_f19_mips64: return "f19"; - case dwarf_f20_mips64: return "f20"; - case dwarf_f21_mips64: return "f21"; - case dwarf_f22_mips64: return "f22"; - case dwarf_f23_mips64: return "f23"; - case dwarf_f24_mips64: return "f24"; - case dwarf_f25_mips64: return "f25"; - case dwarf_f26_mips64: return "f26"; - case dwarf_f27_mips64: return "f27"; - case dwarf_f28_mips64: return "f28"; - case dwarf_f29_mips64: return "f29"; - case dwarf_f30_mips64: return "f30"; - case dwarf_f31_mips64: return "f31"; - case dwarf_fcsr_mips64: return "fcsr"; - case dwarf_fir_mips64: return "fir"; - case dwarf_w0_mips64: return "w0"; - case dwarf_w1_mips64: return "w1"; - case dwarf_w2_mips64: return "w2"; - case dwarf_w3_mips64: return "w3"; - case dwarf_w4_mips64: return "w4"; - case dwarf_w5_mips64: return "w5"; - case dwarf_w6_mips64: return "w6"; - case dwarf_w7_mips64: return "w7"; - case dwarf_w8_mips64: return "w8"; - case dwarf_w9_mips64: return "w9"; - case dwarf_w10_mips64: return "w10"; - case dwarf_w11_mips64: return "w11"; - case dwarf_w12_mips64: return "w12"; - case dwarf_w13_mips64: return "w13"; - case dwarf_w14_mips64: return "w14"; - case dwarf_w15_mips64: return "w15"; - case dwarf_w16_mips64: return "w16"; - case dwarf_w17_mips64: return "w17"; - case dwarf_w18_mips64: return "w18"; - case dwarf_w19_mips64: return "w19"; - case dwarf_w20_mips64: return "w20"; - case dwarf_w21_mips64: return "w21"; - case dwarf_w22_mips64: return "w22"; - case dwarf_w23_mips64: return "w23"; - case dwarf_w24_mips64: return "w24"; - case dwarf_w25_mips64: return "w25"; - case dwarf_w26_mips64: return "w26"; - case dwarf_w27_mips64: return "w27"; - case dwarf_w28_mips64: return "w28"; - case dwarf_w29_mips64: return "w29"; - case dwarf_w30_mips64: return "w30"; - case dwarf_w31_mips64: return "w31"; - case dwarf_mcsr_mips64: return "mcsr"; - case dwarf_mir_mips64: return "mir"; - case dwarf_config5_mips64: return "config5"; +const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num, + bool alternate_name) { + if (alternate_name) { + switch (reg_num) { + case dwarf_sp_mips64: + return "r29"; + case dwarf_r30_mips64: + return "r30"; + case dwarf_ra_mips64: + return "r31"; + case dwarf_f0_mips64: + return "f0"; + case dwarf_f1_mips64: + return "f1"; + case dwarf_f2_mips64: + return "f2"; + case dwarf_f3_mips64: + return "f3"; + case dwarf_f4_mips64: + return "f4"; + case dwarf_f5_mips64: + return "f5"; + case dwarf_f6_mips64: + return "f6"; + case dwarf_f7_mips64: + return "f7"; + case dwarf_f8_mips64: + return "f8"; + case dwarf_f9_mips64: + return "f9"; + case dwarf_f10_mips64: + return "f10"; + case dwarf_f11_mips64: + return "f11"; + case dwarf_f12_mips64: + return "f12"; + case dwarf_f13_mips64: + return "f13"; + case dwarf_f14_mips64: + return "f14"; + case dwarf_f15_mips64: + return "f15"; + case dwarf_f16_mips64: + return "f16"; + case dwarf_f17_mips64: + return "f17"; + case dwarf_f18_mips64: + return "f18"; + case dwarf_f19_mips64: + return "f19"; + case dwarf_f20_mips64: + return "f20"; + case dwarf_f21_mips64: + return "f21"; + case dwarf_f22_mips64: + return "f22"; + case dwarf_f23_mips64: + return "f23"; + case dwarf_f24_mips64: + return "f24"; + case dwarf_f25_mips64: + return "f25"; + case dwarf_f26_mips64: + return "f26"; + case dwarf_f27_mips64: + return "f27"; + case dwarf_f28_mips64: + return "f28"; + case dwarf_f29_mips64: + return "f29"; + case dwarf_f30_mips64: + return "f30"; + case dwarf_f31_mips64: + return "f31"; + case dwarf_w0_mips64: + return "w0"; + case dwarf_w1_mips64: + return "w1"; + case dwarf_w2_mips64: + return "w2"; + case dwarf_w3_mips64: + return "w3"; + case dwarf_w4_mips64: + return "w4"; + case dwarf_w5_mips64: + return "w5"; + case dwarf_w6_mips64: + return "w6"; + case dwarf_w7_mips64: + return "w7"; + case dwarf_w8_mips64: + return "w8"; + case dwarf_w9_mips64: + return "w9"; + case dwarf_w10_mips64: + return "w10"; + case dwarf_w11_mips64: + return "w11"; + case dwarf_w12_mips64: + return "w12"; + case dwarf_w13_mips64: + return "w13"; + case dwarf_w14_mips64: + return "w14"; + case dwarf_w15_mips64: + return "w15"; + case dwarf_w16_mips64: + return "w16"; + case dwarf_w17_mips64: + return "w17"; + case dwarf_w18_mips64: + return "w18"; + case dwarf_w19_mips64: + return "w19"; + case dwarf_w20_mips64: + return "w20"; + case dwarf_w21_mips64: + return "w21"; + case dwarf_w22_mips64: + return "w22"; + case dwarf_w23_mips64: + return "w23"; + case dwarf_w24_mips64: + return "w24"; + case dwarf_w25_mips64: + return "w25"; + case dwarf_w26_mips64: + return "w26"; + case dwarf_w27_mips64: + return "w27"; + case dwarf_w28_mips64: + return "w28"; + case dwarf_w29_mips64: + return "w29"; + case dwarf_w30_mips64: + return "w30"; + case dwarf_w31_mips64: + return "w31"; + case dwarf_mir_mips64: + return "mir"; + case dwarf_mcsr_mips64: + return "mcsr"; + case dwarf_config5_mips64: + return "config5"; + default: + break; } return nullptr; + } + + switch (reg_num) { + case dwarf_zero_mips64: + return "r0"; + case dwarf_r1_mips64: + return "r1"; + case dwarf_r2_mips64: + return "r2"; + case dwarf_r3_mips64: + return "r3"; + case dwarf_r4_mips64: + return "r4"; + case dwarf_r5_mips64: + return "r5"; + case dwarf_r6_mips64: + return "r6"; + case dwarf_r7_mips64: + return "r7"; + case dwarf_r8_mips64: + return "r8"; + case dwarf_r9_mips64: + return "r9"; + case dwarf_r10_mips64: + return "r10"; + case dwarf_r11_mips64: + return "r11"; + case dwarf_r12_mips64: + return "r12"; + case dwarf_r13_mips64: + return "r13"; + case dwarf_r14_mips64: + return "r14"; + case dwarf_r15_mips64: + return "r15"; + case dwarf_r16_mips64: + return "r16"; + case dwarf_r17_mips64: + return "r17"; + case dwarf_r18_mips64: + return "r18"; + case dwarf_r19_mips64: + return "r19"; + case dwarf_r20_mips64: + return "r20"; + case dwarf_r21_mips64: + return "r21"; + case dwarf_r22_mips64: + return "r22"; + case dwarf_r23_mips64: + return "r23"; + case dwarf_r24_mips64: + return "r24"; + case dwarf_r25_mips64: + return "r25"; + case dwarf_r26_mips64: + return "r26"; + case dwarf_r27_mips64: + return "r27"; + case dwarf_gp_mips64: + return "gp"; + case dwarf_sp_mips64: + return "sp"; + case dwarf_r30_mips64: + return "fp"; + case dwarf_ra_mips64: + return "ra"; + case dwarf_sr_mips64: + return "sr"; + case dwarf_lo_mips64: + return "lo"; + case dwarf_hi_mips64: + return "hi"; + case dwarf_bad_mips64: + return "bad"; + case dwarf_cause_mips64: + return "cause"; + case dwarf_pc_mips64: + return "pc"; + case dwarf_f0_mips64: + return "f0"; + case dwarf_f1_mips64: + return "f1"; + case dwarf_f2_mips64: + return "f2"; + case dwarf_f3_mips64: + return "f3"; + case dwarf_f4_mips64: + return "f4"; + case dwarf_f5_mips64: + return "f5"; + case dwarf_f6_mips64: + return "f6"; + case dwarf_f7_mips64: + return "f7"; + case dwarf_f8_mips64: + return "f8"; + case dwarf_f9_mips64: + return "f9"; + case dwarf_f10_mips64: + return "f10"; + case dwarf_f11_mips64: + return "f11"; + case dwarf_f12_mips64: + return "f12"; + case dwarf_f13_mips64: + return "f13"; + case dwarf_f14_mips64: + return "f14"; + case dwarf_f15_mips64: + return "f15"; + case dwarf_f16_mips64: + return "f16"; + case dwarf_f17_mips64: + return "f17"; + case dwarf_f18_mips64: + return "f18"; + case dwarf_f19_mips64: + return "f19"; + case dwarf_f20_mips64: + return "f20"; + case dwarf_f21_mips64: + return "f21"; + case dwarf_f22_mips64: + return "f22"; + case dwarf_f23_mips64: + return "f23"; + case dwarf_f24_mips64: + return "f24"; + case dwarf_f25_mips64: + return "f25"; + case dwarf_f26_mips64: + return "f26"; + case dwarf_f27_mips64: + return "f27"; + case dwarf_f28_mips64: + return "f28"; + case dwarf_f29_mips64: + return "f29"; + case dwarf_f30_mips64: + return "f30"; + case dwarf_f31_mips64: + return "f31"; + case dwarf_fcsr_mips64: + return "fcsr"; + case dwarf_fir_mips64: + return "fir"; + case dwarf_w0_mips64: + return "w0"; + case dwarf_w1_mips64: + return "w1"; + case dwarf_w2_mips64: + return "w2"; + case dwarf_w3_mips64: + return "w3"; + case dwarf_w4_mips64: + return "w4"; + case dwarf_w5_mips64: + return "w5"; + case dwarf_w6_mips64: + return "w6"; + case dwarf_w7_mips64: + return "w7"; + case dwarf_w8_mips64: + return "w8"; + case dwarf_w9_mips64: + return "w9"; + case dwarf_w10_mips64: + return "w10"; + case dwarf_w11_mips64: + return "w11"; + case dwarf_w12_mips64: + return "w12"; + case dwarf_w13_mips64: + return "w13"; + case dwarf_w14_mips64: + return "w14"; + case dwarf_w15_mips64: + return "w15"; + case dwarf_w16_mips64: + return "w16"; + case dwarf_w17_mips64: + return "w17"; + case dwarf_w18_mips64: + return "w18"; + case dwarf_w19_mips64: + return "w19"; + case dwarf_w20_mips64: + return "w20"; + case dwarf_w21_mips64: + return "w21"; + case dwarf_w22_mips64: + return "w22"; + case dwarf_w23_mips64: + return "w23"; + case dwarf_w24_mips64: + return "w24"; + case dwarf_w25_mips64: + return "w25"; + case dwarf_w26_mips64: + return "w26"; + case dwarf_w27_mips64: + return "w27"; + case dwarf_w28_mips64: + return "w28"; + case dwarf_w29_mips64: + return "w29"; + case dwarf_w30_mips64: + return "w30"; + case dwarf_w31_mips64: + return "w31"; + case dwarf_mcsr_mips64: + return "mcsr"; + case dwarf_mir_mips64: + return "mir"; + case dwarf_config5_mips64: + return "config5"; + } + return nullptr; } -bool -EmulateInstructionMIPS64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) -{ - if (reg_kind == eRegisterKindGeneric) - { - switch (reg_num) - { - case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc_mips64; break; - case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp_mips64; break; - case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = dwarf_r30_mips64; break; - case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = dwarf_ra_mips64; break; - case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_sr_mips64; break; - default: - return false; - } +bool EmulateInstructionMIPS64::GetRegisterInfo(RegisterKind reg_kind, + uint32_t reg_num, + RegisterInfo ®_info) { + if (reg_kind == eRegisterKindGeneric) { + switch (reg_num) { + case LLDB_REGNUM_GENERIC_PC: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_pc_mips64; + break; + case LLDB_REGNUM_GENERIC_SP: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_sp_mips64; + break; + case LLDB_REGNUM_GENERIC_FP: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_r30_mips64; + break; + case LLDB_REGNUM_GENERIC_RA: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_ra_mips64; + break; + case LLDB_REGNUM_GENERIC_FLAGS: + reg_kind = eRegisterKindDWARF; + reg_num = dwarf_sr_mips64; + break; + default: + return false; } - - if (reg_kind == eRegisterKindDWARF) - { - ::memset (®_info, 0, sizeof(RegisterInfo)); - ::memset (reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); - - if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 || reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 || reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) - { - reg_info.byte_size = 4; - reg_info.format = eFormatHex; - reg_info.encoding = eEncodingUint; - } - else if ((int)reg_num >= dwarf_zero_mips64 && (int)reg_num <= dwarf_f31_mips64) - { - reg_info.byte_size = 8; - reg_info.format = eFormatHex; - reg_info.encoding = eEncodingUint; - } - else if ((int)reg_num >= dwarf_w0_mips64 && (int)reg_num <= dwarf_w31_mips64) - { - reg_info.byte_size = 16; - reg_info.format = eFormatVectorOfUInt8; - reg_info.encoding = eEncodingVector; - } - else - { - return false; - } - - reg_info.name = GetRegisterName (reg_num, false); - reg_info.alt_name = GetRegisterName (reg_num, true); - reg_info.kinds[eRegisterKindDWARF] = reg_num; - - switch (reg_num) - { - case dwarf_r30_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; break; - case dwarf_ra_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; break; - case dwarf_sp_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; break; - case dwarf_pc_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; break; - case dwarf_sr_mips64: reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; break; - default: break; - } - return true; + } + + if (reg_kind == eRegisterKindDWARF) { + ::memset(®_info, 0, sizeof(RegisterInfo)); + ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); + + if (reg_num == dwarf_sr_mips64 || reg_num == dwarf_fcsr_mips64 || + reg_num == dwarf_fir_mips64 || reg_num == dwarf_mcsr_mips64 || + reg_num == dwarf_mir_mips64 || reg_num == dwarf_config5_mips64) { + reg_info.byte_size = 4; + reg_info.format = eFormatHex; + reg_info.encoding = eEncodingUint; + } else if ((int)reg_num >= dwarf_zero_mips64 && + (int)reg_num <= dwarf_f31_mips64) { + reg_info.byte_size = 8; + reg_info.format = eFormatHex; + reg_info.encoding = eEncodingUint; + } else if ((int)reg_num >= dwarf_w0_mips64 && + (int)reg_num <= dwarf_w31_mips64) { + reg_info.byte_size = 16; + reg_info.format = eFormatVectorOfUInt8; + reg_info.encoding = eEncodingVector; + } else { + return false; } - return false; -} -EmulateInstructionMIPS64::MipsOpcode* -EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name) -{ - static EmulateInstructionMIPS64::MipsOpcode - g_opcodes[] = - { - //---------------------------------------------------------------------- - // Prologue/Epilogue instructions - //---------------------------------------------------------------------- - { "DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "DADDIU rt, rs, immediate" }, - { "ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, "ADDIU rt, rs, immediate" }, - { "SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)" }, - { "LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)" }, - { "DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, "DSUBU rd, rs, rt" }, - { "SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, "SUBU rd, rs, rt" }, - { "DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, "DADDU rd, rs, rt" }, - { "ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, "ADDU rd, rs, rt" }, - { "LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate" }, - - - - - //---------------------------------------------------------------------- - // Load/Store instructions - //---------------------------------------------------------------------- - /* Following list of emulated instructions are required by implementation of hardware watchpoint - for MIPS in lldb. As we just need the address accessed by instructions, we have generalised - all these instructions in 2 functions depending on their addressing modes */ - - { "LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LB rt, offset(base)" }, - { "LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBE rt, offset(base)" }, - { "LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBU rt, offset(base)" }, - { "LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LBUE rt, offset(base)" }, - { "LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDC1 ft, offset(base)" }, - { "LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDL rt, offset(base)" }, - { "LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDR rt, offset(base)" }, - { "LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LLD rt, offset(base)" }, - { "LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LDC2 rt, offset(base)" }, - { "LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LDXC1 fd, index (base)" }, - { "LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LH rt, offset(base)" }, - { "LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHE rt, offset(base)" }, - { "LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHU rt, offset(base)" }, - { "LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LHUE rt, offset(base)" }, - { "LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LL rt, offset(base)" }, - { "LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LLE rt, offset(base)" }, - { "LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LUXC1 fd, index (base)" }, - { "LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LW rt, offset(rs)" }, - { "LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWC1 ft, offset(base)" }, - { "LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWC2 rt, offset(base)" }, - { "LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWE rt, offset(base)" }, - { "LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWL rt, offset(base)" }, - { "LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWLE rt, offset(base)" }, - { "LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWR rt, offset(base)" }, - { "LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "LWRE rt, offset(base)" }, - { "LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "LWXC1 fd, index (base)" }, - - { "SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SB rt, offset(base)" }, - { "SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SBE rt, offset(base)" }, - { "SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SC rt, offset(base)" }, - { "SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SCE rt, offset(base)" }, - { "SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SCD rt, offset(base)" }, - { "SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDL rt, offset(base)" }, - { "SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDR rt, offset(base)" }, - { "SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDC1 ft, offset(base)" }, - { "SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SDC2 rt, offset(base)" }, - { "SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SDXC1 fs, index (base)" }, - { "SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SH rt, offset(base)" }, - { "SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SHE rt, offset(base)" }, - { "SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SUXC1 fs, index (base)" }, - { "SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SW rt, offset(rs)" }, - { "SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWC1 ft, offset(base)" }, - { "SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWC2 rt, offset(base)" }, - { "SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWE rt, offset(base)" }, - { "SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWL rt, offset(base)" }, - { "SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWLE rt, offset(base)" }, - { "SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWR rt, offset(base)" }, - { "SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, "SWRE rt, offset(base)" }, - { "SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, "SWXC1 fs, index (base)" }, - - //---------------------------------------------------------------------- - // Branch instructions - //---------------------------------------------------------------------- - { "BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset" }, - { "BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset" }, - { "BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQL rs,rt,offset" }, - { "BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNEL rs,rt,offset" }, - { "BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BGEZALL rt,offset" }, - { "BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset" }, - { "BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BGEZAL rs,offset" }, - { "BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset" }, - { "BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset" }, - { "BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset" }, - { "BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BLEZALC rs,offset" }, - { "BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BGEZALC rs,offset" }, - { "BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BLTZALC rs,offset" }, - { "BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BGTZALC rs,offset" }, - { "BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BEQZALC rs,offset" }, - { "BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BNEZALC rs,offset" }, - { "BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BEQC rs,rt,offset" }, - { "BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNEC rs,rt,offset" }, - { "BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTC rs,rt,offset" }, - { "BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEC rs,rt,offset" }, - { "BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTUC rs,rt,offset" }, - { "BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEUC rs,rt,offset" }, - { "BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLTZC rt,offset" }, - { "BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLEZC rt,offset" }, - { "BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGEZC rt,offset" }, - { "BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGTZC rt,offset" }, - { "BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BEQZC rt,offset" }, - { "BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BNEZC rt,offset" }, - { "BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset" }, - { "BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset" }, - { "BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset" }, - { "BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset" }, - { "BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset" }, - { "BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset" }, - { "BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZAL rt,offset" }, - { "BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZALL rt,offset" }, - { "BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset" }, - { "BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BOVC rs,rt,offset" }, - { "BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNVC rs,rt,offset" }, - { "J", &EmulateInstructionMIPS64::Emulate_J, "J target" }, - { "JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target" }, - { "JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target" }, - { "JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target" }, - { "JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target" }, - { "JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset" }, - { "JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset" }, - { "JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target" }, - { "JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target" }, - { "BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset" }, - { "BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset" }, - { "BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1FL cc, offset" }, - { "BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1TL cc, offset" }, - { "BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ, "BC1EQZ ft, offset" }, - { "BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ, "BC1NEZ ft, offset" }, - { "BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY2F cc, offset" }, - { "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY2T cc, offset" }, - { "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY4F cc, offset" }, - { "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY4T cc, offset" }, - { "BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16" }, - { "BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16" }, - { "BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16" }, - { "BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16" }, - { "BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16" }, - { "BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16" }, - { "BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16" }, - { "BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16" }, - { "BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16" }, - { "BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16" }, - }; - - static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); - - for (size_t i = 0; i < k_num_mips_opcodes; ++i) - { - if (! strcasecmp (g_opcodes[i].op_name, op_name)) - return &g_opcodes[i]; + reg_info.name = GetRegisterName(reg_num, false); + reg_info.alt_name = GetRegisterName(reg_num, true); + reg_info.kinds[eRegisterKindDWARF] = reg_num; + + switch (reg_num) { + case dwarf_r30_mips64: + reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; + break; + case dwarf_ra_mips64: + reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; + break; + case dwarf_sp_mips64: + reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; + break; + case dwarf_pc_mips64: + reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; + break; + case dwarf_sr_mips64: + reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; + break; + default: + break; } - - return NULL; + return true; + } + return false; } -bool -EmulateInstructionMIPS64::ReadInstruction () -{ - bool success = false; - m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); - if (success) - { - Context read_inst_context; - read_inst_context.type = eContextReadOpcode; - read_inst_context.SetNoArgs (); - m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder()); - } - if (!success) - m_addr = LLDB_INVALID_ADDRESS; - return success; +EmulateInstructionMIPS64::MipsOpcode * +EmulateInstructionMIPS64::GetOpcodeForInstruction(const char *op_name) { + static EmulateInstructionMIPS64::MipsOpcode g_opcodes[] = { + //---------------------------------------------------------------------- + // Prologue/Epilogue instructions + //---------------------------------------------------------------------- + {"DADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, + "DADDIU rt, rs, immediate"}, + {"ADDiu", &EmulateInstructionMIPS64::Emulate_DADDiu, + "ADDIU rt, rs, immediate"}, + {"SD", &EmulateInstructionMIPS64::Emulate_SD, "SD rt, offset(rs)"}, + {"LD", &EmulateInstructionMIPS64::Emulate_LD, "LD rt, offset(base)"}, + {"DSUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, + "DSUBU rd, rs, rt"}, + {"SUBU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, + "SUBU rd, rs, rt"}, + {"DADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, + "DADDU rd, rs, rt"}, + {"ADDU", &EmulateInstructionMIPS64::Emulate_DSUBU_DADDU, + "ADDU rd, rs, rt"}, + {"LUI", &EmulateInstructionMIPS64::Emulate_LUI, "LUI rt, immediate"}, + + //---------------------------------------------------------------------- + // Load/Store instructions + //---------------------------------------------------------------------- + /* Following list of emulated instructions are required by implementation + of hardware watchpoint + for MIPS in lldb. As we just need the address accessed by instructions, + we have generalised + all these instructions in 2 functions depending on their addressing + modes */ + + {"LB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LB rt, offset(base)"}, + {"LBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LBE rt, offset(base)"}, + {"LBU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LBU rt, offset(base)"}, + {"LBUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LBUE rt, offset(base)"}, + {"LDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LDC1 ft, offset(base)"}, + {"LDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LDL rt, offset(base)"}, + {"LDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LDR rt, offset(base)"}, + {"LLD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LLD rt, offset(base)"}, + {"LDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LDC2 rt, offset(base)"}, + {"LDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, + "LDXC1 fd, index (base)"}, + {"LH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LH rt, offset(base)"}, + {"LHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LHE rt, offset(base)"}, + {"LHU", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LHU rt, offset(base)"}, + {"LHUE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LHUE rt, offset(base)"}, + {"LL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LL rt, offset(base)"}, + {"LLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LLE rt, offset(base)"}, + {"LUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, + "LUXC1 fd, index (base)"}, + {"LW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LW rt, offset(rs)"}, + {"LWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LWC1 ft, offset(base)"}, + {"LWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LWC2 rt, offset(base)"}, + {"LWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LWE rt, offset(base)"}, + {"LWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LWL rt, offset(base)"}, + {"LWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LWLE rt, offset(base)"}, + {"LWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LWR rt, offset(base)"}, + {"LWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "LWRE rt, offset(base)"}, + {"LWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, + "LWXC1 fd, index (base)"}, + + {"SB", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SB rt, offset(base)"}, + {"SBE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SBE rt, offset(base)"}, + {"SC", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SC rt, offset(base)"}, + {"SCE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SCE rt, offset(base)"}, + {"SCD", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SCD rt, offset(base)"}, + {"SDL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SDL rt, offset(base)"}, + {"SDR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SDR rt, offset(base)"}, + {"SDC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SDC1 ft, offset(base)"}, + {"SDC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SDC2 rt, offset(base)"}, + {"SDXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, + "SDXC1 fs, index (base)"}, + {"SH", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SH rt, offset(base)"}, + {"SHE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SHE rt, offset(base)"}, + {"SUXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, + "SUXC1 fs, index (base)"}, + {"SW", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SW rt, offset(rs)"}, + {"SWC1", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SWC1 ft, offset(base)"}, + {"SWC2", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SWC2 rt, offset(base)"}, + {"SWE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SWE rt, offset(base)"}, + {"SWL", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SWL rt, offset(base)"}, + {"SWLE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SWLE rt, offset(base)"}, + {"SWR", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SWR rt, offset(base)"}, + {"SWRE", &EmulateInstructionMIPS64::Emulate_LDST_Imm, + "SWRE rt, offset(base)"}, + {"SWXC1", &EmulateInstructionMIPS64::Emulate_LDST_Reg, + "SWXC1 fs, index (base)"}, + + //---------------------------------------------------------------------- + // Branch instructions + //---------------------------------------------------------------------- + {"BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset"}, + {"BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset"}, + {"BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, + "BEQL rs,rt,offset"}, + {"BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, + "BNEL rs,rt,offset"}, + {"BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, + "BGEZALL rt,offset"}, + {"BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset"}, + {"BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, + "BGEZAL rs,offset"}, + {"BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset"}, + {"BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset"}, + {"BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset"}, + {"BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, + "BLEZALC rs,offset"}, + {"BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, + "BGEZALC rs,offset"}, + {"BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, + "BLTZALC rs,offset"}, + {"BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, + "BGTZALC rs,offset"}, + {"BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, + "BEQZALC rs,offset"}, + {"BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C, + "BNEZALC rs,offset"}, + {"BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BEQC rs,rt,offset"}, + {"BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BNEC rs,rt,offset"}, + {"BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BLTC rs,rt,offset"}, + {"BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BGEC rs,rt,offset"}, + {"BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BLTUC rs,rt,offset"}, + {"BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BGEUC rs,rt,offset"}, + {"BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BLTZC rt,offset"}, + {"BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BLEZC rt,offset"}, + {"BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BGEZC rt,offset"}, + {"BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BGTZC rt,offset"}, + {"BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BEQZC rt,offset"}, + {"BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, + "BNEZC rt,offset"}, + {"BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset"}, + {"BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset"}, + {"BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset"}, + {"BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset"}, + {"BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset"}, + {"BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset"}, + {"BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, + "BLTZAL rt,offset"}, + {"BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, + "BLTZALL rt,offset"}, + {"BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset"}, + {"BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BOVC rs,rt,offset"}, + {"BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, + "BNVC rs,rt,offset"}, + {"J", &EmulateInstructionMIPS64::Emulate_J, "J target"}, + {"JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target"}, + {"JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target"}, + {"JALR", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"}, + {"JALR64", &EmulateInstructionMIPS64::Emulate_JALR, "JALR target"}, + {"JALR_HB", &EmulateInstructionMIPS64::Emulate_JALR, "JALR.HB target"}, + {"JIALC", &EmulateInstructionMIPS64::Emulate_JIALC, "JIALC rt,offset"}, + {"JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset"}, + {"JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target"}, + {"JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target"}, + {"BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset"}, + {"BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset"}, + {"BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch, + "BC1FL cc, offset"}, + {"BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch, + "BC1TL cc, offset"}, + {"BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ, + "BC1EQZ ft, offset"}, + {"BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ, + "BC1NEZ ft, offset"}, + {"BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch, + "BC1ANY2F cc, offset"}, + {"BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch, + "BC1ANY2T cc, offset"}, + {"BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch, + "BC1ANY4F cc, offset"}, + {"BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch, + "BC1ANY4T cc, offset"}, + {"BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16"}, + {"BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16"}, + {"BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16"}, + {"BNZ_D", &EmulateInstructionMIPS64::Emulate_BNZD, "BNZ.d wt,s16"}, + {"BZ_B", &EmulateInstructionMIPS64::Emulate_BZB, "BZ.b wt,s16"}, + {"BZ_H", &EmulateInstructionMIPS64::Emulate_BZH, "BZ.h wt,s16"}, + {"BZ_W", &EmulateInstructionMIPS64::Emulate_BZW, "BZ.w wt,s16"}, + {"BZ_D", &EmulateInstructionMIPS64::Emulate_BZD, "BZ.d wt,s16"}, + {"BNZ_V", &EmulateInstructionMIPS64::Emulate_BNZV, "BNZ.V wt,s16"}, + {"BZ_V", &EmulateInstructionMIPS64::Emulate_BZV, "BZ.V wt,s16"}, + }; + + static const size_t k_num_mips_opcodes = llvm::array_lengthof(g_opcodes); + + for (size_t i = 0; i < k_num_mips_opcodes; ++i) { + if (!strcasecmp(g_opcodes[i].op_name, op_name)) + return &g_opcodes[i]; + } + + return NULL; } -bool -EmulateInstructionMIPS64::EvaluateInstruction (uint32_t evaluate_options) -{ - bool success = false; - llvm::MCInst mc_insn; - uint64_t insn_size; - DataExtractor data; - - /* Keep the complexity of the decode logic with the llvm::MCDisassembler class. */ - if (m_opcode.GetData (data)) - { - llvm::MCDisassembler::DecodeStatus decode_status; - llvm::ArrayRef<uint8_t> raw_insn (data.GetDataStart(), data.GetByteSize()); - decode_status = m_disasm->getInstruction (mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); - if (decode_status != llvm::MCDisassembler::Success) - return false; - } +bool EmulateInstructionMIPS64::ReadInstruction() { + bool success = false; + m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, + LLDB_INVALID_ADDRESS, &success); + if (success) { + Context read_inst_context; + read_inst_context.type = eContextReadOpcode; + read_inst_context.SetNoArgs(); + m_opcode.SetOpcode32( + ReadMemoryUnsigned(read_inst_context, m_addr, 4, 0, &success), + GetByteOrder()); + } + if (!success) + m_addr = LLDB_INVALID_ADDRESS; + return success; +} - /* - * mc_insn.getOpcode() returns decoded opcode. However to make use - * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc". - */ - const char *op_name = m_insn_info->getName (mc_insn.getOpcode ()); +bool EmulateInstructionMIPS64::EvaluateInstruction(uint32_t evaluate_options) { + bool success = false; + llvm::MCInst mc_insn; + uint64_t insn_size; + DataExtractor data; + + /* Keep the complexity of the decode logic with the llvm::MCDisassembler + * class. */ + if (m_opcode.GetData(data)) { + llvm::MCDisassembler::DecodeStatus decode_status; + llvm::ArrayRef<uint8_t> raw_insn(data.GetDataStart(), data.GetByteSize()); + decode_status = m_disasm->getInstruction( + mc_insn, insn_size, raw_insn, m_addr, llvm::nulls(), llvm::nulls()); + if (decode_status != llvm::MCDisassembler::Success) + return false; + } + + /* + * mc_insn.getOpcode() returns decoded opcode. However to make use + * of llvm::Mips::<insn> we would need "MipsGenInstrInfo.inc". + */ + const char *op_name = m_insn_info->getName(mc_insn.getOpcode()).data(); + + if (op_name == NULL) + return false; - if (op_name == NULL) - return false; + /* + * Decoding has been done already. Just get the call-back function + * and emulate the instruction. + */ + MipsOpcode *opcode_data = GetOpcodeForInstruction(op_name); - /* - * Decoding has been done already. Just get the call-back function - * and emulate the instruction. - */ - MipsOpcode *opcode_data = GetOpcodeForInstruction (op_name); + if (opcode_data == NULL) + return false; - if (opcode_data == NULL) - return false; + uint64_t old_pc = 0, new_pc = 0; + const bool auto_advance_pc = + evaluate_options & eEmulateInstructionOptionAutoAdvancePC; - uint64_t old_pc = 0, new_pc = 0; - const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; + if (auto_advance_pc) { + old_pc = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; + } - if (auto_advance_pc) - { - old_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; - } + /* emulate instruction */ + success = (this->*opcode_data->callback)(mc_insn); + if (!success) + return false; - /* emulate instruction */ - success = (this->*opcode_data->callback) (mc_insn); + if (auto_advance_pc) { + new_pc = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); if (!success) - return false; + return false; - if (auto_advance_pc) - { - new_pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; - - /* If we haven't changed the PC, change it here */ - if (old_pc == new_pc) - { - new_pc += 4; - Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, new_pc)) - return false; - } + /* If we haven't changed the PC, change it here */ + if (old_pc == new_pc) { + new_pc += 4; + Context context; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + new_pc)) + return false; } + } - return true; + return true; } -bool -EmulateInstructionMIPS64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) -{ - unwind_plan.Clear(); - unwind_plan.SetRegisterKind (eRegisterKindDWARF); +bool EmulateInstructionMIPS64::CreateFunctionEntryUnwind( + UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindDWARF); - UnwindPlan::RowSP row(new UnwindPlan::Row); - const bool can_replace = false; + UnwindPlan::RowSP row(new UnwindPlan::Row); + const bool can_replace = false; - // Our previous Call Frame Address is the stack pointer - row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0); + // Our previous Call Frame Address is the stack pointer + row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp_mips64, 0); - // Our previous PC is in the RA - row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64, can_replace); + // Our previous PC is in the RA + row->SetRegisterLocationToRegister(dwarf_pc_mips64, dwarf_ra_mips64, + can_replace); - unwind_plan.AppendRow (row); + unwind_plan.AppendRow(row); - // All other registers are the same. - unwind_plan.SetSourceName ("EmulateInstructionMIPS64"); - unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); - unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); - unwind_plan.SetReturnAddressRegister (dwarf_ra_mips64); + // All other registers are the same. + unwind_plan.SetSourceName("EmulateInstructionMIPS64"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); + unwind_plan.SetReturnAddressRegister(dwarf_ra_mips64); - return true; + return true; } -bool -EmulateInstructionMIPS64::nonvolatile_reg_p (uint64_t regnum) -{ - switch (regnum) - { - case dwarf_r16_mips64: - case dwarf_r17_mips64: - case dwarf_r18_mips64: - case dwarf_r19_mips64: - case dwarf_r20_mips64: - case dwarf_r21_mips64: - case dwarf_r22_mips64: - case dwarf_r23_mips64: - case dwarf_gp_mips64: - case dwarf_sp_mips64: - case dwarf_r30_mips64: - case dwarf_ra_mips64: - return true; - default: - return false; - } +bool EmulateInstructionMIPS64::nonvolatile_reg_p(uint64_t regnum) { + switch (regnum) { + case dwarf_r16_mips64: + case dwarf_r17_mips64: + case dwarf_r18_mips64: + case dwarf_r19_mips64: + case dwarf_r20_mips64: + case dwarf_r21_mips64: + case dwarf_r22_mips64: + case dwarf_r23_mips64: + case dwarf_gp_mips64: + case dwarf_sp_mips64: + case dwarf_r30_mips64: + case dwarf_ra_mips64: + return true; + default: return false; + } + return false; } -bool -EmulateInstructionMIPS64::Emulate_DADDiu (llvm::MCInst& insn) -{ - // DADDIU rt, rs, immediate - // GPR[rt] <- GPR[rs] + sign_extend(immediate) - - uint8_t dst, src; - bool success = false; - const uint32_t imm16 = insn.getOperand(2).getImm(); - int64_t imm = SignedBits(imm16, 15, 0); - - dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - - // If immediate is greater than 2^16 - 1 then clang generate - // LUI, (D)ADDIU,(D)SUBU instructions in prolog. - // Example - // lui $1, 0x2 - // daddiu $1, $1, -0x5920 - // dsubu $sp, $sp, $1 - // In this case, (D)ADDIU dst and src will be same and not equal to sp - if (dst == src) - { - Context context; - - /* read <src> register */ - const int64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); - if (!success) - return false; - - /* Check if this is daddiu sp, sp, imm16 */ - if (dst == dwarf_sp_mips64) - { - uint64_t result = src_opd_val + imm; - RegisterInfo reg_info_sp; - - if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) - context.SetRegisterPlusOffset (reg_info_sp, imm); - - /* We are allocating bytes on stack */ - context.type = eContextAdjustStackPointer; - - WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips64, result); - return true; - } - - imm += src_opd_val; - context.SetImmediateSigned (imm); - context.type = eContextImmediate; - - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + dst, imm)) - return false; +bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) { + // DADDIU rt, rs, immediate + // GPR[rt] <- GPR[rs] + sign_extend(immediate) + + uint8_t dst, src; + bool success = false; + const uint32_t imm16 = insn.getOperand(2).getImm(); + int64_t imm = SignedBits(imm16, 15, 0); + + dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + + // If immediate is greater than 2^16 - 1 then clang generate + // LUI, (D)ADDIU,(D)SUBU instructions in prolog. + // Example + // lui $1, 0x2 + // daddiu $1, $1, -0x5920 + // dsubu $sp, $sp, $1 + // In this case, (D)ADDIU dst and src will be same and not equal to sp + if (dst == src) { + Context context; + + /* read <src> register */ + const int64_t src_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); + if (!success) + return false; + + /* Check if this is daddiu sp, sp, imm16 */ + if (dst == dwarf_sp_mips64) { + uint64_t result = src_opd_val + imm; + RegisterInfo reg_info_sp; + + if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) + context.SetRegisterPlusOffset(reg_info_sp, imm); + + /* We are allocating bytes on stack */ + context.type = eContextAdjustStackPointer; + + WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, + result); + return true; } - return true; -} + imm += src_opd_val; + context.SetImmediateSigned(imm); + context.type = eContextImmediate; -bool -EmulateInstructionMIPS64::Emulate_SD (llvm::MCInst& insn) -{ - uint64_t address; - RegisterInfo reg_info_base; - RegisterInfo reg_info_src; - bool success = false; - uint32_t imm16 = insn.getOperand(2).getImm(); - uint64_t imm = SignedBits(imm16, 15, 0); - uint32_t src, base; - Context bad_vaddr_context; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, + dwarf_zero_mips64 + dst, imm)) + return false; + } - src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); + return true; +} - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base) - || !GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src)) - return false; +bool EmulateInstructionMIPS64::Emulate_SD(llvm::MCInst &insn) { + uint64_t address; + RegisterInfo reg_info_base; + RegisterInfo reg_info_src; + bool success = false; + uint32_t imm16 = insn.getOperand(2).getImm(); + uint64_t imm = SignedBits(imm16, 15, 0); + uint32_t src, base; + Context bad_vaddr_context; + + src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base, + reg_info_base) || + !GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src, + reg_info_src)) + return false; - /* read SP */ - address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success); - if (!success) - return false; + /* read SP */ + address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base, + 0, &success); + if (!success) + return false; - /* destination address */ - address = address + imm; + /* destination address */ + address = address + imm; - /* We look for sp based non-volatile register stores */ - if (nonvolatile_reg_p (src)) - { - Context context; - RegisterValue data_src; - context.type = eContextPushRegisterOnStack; - context.SetRegisterToRegisterPlusOffset (reg_info_src, reg_info_base, 0); + /* We look for sp based non-volatile register stores */ + if (nonvolatile_reg_p(src)) { + Context context; + RegisterValue data_src; + context.type = eContextPushRegisterOnStack; + context.SetRegisterToRegisterPlusOffset(reg_info_src, reg_info_base, 0); - uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; - Error error; + uint8_t buffer[RegisterValue::kMaxRegisterByteSize]; + Error error; - if (!ReadRegister (®_info_base, data_src)) - return false; + if (!ReadRegister(®_info_base, data_src)) + return false; - if (data_src.GetAsMemoryData (®_info_src, buffer, reg_info_src.byte_size, eByteOrderLittle, error) == 0) - return false; + if (data_src.GetAsMemoryData(®_info_src, buffer, reg_info_src.byte_size, + eByteOrderLittle, error) == 0) + return false; - if (!WriteMemory (context, address, buffer, reg_info_src.byte_size)) - return false; - } + if (!WriteMemory(context, address, buffer, reg_info_src.byte_size)) + return false; + } - /* Set the bad_vaddr register with base address used in the instruction */ - bad_vaddr_context.type = eContextInvalid; - WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address); + /* Set the bad_vaddr register with base address used in the instruction */ + bad_vaddr_context.type = eContextInvalid; + WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, + address); - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_LD (llvm::MCInst& insn) -{ - bool success =false; - uint32_t src, base; - int64_t imm, address; - Context bad_vaddr_context; +bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) { + bool success = false; + uint32_t src, base; + int64_t imm, address; + Context bad_vaddr_context; - src = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - base = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - imm = insn.getOperand(2).getImm(); - - RegisterInfo reg_info_base; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + base, reg_info_base)) - return false; + src = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + base = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + imm = insn.getOperand(2).getImm(); - /* read base register */ - address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + base, 0, &success); - if (!success) - return false; + RegisterInfo reg_info_base; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + base, + reg_info_base)) + return false; - /* destination address */ - address = address + imm; + /* read base register */ + address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + base, + 0, &success); + if (!success) + return false; - /* Set the bad_vaddr register with base address used in the instruction */ - bad_vaddr_context.type = eContextInvalid; - WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, address); + /* destination address */ + address = address + imm; + /* Set the bad_vaddr register with base address used in the instruction */ + bad_vaddr_context.type = eContextInvalid; + WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips64, + address); - if (nonvolatile_reg_p (src)) - { - RegisterValue data_src; - RegisterInfo reg_info_src; + if (nonvolatile_reg_p(src)) { + RegisterValue data_src; + RegisterInfo reg_info_src; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips64 + src, reg_info_src)) - return false; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips64 + src, + reg_info_src)) + return false; - Context context; - context.type = eContextRegisterLoad; + Context context; + context.type = eContextRegisterLoad; - if (!WriteRegister (context, ®_info_src, data_src)) - return false; + if (!WriteRegister(context, ®_info_src, data_src)) + return false; - return true; - } + return true; + } - return false; + return false; } -bool -EmulateInstructionMIPS64::Emulate_LUI (llvm::MCInst& insn) -{ - // LUI rt, immediate - // GPR[rt] <- sign_extend(immediate << 16) +bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) { + // LUI rt, immediate + // GPR[rt] <- sign_extend(immediate << 16) - const uint32_t imm32 = insn.getOperand(1).getImm() << 16; - int64_t imm = SignedBits(imm32, 31, 0); - uint8_t rt; - Context context; - - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - context.SetImmediateSigned (imm); - context.type = eContextImmediate; + const uint32_t imm32 = insn.getOperand(1).getImm() << 16; + int64_t imm = SignedBits(imm32, 31, 0); + uint8_t rt; + Context context; - if (WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + rt, imm)) - return true; + rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + context.SetImmediateSigned(imm); + context.type = eContextImmediate; - return false; + if (WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips64 + rt, + imm)) + return true; + + return false; } -bool -EmulateInstructionMIPS64::Emulate_DSUBU_DADDU (llvm::MCInst& insn) -{ - // DSUBU sp, <src>, <rt> - // DADDU sp, <src>, <rt> - // DADDU dst, sp, <rt> - - bool success = false; - uint64_t result; - uint8_t src, dst, rt; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - dst = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - src = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - - /* Check if sp is destination register */ - if (dst == dwarf_sp_mips64) - { - rt = m_reg_info->getEncodingValue (insn.getOperand(2).getReg()); - - /* read <src> register */ - uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); - if (!success) - return false; - - /* read <rt > register */ - uint64_t rt_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); - if (!success) - return false; - - if (!strcasecmp (op_name, "DSUBU") || !strcasecmp (op_name, "SUBU")) - result = src_opd_val - rt_opd_val; - else - result = src_opd_val + rt_opd_val; - - Context context; - RegisterInfo reg_info_sp; - if (GetRegisterInfo (eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) - context.SetRegisterPlusOffset (reg_info_sp, rt_opd_val); - - /* We are allocating bytes on stack */ - context.type = eContextAdjustStackPointer; - - WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_sp_mips64, result); - - return true; - } - else if (src == dwarf_sp_mips64) - { - rt = m_reg_info->getEncodingValue (insn.getOperand(2).getReg()); +bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) { + // DSUBU sp, <src>, <rt> + // DADDU sp, <src>, <rt> + // DADDU dst, sp, <rt> - /* read <src> register */ - uint64_t src_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); - if (!success) - return false; + bool success = false; + uint64_t result; + uint8_t src, dst, rt; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); - /* read <rt> register */ - uint64_t rt_opd_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); - if (!success) - return false; + dst = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + src = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); - Context context; + /* Check if sp is destination register */ + if (dst == dwarf_sp_mips64) { + rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg()); - if (!strcasecmp (op_name, "DSUBU") || !strcasecmp (op_name, "SUBU")) - result = src_opd_val - rt_opd_val; - else - result = src_opd_val + rt_opd_val; + /* read <src> register */ + uint64_t src_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); + if (!success) + return false; - context.SetImmediateSigned (result); - context.type = eContextImmediate; + /* read <rt > register */ + uint64_t rt_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); + if (!success) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + dst, result)) - return false; - } + if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU")) + result = src_opd_val - rt_opd_val; + else + result = src_opd_val + rt_opd_val; + + Context context; + RegisterInfo reg_info_sp; + if (GetRegisterInfo(eRegisterKindDWARF, dwarf_sp_mips64, reg_info_sp)) + context.SetRegisterPlusOffset(reg_info_sp, rt_opd_val); + + /* We are allocating bytes on stack */ + context.type = eContextAdjustStackPointer; + + WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips64, result); return true; + } else if (src == dwarf_sp_mips64) { + rt = m_reg_info->getEncodingValue(insn.getOperand(2).getReg()); + + /* read <src> register */ + uint64_t src_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success); + if (!success) + return false; + + /* read <rt> register */ + uint64_t rt_opd_val = ReadRegisterUnsigned( + eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); + if (!success) + return false; + + Context context; + + if (!strcasecmp(op_name, "DSUBU") || !strcasecmp(op_name, "SUBU")) + result = src_opd_val - rt_opd_val; + else + result = src_opd_val + rt_opd_val; + + context.SetImmediateSigned(result); + context.type = eContextImmediate; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, + dwarf_zero_mips64 + dst, result)) + return false; + } + + return true; } /* @@ -1038,706 +1314,651 @@ EmulateInstructionMIPS64::Emulate_DSUBU_DADDU (llvm::MCInst& insn) BEQ, BNE : Branch on condition BEQL, BNEL : Branch likely */ -bool -EmulateInstructionMIPS64::Emulate_BXX_3ops (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs, rt; - int64_t offset, pc, rs_val, rt_val, target = 0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - offset = insn.getOperand(2).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) { + bool success = false; + uint32_t rs, rt; + int64_t offset, pc, rs_val, rt_val, target = 0; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); - if (!success) - return false; + rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips64 + rs, 0, &success); + if (!success) + return false; - rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); - if (!success) - return false; + rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips64 + rt, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BEQ") || - !strcasecmp (op_name, "BEQL")) - { - if (rs_val == rt_val) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BNE") || - !strcasecmp (op_name, "BNEL")) - { - if (rs_val != rt_val) - target = pc + offset; - else - target = pc + 8; - } + if (!strcasecmp(op_name, "BEQ") || !strcasecmp(op_name, "BEQL")) { + if (rs_val == rt_val) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BNE") || !strcasecmp(op_name, "BNEL")) { + if (rs_val != rt_val) + target = pc + offset; + else + target = pc + 8; + } - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (offset); + Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(offset); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; - return true; + return true; } -/* +/* Emulate below MIPS Non-Compact conditional branch and link instructions. BLTZAL, BGEZAL : BLTZALL, BGEZALL : Branch likely */ -bool -EmulateInstructionMIPS64::Emulate_Bcond_Link (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs; - int64_t offset, pc, target = 0; - int64_t rs_val; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_Bcond_Link(llvm::MCInst &insn) { + bool success = false; + uint32_t rs; + int64_t offset, pc, target = 0; + int64_t rs_val; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); - if (!success) - return false; + rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips64 + rs, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BLTZAL") || - !strcasecmp (op_name, "BLTZALL")) - { - if (rs_val < 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BGEZAL") || - !strcasecmp (op_name, "BGEZALL")) - { - if (rs_val >= 0) - target = pc + offset; - else - target = pc + 8; - } + if (!strcasecmp(op_name, "BLTZAL") || !strcasecmp(op_name, "BLTZALL")) { + if (rs_val < 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BGEZAL") || + !strcasecmp(op_name, "BGEZALL")) { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 8; + } - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, + pc + 8)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_BAL (llvm::MCInst& insn) -{ - bool success = false; - int64_t offset, pc, target; - - /* - * BAL offset - * offset = sign_ext (offset << 2) - * RA = PC + 8 - * PC = PC + offset - */ - offset = insn.getOperand(0).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_BAL(llvm::MCInst &insn) { + bool success = false; + int64_t offset, pc, target; - target = pc + offset; + /* + * BAL offset + * offset = sign_ext (offset << 2) + * RA = PC + 8 + * PC = PC + offset + */ + offset = insn.getOperand(0).getImm(); - Context context; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + target = pc + offset; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8)) - return false; + Context context; - return true; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, + pc + 8)) + return false; + + return true; } -bool -EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn) -{ - bool success = false; - int64_t offset, pc, target; - - /* - * BALC offset - * offset = sign_ext (offset << 2) - * RA = PC + 4 - * PC = PC + 4 + offset - */ - offset = insn.getOperand(0).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_BALC(llvm::MCInst &insn) { + bool success = false; + int64_t offset, pc, target; - target = pc + offset; + /* + * BALC offset + * offset = sign_ext (offset << 2) + * RA = PC + 4 + * PC = PC + 4 + offset + */ + offset = insn.getOperand(0).getImm(); - Context context; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + target = pc + offset; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4)) - return false; + Context context; - return true; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, + pc + 4)) + return false; + + return true; } -/* +/* Emulate below MIPS conditional branch and link instructions. BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches */ -bool -EmulateInstructionMIPS64::Emulate_Bcond_Link_C (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs; - int64_t offset, pc, rs_val, target = 0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_Bcond_Link_C(llvm::MCInst &insn) { + bool success = false; + uint32_t rs; + int64_t offset, pc, rs_val, target = 0; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); - rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); - if (!success) - return false; + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); - if (!strcasecmp (op_name, "BLEZALC")) - { - if (rs_val <= 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGEZALC")) - { - if (rs_val >= 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BLTZALC")) - { - if (rs_val < 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGTZALC")) - { - if (rs_val > 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BEQZALC")) - { - if (rs_val == 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BNEZALC")) - { - if (rs_val != 0) - target = pc + offset; - else - target = pc + 4; - } + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - Context context; + rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips64 + rs, 0, &success); + if (!success) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!strcasecmp(op_name, "BLEZALC")) { + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGEZALC")) { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BLTZALC")) { + if (rs_val < 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGTZALC")) { + if (rs_val > 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BEQZALC")) { + if (rs_val == 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BNEZALC")) { + if (rs_val != 0) + target = pc + offset; + else + target = pc + 4; + } - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4)) - return false; + Context context; - return true; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, + pc + 4)) + return false; + + return true; } -/* +/* Emulate below MIPS branch instructions. BLTZL, BGEZL, BGTZL, BLEZL : Branch likely BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches */ -bool -EmulateInstructionMIPS64::Emulate_BXX_2ops (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs; - int64_t offset, pc, rs_val, target = 0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) { + bool success = false; + uint32_t rs; + int64_t offset, pc, rs_val, target = 0; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); - rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); - if (!success) - return false; + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); - if (!strcasecmp (op_name, "BLTZL") || - !strcasecmp (op_name, "BLTZ")) - { - if (rs_val < 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BGEZL") || - !strcasecmp (op_name, "BGEZ")) - { - if (rs_val >= 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BGTZL") || - !strcasecmp (op_name, "BGTZ")) - { - if (rs_val > 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BLEZL") || - !strcasecmp (op_name, "BLEZ")) - { - if (rs_val <= 0) - target = pc + offset; - else - target = pc + 8; - } + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (offset); + rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips64 + rs, 0, &success); + if (!success) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!strcasecmp(op_name, "BLTZL") || !strcasecmp(op_name, "BLTZ")) { + if (rs_val < 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BGEZL") || !strcasecmp(op_name, "BGEZ")) { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BGTZL") || !strcasecmp(op_name, "BGTZ")) { + if (rs_val > 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BLEZL") || !strcasecmp(op_name, "BLEZ")) { + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 8; + } - return true; + Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(offset); + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; + + return true; } -bool -EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn) -{ - bool success = false; - int64_t offset, pc, target; +bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) { + bool success = false; + int64_t offset, pc, target; - /* - * BC offset - * offset = sign_ext (offset << 2) - * PC = PC + 4 + offset - */ - offset = insn.getOperand(0).getImm(); + /* + * BC offset + * offset = sign_ext (offset << 2) + * PC = PC + 4 + offset + */ + offset = insn.getOperand(0).getImm(); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - target = pc + offset; + target = pc + offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; - return true; + return true; } -static int -IsAdd64bitOverflow (int64_t a, int64_t b) -{ - int64_t r = (uint64_t) a + (uint64_t) b; +static int IsAdd64bitOverflow(int64_t a, int64_t b) { + int64_t r = (uint64_t)a + (uint64_t)b; return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0); } /* Emulate below MIPS branch instructions. - BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch instructions with no delay slot + BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch + instructions with no delay slot */ -bool -EmulateInstructionMIPS64::Emulate_BXX_3ops_C (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs, rt; - int64_t offset, pc, rs_val, rt_val, target = 0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - offset = insn.getOperand(2).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) { + bool success = false; + uint32_t rs, rt; + int64_t offset, pc, rs_val, rt_val, target = 0; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); + + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + rt = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + offset = insn.getOperand(2).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); - if (!success) - return false; + rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips64 + rs, 0, &success); + if (!success) + return false; - rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); - if (!success) - return false; + rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips64 + rt, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BEQC")) - { - if (rs_val == rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BNEC")) - { - if (rs_val != rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BLTC")) - { - if (rs_val < rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGEC")) - { - if (rs_val >= rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BLTUC")) - { - if (rs_val < rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGEUC")) - { - if ((uint32_t)rs_val >= (uint32_t)rt_val) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BOVC")) - { - if (IsAdd64bitOverflow (rs_val, rt_val)) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BNVC")) - { - if (!IsAdd64bitOverflow (rs_val, rt_val)) - target = pc + offset; - else - target = pc + 4; - } + if (!strcasecmp(op_name, "BEQC")) { + if (rs_val == rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BNEC")) { + if (rs_val != rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BLTC")) { + if (rs_val < rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGEC")) { + if (rs_val >= rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BLTUC")) { + if (rs_val < rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGEUC")) { + if ((uint32_t)rs_val >= (uint32_t)rt_val) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BOVC")) { + if (IsAdd64bitOverflow(rs_val, rt_val)) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BNVC")) { + if (!IsAdd64bitOverflow(rs_val, rt_val)) + target = pc + offset; + else + target = pc + 4; + } - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (current_inst_size + offset); + Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(current_inst_size + offset); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; - return true; + return true; } -/* +/* Emulate below MIPS branch instructions. BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches */ -bool -EmulateInstructionMIPS64::Emulate_BXX_2ops_C (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs; - int64_t offset, pc, target = 0; - int64_t rs_val; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); - - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) { + bool success = false; + uint32_t rs; + int64_t offset, pc, target = 0; + int64_t rs_val; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize(); + + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); - if (!success) - return false; + rs_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips64 + rs, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BLTZC")) - { - if (rs_val < 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BLEZC")) - { - if (rs_val <= 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGEZC")) - { - if (rs_val >= 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BGTZC")) - { - if (rs_val > 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BEQZC")) - { - if (rs_val == 0) - target = pc + offset; - else - target = pc + 4; - } - else if (!strcasecmp (op_name, "BNEZC")) - { - if (rs_val != 0) - target = pc + offset; - else - target = pc + 4; - } + if (!strcasecmp(op_name, "BLTZC")) { + if (rs_val < 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BLEZC")) { + if (rs_val <= 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGEZC")) { + if (rs_val >= 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BGTZC")) { + if (rs_val > 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BEQZC")) { + if (rs_val == 0) + target = pc + offset; + else + target = pc + 4; + } else if (!strcasecmp(op_name, "BNEZC")) { + if (rs_val != 0) + target = pc + offset; + else + target = pc + 4; + } - Context context; - context.type = eContextRelativeBranchImmediate; - context.SetImmediate (current_inst_size + offset); + Context context; + context.type = eContextRelativeBranchImmediate; + context.SetImmediate(current_inst_size + offset); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_J (llvm::MCInst& insn) -{ - bool success = false; - uint64_t offset, pc; +bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) { + bool success = false; + uint64_t offset, pc; - /* - * J offset - * offset = sign_ext (offset << 2) - * PC = PC[63-28] | offset - */ - offset = insn.getOperand(0).getImm(); + /* + * J offset + * offset = sign_ext (offset << 2) + * PC = PC[63-28] | offset + */ + offset = insn.getOperand(0).getImm(); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - /* This is a PC-region branch and not PC-relative */ - pc = (pc & 0xFFFFFFFFF0000000ULL) | offset; + /* This is a PC-region branch and not PC-relative */ + pc = (pc & 0xFFFFFFFFF0000000ULL) | offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, pc)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, pc)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_JAL (llvm::MCInst& insn) -{ - bool success = false; - uint64_t offset, target, pc; +bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) { + bool success = false; + uint64_t offset, target, pc; - /* - * JAL offset - * offset = sign_ext (offset << 2) - * PC = PC[63-28] | offset - */ - offset = insn.getOperand(0).getImm(); + /* + * JAL offset + * offset = sign_ext (offset << 2) + * PC = PC[63-28] | offset + */ + offset = insn.getOperand(0).getImm(); - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - /* This is a PC-region branch and not PC-relative */ - target = (pc & 0xFFFFFFFFF0000000ULL) | offset; + /* This is a PC-region branch and not PC-relative */ + target = (pc & 0xFFFFFFFFF0000000ULL) | offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, + pc + 8)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_JALR (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs, rt; - uint64_t pc, rs_val; - - /* - * JALR rt, rs - * GPR[rt] = PC + 8 - * PC = GPR[rs] - */ - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - rs = m_reg_info->getEncodingValue (insn.getOperand(1).getReg()); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_JALR(llvm::MCInst &insn) { + bool success = false; + uint32_t rs, rt; + uint64_t pc, rs_val; + + /* + * JALR rt, rs + * GPR[rt] = PC + 8 + * PC = GPR[rs] + */ + rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + rs = m_reg_info->getEncodingValue(insn.getOperand(1).getReg()); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); - if (!success) - return false; + rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, + &success); + if (!success) + return false; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + rs_val)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_zero_mips64 + rt, pc + 8)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, + dwarf_zero_mips64 + rt, pc + 8)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_JIALC (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rt; - int64_t target, offset, pc, rt_val; - - /* - * JIALC rt, offset - * offset = sign_ext (offset) - * PC = GPR[rt] + offset - * RA = PC + 4 - */ - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_JIALC(llvm::MCInst &insn) { + bool success = false; + uint32_t rt; + int64_t target, offset, pc, rt_val; + + /* + * JIALC rt, offset + * offset = sign_ext (offset) + * PC = GPR[rt] + offset + * RA = PC + 4 + */ + rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); - if (!success) - return false; + rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips64 + rt, 0, &success); + if (!success) + return false; - target = rt_val + offset; + target = rt_val + offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_ra_mips64, + pc + 4)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_JIC (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rt; - int64_t target, offset, rt_val; - - /* - * JIC rt, offset - * offset = sign_ext (offset) - * PC = GPR[rt] + offset - */ - rt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) { + bool success = false; + uint32_t rt; + int64_t target, offset, rt_val; + + /* + * JIC rt, offset + * offset = sign_ext (offset) + * PC = GPR[rt] + offset + */ + rt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + rt_val = (int64_t)ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips64 + rt, 0, &success); + if (!success) + return false; - target = rt_val + offset; + target = rt_val + offset; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_JR (llvm::MCInst& insn) -{ - bool success = false; - uint32_t rs; - uint64_t rs_val; +bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) { + bool success = false; + uint32_t rs; + uint64_t rs_val; - /* - * JR rs - * PC = GPR[rs] - */ - rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); + /* + * JR rs + * PC = GPR[rs] + */ + rs = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); - rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success); - if (!success) - return false; + rs_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, + &success); + if (!success) + return false; - Context context; + Context context; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, rs_val)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + rs_val)) + return false; - return true; + return true; } /* @@ -1745,428 +1966,410 @@ EmulateInstructionMIPS64::Emulate_JR (llvm::MCInst& insn) BC1F, BC1FL : Branch on FP False (L stands for branch likely) BC1T, BC1TL : Branch on FP True (L stands for branch likely) */ -bool -EmulateInstructionMIPS64::Emulate_FP_branch (llvm::MCInst& insn) -{ - bool success = false; - uint32_t cc, fcsr; - int64_t pc, offset, target = 0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - /* - * BC1F cc, offset - * condition <- (FPConditionCode(cc) == 0) - * if condition then - * offset = sign_ext (offset) - * PC = PC + offset - */ - cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) { + bool success = false; + uint32_t cc, fcsr; + int64_t pc, offset, target = 0; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); + + /* + * BC1F cc, offset + * condition <- (FPConditionCode(cc) == 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + offset + */ + cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success); - if (!success) - return false; + fcsr = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success); + if (!success) + return false; - /* fcsr[23], fcsr[25-31] are vaild condition bits */ - fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); - - if (!strcasecmp (op_name, "BC1F") || - !strcasecmp (op_name, "BC1FL")) - { - if ((fcsr & (1 << cc)) == 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BC1T") || - !strcasecmp (op_name, "BC1TL")) - { - if ((fcsr & (1 << cc)) != 0) - target = pc + offset; - else - target = pc + 8; - } + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); - Context context; + if (!strcasecmp(op_name, "BC1F") || !strcasecmp(op_name, "BC1FL")) { + if ((fcsr & (1 << cc)) == 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BC1T") || !strcasecmp(op_name, "BC1TL")) { + if ((fcsr & (1 << cc)) != 0) + target = pc + offset; + else + target = pc + 8; + } - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + Context context; - return true; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; + + return true; } -bool -EmulateInstructionMIPS64::Emulate_BC1EQZ (llvm::MCInst& insn) -{ - bool success = false; - uint32_t ft; - uint64_t ft_val; - int64_t target, pc, offset; - - /* - * BC1EQZ ft, offset - * condition <- (FPR[ft].bit0 == 0) - * if condition then - * offset = sign_ext (offset) - * PC = PC + 4 + offset - */ - ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) { + bool success = false; + uint32_t ft; + uint64_t ft_val; + int64_t target, pc, offset; + + /* + * BC1EQZ ft, offset + * condition <- (FPR[ft].bit0 == 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + 4 + offset + */ + ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success); - if (!success) - return false; + ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, + &success); + if (!success) + return false; - if ((ft_val & 1) == 0) - target = pc + 4 + offset; - else - target = pc + 8; - - Context context; + if ((ft_val & 1) == 0) + target = pc + 4 + offset; + else + target = pc + 8; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + Context context; - return true; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; + + return true; } -bool -EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn) -{ - bool success = false; - uint32_t ft; - uint64_t ft_val; - int64_t target, pc, offset; - - /* - * BC1NEZ ft, offset - * condition <- (FPR[ft].bit0 != 0) - * if condition then - * offset = sign_ext (offset) - * PC = PC + 4 + offset - */ - ft = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) { + bool success = false; + uint32_t ft; + uint64_t ft_val; + int64_t target, pc, offset; + + /* + * BC1NEZ ft, offset + * condition <- (FPR[ft].bit0 != 0) + * if condition then + * offset = sign_ext (offset) + * PC = PC + 4 + offset + */ + ft = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); + + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - ft_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, &success); - if (!success) - return false; + ft_val = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips64 + ft, 0, + &success); + if (!success) + return false; - if ((ft_val & 1) != 0) - target = pc + 4 + offset; - else - target = pc + 8; - - Context context; + if ((ft_val & 1) != 0) + target = pc + 4 + offset; + else + target = pc + 8; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + Context context; - return true; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; + + return true; } /* Emulate MIPS-3D Branch instructions - BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes False/True - BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes False/True + BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes + False/True + BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes + False/True */ -bool -EmulateInstructionMIPS64::Emulate_3D_branch (llvm::MCInst& insn) -{ - bool success = false; - uint32_t cc, fcsr; - int64_t pc, offset, target = 0; - const char *op_name = m_insn_info->getName (insn.getOpcode ()); - - cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - offset = insn.getOperand(1).getImm(); - - pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) { + bool success = false; + uint32_t cc, fcsr; + int64_t pc, offset, target = 0; + const char *op_name = m_insn_info->getName(insn.getOpcode()).data(); - fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success); - if (!success) - return false; + cc = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + offset = insn.getOperand(1).getImm(); - /* fcsr[23], fcsr[25-31] are vaild condition bits */ - fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); + pc = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - if (!strcasecmp (op_name, "BC1ANY2F")) - { - /* if any one bit is 0 */ - if (((fcsr >> cc) & 3) != 3) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BC1ANY2T")) - { - /* if any one bit is 1 */ - if (((fcsr >> cc) & 3) != 0) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BC1ANY4F")) - { - /* if any one bit is 0 */ - if (((fcsr >> cc) & 0xf) != 0xf) - target = pc + offset; - else - target = pc + 8; - } - else if (!strcasecmp (op_name, "BC1ANY4T")) - { - /* if any one bit is 1 */ - if (((fcsr >> cc) & 0xf) != 0) - target = pc + offset; - else - target = pc + 8; - } + fcsr = (uint32_t)ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_fcsr_mips64, + 0, &success); + if (!success) + return false; - Context context; + /* fcsr[23], fcsr[25-31] are vaild condition bits */ + fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01); - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!strcasecmp(op_name, "BC1ANY2F")) { + /* if any one bit is 0 */ + if (((fcsr >> cc) & 3) != 3) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BC1ANY2T")) { + /* if any one bit is 1 */ + if (((fcsr >> cc) & 3) != 0) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BC1ANY4F")) { + /* if any one bit is 0 */ + if (((fcsr >> cc) & 0xf) != 0xf) + target = pc + offset; + else + target = pc + 8; + } else if (!strcasecmp(op_name, "BC1ANY4T")) { + /* if any one bit is 1 */ + if (((fcsr >> cc) & 0xf) != 0) + target = pc + offset; + else + target = pc + 8; + } - return true; + Context context; + + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; + + return true; } -bool -EmulateInstructionMIPS64::Emulate_BNZB (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 1, true); +bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 1, true); } -bool -EmulateInstructionMIPS64::Emulate_BNZH (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 2, true); +bool EmulateInstructionMIPS64::Emulate_BNZH(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 2, true); } -bool -EmulateInstructionMIPS64::Emulate_BNZW (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 4, true); +bool EmulateInstructionMIPS64::Emulate_BNZW(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 4, true); } -bool -EmulateInstructionMIPS64::Emulate_BNZD (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 8, true); +bool EmulateInstructionMIPS64::Emulate_BNZD(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 8, true); } -bool -EmulateInstructionMIPS64::Emulate_BZB (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 1, false); +bool EmulateInstructionMIPS64::Emulate_BZB(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 1, false); } -bool -EmulateInstructionMIPS64::Emulate_BZH (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 2, false); +bool EmulateInstructionMIPS64::Emulate_BZH(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 2, false); } -bool -EmulateInstructionMIPS64::Emulate_BZW (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 4, false); +bool EmulateInstructionMIPS64::Emulate_BZW(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 4, false); } -bool -EmulateInstructionMIPS64::Emulate_BZD (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_DF(insn, 8, false); +bool EmulateInstructionMIPS64::Emulate_BZD(llvm::MCInst &insn) { + return Emulate_MSA_Branch_DF(insn, 8, false); } -bool -EmulateInstructionMIPS64::Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz) -{ - bool success = false, branch_hit = true; - int64_t target = 0; - RegisterValue reg_value; - const uint8_t *ptr = NULL; +bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn, + int element_byte_size, + bool bnz) { + bool success = false, branch_hit = true; + int64_t target = 0; + RegisterValue reg_value; + const uint8_t *ptr = NULL; - uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - int64_t offset = insn.getOperand(1).getImm(); + uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + int64_t offset = insn.getOperand(1).getImm(); - int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; + int64_t pc = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) - ptr = (const uint8_t *)reg_value.GetBytes(); - else - return false; + if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) + ptr = (const uint8_t *)reg_value.GetBytes(); + else + return false; - for(int i = 0; i < 16 / element_byte_size; i++) - { - switch(element_byte_size) - { - case 1: - if((*ptr == 0 && bnz) || (*ptr != 0 && !bnz) ) - branch_hit = false; - break; - case 2: - if ((*(const uint16_t *)ptr == 0 && bnz) || (*(const uint16_t *)ptr != 0 && !bnz)) - branch_hit = false; - break; - case 4: - if ((*(const uint32_t *)ptr == 0 && bnz) || (*(const uint32_t *)ptr != 0 && !bnz)) - branch_hit = false; - break; - case 8: - if ((*(const uint64_t *)ptr == 0 && bnz) || (*(const uint64_t *)ptr != 0 && !bnz)) - branch_hit = false; - break; - } - if(!branch_hit) - break; - ptr = ptr + element_byte_size; + for (int i = 0; i < 16 / element_byte_size; i++) { + switch (element_byte_size) { + case 1: + if ((*ptr == 0 && bnz) || (*ptr != 0 && !bnz)) + branch_hit = false; + break; + case 2: + if ((*(const uint16_t *)ptr == 0 && bnz) || + (*(const uint16_t *)ptr != 0 && !bnz)) + branch_hit = false; + break; + case 4: + if ((*(const uint32_t *)ptr == 0 && bnz) || + (*(const uint32_t *)ptr != 0 && !bnz)) + branch_hit = false; + break; + case 8: + if ((*(const uint64_t *)ptr == 0 && bnz) || + (*(const uint64_t *)ptr != 0 && !bnz)) + branch_hit = false; + break; } + if (!branch_hit) + break; + ptr = ptr + element_byte_size; + } - if(branch_hit) - target = pc + offset; - else - target = pc + 8; + if (branch_hit) + target = pc + offset; + else + target = pc + 8; - Context context; - context.type = eContextRelativeBranchImmediate; + Context context; + context.type = eContextRelativeBranchImmediate; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_BNZV (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_V (insn, true); +bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) { + return Emulate_MSA_Branch_V(insn, true); } -bool -EmulateInstructionMIPS64::Emulate_BZV (llvm::MCInst& insn) -{ - return Emulate_MSA_Branch_V (insn, false); +bool EmulateInstructionMIPS64::Emulate_BZV(llvm::MCInst &insn) { + return Emulate_MSA_Branch_V(insn, false); } -bool -EmulateInstructionMIPS64::Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz) -{ - bool success = false; - int64_t target = 0; - llvm::APInt wr_val = llvm::APInt::getNullValue(128); - llvm::APInt fail_value = llvm::APInt::getMaxValue(128); - llvm::APInt zero_value = llvm::APInt::getNullValue(128); - RegisterValue reg_value; - - uint32_t wt = m_reg_info->getEncodingValue (insn.getOperand(0).getReg()); - int64_t offset = insn.getOperand(1).getImm(); - - int64_t pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); - if (!success) - return false; +bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn, + bool bnz) { + bool success = false; + int64_t target = 0; + llvm::APInt wr_val = llvm::APInt::getNullValue(128); + llvm::APInt fail_value = llvm::APInt::getMaxValue(128); + llvm::APInt zero_value = llvm::APInt::getNullValue(128); + RegisterValue reg_value; + + uint32_t wt = m_reg_info->getEncodingValue(insn.getOperand(0).getReg()); + int64_t offset = insn.getOperand(1).getImm(); + + int64_t pc = + ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc_mips64, 0, &success); + if (!success) + return false; - if (ReadRegister (eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) - wr_val = reg_value.GetAsUInt128(fail_value); - else - return false; + if (ReadRegister(eRegisterKindDWARF, dwarf_w0_mips64 + wt, reg_value)) + wr_val = reg_value.GetAsUInt128(fail_value); + else + return false; - if((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz)) - target = pc + offset; - else - target = pc + 8; + if ((llvm::APInt::isSameValue(zero_value, wr_val) && !bnz) || + (!llvm::APInt::isSameValue(zero_value, wr_val) && bnz)) + target = pc + offset; + else + target = pc + 8; - Context context; - context.type = eContextRelativeBranchImmediate; + Context context; + context.type = eContextRelativeBranchImmediate; - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target)) - return false; + if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, + target)) + return false; - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_LDST_Imm (llvm::MCInst& insn) -{ - bool success = false; - uint32_t base; - int64_t imm, address; - Context bad_vaddr_context; +bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) { + bool success = false; + uint32_t base; + int64_t imm, address; + Context bad_vaddr_context; - uint32_t num_operands = insn.getNumOperands(); - base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); - imm = insn.getOperand(num_operands-1).getImm(); + uint32_t num_operands = insn.getNumOperands(); + base = + m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); + imm = insn.getOperand(num_operands - 1).getImm(); - RegisterInfo reg_info_base; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) - return false; + RegisterInfo reg_info_base; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, + reg_info_base)) + return false; - /* read base register */ - address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + /* read base register */ + address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0, + &success); + if (!success) + return false; - /* destination address */ - address = address + imm; + /* destination address */ + address = address + imm; - /* Set the bad_vaddr register with base address used in the instruction */ - bad_vaddr_context.type = eContextInvalid; - WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + /* Set the bad_vaddr register with base address used in the instruction */ + bad_vaddr_context.type = eContextInvalid; + WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, + address); - return true; + return true; } -bool -EmulateInstructionMIPS64::Emulate_LDST_Reg (llvm::MCInst& insn) -{ - bool success = false; - uint32_t base, index; - int64_t address, index_address; - Context bad_vaddr_context; - - uint32_t num_operands = insn.getNumOperands(); - base = m_reg_info->getEncodingValue (insn.getOperand(num_operands-2).getReg()); - index = m_reg_info->getEncodingValue (insn.getOperand(num_operands-1).getReg()); - - RegisterInfo reg_info_base, reg_info_index; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + base, reg_info_base)) - return false; +bool EmulateInstructionMIPS64::Emulate_LDST_Reg(llvm::MCInst &insn) { + bool success = false; + uint32_t base, index; + int64_t address, index_address; + Context bad_vaddr_context; + + uint32_t num_operands = insn.getNumOperands(); + base = + m_reg_info->getEncodingValue(insn.getOperand(num_operands - 2).getReg()); + index = + m_reg_info->getEncodingValue(insn.getOperand(num_operands - 1).getReg()); + + RegisterInfo reg_info_base, reg_info_index; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + base, + reg_info_base)) + return false; - if (!GetRegisterInfo (eRegisterKindDWARF, dwarf_zero_mips + index, reg_info_index)) - return false; + if (!GetRegisterInfo(eRegisterKindDWARF, dwarf_zero_mips + index, + reg_info_index)) + return false; - /* read base register */ - address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + base, 0, &success); - if (!success) - return false; + /* read base register */ + address = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_zero_mips + base, 0, + &success); + if (!success) + return false; - /* read index register */ - index_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips + index, 0, &success); - if (!success) - return false; + /* read index register */ + index_address = ReadRegisterUnsigned(eRegisterKindDWARF, + dwarf_zero_mips + index, 0, &success); + if (!success) + return false; - /* destination address */ - address = address + index_address; + /* destination address */ + address = address + index_address; - /* Set the bad_vaddr register with base address used in the instruction */ - bad_vaddr_context.type = eContextInvalid; - WriteRegisterUnsigned (bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, address); + /* Set the bad_vaddr register with base address used in the instruction */ + bad_vaddr_context.type = eContextInvalid; + WriteRegisterUnsigned(bad_vaddr_context, eRegisterKindDWARF, dwarf_bad_mips, + address); - return true; + return true; } diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h index 4ee690bbf184..5543615efade 100644 --- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h +++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h @@ -18,232 +18,170 @@ #include "lldb/Core/Error.h" #include "lldb/Interpreter/OptionValue.h" -namespace llvm -{ - class MCDisassembler; - class MCSubtargetInfo; - class MCRegisterInfo; - class MCAsmInfo; - class MCContext; - class MCInstrInfo; - class MCInst; +namespace llvm { +class MCDisassembler; +class MCSubtargetInfo; +class MCRegisterInfo; +class MCAsmInfo; +class MCContext; +class MCInstrInfo; +class MCInst; } // namespace llvm -class EmulateInstructionMIPS64 : public lldb_private::EmulateInstruction -{ -public: - EmulateInstructionMIPS64(const lldb_private::ArchSpec &arch); - - static void - Initialize (); - - static void - Terminate (); - - static lldb_private::ConstString - GetPluginNameStatic (); - - static const char * - GetPluginDescriptionStatic (); - - static lldb_private::EmulateInstruction * - CreateInstance (const lldb_private::ArchSpec &arch, - lldb_private::InstructionType inst_type); - - static bool - SupportsEmulatingInstructionsOfTypeStatic (lldb_private::InstructionType inst_type) - { - switch (inst_type) - { - case lldb_private::eInstructionTypeAny: - case lldb_private::eInstructionTypePrologueEpilogue: - case lldb_private::eInstructionTypePCModifying: - return true; - - case lldb_private::eInstructionTypeAll: - return false; - } - return false; - } +class EmulateInstructionMIPS64 : public lldb_private::EmulateInstruction { +public: + EmulateInstructionMIPS64(const lldb_private::ArchSpec &arch); - lldb_private::ConstString - GetPluginName() override; + static void Initialize(); - uint32_t - GetPluginVersion() override - { - return 1; - } + static void Terminate(); - bool - SetTargetTriple(const lldb_private::ArchSpec &arch) override; - - bool - SupportsEmulatingInstructionsOfType(lldb_private::InstructionType inst_type) override - { - return SupportsEmulatingInstructionsOfTypeStatic (inst_type); - } + static lldb_private::ConstString GetPluginNameStatic(); + + static const char *GetPluginDescriptionStatic(); - bool - ReadInstruction() override; - - bool - EvaluateInstruction(uint32_t evaluate_options) override; - - bool - TestEmulation(lldb_private::Stream *out_stream, - lldb_private::ArchSpec &arch, - lldb_private::OptionValueDictionary *test_data) override - { - return false; + static lldb_private::EmulateInstruction * + CreateInstance(const lldb_private::ArchSpec &arch, + lldb_private::InstructionType inst_type); + + static bool SupportsEmulatingInstructionsOfTypeStatic( + lldb_private::InstructionType inst_type) { + switch (inst_type) { + case lldb_private::eInstructionTypeAny: + case lldb_private::eInstructionTypePrologueEpilogue: + case lldb_private::eInstructionTypePCModifying: + return true; + + case lldb_private::eInstructionTypeAll: + return false; } + return false; + } + + lldb_private::ConstString GetPluginName() override; - bool - GetRegisterInfo(lldb::RegisterKind reg_kind, - uint32_t reg_num, - lldb_private::RegisterInfo ®_info) override; + uint32_t GetPluginVersion() override { return 1; } - bool - CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override; + bool SetTargetTriple(const lldb_private::ArchSpec &arch) override; + + bool SupportsEmulatingInstructionsOfType( + lldb_private::InstructionType inst_type) override { + return SupportsEmulatingInstructionsOfTypeStatic(inst_type); + } + + bool ReadInstruction() override; + + bool EvaluateInstruction(uint32_t evaluate_options) override; + + bool TestEmulation(lldb_private::Stream *out_stream, + lldb_private::ArchSpec &arch, + lldb_private::OptionValueDictionary *test_data) override { + return false; + } + + bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, + lldb_private::RegisterInfo ®_info) override; + + bool + CreateFunctionEntryUnwind(lldb_private::UnwindPlan &unwind_plan) override; protected: - typedef struct - { - const char *op_name; - bool (EmulateInstructionMIPS64::*callback) (llvm::MCInst& insn); - const char *insn_name; - } MipsOpcode; - - static MipsOpcode* - GetOpcodeForInstruction (const char *op_name); + typedef struct { + const char *op_name; + bool (EmulateInstructionMIPS64::*callback)(llvm::MCInst &insn); + const char *insn_name; + } MipsOpcode; + + static MipsOpcode *GetOpcodeForInstruction(const char *op_name); - bool - Emulate_DADDiu (llvm::MCInst& insn); + bool Emulate_DADDiu(llvm::MCInst &insn); - bool - Emulate_DSUBU_DADDU (llvm::MCInst& insn); + bool Emulate_DSUBU_DADDU(llvm::MCInst &insn); - bool - Emulate_LUI (llvm::MCInst& insn); + bool Emulate_LUI(llvm::MCInst &insn); - bool - Emulate_SD (llvm::MCInst& insn); + bool Emulate_SD(llvm::MCInst &insn); - bool - Emulate_LD (llvm::MCInst& insn); + bool Emulate_LD(llvm::MCInst &insn); - bool - Emulate_LDST_Imm (llvm::MCInst& insn); + bool Emulate_LDST_Imm(llvm::MCInst &insn); - bool - Emulate_LDST_Reg (llvm::MCInst& insn); + bool Emulate_LDST_Reg(llvm::MCInst &insn); - bool - Emulate_BXX_3ops (llvm::MCInst& insn); + bool Emulate_BXX_3ops(llvm::MCInst &insn); - bool - Emulate_BXX_3ops_C (llvm::MCInst& insn); + bool Emulate_BXX_3ops_C(llvm::MCInst &insn); - bool - Emulate_BXX_2ops (llvm::MCInst& insn); + bool Emulate_BXX_2ops(llvm::MCInst &insn); - bool - Emulate_BXX_2ops_C (llvm::MCInst& insn); + bool Emulate_BXX_2ops_C(llvm::MCInst &insn); - bool - Emulate_Bcond_Link_C (llvm::MCInst& insn); + bool Emulate_Bcond_Link_C(llvm::MCInst &insn); - bool - Emulate_Bcond_Link (llvm::MCInst& insn); + bool Emulate_Bcond_Link(llvm::MCInst &insn); - bool - Emulate_FP_branch (llvm::MCInst& insn); + bool Emulate_FP_branch(llvm::MCInst &insn); - bool - Emulate_3D_branch (llvm::MCInst& insn); + bool Emulate_3D_branch(llvm::MCInst &insn); - bool - Emulate_BAL (llvm::MCInst& insn); + bool Emulate_BAL(llvm::MCInst &insn); - bool - Emulate_BALC (llvm::MCInst& insn); + bool Emulate_BALC(llvm::MCInst &insn); - bool - Emulate_BC (llvm::MCInst& insn); + bool Emulate_BC(llvm::MCInst &insn); - bool - Emulate_J (llvm::MCInst& insn); + bool Emulate_J(llvm::MCInst &insn); - bool - Emulate_JAL (llvm::MCInst& insn); + bool Emulate_JAL(llvm::MCInst &insn); - bool - Emulate_JALR (llvm::MCInst& insn); + bool Emulate_JALR(llvm::MCInst &insn); - bool - Emulate_JIALC (llvm::MCInst& insn); + bool Emulate_JIALC(llvm::MCInst &insn); - bool - Emulate_JIC (llvm::MCInst& insn); + bool Emulate_JIC(llvm::MCInst &insn); - bool - Emulate_JR (llvm::MCInst& insn); + bool Emulate_JR(llvm::MCInst &insn); - bool - Emulate_BC1EQZ (llvm::MCInst& insn); + bool Emulate_BC1EQZ(llvm::MCInst &insn); - bool - Emulate_BC1NEZ (llvm::MCInst& insn); + bool Emulate_BC1NEZ(llvm::MCInst &insn); - bool - Emulate_BNZB (llvm::MCInst& insn); + bool Emulate_BNZB(llvm::MCInst &insn); - bool - Emulate_BNZH (llvm::MCInst& insn); + bool Emulate_BNZH(llvm::MCInst &insn); - bool - Emulate_BNZW (llvm::MCInst& insn); + bool Emulate_BNZW(llvm::MCInst &insn); - bool - Emulate_BNZD (llvm::MCInst& insn); + bool Emulate_BNZD(llvm::MCInst &insn); - bool - Emulate_BZB (llvm::MCInst& insn); + bool Emulate_BZB(llvm::MCInst &insn); - bool - Emulate_BZH (llvm::MCInst& insn); + bool Emulate_BZH(llvm::MCInst &insn); - bool - Emulate_BZW (llvm::MCInst& insn); + bool Emulate_BZW(llvm::MCInst &insn); - bool - Emulate_BZD (llvm::MCInst& insn); + bool Emulate_BZD(llvm::MCInst &insn); - bool - Emulate_MSA_Branch_DF (llvm::MCInst& insn, int element_byte_size, bool bnz); + bool Emulate_MSA_Branch_DF(llvm::MCInst &insn, int element_byte_size, + bool bnz); - bool - Emulate_BNZV (llvm::MCInst& insn); + bool Emulate_BNZV(llvm::MCInst &insn); - bool - Emulate_BZV (llvm::MCInst& insn); + bool Emulate_BZV(llvm::MCInst &insn); - bool - Emulate_MSA_Branch_V (llvm::MCInst& insn, bool bnz); + bool Emulate_MSA_Branch_V(llvm::MCInst &insn, bool bnz); - bool - nonvolatile_reg_p (uint64_t regnum); + bool nonvolatile_reg_p(uint64_t regnum); - const char * - GetRegisterName (unsigned reg_num, bool altnernate_name); + const char *GetRegisterName(unsigned reg_num, bool altnernate_name); private: - std::unique_ptr<llvm::MCDisassembler> m_disasm; - std::unique_ptr<llvm::MCSubtargetInfo> m_subtype_info; - std::unique_ptr<llvm::MCRegisterInfo> m_reg_info; - std::unique_ptr<llvm::MCAsmInfo> m_asm_info; - std::unique_ptr<llvm::MCContext> m_context; - std::unique_ptr<llvm::MCInstrInfo> m_insn_info; + std::unique_ptr<llvm::MCDisassembler> m_disasm; + std::unique_ptr<llvm::MCSubtargetInfo> m_subtype_info; + std::unique_ptr<llvm::MCRegisterInfo> m_reg_info; + std::unique_ptr<llvm::MCAsmInfo> m_asm_info; + std::unique_ptr<llvm::MCContext> m_context; + std::unique_ptr<llvm::MCInstrInfo> m_insn_info; }; #endif // EmulateInstructionMIPS64_h_ |