//===-- EmulateInstructionARM.cpp -----------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include <cstdlib> #include <optional> #include "EmulateInstructionARM.h" #include "EmulationStateARM.h" #include "lldb/Core/Address.h" #include "lldb/Core/PluginManager.h" #include "lldb/Host/PosixApi.h" #include "lldb/Interpreter/OptionValueArray.h" #include "lldb/Interpreter/OptionValueDictionary.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Stream.h" #include "Plugins/Process/Utility/ARMDefines.h" #include "Plugins/Process/Utility/ARMUtils.h" #include "Utility/ARM_DWARF_Registers.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/MathExtras.h" usingnamespacelldb; usingnamespacelldb_private; LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM, InstructionARM) // Convenient macro definitions. #define APSR_C … #define APSR_V … #define AlignPC(pc_val) … // // ITSession implementation // static std::optional<RegisterInfo> GetARMDWARFRegisterInfo(unsigned reg_num) { … } // A8.6.50 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition. static uint32_t CountITSize(uint32_t ITMask) { … } // Init ITState. Note that at least one bit is always 1 in mask. bool ITSession::InitIT(uint32_t bits7_0) { … } // Update ITState if necessary. void ITSession::ITAdvance() { … } // Return true if we're inside an IT Block. bool ITSession::InITBlock() { … } // Return true if we're the last instruction inside an IT Block. bool ITSession::LastInITBlock() { … } // Get condition bits for the current thumb instruction. uint32_t ITSession::GetCond() { … } // ARM constants used during decoding #define REG_RD … #define LDM_REGLIST … #define SP_REG … #define LR_REG … #define PC_REG … #define PC_REGLIST_BIT … #define ARMv4 … #define ARMv4T … #define ARMv5T … #define ARMv5TE … #define ARMv5TEJ … #define ARMv6 … #define ARMv6K … #define ARMv6T2 … #define ARMv7 … #define ARMv7S … #define ARMv8 … #define ARMvAll … #define ARMV4T_ABOVE … #define ARMV5_ABOVE … #define ARMV5TE_ABOVE … #define ARMV5J_ABOVE … #define ARMV6_ABOVE … #define ARMV6T2_ABOVE … #define ARMV7_ABOVE … #define No_VFP … #define VFPv1 … #define VFPv2 … #define VFPv3 … #define AdvancedSIMD … #define VFPv1_ABOVE … #define VFPv2_ABOVE … #define VFPv2v3 … // // EmulateInstructionARM implementation // void EmulateInstructionARM::Initialize() { … } void EmulateInstructionARM::Terminate() { … } llvm::StringRef EmulateInstructionARM::GetPluginDescriptionStatic() { … } EmulateInstruction * EmulateInstructionARM::CreateInstance(const ArchSpec &arch, InstructionType inst_type) { … } bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) { … } // Write "bits (32) UNKNOWN" to memory address "address". Helper function for // many ARM instructions. bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) { … } // Write "bits (32) UNKNOWN" to register n. Helper function for many ARM // instructions. bool EmulateInstructionARM::WriteBits32Unknown(int n) { … } std::optional<RegisterInfo> EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num) { … } uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const { … } uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const { … } // 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) { … } // 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) { … } // 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) { … } // Set r7 or ip to the current stack pointer. // MOV (register) bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode, const ARMEncoding encoding) { … } // Move from high register (r8-r15) to low register (r0-r7). // MOV (register) bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode, const ARMEncoding encoding) { … } // Move from register to register. // MOV (register) bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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 limited to only a few forms of the // instruction. bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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) { … } // 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) { … } // An add operation to adjust the SP. // ADD (SP plus immediate) bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode, const ARMEncoding encoding) { … } // An add operation to adjust the SP. // ADD (SP plus register) bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // Set r7 to point to some ip offset. // SUB (immediate) bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode, const ARMEncoding encoding) { … } // Set ip to point to some stack offset. // SUB (SP minus immediate) bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // A store operation to the stack that also updates the SP. bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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) { … } // SVC (previously SWI) bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode, const ARMEncoding encoding) { … } // If Then makes up to four following instructions (the IT block) conditional. bool EmulateInstructionARM::EmulateIT(const uint32_t opcode, const ARMEncoding encoding) { … } bool EmulateInstructionARM::EmulateNop(const uint32_t opcode, const ARMEncoding encoding) { … } // Branch causes a branch to a target address. bool EmulateInstructionARM::EmulateB(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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. // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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::EmulateShiftImm(const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) { … } bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type) { … } // 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 can be written back to the base register. bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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 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) { … } bool EmulateInstructionARM::EmulateSTRBThumb(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) { … } // 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) { … } // 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) { … } // 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) { … } // 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 // 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) { … } // 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) { … } // 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) { … } // 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 (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) { … } // LDRB (immediate, Thumb) bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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) { … } // 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) { … } // LDRH (literal) calculates 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) 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // UXTB extracts an 8-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 8-bit value. bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // 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 (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 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) { … } // 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) { … } // 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. // It can optionally update the condition flags based on the result. bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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::EmulateSUBImmARM(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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) { … } // 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) { … } // 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) { … } // A8.6.216 SUB (SP minus register) bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode, const ARMEncoding encoding) { … } // A8.6.7 ADD (register-shifted register) bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode, const ARMEncoding encoding) { … } // A8.6.213 SUB (register) bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // A8.6.197 STRB (immediate, ARM) bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode, const ARMEncoding encoding) { … } // A8.6.194 STR (immediate, ARM) bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode, const ARMEncoding encoding) { … } // 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) { … } // 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) { … } // 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) { … } // A8.6.201 STRD (register) bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode, const ARMEncoding encoding) { … } // A8.6.319 VLDM // 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) { … } // A8.6.399 VSTM // 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) { … } // A8.6.320 // 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) { … } // A8.6.400 VSTR // 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) { … } // A8.6.307 VLDI1 (multiple single elements) 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) { … } // A8.6.308 VLD1 (single element to one lane) // bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode, const ARMEncoding encoding) { … } // A8.6.391 VST1 (multiple single elements) 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) { … } // 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) { … } // 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) { … } // 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) { … } EmulateInstructionARM::ARMOpcode * EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode, uint32_t arm_isa) { … } EmulateInstructionARM::ARMOpcode * EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode, uint32_t arm_isa) { … } bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) { … } bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode, const Address &inst_addr, Target *target) { … } bool EmulateInstructionARM::ReadInstruction() { … } uint32_t EmulateInstructionARM::ArchVersion() { … } bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) { … } uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) { … } bool EmulateInstructionARM::InITBlock() { … } bool EmulateInstructionARM::LastInITBlock() { … } bool EmulateInstructionARM::BadMode(uint32_t mode) { … } bool EmulateInstructionARM::CurrentModeIsPrivileged() { … } void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask, bool affect_execstate) { … } bool EmulateInstructionARM::BranchWritePC(const Context &context, uint32_t addr) { … } // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by // inspecting addr. bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) { … } // Dispatches to either BXWritePC or BranchWritePC based on architecture // versions. bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) { … } // Dispatches to either BXWritePC or BranchWritePC based on architecture // versions and current instruction set. bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) { … } EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() { … } // 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) { … } // 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() { … } // 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 EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) { … } // Write the result to the ARM core register Rd, and optionally update the // condition flags based on the result. // // This helper method tries to encapsulate the following pseudocode from the // ARM Architecture Reference Manual: // // if d == 15 then // Can only occur for encoding A1 // 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 unchanged // // 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) { … } // This helper method tries to encapsulate the following pseudocode from the // ARM Architecture Reference Manual: // // APSR.N = result<31>; // APSR.Z = IsZeroBit(result); // APSR.C = carry; // APSR.V = overflow // // 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) { … } bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) { … } EmulateInstruction::InstructionCondition EmulateInstructionARM::GetInstructionCondition() { … } bool EmulateInstructionARM::TestEmulation(Stream &out_stream, ArchSpec &arch, OptionValueDictionary *test_data) { … } // // // const char * // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num) //{ // if (reg_kind == eRegisterKindGeneric) // { // switch (reg_num) // { // case LLDB_REGNUM_GENERIC_PC: return "pc"; // case LLDB_REGNUM_GENERIC_SP: return "sp"; // case LLDB_REGNUM_GENERIC_FP: return "fp"; // case LLDB_REGNUM_GENERIC_RA: return "lr"; // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr"; // default: return NULL; // } // } // else if (reg_kind == eRegisterKindDWARF) // { // return GetARMDWARFRegisterName (reg_num); // } // return NULL; //} // bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) { … }