Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
39644 views
//===-- EmulateInstructionARM.cpp -----------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <cstdlib>9#include <optional>1011#include "EmulateInstructionARM.h"12#include "EmulationStateARM.h"13#include "lldb/Core/Address.h"14#include "lldb/Core/PluginManager.h"15#include "lldb/Host/PosixApi.h"16#include "lldb/Interpreter/OptionValueArray.h"17#include "lldb/Interpreter/OptionValueDictionary.h"18#include "lldb/Symbol/UnwindPlan.h"19#include "lldb/Utility/ArchSpec.h"20#include "lldb/Utility/Stream.h"2122#include "Plugins/Process/Utility/ARMDefines.h"23#include "Plugins/Process/Utility/ARMUtils.h"24#include "Utility/ARM_DWARF_Registers.h"2526#include "llvm/ADT/STLExtras.h"27#include "llvm/Support/MathExtras.h"2829using namespace lldb;30using namespace lldb_private;3132LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM, InstructionARM)3334// Convenient macro definitions.35#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)36#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)3738#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)3940//41// ITSession implementation42//4344static std::optional<RegisterInfo> GetARMDWARFRegisterInfo(unsigned reg_num) {45RegisterInfo reg_info;46::memset(®_info, 0, sizeof(RegisterInfo));47::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));4849if (reg_num >= dwarf_q0 && reg_num <= dwarf_q15) {50reg_info.byte_size = 16;51reg_info.format = eFormatVectorOfUInt8;52reg_info.encoding = eEncodingVector;53}5455if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) {56reg_info.byte_size = 8;57reg_info.format = eFormatFloat;58reg_info.encoding = eEncodingIEEE754;59} else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) {60reg_info.byte_size = 4;61reg_info.format = eFormatFloat;62reg_info.encoding = eEncodingIEEE754;63} else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) {64reg_info.byte_size = 12;65reg_info.format = eFormatFloat;66reg_info.encoding = eEncodingIEEE754;67} else {68reg_info.byte_size = 4;69reg_info.format = eFormatHex;70reg_info.encoding = eEncodingUint;71}7273reg_info.kinds[eRegisterKindDWARF] = reg_num;7475switch (reg_num) {76case dwarf_r0:77reg_info.name = "r0";78break;79case dwarf_r1:80reg_info.name = "r1";81break;82case dwarf_r2:83reg_info.name = "r2";84break;85case dwarf_r3:86reg_info.name = "r3";87break;88case dwarf_r4:89reg_info.name = "r4";90break;91case dwarf_r5:92reg_info.name = "r5";93break;94case dwarf_r6:95reg_info.name = "r6";96break;97case dwarf_r7:98reg_info.name = "r7";99reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;100break;101case dwarf_r8:102reg_info.name = "r8";103break;104case dwarf_r9:105reg_info.name = "r9";106break;107case dwarf_r10:108reg_info.name = "r10";109break;110case dwarf_r11:111reg_info.name = "r11";112break;113case dwarf_r12:114reg_info.name = "r12";115break;116case dwarf_sp:117reg_info.name = "sp";118reg_info.alt_name = "r13";119reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;120break;121case dwarf_lr:122reg_info.name = "lr";123reg_info.alt_name = "r14";124reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;125break;126case dwarf_pc:127reg_info.name = "pc";128reg_info.alt_name = "r15";129reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;130break;131case dwarf_cpsr:132reg_info.name = "cpsr";133reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;134break;135136case dwarf_s0:137reg_info.name = "s0";138break;139case dwarf_s1:140reg_info.name = "s1";141break;142case dwarf_s2:143reg_info.name = "s2";144break;145case dwarf_s3:146reg_info.name = "s3";147break;148case dwarf_s4:149reg_info.name = "s4";150break;151case dwarf_s5:152reg_info.name = "s5";153break;154case dwarf_s6:155reg_info.name = "s6";156break;157case dwarf_s7:158reg_info.name = "s7";159break;160case dwarf_s8:161reg_info.name = "s8";162break;163case dwarf_s9:164reg_info.name = "s9";165break;166case dwarf_s10:167reg_info.name = "s10";168break;169case dwarf_s11:170reg_info.name = "s11";171break;172case dwarf_s12:173reg_info.name = "s12";174break;175case dwarf_s13:176reg_info.name = "s13";177break;178case dwarf_s14:179reg_info.name = "s14";180break;181case dwarf_s15:182reg_info.name = "s15";183break;184case dwarf_s16:185reg_info.name = "s16";186break;187case dwarf_s17:188reg_info.name = "s17";189break;190case dwarf_s18:191reg_info.name = "s18";192break;193case dwarf_s19:194reg_info.name = "s19";195break;196case dwarf_s20:197reg_info.name = "s20";198break;199case dwarf_s21:200reg_info.name = "s21";201break;202case dwarf_s22:203reg_info.name = "s22";204break;205case dwarf_s23:206reg_info.name = "s23";207break;208case dwarf_s24:209reg_info.name = "s24";210break;211case dwarf_s25:212reg_info.name = "s25";213break;214case dwarf_s26:215reg_info.name = "s26";216break;217case dwarf_s27:218reg_info.name = "s27";219break;220case dwarf_s28:221reg_info.name = "s28";222break;223case dwarf_s29:224reg_info.name = "s29";225break;226case dwarf_s30:227reg_info.name = "s30";228break;229case dwarf_s31:230reg_info.name = "s31";231break;232233// FPA Registers 0-7234case dwarf_f0:235reg_info.name = "f0";236break;237case dwarf_f1:238reg_info.name = "f1";239break;240case dwarf_f2:241reg_info.name = "f2";242break;243case dwarf_f3:244reg_info.name = "f3";245break;246case dwarf_f4:247reg_info.name = "f4";248break;249case dwarf_f5:250reg_info.name = "f5";251break;252case dwarf_f6:253reg_info.name = "f6";254break;255case dwarf_f7:256reg_info.name = "f7";257break;258259// Intel wireless MMX general purpose registers 0 - 7 XScale accumulator260// register 0 - 7 (they do overlap with wCGR0 - wCGR7)261case dwarf_wCGR0:262reg_info.name = "wCGR0/ACC0";263break;264case dwarf_wCGR1:265reg_info.name = "wCGR1/ACC1";266break;267case dwarf_wCGR2:268reg_info.name = "wCGR2/ACC2";269break;270case dwarf_wCGR3:271reg_info.name = "wCGR3/ACC3";272break;273case dwarf_wCGR4:274reg_info.name = "wCGR4/ACC4";275break;276case dwarf_wCGR5:277reg_info.name = "wCGR5/ACC5";278break;279case dwarf_wCGR6:280reg_info.name = "wCGR6/ACC6";281break;282case dwarf_wCGR7:283reg_info.name = "wCGR7/ACC7";284break;285286// Intel wireless MMX data registers 0 - 15287case dwarf_wR0:288reg_info.name = "wR0";289break;290case dwarf_wR1:291reg_info.name = "wR1";292break;293case dwarf_wR2:294reg_info.name = "wR2";295break;296case dwarf_wR3:297reg_info.name = "wR3";298break;299case dwarf_wR4:300reg_info.name = "wR4";301break;302case dwarf_wR5:303reg_info.name = "wR5";304break;305case dwarf_wR6:306reg_info.name = "wR6";307break;308case dwarf_wR7:309reg_info.name = "wR7";310break;311case dwarf_wR8:312reg_info.name = "wR8";313break;314case dwarf_wR9:315reg_info.name = "wR9";316break;317case dwarf_wR10:318reg_info.name = "wR10";319break;320case dwarf_wR11:321reg_info.name = "wR11";322break;323case dwarf_wR12:324reg_info.name = "wR12";325break;326case dwarf_wR13:327reg_info.name = "wR13";328break;329case dwarf_wR14:330reg_info.name = "wR14";331break;332case dwarf_wR15:333reg_info.name = "wR15";334break;335336case dwarf_spsr:337reg_info.name = "spsr";338break;339case dwarf_spsr_fiq:340reg_info.name = "spsr_fiq";341break;342case dwarf_spsr_irq:343reg_info.name = "spsr_irq";344break;345case dwarf_spsr_abt:346reg_info.name = "spsr_abt";347break;348case dwarf_spsr_und:349reg_info.name = "spsr_und";350break;351case dwarf_spsr_svc:352reg_info.name = "spsr_svc";353break;354355case dwarf_r8_usr:356reg_info.name = "r8_usr";357break;358case dwarf_r9_usr:359reg_info.name = "r9_usr";360break;361case dwarf_r10_usr:362reg_info.name = "r10_usr";363break;364case dwarf_r11_usr:365reg_info.name = "r11_usr";366break;367case dwarf_r12_usr:368reg_info.name = "r12_usr";369break;370case dwarf_r13_usr:371reg_info.name = "r13_usr";372break;373case dwarf_r14_usr:374reg_info.name = "r14_usr";375break;376case dwarf_r8_fiq:377reg_info.name = "r8_fiq";378break;379case dwarf_r9_fiq:380reg_info.name = "r9_fiq";381break;382case dwarf_r10_fiq:383reg_info.name = "r10_fiq";384break;385case dwarf_r11_fiq:386reg_info.name = "r11_fiq";387break;388case dwarf_r12_fiq:389reg_info.name = "r12_fiq";390break;391case dwarf_r13_fiq:392reg_info.name = "r13_fiq";393break;394case dwarf_r14_fiq:395reg_info.name = "r14_fiq";396break;397case dwarf_r13_irq:398reg_info.name = "r13_irq";399break;400case dwarf_r14_irq:401reg_info.name = "r14_irq";402break;403case dwarf_r13_abt:404reg_info.name = "r13_abt";405break;406case dwarf_r14_abt:407reg_info.name = "r14_abt";408break;409case dwarf_r13_und:410reg_info.name = "r13_und";411break;412case dwarf_r14_und:413reg_info.name = "r14_und";414break;415case dwarf_r13_svc:416reg_info.name = "r13_svc";417break;418case dwarf_r14_svc:419reg_info.name = "r14_svc";420break;421422// Intel wireless MMX control register in co-processor 0 - 7423case dwarf_wC0:424reg_info.name = "wC0";425break;426case dwarf_wC1:427reg_info.name = "wC1";428break;429case dwarf_wC2:430reg_info.name = "wC2";431break;432case dwarf_wC3:433reg_info.name = "wC3";434break;435case dwarf_wC4:436reg_info.name = "wC4";437break;438case dwarf_wC5:439reg_info.name = "wC5";440break;441case dwarf_wC6:442reg_info.name = "wC6";443break;444case dwarf_wC7:445reg_info.name = "wC7";446break;447448// VFP-v3/Neon449case dwarf_d0:450reg_info.name = "d0";451break;452case dwarf_d1:453reg_info.name = "d1";454break;455case dwarf_d2:456reg_info.name = "d2";457break;458case dwarf_d3:459reg_info.name = "d3";460break;461case dwarf_d4:462reg_info.name = "d4";463break;464case dwarf_d5:465reg_info.name = "d5";466break;467case dwarf_d6:468reg_info.name = "d6";469break;470case dwarf_d7:471reg_info.name = "d7";472break;473case dwarf_d8:474reg_info.name = "d8";475break;476case dwarf_d9:477reg_info.name = "d9";478break;479case dwarf_d10:480reg_info.name = "d10";481break;482case dwarf_d11:483reg_info.name = "d11";484break;485case dwarf_d12:486reg_info.name = "d12";487break;488case dwarf_d13:489reg_info.name = "d13";490break;491case dwarf_d14:492reg_info.name = "d14";493break;494case dwarf_d15:495reg_info.name = "d15";496break;497case dwarf_d16:498reg_info.name = "d16";499break;500case dwarf_d17:501reg_info.name = "d17";502break;503case dwarf_d18:504reg_info.name = "d18";505break;506case dwarf_d19:507reg_info.name = "d19";508break;509case dwarf_d20:510reg_info.name = "d20";511break;512case dwarf_d21:513reg_info.name = "d21";514break;515case dwarf_d22:516reg_info.name = "d22";517break;518case dwarf_d23:519reg_info.name = "d23";520break;521case dwarf_d24:522reg_info.name = "d24";523break;524case dwarf_d25:525reg_info.name = "d25";526break;527case dwarf_d26:528reg_info.name = "d26";529break;530case dwarf_d27:531reg_info.name = "d27";532break;533case dwarf_d28:534reg_info.name = "d28";535break;536case dwarf_d29:537reg_info.name = "d29";538break;539case dwarf_d30:540reg_info.name = "d30";541break;542case dwarf_d31:543reg_info.name = "d31";544break;545546// NEON 128-bit vector registers (overlays the d registers)547case dwarf_q0:548reg_info.name = "q0";549break;550case dwarf_q1:551reg_info.name = "q1";552break;553case dwarf_q2:554reg_info.name = "q2";555break;556case dwarf_q3:557reg_info.name = "q3";558break;559case dwarf_q4:560reg_info.name = "q4";561break;562case dwarf_q5:563reg_info.name = "q5";564break;565case dwarf_q6:566reg_info.name = "q6";567break;568case dwarf_q7:569reg_info.name = "q7";570break;571case dwarf_q8:572reg_info.name = "q8";573break;574case dwarf_q9:575reg_info.name = "q9";576break;577case dwarf_q10:578reg_info.name = "q10";579break;580case dwarf_q11:581reg_info.name = "q11";582break;583case dwarf_q12:584reg_info.name = "q12";585break;586case dwarf_q13:587reg_info.name = "q13";588break;589case dwarf_q14:590reg_info.name = "q14";591break;592case dwarf_q15:593reg_info.name = "q15";594break;595596default:597return {};598}599return reg_info;600}601602// A8.6.50603// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.604static uint32_t CountITSize(uint32_t ITMask) {605// First count the trailing zeros of the IT mask.606uint32_t TZ = llvm::countr_zero(ITMask);607if (TZ > 3) {608return 0;609}610return (4 - TZ);611}612613// Init ITState. Note that at least one bit is always 1 in mask.614bool ITSession::InitIT(uint32_t bits7_0) {615ITCounter = CountITSize(Bits32(bits7_0, 3, 0));616if (ITCounter == 0)617return false;618619// A8.6.50 IT620unsigned short FirstCond = Bits32(bits7_0, 7, 4);621if (FirstCond == 0xF) {622return false;623}624if (FirstCond == 0xE && ITCounter != 1) {625return false;626}627628ITState = bits7_0;629return true;630}631632// Update ITState if necessary.633void ITSession::ITAdvance() {634// assert(ITCounter);635--ITCounter;636if (ITCounter == 0)637ITState = 0;638else {639unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;640SetBits32(ITState, 4, 0, NewITState4_0);641}642}643644// Return true if we're inside an IT Block.645bool ITSession::InITBlock() { return ITCounter != 0; }646647// Return true if we're the last instruction inside an IT Block.648bool ITSession::LastInITBlock() { return ITCounter == 1; }649650// Get condition bits for the current thumb instruction.651uint32_t ITSession::GetCond() {652if (InITBlock())653return Bits32(ITState, 7, 4);654else655return COND_AL;656}657658// ARM constants used during decoding659#define REG_RD 0660#define LDM_REGLIST 1661#define SP_REG 13662#define LR_REG 14663#define PC_REG 15664#define PC_REGLIST_BIT 0x8000665666#define ARMv4 (1u << 0)667#define ARMv4T (1u << 1)668#define ARMv5T (1u << 2)669#define ARMv5TE (1u << 3)670#define ARMv5TEJ (1u << 4)671#define ARMv6 (1u << 5)672#define ARMv6K (1u << 6)673#define ARMv6T2 (1u << 7)674#define ARMv7 (1u << 8)675#define ARMv7S (1u << 9)676#define ARMv8 (1u << 10)677#define ARMvAll (0xffffffffu)678679#define ARMV4T_ABOVE \680(ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | \681ARMv7S | ARMv8)682#define ARMV5_ABOVE \683(ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | \684ARMv8)685#define ARMV5TE_ABOVE \686(ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)687#define ARMV5J_ABOVE \688(ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)689#define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)690#define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8)691#define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8)692693#define No_VFP 0694#define VFPv1 (1u << 1)695#define VFPv2 (1u << 2)696#define VFPv3 (1u << 3)697#define AdvancedSIMD (1u << 4)698699#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)700#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)701#define VFPv2v3 (VFPv2 | VFPv3)702703//704// EmulateInstructionARM implementation705//706707void EmulateInstructionARM::Initialize() {708PluginManager::RegisterPlugin(GetPluginNameStatic(),709GetPluginDescriptionStatic(), CreateInstance);710}711712void EmulateInstructionARM::Terminate() {713PluginManager::UnregisterPlugin(CreateInstance);714}715716llvm::StringRef EmulateInstructionARM::GetPluginDescriptionStatic() {717return "Emulate instructions for the ARM architecture.";718}719720EmulateInstruction *721EmulateInstructionARM::CreateInstance(const ArchSpec &arch,722InstructionType inst_type) {723if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(724inst_type)) {725if (arch.GetTriple().getArch() == llvm::Triple::arm) {726std::unique_ptr<EmulateInstructionARM> emulate_insn_up(727new EmulateInstructionARM(arch));728729if (emulate_insn_up)730return emulate_insn_up.release();731} else if (arch.GetTriple().getArch() == llvm::Triple::thumb) {732std::unique_ptr<EmulateInstructionARM> emulate_insn_up(733new EmulateInstructionARM(arch));734735if (emulate_insn_up)736return emulate_insn_up.release();737}738}739740return nullptr;741}742743bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) {744if (arch.GetTriple().getArch() == llvm::Triple::arm)745return true;746else if (arch.GetTriple().getArch() == llvm::Triple::thumb)747return true;748749return false;750}751752// Write "bits (32) UNKNOWN" to memory address "address". Helper function for753// many ARM instructions.754bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) {755EmulateInstruction::Context context;756context.type = EmulateInstruction::eContextWriteMemoryRandomBits;757context.SetNoArgs();758759uint32_t random_data = rand();760const uint32_t addr_byte_size = GetAddressByteSize();761762return MemAWrite(context, address, random_data, addr_byte_size);763}764765// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM766// instructions.767bool EmulateInstructionARM::WriteBits32Unknown(int n) {768EmulateInstruction::Context context;769context.type = EmulateInstruction::eContextWriteRegisterRandomBits;770context.SetNoArgs();771772bool success;773uint32_t data =774ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);775776if (!success)777return false;778779if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data))780return false;781782return true;783}784785std::optional<RegisterInfo>786EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind,787uint32_t reg_num) {788if (reg_kind == eRegisterKindGeneric) {789switch (reg_num) {790case LLDB_REGNUM_GENERIC_PC:791reg_kind = eRegisterKindDWARF;792reg_num = dwarf_pc;793break;794case LLDB_REGNUM_GENERIC_SP:795reg_kind = eRegisterKindDWARF;796reg_num = dwarf_sp;797break;798case LLDB_REGNUM_GENERIC_FP:799reg_kind = eRegisterKindDWARF;800reg_num = dwarf_r7;801break;802case LLDB_REGNUM_GENERIC_RA:803reg_kind = eRegisterKindDWARF;804reg_num = dwarf_lr;805break;806case LLDB_REGNUM_GENERIC_FLAGS:807reg_kind = eRegisterKindDWARF;808reg_num = dwarf_cpsr;809break;810default:811return {};812}813}814815if (reg_kind == eRegisterKindDWARF)816return GetARMDWARFRegisterInfo(reg_num);817return {};818}819820uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {821if (m_arch.GetTriple().isAndroid())822return LLDB_INVALID_REGNUM; // Don't use frame pointer on android823bool is_apple = false;824if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)825is_apple = true;826switch (m_arch.GetTriple().getOS()) {827case llvm::Triple::Darwin:828case llvm::Triple::MacOSX:829case llvm::Triple::IOS:830case llvm::Triple::TvOS:831case llvm::Triple::WatchOS:832case llvm::Triple::XROS:833case llvm::Triple::BridgeOS:834is_apple = true;835break;836default:837break;838}839840/* On Apple iOS et al, the frame pointer register is always r7.841* Typically on other ARM systems, thumb code uses r7; arm code uses r11.842* Windows on ARM, which is in thumb mode, uses r11 though.843*/844845uint32_t fp_regnum = 11;846847if (is_apple)848fp_regnum = 7;849850if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())851fp_regnum = 7;852853return fp_regnum;854}855856uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {857bool is_apple = false;858if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)859is_apple = true;860switch (m_arch.GetTriple().getOS()) {861case llvm::Triple::Darwin:862case llvm::Triple::MacOSX:863case llvm::Triple::IOS:864is_apple = true;865break;866default:867break;868}869870/* On Apple iOS et al, the frame pointer register is always r7.871* Typically on other ARM systems, thumb code uses r7; arm code uses r11.872* Windows on ARM, which is in thumb mode, uses r11 though.873*/874875uint32_t fp_regnum = dwarf_r11;876877if (is_apple)878fp_regnum = dwarf_r7;879880if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())881fp_regnum = dwarf_r7;882883return fp_regnum;884}885886// Push Multiple Registers stores multiple registers to the stack, storing to887// consecutive memory locations ending just below the address in SP, and888// updates889// SP to point to the start of the stored data.890bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,891const ARMEncoding encoding) {892#if 0893// ARM pseudo code...894if (ConditionPassed())895{896EncodingSpecificOperations();897NullCheckIfThumbEE(13);898address = SP - 4*BitCount(registers);899900for (i = 0 to 14)901{902if (registers<i> == '1')903{904if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1905MemA[address,4] = bits(32) UNKNOWN;906else907MemA[address,4] = R[i];908address = address + 4;909}910}911912if (registers<15> == '1') // Only possible for encoding A1 or A2913MemA[address,4] = PCStoreValue();914915SP = SP - 4*BitCount(registers);916}917#endif918919bool success = false;920if (ConditionPassed(opcode)) {921const uint32_t addr_byte_size = GetAddressByteSize();922const addr_t sp = ReadCoreReg(SP_REG, &success);923if (!success)924return false;925uint32_t registers = 0;926uint32_t Rt; // the source register927switch (encoding) {928case eEncodingT1:929registers = Bits32(opcode, 7, 0);930// The M bit represents LR.931if (Bit32(opcode, 8))932registers |= (1u << 14);933// if BitCount(registers) < 1 then UNPREDICTABLE;934if (BitCount(registers) < 1)935return false;936break;937case eEncodingT2:938// Ignore bits 15 & 13.939registers = Bits32(opcode, 15, 0) & ~0xa000;940// if BitCount(registers) < 2 then UNPREDICTABLE;941if (BitCount(registers) < 2)942return false;943break;944case eEncodingT3:945Rt = Bits32(opcode, 15, 12);946// if BadReg(t) then UNPREDICTABLE;947if (BadReg(Rt))948return false;949registers = (1u << Rt);950break;951case eEncodingA1:952registers = Bits32(opcode, 15, 0);953// Instead of return false, let's handle the following case as well,954// which amounts to pushing one reg onto the full descending stacks.955// if BitCount(register_list) < 2 then SEE STMDB / STMFD;956break;957case eEncodingA2:958Rt = Bits32(opcode, 15, 12);959// if t == 13 then UNPREDICTABLE;960if (Rt == dwarf_sp)961return false;962registers = (1u << Rt);963break;964default:965return false;966}967addr_t sp_offset = addr_byte_size * BitCount(registers);968addr_t addr = sp - sp_offset;969uint32_t i;970971EmulateInstruction::Context context;972context.type = EmulateInstruction::eContextPushRegisterOnStack;973std::optional<RegisterInfo> sp_reg =974GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);975for (i = 0; i < 15; ++i) {976if (BitIsSet(registers, i)) {977std::optional<RegisterInfo> reg_info =978GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);979context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);980uint32_t reg_value = ReadCoreReg(i, &success);981if (!success)982return false;983if (!MemAWrite(context, addr, reg_value, addr_byte_size))984return false;985addr += addr_byte_size;986}987}988989if (BitIsSet(registers, 15)) {990std::optional<RegisterInfo> reg_info =991GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);992context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);993const uint32_t pc = ReadCoreReg(PC_REG, &success);994if (!success)995return false;996if (!MemAWrite(context, addr, pc, addr_byte_size))997return false;998}9991000context.type = EmulateInstruction::eContextAdjustStackPointer;1001context.SetImmediateSigned(-sp_offset);10021003if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,1004LLDB_REGNUM_GENERIC_SP, sp - sp_offset))1005return false;1006}1007return true;1008}10091010// Pop Multiple Registers loads multiple registers from the stack, loading from1011// consecutive memory locations staring at the address in SP, and updates1012// SP to point just above the loaded data.1013bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,1014const ARMEncoding encoding) {1015#if 01016// ARM pseudo code...1017if (ConditionPassed())1018{1019EncodingSpecificOperations(); NullCheckIfThumbEE(13);1020address = SP;1021for i = 0 to 141022if registers<i> == '1' then1023R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;1024if registers<15> == '1' then1025if UnalignedAllowed then1026LoadWritePC(MemU[address,4]);1027else1028LoadWritePC(MemA[address,4]);1029if registers<13> == '0' then SP = SP + 4*BitCount(registers);1030if registers<13> == '1' then SP = bits(32) UNKNOWN;1031}1032#endif10331034bool success = false;10351036if (ConditionPassed(opcode)) {1037const uint32_t addr_byte_size = GetAddressByteSize();1038const addr_t sp = ReadCoreReg(SP_REG, &success);1039if (!success)1040return false;1041uint32_t registers = 0;1042uint32_t Rt; // the destination register1043switch (encoding) {1044case eEncodingT1:1045registers = Bits32(opcode, 7, 0);1046// The P bit represents PC.1047if (Bit32(opcode, 8))1048registers |= (1u << 15);1049// if BitCount(registers) < 1 then UNPREDICTABLE;1050if (BitCount(registers) < 1)1051return false;1052break;1053case eEncodingT2:1054// Ignore bit 13.1055registers = Bits32(opcode, 15, 0) & ~0x2000;1056// if BitCount(registers) < 2 || (P == '1' && M == '1') then1057// UNPREDICTABLE;1058if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))1059return false;1060// if registers<15> == '1' && InITBlock() && !LastInITBlock() then1061// UNPREDICTABLE;1062if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())1063return false;1064break;1065case eEncodingT3:1066Rt = Bits32(opcode, 15, 12);1067// if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then1068// UNPREDICTABLE;1069if (Rt == 13)1070return false;1071if (Rt == 15 && InITBlock() && !LastInITBlock())1072return false;1073registers = (1u << Rt);1074break;1075case eEncodingA1:1076registers = Bits32(opcode, 15, 0);1077// Instead of return false, let's handle the following case as well,1078// which amounts to popping one reg from the full descending stacks.1079// if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;10801081// if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;1082if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)1083return false;1084break;1085case eEncodingA2:1086Rt = Bits32(opcode, 15, 12);1087// if t == 13 then UNPREDICTABLE;1088if (Rt == dwarf_sp)1089return false;1090registers = (1u << Rt);1091break;1092default:1093return false;1094}1095addr_t sp_offset = addr_byte_size * BitCount(registers);1096addr_t addr = sp;1097uint32_t i, data;10981099EmulateInstruction::Context context;1100context.type = EmulateInstruction::eContextPopRegisterOffStack;11011102std::optional<RegisterInfo> sp_reg =1103GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);11041105for (i = 0; i < 15; ++i) {1106if (BitIsSet(registers, i)) {1107context.SetAddress(addr);1108data = MemARead(context, addr, 4, 0, &success);1109if (!success)1110return false;1111if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,1112data))1113return false;1114addr += addr_byte_size;1115}1116}11171118if (BitIsSet(registers, 15)) {1119context.SetRegisterPlusOffset(*sp_reg, addr - sp);1120data = MemARead(context, addr, 4, 0, &success);1121if (!success)1122return false;1123// In ARMv5T and above, this is an interworking branch.1124if (!LoadWritePC(context, data))1125return false;1126// addr += addr_byte_size;1127}11281129context.type = EmulateInstruction::eContextAdjustStackPointer;1130context.SetImmediateSigned(sp_offset);11311132if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,1133LLDB_REGNUM_GENERIC_SP, sp + sp_offset))1134return false;1135}1136return true;1137}11381139// Set r7 or ip to point to saved value residing within the stack.1140// ADD (SP plus immediate)1141bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,1142const ARMEncoding encoding) {1143#if 01144// ARM pseudo code...1145if (ConditionPassed())1146{1147EncodingSpecificOperations();1148(result, carry, overflow) = AddWithCarry(SP, imm32, '0');1149if d == 15 then1150ALUWritePC(result); // setflags is always FALSE here1151else1152R[d] = result;1153if setflags then1154APSR.N = result<31>;1155APSR.Z = IsZeroBit(result);1156APSR.C = carry;1157APSR.V = overflow;1158}1159#endif11601161bool success = false;11621163if (ConditionPassed(opcode)) {1164const addr_t sp = ReadCoreReg(SP_REG, &success);1165if (!success)1166return false;1167uint32_t Rd; // the destination register1168uint32_t imm32;1169switch (encoding) {1170case eEncodingT1:1171Rd = 7;1172imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)1173break;1174case eEncodingA1:1175Rd = Bits32(opcode, 15, 12);1176imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)1177break;1178default:1179return false;1180}1181addr_t sp_offset = imm32;1182addr_t addr = sp + sp_offset; // a pointer to the stack area11831184EmulateInstruction::Context context;1185if (Rd == GetFramePointerRegisterNumber())1186context.type = eContextSetFramePointer;1187else1188context.type = EmulateInstruction::eContextRegisterPlusOffset;1189std::optional<RegisterInfo> sp_reg =1190GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);1191context.SetRegisterPlusOffset(*sp_reg, sp_offset);11921193if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd,1194addr))1195return false;1196}1197return true;1198}11991200// Set r7 or ip to the current stack pointer.1201// MOV (register)1202bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,1203const ARMEncoding encoding) {1204#if 01205// ARM pseudo code...1206if (ConditionPassed())1207{1208EncodingSpecificOperations();1209result = R[m];1210if d == 15 then1211ALUWritePC(result); // setflags is always FALSE here1212else1213R[d] = result;1214if setflags then1215APSR.N = result<31>;1216APSR.Z = IsZeroBit(result);1217// APSR.C unchanged1218// APSR.V unchanged1219}1220#endif12211222bool success = false;12231224if (ConditionPassed(opcode)) {1225const addr_t sp = ReadCoreReg(SP_REG, &success);1226if (!success)1227return false;1228uint32_t Rd; // the destination register1229switch (encoding) {1230case eEncodingT1:1231Rd = 7;1232break;1233case eEncodingA1:1234Rd = 12;1235break;1236default:1237return false;1238}12391240EmulateInstruction::Context context;1241if (Rd == GetFramePointerRegisterNumber())1242context.type = EmulateInstruction::eContextSetFramePointer;1243else1244context.type = EmulateInstruction::eContextRegisterPlusOffset;1245std::optional<RegisterInfo> sp_reg =1246GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);1247context.SetRegisterPlusOffset(*sp_reg, 0);12481249if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))1250return false;1251}1252return true;1253}12541255// Move from high register (r8-r15) to low register (r0-r7).1256// MOV (register)1257bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,1258const ARMEncoding encoding) {1259return EmulateMOVRdRm(opcode, encoding);1260}12611262// Move from register to register.1263// MOV (register)1264bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,1265const ARMEncoding encoding) {1266#if 01267// ARM pseudo code...1268if (ConditionPassed())1269{1270EncodingSpecificOperations();1271result = R[m];1272if d == 15 then1273ALUWritePC(result); // setflags is always FALSE here1274else1275R[d] = result;1276if setflags then1277APSR.N = result<31>;1278APSR.Z = IsZeroBit(result);1279// APSR.C unchanged1280// APSR.V unchanged1281}1282#endif12831284bool success = false;12851286if (ConditionPassed(opcode)) {1287uint32_t Rm; // the source register1288uint32_t Rd; // the destination register1289bool setflags;1290switch (encoding) {1291case eEncodingT1:1292Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);1293Rm = Bits32(opcode, 6, 3);1294setflags = false;1295if (Rd == 15 && InITBlock() && !LastInITBlock())1296return false;1297break;1298case eEncodingT2:1299Rd = Bits32(opcode, 2, 0);1300Rm = Bits32(opcode, 5, 3);1301setflags = true;1302if (InITBlock())1303return false;1304break;1305case eEncodingT3:1306Rd = Bits32(opcode, 11, 8);1307Rm = Bits32(opcode, 3, 0);1308setflags = BitIsSet(opcode, 20);1309// if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;1310if (setflags && (BadReg(Rd) || BadReg(Rm)))1311return false;1312// if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then1313// UNPREDICTABLE;1314if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))1315return false;1316break;1317case eEncodingA1:1318Rd = Bits32(opcode, 15, 12);1319Rm = Bits32(opcode, 3, 0);1320setflags = BitIsSet(opcode, 20);13211322// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related1323// instructions;1324if (Rd == 15 && setflags)1325return EmulateSUBSPcLrEtc(opcode, encoding);1326break;1327default:1328return false;1329}1330uint32_t result = ReadCoreReg(Rm, &success);1331if (!success)1332return false;13331334// The context specifies that Rm is to be moved into Rd.1335EmulateInstruction::Context context;1336if (Rd == 13)1337context.type = EmulateInstruction::eContextAdjustStackPointer;1338else if (Rd == GetFramePointerRegisterNumber() && Rm == 13)1339context.type = EmulateInstruction::eContextSetFramePointer;1340else1341context.type = EmulateInstruction::eContextRegisterPlusOffset;1342std::optional<RegisterInfo> dwarf_reg =1343GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);1344context.SetRegisterPlusOffset(*dwarf_reg, 0);13451346if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))1347return false;1348}1349return true;1350}13511352// Move (immediate) writes an immediate value to the destination register. It1353// can optionally update the condition flags based on the value.1354// MOV (immediate)1355bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,1356const ARMEncoding encoding) {1357#if 01358// ARM pseudo code...1359if (ConditionPassed())1360{1361EncodingSpecificOperations();1362result = imm32;1363if d == 15 then // Can only occur for ARM encoding1364ALUWritePC(result); // setflags is always FALSE here1365else1366R[d] = result;1367if setflags then1368APSR.N = result<31>;1369APSR.Z = IsZeroBit(result);1370APSR.C = carry;1371// APSR.V unchanged1372}1373#endif13741375if (ConditionPassed(opcode)) {1376uint32_t Rd; // the destination register1377uint32_t imm32; // the immediate value to be written to Rd1378uint32_t carry =13790; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.1380// for setflags == false, this value is a don't care initialized to1381// 0 to silence the static analyzer1382bool setflags;1383switch (encoding) {1384case eEncodingT1:1385Rd = Bits32(opcode, 10, 8);1386setflags = !InITBlock();1387imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)1388carry = APSR_C;13891390break;13911392case eEncodingT2:1393Rd = Bits32(opcode, 11, 8);1394setflags = BitIsSet(opcode, 20);1395imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);1396if (BadReg(Rd))1397return false;13981399break;14001401case eEncodingT3: {1402// d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,1403// 32);1404Rd = Bits32(opcode, 11, 8);1405setflags = false;1406uint32_t imm4 = Bits32(opcode, 19, 16);1407uint32_t imm3 = Bits32(opcode, 14, 12);1408uint32_t i = Bit32(opcode, 26);1409uint32_t imm8 = Bits32(opcode, 7, 0);1410imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;14111412// if BadReg(d) then UNPREDICTABLE;1413if (BadReg(Rd))1414return false;1415} break;14161417case eEncodingA1:1418// d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =1419// ARMExpandImm_C(imm12, APSR.C);1420Rd = Bits32(opcode, 15, 12);1421setflags = BitIsSet(opcode, 20);1422imm32 = ARMExpandImm_C(opcode, APSR_C, carry);14231424// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related1425// instructions;1426if ((Rd == 15) && setflags)1427return EmulateSUBSPcLrEtc(opcode, encoding);14281429break;14301431case eEncodingA2: {1432// d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);1433Rd = Bits32(opcode, 15, 12);1434setflags = false;1435uint32_t imm4 = Bits32(opcode, 19, 16);1436uint32_t imm12 = Bits32(opcode, 11, 0);1437imm32 = (imm4 << 12) | imm12;14381439// if d == 15 then UNPREDICTABLE;1440if (Rd == 15)1441return false;1442} break;14431444default:1445return false;1446}1447uint32_t result = imm32;14481449// The context specifies that an immediate is to be moved into Rd.1450EmulateInstruction::Context context;1451context.type = EmulateInstruction::eContextImmediate;1452context.SetNoArgs();14531454if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))1455return false;1456}1457return true;1458}14591460// MUL multiplies two register values. The least significant 32 bits of the1461// result are written to the destination1462// register. These 32 bits do not depend on whether the source register values1463// are considered to be signed values or unsigned values.1464//1465// Optionally, it can update the condition flags based on the result. In the1466// Thumb instruction set, this option is limited to only a few forms of the1467// instruction.1468bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,1469const ARMEncoding encoding) {1470#if 01471if ConditionPassed() then1472EncodingSpecificOperations();1473operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results1474operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results1475result = operand1 * operand2;1476R[d] = result<31:0>;1477if setflags then1478APSR.N = result<31>;1479APSR.Z = IsZeroBit(result);1480if ArchVersion() == 4 then1481APSR.C = bit UNKNOWN;1482// else APSR.C unchanged1483// APSR.V always unchanged1484#endif14851486if (ConditionPassed(opcode)) {1487uint32_t d;1488uint32_t n;1489uint32_t m;1490bool setflags;14911492// EncodingSpecificOperations();1493switch (encoding) {1494case eEncodingT1:1495// d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();1496d = Bits32(opcode, 2, 0);1497n = Bits32(opcode, 5, 3);1498m = Bits32(opcode, 2, 0);1499setflags = !InITBlock();15001501// if ArchVersion() < 6 && d == n then UNPREDICTABLE;1502if ((ArchVersion() < ARMv6) && (d == n))1503return false;15041505break;15061507case eEncodingT2:1508// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;1509d = Bits32(opcode, 11, 8);1510n = Bits32(opcode, 19, 16);1511m = Bits32(opcode, 3, 0);1512setflags = false;15131514// if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;1515if (BadReg(d) || BadReg(n) || BadReg(m))1516return false;15171518break;15191520case eEncodingA1:1521// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');1522d = Bits32(opcode, 19, 16);1523n = Bits32(opcode, 3, 0);1524m = Bits32(opcode, 11, 8);1525setflags = BitIsSet(opcode, 20);15261527// if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;1528if ((d == 15) || (n == 15) || (m == 15))1529return false;15301531// if ArchVersion() < 6 && d == n then UNPREDICTABLE;1532if ((ArchVersion() < ARMv6) && (d == n))1533return false;15341535break;15361537default:1538return false;1539}15401541bool success = false;15421543// operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final1544// results1545uint64_t operand1 =1546ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);1547if (!success)1548return false;15491550// operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final1551// results1552uint64_t operand2 =1553ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);1554if (!success)1555return false;15561557// result = operand1 * operand2;1558uint64_t result = operand1 * operand2;15591560// R[d] = result<31:0>;1561std::optional<RegisterInfo> op1_reg =1562GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);1563std::optional<RegisterInfo> op2_reg =1564GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);15651566EmulateInstruction::Context context;1567context.type = eContextArithmetic;1568context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);15691570if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,1571(0x0000ffff & result)))1572return false;15731574// if setflags then1575if (setflags) {1576// APSR.N = result<31>;1577// APSR.Z = IsZeroBit(result);1578m_new_inst_cpsr = m_opcode_cpsr;1579SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31));1580SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);1581if (m_new_inst_cpsr != m_opcode_cpsr) {1582if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,1583LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))1584return false;1585}15861587// if ArchVersion() == 4 then1588// APSR.C = bit UNKNOWN;1589}1590}1591return true;1592}15931594// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to1595// the destination register. It can optionally update the condition flags based1596// on the value.1597bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,1598const ARMEncoding encoding) {1599#if 01600// ARM pseudo code...1601if (ConditionPassed())1602{1603EncodingSpecificOperations();1604result = NOT(imm32);1605if d == 15 then // Can only occur for ARM encoding1606ALUWritePC(result); // setflags is always FALSE here1607else1608R[d] = result;1609if setflags then1610APSR.N = result<31>;1611APSR.Z = IsZeroBit(result);1612APSR.C = carry;1613// APSR.V unchanged1614}1615#endif16161617if (ConditionPassed(opcode)) {1618uint32_t Rd; // the destination register1619uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C1620uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C1621bool setflags;1622switch (encoding) {1623case eEncodingT1:1624Rd = Bits32(opcode, 11, 8);1625setflags = BitIsSet(opcode, 20);1626imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);1627break;1628case eEncodingA1:1629Rd = Bits32(opcode, 15, 12);1630setflags = BitIsSet(opcode, 20);1631imm32 = ARMExpandImm_C(opcode, APSR_C, carry);16321633// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related1634// instructions;1635if (Rd == 15 && setflags)1636return EmulateSUBSPcLrEtc(opcode, encoding);1637break;1638default:1639return false;1640}1641uint32_t result = ~imm32;16421643// The context specifies that an immediate is to be moved into Rd.1644EmulateInstruction::Context context;1645context.type = EmulateInstruction::eContextImmediate;1646context.SetNoArgs();16471648if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))1649return false;1650}1651return true;1652}16531654// Bitwise NOT (register) writes the bitwise inverse of a register value to the1655// destination register. It can optionally update the condition flags based on1656// the result.1657bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,1658const ARMEncoding encoding) {1659#if 01660// ARM pseudo code...1661if (ConditionPassed())1662{1663EncodingSpecificOperations();1664(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);1665result = NOT(shifted);1666if d == 15 then // Can only occur for ARM encoding1667ALUWritePC(result); // setflags is always FALSE here1668else1669R[d] = result;1670if setflags then1671APSR.N = result<31>;1672APSR.Z = IsZeroBit(result);1673APSR.C = carry;1674// APSR.V unchanged1675}1676#endif16771678if (ConditionPassed(opcode)) {1679uint32_t Rm; // the source register1680uint32_t Rd; // the destination register1681ARM_ShifterType shift_t;1682uint32_t shift_n; // the shift applied to the value read from Rm1683bool setflags;1684uint32_t carry; // the carry bit after the shift operation1685switch (encoding) {1686case eEncodingT1:1687Rd = Bits32(opcode, 2, 0);1688Rm = Bits32(opcode, 5, 3);1689setflags = !InITBlock();1690shift_t = SRType_LSL;1691shift_n = 0;1692if (InITBlock())1693return false;1694break;1695case eEncodingT2:1696Rd = Bits32(opcode, 11, 8);1697Rm = Bits32(opcode, 3, 0);1698setflags = BitIsSet(opcode, 20);1699shift_n = DecodeImmShiftThumb(opcode, shift_t);1700// if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;1701if (BadReg(Rd) || BadReg(Rm))1702return false;1703break;1704case eEncodingA1:1705Rd = Bits32(opcode, 15, 12);1706Rm = Bits32(opcode, 3, 0);1707setflags = BitIsSet(opcode, 20);1708shift_n = DecodeImmShiftARM(opcode, shift_t);1709break;1710default:1711return false;1712}1713bool success = false;1714uint32_t value = ReadCoreReg(Rm, &success);1715if (!success)1716return false;17171718uint32_t shifted =1719Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);1720if (!success)1721return false;1722uint32_t result = ~shifted;17231724// The context specifies that an immediate is to be moved into Rd.1725EmulateInstruction::Context context;1726context.type = EmulateInstruction::eContextImmediate;1727context.SetNoArgs();17281729if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))1730return false;1731}1732return true;1733}17341735// PC relative immediate load into register, possibly followed by ADD (SP plus1736// register).1737// LDR (literal)1738bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode,1739const ARMEncoding encoding) {1740#if 01741// ARM pseudo code...1742if (ConditionPassed())1743{1744EncodingSpecificOperations(); NullCheckIfThumbEE(15);1745base = Align(PC,4);1746address = if add then (base + imm32) else (base - imm32);1747data = MemU[address,4];1748if t == 15 then1749if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;1750elsif UnalignedSupport() || address<1:0> = '00' then1751R[t] = data;1752else // Can only apply before ARMv71753if CurrentInstrSet() == InstrSet_ARM then1754R[t] = ROR(data, 8*UInt(address<1:0>));1755else1756R[t] = bits(32) UNKNOWN;1757}1758#endif17591760if (ConditionPassed(opcode)) {1761bool success = false;1762const uint32_t pc = ReadCoreReg(PC_REG, &success);1763if (!success)1764return false;17651766// PC relative immediate load context1767EmulateInstruction::Context context;1768context.type = EmulateInstruction::eContextRegisterPlusOffset;1769std::optional<RegisterInfo> pc_reg =1770GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);1771context.SetRegisterPlusOffset(*pc_reg, 0);17721773uint32_t Rt; // the destination register1774uint32_t imm32; // immediate offset from the PC1775bool add; // +imm32 or -imm32?1776addr_t base; // the base address1777addr_t address; // the PC relative address1778uint32_t data; // the literal data value from the PC relative load1779switch (encoding) {1780case eEncodingT1:1781Rt = Bits32(opcode, 10, 8);1782imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);1783add = true;1784break;1785case eEncodingT2:1786Rt = Bits32(opcode, 15, 12);1787imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);1788add = BitIsSet(opcode, 23);1789if (Rt == 15 && InITBlock() && !LastInITBlock())1790return false;1791break;1792default:1793return false;1794}17951796base = Align(pc, 4);1797if (add)1798address = base + imm32;1799else1800address = base - imm32;18011802context.SetRegisterPlusOffset(*pc_reg, address - base);1803data = MemURead(context, address, 4, 0, &success);1804if (!success)1805return false;18061807if (Rt == 15) {1808if (Bits32(address, 1, 0) == 0) {1809// In ARMv5T and above, this is an interworking branch.1810if (!LoadWritePC(context, data))1811return false;1812} else1813return false;1814} else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {1815if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,1816data))1817return false;1818} else // We don't handle ARM for now.1819return false;1820}1821return true;1822}18231824// An add operation to adjust the SP.1825// ADD (SP plus immediate)1826bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode,1827const ARMEncoding encoding) {1828#if 01829// ARM pseudo code...1830if (ConditionPassed())1831{1832EncodingSpecificOperations();1833(result, carry, overflow) = AddWithCarry(SP, imm32, '0');1834if d == 15 then // Can only occur for ARM encoding1835ALUWritePC(result); // setflags is always FALSE here1836else1837R[d] = result;1838if setflags then1839APSR.N = result<31>;1840APSR.Z = IsZeroBit(result);1841APSR.C = carry;1842APSR.V = overflow;1843}1844#endif18451846bool success = false;18471848if (ConditionPassed(opcode)) {1849const addr_t sp = ReadCoreReg(SP_REG, &success);1850if (!success)1851return false;1852uint32_t imm32; // the immediate operand1853uint32_t d;1854bool setflags;1855switch (encoding) {1856case eEncodingT1:1857// d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);1858d = Bits32(opcode, 10, 8);1859imm32 = (Bits32(opcode, 7, 0) << 2);1860setflags = false;1861break;18621863case eEncodingT2:1864// d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);1865d = 13;1866imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)1867setflags = false;1868break;18691870case eEncodingT3:1871// d = UInt(Rd); setflags = (S == "1"); imm32 =1872// ThumbExpandImm(i:imm3:imm8);1873d = Bits32(opcode, 11, 8);1874imm32 = ThumbExpandImm(opcode);1875setflags = Bit32(opcode, 20);18761877// if Rd == "1111" && S == "1" then SEE CMN (immediate);1878if (d == 15 && setflags == 1)1879return false; // CMN (immediate) not yet supported18801881// if d == 15 && S == "0" then UNPREDICTABLE;1882if (d == 15 && setflags == 0)1883return false;1884break;18851886case eEncodingT4: {1887// if Rn == '1111' then SEE ADR;1888// d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);1889d = Bits32(opcode, 11, 8);1890setflags = false;1891uint32_t i = Bit32(opcode, 26);1892uint32_t imm3 = Bits32(opcode, 14, 12);1893uint32_t imm8 = Bits32(opcode, 7, 0);1894imm32 = (i << 11) | (imm3 << 8) | imm8;18951896// if d == 15 then UNPREDICTABLE;1897if (d == 15)1898return false;1899} break;19001901default:1902return false;1903}1904// (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');1905AddWithCarryResult res = AddWithCarry(sp, imm32, 0);19061907EmulateInstruction::Context context;1908if (d == 13)1909context.type = EmulateInstruction::eContextAdjustStackPointer;1910else1911context.type = EmulateInstruction::eContextRegisterPlusOffset;19121913std::optional<RegisterInfo> sp_reg =1914GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);1915context.SetRegisterPlusOffset(*sp_reg, res.result - sp);19161917if (d == 15) {1918if (!ALUWritePC(context, res.result))1919return false;1920} else {1921// R[d] = result;1922// if setflags then1923// APSR.N = result<31>;1924// APSR.Z = IsZeroBit(result);1925// APSR.C = carry;1926// APSR.V = overflow;1927if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,1928res.carry_out, res.overflow))1929return false;1930}1931}1932return true;1933}19341935// An add operation to adjust the SP.1936// ADD (SP plus register)1937bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,1938const ARMEncoding encoding) {1939#if 01940// ARM pseudo code...1941if (ConditionPassed())1942{1943EncodingSpecificOperations();1944shifted = Shift(R[m], shift_t, shift_n, APSR.C);1945(result, carry, overflow) = AddWithCarry(SP, shifted, '0');1946if d == 15 then1947ALUWritePC(result); // setflags is always FALSE here1948else1949R[d] = result;1950if setflags then1951APSR.N = result<31>;1952APSR.Z = IsZeroBit(result);1953APSR.C = carry;1954APSR.V = overflow;1955}1956#endif19571958bool success = false;19591960if (ConditionPassed(opcode)) {1961const addr_t sp = ReadCoreReg(SP_REG, &success);1962if (!success)1963return false;1964uint32_t Rm; // the second operand1965switch (encoding) {1966case eEncodingT2:1967Rm = Bits32(opcode, 6, 3);1968break;1969default:1970return false;1971}1972int32_t reg_value = ReadCoreReg(Rm, &success);1973if (!success)1974return false;19751976addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value19771978EmulateInstruction::Context context;1979context.type = eContextArithmetic;1980std::optional<RegisterInfo> sp_reg =1981GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);1982std::optional<RegisterInfo> other_reg =1983GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);1984context.SetRegisterRegisterOperands(*sp_reg, *other_reg);19851986if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,1987LLDB_REGNUM_GENERIC_SP, addr))1988return false;1989}1990return true;1991}19921993// Branch with Link and Exchange Instruction Sets (immediate) calls a1994// subroutine at a PC-relative address, and changes instruction set from ARM to1995// Thumb, or from Thumb to ARM.1996// BLX (immediate)1997bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,1998const ARMEncoding encoding) {1999#if 02000// ARM pseudo code...2001if (ConditionPassed())2002{2003EncodingSpecificOperations();2004if CurrentInstrSet() == InstrSet_ARM then2005LR = PC - 4;2006else2007LR = PC<31:1> : '1';2008if targetInstrSet == InstrSet_ARM then2009targetAddress = Align(PC,4) + imm32;2010else2011targetAddress = PC + imm32;2012SelectInstrSet(targetInstrSet);2013BranchWritePC(targetAddress);2014}2015#endif20162017bool success = true;20182019if (ConditionPassed(opcode)) {2020EmulateInstruction::Context context;2021context.type = EmulateInstruction::eContextRelativeBranchImmediate;2022const uint32_t pc = ReadCoreReg(PC_REG, &success);2023if (!success)2024return false;2025addr_t lr; // next instruction address2026addr_t target; // target address2027int32_t imm32; // PC-relative offset2028switch (encoding) {2029case eEncodingT1: {2030lr = pc | 1u; // return address2031uint32_t S = Bit32(opcode, 26);2032uint32_t imm10 = Bits32(opcode, 25, 16);2033uint32_t J1 = Bit32(opcode, 13);2034uint32_t J2 = Bit32(opcode, 11);2035uint32_t imm11 = Bits32(opcode, 10, 0);2036uint32_t I1 = !(J1 ^ S);2037uint32_t I2 = !(J2 ^ S);2038uint32_t imm25 =2039(S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);2040imm32 = llvm::SignExtend32<25>(imm25);2041target = pc + imm32;2042SelectInstrSet(eModeThumb);2043context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2044if (InITBlock() && !LastInITBlock())2045return false;2046break;2047}2048case eEncodingT2: {2049lr = pc | 1u; // return address2050uint32_t S = Bit32(opcode, 26);2051uint32_t imm10H = Bits32(opcode, 25, 16);2052uint32_t J1 = Bit32(opcode, 13);2053uint32_t J2 = Bit32(opcode, 11);2054uint32_t imm10L = Bits32(opcode, 10, 1);2055uint32_t I1 = !(J1 ^ S);2056uint32_t I2 = !(J2 ^ S);2057uint32_t imm25 =2058(S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);2059imm32 = llvm::SignExtend32<25>(imm25);2060target = Align(pc, 4) + imm32;2061SelectInstrSet(eModeARM);2062context.SetISAAndImmediateSigned(eModeARM, 4 + imm32);2063if (InITBlock() && !LastInITBlock())2064return false;2065break;2066}2067case eEncodingA1:2068lr = pc - 4; // return address2069imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);2070target = Align(pc, 4) + imm32;2071SelectInstrSet(eModeARM);2072context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);2073break;2074case eEncodingA2:2075lr = pc - 4; // return address2076imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 |2077Bits32(opcode, 24, 24) << 1);2078target = pc + imm32;2079SelectInstrSet(eModeThumb);2080context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32);2081break;2082default:2083return false;2084}2085if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2086LLDB_REGNUM_GENERIC_RA, lr))2087return false;2088if (!BranchWritePC(context, target))2089return false;2090if (m_opcode_cpsr != m_new_inst_cpsr)2091if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2092LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))2093return false;2094}2095return true;2096}20972098// Branch with Link and Exchange (register) calls a subroutine at an address2099// and instruction set specified by a register.2100// BLX (register)2101bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,2102const ARMEncoding encoding) {2103#if 02104// ARM pseudo code...2105if (ConditionPassed())2106{2107EncodingSpecificOperations();2108target = R[m];2109if CurrentInstrSet() == InstrSet_ARM then2110next_instr_addr = PC - 4;2111LR = next_instr_addr;2112else2113next_instr_addr = PC - 2;2114LR = next_instr_addr<31:1> : '1';2115BXWritePC(target);2116}2117#endif21182119bool success = false;21202121if (ConditionPassed(opcode)) {2122EmulateInstruction::Context context;2123context.type = EmulateInstruction::eContextAbsoluteBranchRegister;2124const uint32_t pc = ReadCoreReg(PC_REG, &success);2125addr_t lr; // next instruction address2126if (!success)2127return false;2128uint32_t Rm; // the register with the target address2129switch (encoding) {2130case eEncodingT1:2131lr = (pc - 2) | 1u; // return address2132Rm = Bits32(opcode, 6, 3);2133// if m == 15 then UNPREDICTABLE;2134if (Rm == 15)2135return false;2136if (InITBlock() && !LastInITBlock())2137return false;2138break;2139case eEncodingA1:2140lr = pc - 4; // return address2141Rm = Bits32(opcode, 3, 0);2142// if m == 15 then UNPREDICTABLE;2143if (Rm == 15)2144return false;2145break;2146default:2147return false;2148}2149addr_t target = ReadCoreReg(Rm, &success);2150if (!success)2151return false;2152std::optional<RegisterInfo> dwarf_reg =2153GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);2154context.SetRegister(*dwarf_reg);2155if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2156LLDB_REGNUM_GENERIC_RA, lr))2157return false;2158if (!BXWritePC(context, target))2159return false;2160}2161return true;2162}21632164// Branch and Exchange causes a branch to an address and instruction set2165// specified by a register.2166bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,2167const ARMEncoding encoding) {2168#if 02169// ARM pseudo code...2170if (ConditionPassed())2171{2172EncodingSpecificOperations();2173BXWritePC(R[m]);2174}2175#endif21762177if (ConditionPassed(opcode)) {2178EmulateInstruction::Context context;2179context.type = EmulateInstruction::eContextAbsoluteBranchRegister;2180uint32_t Rm; // the register with the target address2181switch (encoding) {2182case eEncodingT1:2183Rm = Bits32(opcode, 6, 3);2184if (InITBlock() && !LastInITBlock())2185return false;2186break;2187case eEncodingA1:2188Rm = Bits32(opcode, 3, 0);2189break;2190default:2191return false;2192}2193bool success = false;2194addr_t target = ReadCoreReg(Rm, &success);2195if (!success)2196return false;21972198std::optional<RegisterInfo> dwarf_reg =2199GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);2200context.SetRegister(*dwarf_reg);2201if (!BXWritePC(context, target))2202return false;2203}2204return true;2205}22062207// Branch and Exchange Jazelle attempts to change to Jazelle state. If the2208// attempt fails, it branches to an address and instruction set specified by a2209// register as though it were a BX instruction.2210//2211// TODO: Emulate Jazelle architecture?2212// We currently assume that switching to Jazelle state fails, thus2213// treating BXJ as a BX operation.2214bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,2215const ARMEncoding encoding) {2216#if 02217// ARM pseudo code...2218if (ConditionPassed())2219{2220EncodingSpecificOperations();2221if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then2222BXWritePC(R[m]);2223else2224if JazelleAcceptsExecution() then2225SwitchToJazelleExecution();2226else2227SUBARCHITECTURE_DEFINED handler call;2228}2229#endif22302231if (ConditionPassed(opcode)) {2232EmulateInstruction::Context context;2233context.type = EmulateInstruction::eContextAbsoluteBranchRegister;2234uint32_t Rm; // the register with the target address2235switch (encoding) {2236case eEncodingT1:2237Rm = Bits32(opcode, 19, 16);2238if (BadReg(Rm))2239return false;2240if (InITBlock() && !LastInITBlock())2241return false;2242break;2243case eEncodingA1:2244Rm = Bits32(opcode, 3, 0);2245if (Rm == 15)2246return false;2247break;2248default:2249return false;2250}2251bool success = false;2252addr_t target = ReadCoreReg(Rm, &success);2253if (!success)2254return false;22552256std::optional<RegisterInfo> dwarf_reg =2257GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);2258context.SetRegister(*dwarf_reg);2259if (!BXWritePC(context, target))2260return false;2261}2262return true;2263}22642265// Set r7 to point to some ip offset.2266// SUB (immediate)2267bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,2268const ARMEncoding encoding) {2269#if 02270// ARM pseudo code...2271if (ConditionPassed())2272{2273EncodingSpecificOperations();2274(result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');2275if d == 15 then // Can only occur for ARM encoding2276ALUWritePC(result); // setflags is always FALSE here2277else2278R[d] = result;2279if setflags then2280APSR.N = result<31>;2281APSR.Z = IsZeroBit(result);2282APSR.C = carry;2283APSR.V = overflow;2284}2285#endif22862287if (ConditionPassed(opcode)) {2288bool success = false;2289const addr_t ip = ReadCoreReg(12, &success);2290if (!success)2291return false;2292uint32_t imm32;2293switch (encoding) {2294case eEncodingA1:2295imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)2296break;2297default:2298return false;2299}2300addr_t ip_offset = imm32;2301addr_t addr = ip - ip_offset; // the adjusted ip value23022303EmulateInstruction::Context context;2304context.type = EmulateInstruction::eContextRegisterPlusOffset;2305std::optional<RegisterInfo> dwarf_reg =2306GetRegisterInfo(eRegisterKindDWARF, dwarf_r12);2307context.SetRegisterPlusOffset(*dwarf_reg, -ip_offset);23082309if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr))2310return false;2311}2312return true;2313}23142315// Set ip to point to some stack offset.2316// SUB (SP minus immediate)2317bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,2318const ARMEncoding encoding) {2319#if 02320// ARM pseudo code...2321if (ConditionPassed())2322{2323EncodingSpecificOperations();2324(result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');2325if d == 15 then // Can only occur for ARM encoding2326ALUWritePC(result); // setflags is always FALSE here2327else2328R[d] = result;2329if setflags then2330APSR.N = result<31>;2331APSR.Z = IsZeroBit(result);2332APSR.C = carry;2333APSR.V = overflow;2334}2335#endif23362337if (ConditionPassed(opcode)) {2338bool success = false;2339const addr_t sp = ReadCoreReg(SP_REG, &success);2340if (!success)2341return false;2342uint32_t imm32;2343switch (encoding) {2344case eEncodingA1:2345imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)2346break;2347default:2348return false;2349}2350addr_t sp_offset = imm32;2351addr_t addr = sp - sp_offset; // the adjusted stack pointer value23522353EmulateInstruction::Context context;2354context.type = EmulateInstruction::eContextRegisterPlusOffset;2355std::optional<RegisterInfo> dwarf_reg =2356GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);2357context.SetRegisterPlusOffset(*dwarf_reg, -sp_offset);23582359if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr))2360return false;2361}2362return true;2363}23642365// This instruction subtracts an immediate value from the SP value, and writes2366// the result to the destination register.2367//2368// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local2369// storage.2370bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,2371const ARMEncoding encoding) {2372#if 02373// ARM pseudo code...2374if (ConditionPassed())2375{2376EncodingSpecificOperations();2377(result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');2378if d == 15 then // Can only occur for ARM encoding2379ALUWritePC(result); // setflags is always FALSE here2380else2381R[d] = result;2382if setflags then2383APSR.N = result<31>;2384APSR.Z = IsZeroBit(result);2385APSR.C = carry;2386APSR.V = overflow;2387}2388#endif23892390bool success = false;2391if (ConditionPassed(opcode)) {2392const addr_t sp = ReadCoreReg(SP_REG, &success);2393if (!success)2394return false;23952396uint32_t Rd;2397bool setflags;2398uint32_t imm32;2399switch (encoding) {2400case eEncodingT1:2401Rd = 13;2402setflags = false;2403imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)2404break;2405case eEncodingT2:2406Rd = Bits32(opcode, 11, 8);2407setflags = BitIsSet(opcode, 20);2408imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)2409if (Rd == 15 && setflags)2410return EmulateCMPImm(opcode, eEncodingT2);2411if (Rd == 15 && !setflags)2412return false;2413break;2414case eEncodingT3:2415Rd = Bits32(opcode, 11, 8);2416setflags = false;2417imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)2418if (Rd == 15)2419return false;2420break;2421case eEncodingA1:2422Rd = Bits32(opcode, 15, 12);2423setflags = BitIsSet(opcode, 20);2424imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)24252426// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related2427// instructions;2428if (Rd == 15 && setflags)2429return EmulateSUBSPcLrEtc(opcode, encoding);2430break;2431default:2432return false;2433}2434AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);24352436EmulateInstruction::Context context;2437if (Rd == 13) {2438uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting2439// to negate it, or the wrong2440// value gets passed down to context.SetImmediateSigned.2441context.type = EmulateInstruction::eContextAdjustStackPointer;2442context.SetImmediateSigned(-imm64); // the stack pointer offset2443} else {2444context.type = EmulateInstruction::eContextImmediate;2445context.SetNoArgs();2446}24472448if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,2449res.carry_out, res.overflow))2450return false;2451}2452return true;2453}24542455// A store operation to the stack that also updates the SP.2456bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,2457const ARMEncoding encoding) {2458#if 02459// ARM pseudo code...2460if (ConditionPassed())2461{2462EncodingSpecificOperations();2463offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);2464address = if index then offset_addr else R[n];2465MemU[address,4] = if t == 15 then PCStoreValue() else R[t];2466if wback then R[n] = offset_addr;2467}2468#endif24692470bool success = false;2471if (ConditionPassed(opcode)) {2472const uint32_t addr_byte_size = GetAddressByteSize();2473const addr_t sp = ReadCoreReg(SP_REG, &success);2474if (!success)2475return false;2476uint32_t Rt; // the source register2477uint32_t imm12;2478uint32_t2479Rn; // This function assumes Rn is the SP, but we should verify that.24802481bool index;2482bool add;2483bool wback;2484switch (encoding) {2485case eEncodingA1:2486Rt = Bits32(opcode, 15, 12);2487imm12 = Bits32(opcode, 11, 0);2488Rn = Bits32(opcode, 19, 16);24892490if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP.2491return false;24922493index = BitIsSet(opcode, 24);2494add = BitIsSet(opcode, 23);2495wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));24962497if (wback && ((Rn == 15) || (Rn == Rt)))2498return false;2499break;2500default:2501return false;2502}2503addr_t offset_addr;2504if (add)2505offset_addr = sp + imm12;2506else2507offset_addr = sp - imm12;25082509addr_t addr;2510if (index)2511addr = offset_addr;2512else2513addr = sp;25142515EmulateInstruction::Context context;2516context.type = EmulateInstruction::eContextPushRegisterOnStack;2517std::optional<RegisterInfo> sp_reg =2518GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);2519std::optional<RegisterInfo> dwarf_reg =2520GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt);25212522context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);2523if (Rt != 15) {2524uint32_t reg_value = ReadCoreReg(Rt, &success);2525if (!success)2526return false;2527if (!MemUWrite(context, addr, reg_value, addr_byte_size))2528return false;2529} else {2530const uint32_t pc = ReadCoreReg(PC_REG, &success);2531if (!success)2532return false;2533if (!MemUWrite(context, addr, pc, addr_byte_size))2534return false;2535}25362537if (wback) {2538context.type = EmulateInstruction::eContextAdjustStackPointer;2539context.SetImmediateSigned(addr - sp);2540if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2541LLDB_REGNUM_GENERIC_SP, offset_addr))2542return false;2543}2544}2545return true;2546}25472548// Vector Push stores multiple extension registers to the stack. It also2549// updates SP to point to the start of the stored data.2550bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,2551const ARMEncoding encoding) {2552#if 02553// ARM pseudo code...2554if (ConditionPassed())2555{2556EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);2557address = SP - imm32;2558SP = SP - imm32;2559if single_regs then2560for r = 0 to regs-12561MemA[address,4] = S[d+r]; address = address+4;2562else2563for r = 0 to regs-12564// Store as two word-aligned words in the correct order for2565// current endianness.2566MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;2567MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;2568address = address+8;2569}2570#endif25712572bool success = false;2573if (ConditionPassed(opcode)) {2574const uint32_t addr_byte_size = GetAddressByteSize();2575const addr_t sp = ReadCoreReg(SP_REG, &success);2576if (!success)2577return false;2578bool single_regs;2579uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register2580uint32_t imm32; // stack offset2581uint32_t regs; // number of registers2582switch (encoding) {2583case eEncodingT1:2584case eEncodingA1:2585single_regs = false;2586d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);2587imm32 = Bits32(opcode, 7, 0) * addr_byte_size;2588// If UInt(imm8) is odd, see "FSTMX".2589regs = Bits32(opcode, 7, 0) / 2;2590// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;2591if (regs == 0 || regs > 16 || (d + regs) > 32)2592return false;2593break;2594case eEncodingT2:2595case eEncodingA2:2596single_regs = true;2597d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);2598imm32 = Bits32(opcode, 7, 0) * addr_byte_size;2599regs = Bits32(opcode, 7, 0);2600// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;2601if (regs == 0 || regs > 16 || (d + regs) > 32)2602return false;2603break;2604default:2605return false;2606}2607uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;2608uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;2609addr_t sp_offset = imm32;2610addr_t addr = sp - sp_offset;2611uint32_t i;26122613EmulateInstruction::Context context;2614context.type = EmulateInstruction::eContextPushRegisterOnStack;26152616std::optional<RegisterInfo> sp_reg =2617GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);2618for (i = 0; i < regs; ++i) {2619std::optional<RegisterInfo> dwarf_reg =2620GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);2621context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);2622// uint64_t to accommodate 64-bit registers.2623uint64_t reg_value = ReadRegisterUnsigned(*dwarf_reg, 0, &success);2624if (!success)2625return false;2626if (!MemAWrite(context, addr, reg_value, reg_byte_size))2627return false;2628addr += reg_byte_size;2629}26302631context.type = EmulateInstruction::eContextAdjustStackPointer;2632context.SetImmediateSigned(-sp_offset);26332634if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2635LLDB_REGNUM_GENERIC_SP, sp - sp_offset))2636return false;2637}2638return true;2639}26402641// Vector Pop loads multiple extension registers from the stack. It also2642// updates SP to point just above the loaded data.2643bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,2644const ARMEncoding encoding) {2645#if 02646// ARM pseudo code...2647if (ConditionPassed())2648{2649EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);2650address = SP;2651SP = SP + imm32;2652if single_regs then2653for r = 0 to regs-12654S[d+r] = MemA[address,4]; address = address+4;2655else2656for r = 0 to regs-12657word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;2658// Combine the word-aligned words in the correct order for2659// current endianness.2660D[d+r] = if BigEndian() then word1:word2 else word2:word1;2661}2662#endif26632664bool success = false;2665if (ConditionPassed(opcode)) {2666const uint32_t addr_byte_size = GetAddressByteSize();2667const addr_t sp = ReadCoreReg(SP_REG, &success);2668if (!success)2669return false;2670bool single_regs;2671uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register2672uint32_t imm32; // stack offset2673uint32_t regs; // number of registers2674switch (encoding) {2675case eEncodingT1:2676case eEncodingA1:2677single_regs = false;2678d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);2679imm32 = Bits32(opcode, 7, 0) * addr_byte_size;2680// If UInt(imm8) is odd, see "FLDMX".2681regs = Bits32(opcode, 7, 0) / 2;2682// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;2683if (regs == 0 || regs > 16 || (d + regs) > 32)2684return false;2685break;2686case eEncodingT2:2687case eEncodingA2:2688single_regs = true;2689d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);2690imm32 = Bits32(opcode, 7, 0) * addr_byte_size;2691regs = Bits32(opcode, 7, 0);2692// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;2693if (regs == 0 || regs > 16 || (d + regs) > 32)2694return false;2695break;2696default:2697return false;2698}2699uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;2700uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;2701addr_t sp_offset = imm32;2702addr_t addr = sp;2703uint32_t i;2704uint64_t data; // uint64_t to accommodate 64-bit registers.27052706EmulateInstruction::Context context;2707context.type = EmulateInstruction::eContextPopRegisterOffStack;27082709for (i = 0; i < regs; ++i) {2710std::optional<RegisterInfo> dwarf_reg =2711GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);2712context.SetAddress(addr);2713data = MemARead(context, addr, reg_byte_size, 0, &success);2714if (!success)2715return false;2716if (!WriteRegisterUnsigned(context, *dwarf_reg, data))2717return false;2718addr += reg_byte_size;2719}27202721context.type = EmulateInstruction::eContextAdjustStackPointer;2722context.SetImmediateSigned(sp_offset);27232724if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2725LLDB_REGNUM_GENERIC_SP, sp + sp_offset))2726return false;2727}2728return true;2729}27302731// SVC (previously SWI)2732bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode,2733const ARMEncoding encoding) {2734#if 02735// ARM pseudo code...2736if (ConditionPassed())2737{2738EncodingSpecificOperations();2739CallSupervisor();2740}2741#endif27422743bool success = false;27442745if (ConditionPassed(opcode)) {2746const uint32_t pc = ReadCoreReg(PC_REG, &success);2747addr_t lr; // next instruction address2748if (!success)2749return false;2750uint32_t imm32; // the immediate constant2751uint32_t mode; // ARM or Thumb mode2752switch (encoding) {2753case eEncodingT1:2754lr = (pc + 2) | 1u; // return address2755imm32 = Bits32(opcode, 7, 0);2756mode = eModeThumb;2757break;2758case eEncodingA1:2759lr = pc + 4; // return address2760imm32 = Bits32(opcode, 23, 0);2761mode = eModeARM;2762break;2763default:2764return false;2765}27662767EmulateInstruction::Context context;2768context.type = EmulateInstruction::eContextSupervisorCall;2769context.SetISAAndImmediate(mode, imm32);2770if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2771LLDB_REGNUM_GENERIC_RA, lr))2772return false;2773}2774return true;2775}27762777// If Then makes up to four following instructions (the IT block) conditional.2778bool EmulateInstructionARM::EmulateIT(const uint32_t opcode,2779const ARMEncoding encoding) {2780#if 02781// ARM pseudo code...2782EncodingSpecificOperations();2783ITSTATE.IT<7:0> = firstcond:mask;2784#endif27852786m_it_session.InitIT(Bits32(opcode, 7, 0));2787return true;2788}27892790bool EmulateInstructionARM::EmulateNop(const uint32_t opcode,2791const ARMEncoding encoding) {2792// NOP, nothing to do...2793return true;2794}27952796// Branch causes a branch to a target address.2797bool EmulateInstructionARM::EmulateB(const uint32_t opcode,2798const ARMEncoding encoding) {2799#if 02800// ARM pseudo code...2801if (ConditionPassed())2802{2803EncodingSpecificOperations();2804BranchWritePC(PC + imm32);2805}2806#endif28072808bool success = false;28092810if (ConditionPassed(opcode)) {2811EmulateInstruction::Context context;2812context.type = EmulateInstruction::eContextRelativeBranchImmediate;2813const uint32_t pc = ReadCoreReg(PC_REG, &success);2814if (!success)2815return false;2816addr_t target; // target address2817int32_t imm32; // PC-relative offset2818switch (encoding) {2819case eEncodingT1:2820// The 'cond' field is handled in EmulateInstructionARM::CurrentCond().2821imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);2822target = pc + imm32;2823context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2824break;2825case eEncodingT2:2826imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1);2827target = pc + imm32;2828context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2829break;2830case eEncodingT3:2831// The 'cond' field is handled in EmulateInstructionARM::CurrentCond().2832{2833if (Bits32(opcode, 25, 23) == 7)2834return false; // See Branches and miscellaneous control on page2835// A6-235.28362837uint32_t S = Bit32(opcode, 26);2838uint32_t imm6 = Bits32(opcode, 21, 16);2839uint32_t J1 = Bit32(opcode, 13);2840uint32_t J2 = Bit32(opcode, 11);2841uint32_t imm11 = Bits32(opcode, 10, 0);2842uint32_t imm21 =2843(S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);2844imm32 = llvm::SignExtend32<21>(imm21);2845target = pc + imm32;2846context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2847break;2848}2849case eEncodingT4: {2850uint32_t S = Bit32(opcode, 26);2851uint32_t imm10 = Bits32(opcode, 25, 16);2852uint32_t J1 = Bit32(opcode, 13);2853uint32_t J2 = Bit32(opcode, 11);2854uint32_t imm11 = Bits32(opcode, 10, 0);2855uint32_t I1 = !(J1 ^ S);2856uint32_t I2 = !(J2 ^ S);2857uint32_t imm25 =2858(S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);2859imm32 = llvm::SignExtend32<25>(imm25);2860target = pc + imm32;2861context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2862break;2863}2864case eEncodingA1:2865imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);2866target = pc + imm32;2867context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);2868break;2869default:2870return false;2871}2872if (!BranchWritePC(context, target))2873return false;2874}2875return true;2876}28772878// Compare and Branch on Nonzero and Compare and Branch on Zero compare the2879// value in a register with zero and conditionally branch forward a constant2880// value. They do not affect the condition flags. CBNZ, CBZ2881bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,2882const ARMEncoding encoding) {2883#if 02884// ARM pseudo code...2885EncodingSpecificOperations();2886if nonzero ^ IsZero(R[n]) then2887BranchWritePC(PC + imm32);2888#endif28892890bool success = false;28912892// Read the register value from the operand register Rn.2893uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);2894if (!success)2895return false;28962897EmulateInstruction::Context context;2898context.type = EmulateInstruction::eContextRelativeBranchImmediate;2899const uint32_t pc = ReadCoreReg(PC_REG, &success);2900if (!success)2901return false;29022903addr_t target; // target address2904uint32_t imm32; // PC-relative offset to branch forward2905bool nonzero;2906switch (encoding) {2907case eEncodingT1:2908imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;2909nonzero = BitIsSet(opcode, 11);2910target = pc + imm32;2911context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2912break;2913default:2914return false;2915}2916if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))2917if (!BranchWritePC(context, target))2918return false;29192920return true;2921}29222923// Table Branch Byte causes a PC-relative forward branch using a table of2924// single byte offsets.2925// A base register provides a pointer to the table, and a second register2926// supplies an index into the table.2927// The branch length is twice the value of the byte returned from the table.2928//2929// Table Branch Halfword causes a PC-relative forward branch using a table of2930// single halfword offsets.2931// A base register provides a pointer to the table, and a second register2932// supplies an index into the table.2933// The branch length is twice the value of the halfword returned from the2934// table. TBB, TBH2935bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,2936const ARMEncoding encoding) {2937#if 02938// ARM pseudo code...2939EncodingSpecificOperations(); NullCheckIfThumbEE(n);2940if is_tbh then2941halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);2942else2943halfwords = UInt(MemU[R[n]+R[m], 1]);2944BranchWritePC(PC + 2*halfwords);2945#endif29462947bool success = false;29482949if (ConditionPassed(opcode)) {2950uint32_t Rn; // the base register which contains the address of the table of2951// branch lengths2952uint32_t Rm; // the index register which contains an integer pointing to a2953// byte/halfword in the table2954bool is_tbh; // true if table branch halfword2955switch (encoding) {2956case eEncodingT1:2957Rn = Bits32(opcode, 19, 16);2958Rm = Bits32(opcode, 3, 0);2959is_tbh = BitIsSet(opcode, 4);2960if (Rn == 13 || BadReg(Rm))2961return false;2962if (InITBlock() && !LastInITBlock())2963return false;2964break;2965default:2966return false;2967}29682969// Read the address of the table from the operand register Rn. The PC can2970// be used, in which case the table immediately follows this instruction.2971uint32_t base = ReadCoreReg(Rn, &success);2972if (!success)2973return false;29742975// the table index2976uint32_t index = ReadCoreReg(Rm, &success);2977if (!success)2978return false;29792980// the offsetted table address2981addr_t addr = base + (is_tbh ? index * 2 : index);29822983// PC-relative offset to branch forward2984EmulateInstruction::Context context;2985context.type = EmulateInstruction::eContextTableBranchReadMemory;2986uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;2987if (!success)2988return false;29892990const uint32_t pc = ReadCoreReg(PC_REG, &success);2991if (!success)2992return false;29932994// target address2995addr_t target = pc + offset;2996context.type = EmulateInstruction::eContextRelativeBranchImmediate;2997context.SetISAAndImmediateSigned(eModeThumb, 4 + offset);29982999if (!BranchWritePC(context, target))3000return false;3001}30023003return true;3004}30053006// This instruction adds an immediate value to a register value, and writes the3007// result to the destination register. It can optionally update the condition3008// flags based on the result.3009bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,3010const ARMEncoding encoding) {3011#if 03012if ConditionPassed() then3013EncodingSpecificOperations();3014(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');3015R[d] = result;3016if setflags then3017APSR.N = result<31>;3018APSR.Z = IsZeroBit(result);3019APSR.C = carry;3020APSR.V = overflow;3021#endif30223023bool success = false;30243025if (ConditionPassed(opcode)) {3026uint32_t d;3027uint32_t n;3028bool setflags;3029uint32_t imm32;3030uint32_t carry_out;30313032// EncodingSpecificOperations();3033switch (encoding) {3034case eEncodingT1:3035// d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =3036// ZeroExtend(imm3, 32);3037d = Bits32(opcode, 2, 0);3038n = Bits32(opcode, 5, 3);3039setflags = !InITBlock();3040imm32 = Bits32(opcode, 8, 6);30413042break;30433044case eEncodingT2:3045// d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =3046// ZeroExtend(imm8, 32);3047d = Bits32(opcode, 10, 8);3048n = Bits32(opcode, 10, 8);3049setflags = !InITBlock();3050imm32 = Bits32(opcode, 7, 0);30513052break;30533054case eEncodingT3:3055// if Rd == '1111' && S == '1' then SEE CMN (immediate);3056// d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =3057// ThumbExpandImm(i:imm3:imm8);3058d = Bits32(opcode, 11, 8);3059n = Bits32(opcode, 19, 16);3060setflags = BitIsSet(opcode, 20);3061imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out);30623063// if Rn == '1101' then SEE ADD (SP plus immediate);3064if (n == 13)3065return EmulateADDSPImm(opcode, eEncodingT3);30663067// if BadReg(d) || n == 15 then UNPREDICTABLE;3068if (BadReg(d) || (n == 15))3069return false;30703071break;30723073case eEncodingT4: {3074// if Rn == '1111' then SEE ADR;3075// d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =3076// ZeroExtend(i:imm3:imm8, 32);3077d = Bits32(opcode, 11, 8);3078n = Bits32(opcode, 19, 16);3079setflags = false;3080uint32_t i = Bit32(opcode, 26);3081uint32_t imm3 = Bits32(opcode, 14, 12);3082uint32_t imm8 = Bits32(opcode, 7, 0);3083imm32 = (i << 11) | (imm3 << 8) | imm8;30843085// if Rn == '1101' then SEE ADD (SP plus immediate);3086if (n == 13)3087return EmulateADDSPImm(opcode, eEncodingT4);30883089// if BadReg(d) then UNPREDICTABLE;3090if (BadReg(d))3091return false;30923093break;3094}30953096default:3097return false;3098}30993100uint64_t Rn =3101ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);3102if (!success)3103return false;31043105//(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');3106AddWithCarryResult res = AddWithCarry(Rn, imm32, 0);31073108std::optional<RegisterInfo> reg_n =3109GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);3110EmulateInstruction::Context context;3111context.type = eContextArithmetic;3112context.SetRegisterPlusOffset(*reg_n, imm32);31133114// R[d] = result;3115// if setflags then3116// APSR.N = result<31>;3117// APSR.Z = IsZeroBit(result);3118// APSR.C = carry;3119// APSR.V = overflow;3120if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,3121res.carry_out, res.overflow))3122return false;3123}3124return true;3125}31263127// This instruction adds an immediate value to a register value, and writes the3128// result to the destination register. It can optionally update the condition3129// flags based on the result.3130bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,3131const ARMEncoding encoding) {3132#if 03133// ARM pseudo code...3134if ConditionPassed() then3135EncodingSpecificOperations();3136(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');3137if d == 15 then3138ALUWritePC(result); // setflags is always FALSE here3139else3140R[d] = result;3141if setflags then3142APSR.N = result<31>;3143APSR.Z = IsZeroBit(result);3144APSR.C = carry;3145APSR.V = overflow;3146#endif31473148bool success = false;31493150if (ConditionPassed(opcode)) {3151uint32_t Rd, Rn;3152uint32_t3153imm32; // the immediate value to be added to the value obtained from Rn3154bool setflags;3155switch (encoding) {3156case eEncodingA1:3157Rd = Bits32(opcode, 15, 12);3158Rn = Bits32(opcode, 19, 16);3159setflags = BitIsSet(opcode, 20);3160imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)3161break;3162default:3163return false;3164}31653166// Read the first operand.3167uint32_t val1 = ReadCoreReg(Rn, &success);3168if (!success)3169return false;31703171AddWithCarryResult res = AddWithCarry(val1, imm32, 0);31723173EmulateInstruction::Context context;3174if (Rd == 13)3175context.type = EmulateInstruction::eContextAdjustStackPointer;3176else if (Rd == GetFramePointerRegisterNumber())3177context.type = EmulateInstruction::eContextSetFramePointer;3178else3179context.type = EmulateInstruction::eContextRegisterPlusOffset;31803181std::optional<RegisterInfo> dwarf_reg =3182GetRegisterInfo(eRegisterKindDWARF, Rn);3183context.SetRegisterPlusOffset(*dwarf_reg, imm32);31843185if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,3186res.carry_out, res.overflow))3187return false;3188}3189return true;3190}31913192// This instruction adds a register value and an optionally-shifted register3193// value, and writes the result to the destination register. It can optionally3194// update the condition flags based on the result.3195bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,3196const ARMEncoding encoding) {3197#if 03198// ARM pseudo code...3199if ConditionPassed() then3200EncodingSpecificOperations();3201shifted = Shift(R[m], shift_t, shift_n, APSR.C);3202(result, carry, overflow) = AddWithCarry(R[n], shifted, '0');3203if d == 15 then3204ALUWritePC(result); // setflags is always FALSE here3205else3206R[d] = result;3207if setflags then3208APSR.N = result<31>;3209APSR.Z = IsZeroBit(result);3210APSR.C = carry;3211APSR.V = overflow;3212#endif32133214bool success = false;32153216if (ConditionPassed(opcode)) {3217uint32_t Rd, Rn, Rm;3218ARM_ShifterType shift_t;3219uint32_t shift_n; // the shift applied to the value read from Rm3220bool setflags;3221switch (encoding) {3222case eEncodingT1:3223Rd = Bits32(opcode, 2, 0);3224Rn = Bits32(opcode, 5, 3);3225Rm = Bits32(opcode, 8, 6);3226setflags = !InITBlock();3227shift_t = SRType_LSL;3228shift_n = 0;3229break;3230case eEncodingT2:3231Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);3232Rm = Bits32(opcode, 6, 3);3233setflags = false;3234shift_t = SRType_LSL;3235shift_n = 0;3236if (Rn == 15 && Rm == 15)3237return false;3238if (Rd == 15 && InITBlock() && !LastInITBlock())3239return false;3240break;3241case eEncodingA1:3242Rd = Bits32(opcode, 15, 12);3243Rn = Bits32(opcode, 19, 16);3244Rm = Bits32(opcode, 3, 0);3245setflags = BitIsSet(opcode, 20);3246shift_n = DecodeImmShiftARM(opcode, shift_t);3247break;3248default:3249return false;3250}32513252// Read the first operand.3253uint32_t val1 = ReadCoreReg(Rn, &success);3254if (!success)3255return false;32563257// Read the second operand.3258uint32_t val2 = ReadCoreReg(Rm, &success);3259if (!success)3260return false;32613262uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);3263if (!success)3264return false;3265AddWithCarryResult res = AddWithCarry(val1, shifted, 0);32663267EmulateInstruction::Context context;3268context.type = eContextArithmetic;3269std::optional<RegisterInfo> op1_reg =3270GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn);3271std::optional<RegisterInfo> op2_reg =3272GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);3273context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);32743275if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,3276res.carry_out, res.overflow))3277return false;3278}3279return true;3280}32813282// Compare Negative (immediate) adds a register value and an immediate value.3283// It updates the condition flags based on the result, and discards the result.3284bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,3285const ARMEncoding encoding) {3286#if 03287// ARM pseudo code...3288if ConditionPassed() then3289EncodingSpecificOperations();3290(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');3291APSR.N = result<31>;3292APSR.Z = IsZeroBit(result);3293APSR.C = carry;3294APSR.V = overflow;3295#endif32963297bool success = false;32983299uint32_t Rn; // the first operand3300uint32_t imm32; // the immediate value to be compared with3301switch (encoding) {3302case eEncodingT1:3303Rn = Bits32(opcode, 19, 16);3304imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)3305if (Rn == 15)3306return false;3307break;3308case eEncodingA1:3309Rn = Bits32(opcode, 19, 16);3310imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)3311break;3312default:3313return false;3314}3315// Read the register value from the operand register Rn.3316uint32_t reg_val = ReadCoreReg(Rn, &success);3317if (!success)3318return false;33193320AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);33213322EmulateInstruction::Context context;3323context.type = EmulateInstruction::eContextImmediate;3324context.SetNoArgs();3325return WriteFlags(context, res.result, res.carry_out, res.overflow);3326}33273328// Compare Negative (register) adds a register value and an optionally-shifted3329// register value. It updates the condition flags based on the result, and3330// discards the result.3331bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,3332const ARMEncoding encoding) {3333#if 03334// ARM pseudo code...3335if ConditionPassed() then3336EncodingSpecificOperations();3337shifted = Shift(R[m], shift_t, shift_n, APSR.C);3338(result, carry, overflow) = AddWithCarry(R[n], shifted, '0');3339APSR.N = result<31>;3340APSR.Z = IsZeroBit(result);3341APSR.C = carry;3342APSR.V = overflow;3343#endif33443345bool success = false;33463347uint32_t Rn; // the first operand3348uint32_t Rm; // the second operand3349ARM_ShifterType shift_t;3350uint32_t shift_n; // the shift applied to the value read from Rm3351switch (encoding) {3352case eEncodingT1:3353Rn = Bits32(opcode, 2, 0);3354Rm = Bits32(opcode, 5, 3);3355shift_t = SRType_LSL;3356shift_n = 0;3357break;3358case eEncodingT2:3359Rn = Bits32(opcode, 19, 16);3360Rm = Bits32(opcode, 3, 0);3361shift_n = DecodeImmShiftThumb(opcode, shift_t);3362// if n == 15 || BadReg(m) then UNPREDICTABLE;3363if (Rn == 15 || BadReg(Rm))3364return false;3365break;3366case eEncodingA1:3367Rn = Bits32(opcode, 19, 16);3368Rm = Bits32(opcode, 3, 0);3369shift_n = DecodeImmShiftARM(opcode, shift_t);3370break;3371default:3372return false;3373}3374// Read the register value from register Rn.3375uint32_t val1 = ReadCoreReg(Rn, &success);3376if (!success)3377return false;33783379// Read the register value from register Rm.3380uint32_t val2 = ReadCoreReg(Rm, &success);3381if (!success)3382return false;33833384uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);3385if (!success)3386return false;3387AddWithCarryResult res = AddWithCarry(val1, shifted, 0);33883389EmulateInstruction::Context context;3390context.type = EmulateInstruction::eContextImmediate;3391context.SetNoArgs();3392return WriteFlags(context, res.result, res.carry_out, res.overflow);3393}33943395// Compare (immediate) subtracts an immediate value from a register value. It3396// updates the condition flags based on the result, and discards the result.3397bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,3398const ARMEncoding encoding) {3399#if 03400// ARM pseudo code...3401if ConditionPassed() then3402EncodingSpecificOperations();3403(result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');3404APSR.N = result<31>;3405APSR.Z = IsZeroBit(result);3406APSR.C = carry;3407APSR.V = overflow;3408#endif34093410bool success = false;34113412uint32_t Rn; // the first operand3413uint32_t imm32; // the immediate value to be compared with3414switch (encoding) {3415case eEncodingT1:3416Rn = Bits32(opcode, 10, 8);3417imm32 = Bits32(opcode, 7, 0);3418break;3419case eEncodingT2:3420Rn = Bits32(opcode, 19, 16);3421imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)3422if (Rn == 15)3423return false;3424break;3425case eEncodingA1:3426Rn = Bits32(opcode, 19, 16);3427imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)3428break;3429default:3430return false;3431}3432// Read the register value from the operand register Rn.3433uint32_t reg_val = ReadCoreReg(Rn, &success);3434if (!success)3435return false;34363437AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);34383439EmulateInstruction::Context context;3440context.type = EmulateInstruction::eContextImmediate;3441context.SetNoArgs();3442return WriteFlags(context, res.result, res.carry_out, res.overflow);3443}34443445// Compare (register) subtracts an optionally-shifted register value from a3446// register value. It updates the condition flags based on the result, and3447// discards the result.3448bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,3449const ARMEncoding encoding) {3450#if 03451// ARM pseudo code...3452if ConditionPassed() then3453EncodingSpecificOperations();3454shifted = Shift(R[m], shift_t, shift_n, APSR.C);3455(result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');3456APSR.N = result<31>;3457APSR.Z = IsZeroBit(result);3458APSR.C = carry;3459APSR.V = overflow;3460#endif34613462bool success = false;34633464uint32_t Rn; // the first operand3465uint32_t Rm; // the second operand3466ARM_ShifterType shift_t;3467uint32_t shift_n; // the shift applied to the value read from Rm3468switch (encoding) {3469case eEncodingT1:3470Rn = Bits32(opcode, 2, 0);3471Rm = Bits32(opcode, 5, 3);3472shift_t = SRType_LSL;3473shift_n = 0;3474break;3475case eEncodingT2:3476Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);3477Rm = Bits32(opcode, 6, 3);3478shift_t = SRType_LSL;3479shift_n = 0;3480if (Rn < 8 && Rm < 8)3481return false;3482if (Rn == 15 || Rm == 15)3483return false;3484break;3485case eEncodingT3:3486Rn = Bits32(opcode, 19, 16);3487Rm = Bits32(opcode, 3, 0);3488shift_n = DecodeImmShiftThumb(opcode, shift_t);3489if (Rn == 15 || BadReg(Rm))3490return false;3491break;3492case eEncodingA1:3493Rn = Bits32(opcode, 19, 16);3494Rm = Bits32(opcode, 3, 0);3495shift_n = DecodeImmShiftARM(opcode, shift_t);3496break;3497default:3498return false;3499}3500// Read the register value from register Rn.3501uint32_t val1 = ReadCoreReg(Rn, &success);3502if (!success)3503return false;35043505// Read the register value from register Rm.3506uint32_t val2 = ReadCoreReg(Rm, &success);3507if (!success)3508return false;35093510uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);3511if (!success)3512return false;3513AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);35143515EmulateInstruction::Context context;3516context.type = EmulateInstruction::eContextImmediate;3517context.SetNoArgs();3518return WriteFlags(context, res.result, res.carry_out, res.overflow);3519}35203521// Arithmetic Shift Right (immediate) shifts a register value right by an3522// immediate number of bits, shifting in copies of its sign bit, and writes the3523// result to the destination register. It can optionally update the condition3524// flags based on the result.3525bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,3526const ARMEncoding encoding) {3527#if 03528// ARM pseudo code...3529if ConditionPassed() then3530EncodingSpecificOperations();3531(result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);3532if d == 15 then // Can only occur for ARM encoding3533ALUWritePC(result); // setflags is always FALSE here3534else3535R[d] = result;3536if setflags then3537APSR.N = result<31>;3538APSR.Z = IsZeroBit(result);3539APSR.C = carry;3540// APSR.V unchanged3541#endif35423543return EmulateShiftImm(opcode, encoding, SRType_ASR);3544}35453546// Arithmetic Shift Right (register) shifts a register value right by a3547// variable number of bits, shifting in copies of its sign bit, and writes the3548// result to the destination register. The variable number of bits is read from3549// the bottom byte of a register. It can optionally update the condition flags3550// based on the result.3551bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,3552const ARMEncoding encoding) {3553#if 03554// ARM pseudo code...3555if ConditionPassed() then3556EncodingSpecificOperations();3557shift_n = UInt(R[m]<7:0>);3558(result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);3559R[d] = result;3560if setflags then3561APSR.N = result<31>;3562APSR.Z = IsZeroBit(result);3563APSR.C = carry;3564// APSR.V unchanged3565#endif35663567return EmulateShiftReg(opcode, encoding, SRType_ASR);3568}35693570// Logical Shift Left (immediate) shifts a register value left by an immediate3571// number of bits, shifting in zeros, and writes the result to the destination3572// register. It can optionally update the condition flags based on the result.3573bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,3574const ARMEncoding encoding) {3575#if 03576// ARM pseudo code...3577if ConditionPassed() then3578EncodingSpecificOperations();3579(result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);3580if d == 15 then // Can only occur for ARM encoding3581ALUWritePC(result); // setflags is always FALSE here3582else3583R[d] = result;3584if setflags then3585APSR.N = result<31>;3586APSR.Z = IsZeroBit(result);3587APSR.C = carry;3588// APSR.V unchanged3589#endif35903591return EmulateShiftImm(opcode, encoding, SRType_LSL);3592}35933594// Logical Shift Left (register) shifts a register value left by a variable3595// number of bits, shifting in zeros, and writes the result to the destination3596// register. The variable number of bits is read from the bottom byte of a3597// register. It can optionally update the condition flags based on the result.3598bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,3599const ARMEncoding encoding) {3600#if 03601// ARM pseudo code...3602if ConditionPassed() then3603EncodingSpecificOperations();3604shift_n = UInt(R[m]<7:0>);3605(result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);3606R[d] = result;3607if setflags then3608APSR.N = result<31>;3609APSR.Z = IsZeroBit(result);3610APSR.C = carry;3611// APSR.V unchanged3612#endif36133614return EmulateShiftReg(opcode, encoding, SRType_LSL);3615}36163617// Logical Shift Right (immediate) shifts a register value right by an3618// immediate number of bits, shifting in zeros, and writes the result to the3619// destination register. It can optionally update the condition flags based on3620// the result.3621bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,3622const ARMEncoding encoding) {3623#if 03624// ARM pseudo code...3625if ConditionPassed() then3626EncodingSpecificOperations();3627(result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);3628if d == 15 then // Can only occur for ARM encoding3629ALUWritePC(result); // setflags is always FALSE here3630else3631R[d] = result;3632if setflags then3633APSR.N = result<31>;3634APSR.Z = IsZeroBit(result);3635APSR.C = carry;3636// APSR.V unchanged3637#endif36383639return EmulateShiftImm(opcode, encoding, SRType_LSR);3640}36413642// Logical Shift Right (register) shifts a register value right by a variable3643// number of bits, shifting in zeros, and writes the result to the destination3644// register. The variable number of bits is read from the bottom byte of a3645// register. It can optionally update the condition flags based on the result.3646bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,3647const ARMEncoding encoding) {3648#if 03649// ARM pseudo code...3650if ConditionPassed() then3651EncodingSpecificOperations();3652shift_n = UInt(R[m]<7:0>);3653(result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);3654R[d] = result;3655if setflags then3656APSR.N = result<31>;3657APSR.Z = IsZeroBit(result);3658APSR.C = carry;3659// APSR.V unchanged3660#endif36613662return EmulateShiftReg(opcode, encoding, SRType_LSR);3663}36643665// Rotate Right (immediate) provides the value of the contents of a register3666// rotated by a constant value. The bits that are rotated off the right end are3667// inserted into the vacated bit positions on the left. It can optionally3668// update the condition flags based on the result.3669bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,3670const ARMEncoding encoding) {3671#if 03672// ARM pseudo code...3673if ConditionPassed() then3674EncodingSpecificOperations();3675(result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);3676if d == 15 then // Can only occur for ARM encoding3677ALUWritePC(result); // setflags is always FALSE here3678else3679R[d] = result;3680if setflags then3681APSR.N = result<31>;3682APSR.Z = IsZeroBit(result);3683APSR.C = carry;3684// APSR.V unchanged3685#endif36863687return EmulateShiftImm(opcode, encoding, SRType_ROR);3688}36893690// Rotate Right (register) provides the value of the contents of a register3691// rotated by a variable number of bits. The bits that are rotated off the3692// right end are inserted into the vacated bit positions on the left. The3693// variable number of bits is read from the bottom byte of a register. It can3694// optionally update the condition flags based on the result.3695bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,3696const ARMEncoding encoding) {3697#if 03698// ARM pseudo code...3699if ConditionPassed() then3700EncodingSpecificOperations();3701shift_n = UInt(R[m]<7:0>);3702(result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);3703R[d] = result;3704if setflags then3705APSR.N = result<31>;3706APSR.Z = IsZeroBit(result);3707APSR.C = carry;3708// APSR.V unchanged3709#endif37103711return EmulateShiftReg(opcode, encoding, SRType_ROR);3712}37133714// Rotate Right with Extend provides the value of the contents of a register3715// shifted right by one place, with the carry flag shifted into bit [31].3716//3717// RRX can optionally update the condition flags based on the result.3718// In that case, bit [0] is shifted into the carry flag.3719bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,3720const ARMEncoding encoding) {3721#if 03722// ARM pseudo code...3723if ConditionPassed() then3724EncodingSpecificOperations();3725(result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);3726if d == 15 then // Can only occur for ARM encoding3727ALUWritePC(result); // setflags is always FALSE here3728else3729R[d] = result;3730if setflags then3731APSR.N = result<31>;3732APSR.Z = IsZeroBit(result);3733APSR.C = carry;3734// APSR.V unchanged3735#endif37363737return EmulateShiftImm(opcode, encoding, SRType_RRX);3738}37393740bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,3741const ARMEncoding encoding,3742ARM_ShifterType shift_type) {3743// assert(shift_type == SRType_ASR3744// || shift_type == SRType_LSL3745// || shift_type == SRType_LSR3746// || shift_type == SRType_ROR3747// || shift_type == SRType_RRX);37483749bool success = false;37503751if (ConditionPassed(opcode)) {3752uint32_t Rd; // the destination register3753uint32_t Rm; // the first operand register3754uint32_t imm5; // encoding for the shift amount3755uint32_t carry; // the carry bit after the shift operation3756bool setflags;37573758// Special case handling!3759// A8.6.139 ROR (immediate) -- Encoding T13760ARMEncoding use_encoding = encoding;3761if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {3762// Morph the T1 encoding from the ARM Architecture Manual into T23763// encoding to have the same decoding of bit fields as the other Thumb23764// shift operations.3765use_encoding = eEncodingT2;3766}37673768switch (use_encoding) {3769case eEncodingT1:3770Rd = Bits32(opcode, 2, 0);3771Rm = Bits32(opcode, 5, 3);3772setflags = !InITBlock();3773imm5 = Bits32(opcode, 10, 6);3774break;3775case eEncodingT2:3776// A8.6.141 RRX3777// There's no imm form of RRX instructions.3778if (shift_type == SRType_RRX)3779return false;37803781Rd = Bits32(opcode, 11, 8);3782Rm = Bits32(opcode, 3, 0);3783setflags = BitIsSet(opcode, 20);3784imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);3785if (BadReg(Rd) || BadReg(Rm))3786return false;3787break;3788case eEncodingA1:3789Rd = Bits32(opcode, 15, 12);3790Rm = Bits32(opcode, 3, 0);3791setflags = BitIsSet(opcode, 20);3792imm5 = Bits32(opcode, 11, 7);3793break;3794default:3795return false;3796}37973798// A8.6.139 ROR (immediate)3799if (shift_type == SRType_ROR && imm5 == 0)3800shift_type = SRType_RRX;38013802// Get the first operand.3803uint32_t value = ReadCoreReg(Rm, &success);3804if (!success)3805return false;38063807// Decode the shift amount if not RRX.3808uint32_t amt =3809(shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));38103811uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);3812if (!success)3813return false;38143815// The context specifies that an immediate is to be moved into Rd.3816EmulateInstruction::Context context;3817context.type = EmulateInstruction::eContextImmediate;3818context.SetNoArgs();38193820if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))3821return false;3822}3823return true;3824}38253826bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,3827const ARMEncoding encoding,3828ARM_ShifterType shift_type) {3829// assert(shift_type == SRType_ASR3830// || shift_type == SRType_LSL3831// || shift_type == SRType_LSR3832// || shift_type == SRType_ROR);38333834bool success = false;38353836if (ConditionPassed(opcode)) {3837uint32_t Rd; // the destination register3838uint32_t Rn; // the first operand register3839uint32_t3840Rm; // the register whose bottom byte contains the amount to shift by3841uint32_t carry; // the carry bit after the shift operation3842bool setflags;3843switch (encoding) {3844case eEncodingT1:3845Rd = Bits32(opcode, 2, 0);3846Rn = Rd;3847Rm = Bits32(opcode, 5, 3);3848setflags = !InITBlock();3849break;3850case eEncodingT2:3851Rd = Bits32(opcode, 11, 8);3852Rn = Bits32(opcode, 19, 16);3853Rm = Bits32(opcode, 3, 0);3854setflags = BitIsSet(opcode, 20);3855if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))3856return false;3857break;3858case eEncodingA1:3859Rd = Bits32(opcode, 15, 12);3860Rn = Bits32(opcode, 3, 0);3861Rm = Bits32(opcode, 11, 8);3862setflags = BitIsSet(opcode, 20);3863if (Rd == 15 || Rn == 15 || Rm == 15)3864return false;3865break;3866default:3867return false;3868}38693870// Get the first operand.3871uint32_t value = ReadCoreReg(Rn, &success);3872if (!success)3873return false;3874// Get the Rm register content.3875uint32_t val = ReadCoreReg(Rm, &success);3876if (!success)3877return false;38783879// Get the shift amount.3880uint32_t amt = Bits32(val, 7, 0);38813882uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);3883if (!success)3884return false;38853886// The context specifies that an immediate is to be moved into Rd.3887EmulateInstruction::Context context;3888context.type = EmulateInstruction::eContextImmediate;3889context.SetNoArgs();38903891if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))3892return false;3893}3894return true;3895}38963897// LDM loads multiple registers from consecutive memory locations, using an3898// address from a base register. Optionally the address just above the highest3899// of those locations can be written back to the base register.3900bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,3901const ARMEncoding encoding) {3902#if 03903// ARM pseudo code...3904if ConditionPassed()3905EncodingSpecificOperations(); NullCheckIfThumbEE (n);3906address = R[n];39073908for i = 0 to 143909if registers<i> == '1' then3910R[i] = MemA[address, 4]; address = address + 4;3911if registers<15> == '1' then3912LoadWritePC (MemA[address, 4]);39133914if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);3915if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A139163917#endif39183919bool success = false;3920if (ConditionPassed(opcode)) {3921uint32_t n;3922uint32_t registers = 0;3923bool wback;3924const uint32_t addr_byte_size = GetAddressByteSize();3925switch (encoding) {3926case eEncodingT1:3927// n = UInt(Rn); registers = '00000000':register_list; wback =3928// (registers<n> == '0');3929n = Bits32(opcode, 10, 8);3930registers = Bits32(opcode, 7, 0);3931registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.3932wback = BitIsClear(registers, n);3933// if BitCount(registers) < 1 then UNPREDICTABLE;3934if (BitCount(registers) < 1)3935return false;3936break;3937case eEncodingT2:3938// if W == '1' && Rn == '1101' then SEE POP;3939// n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');3940n = Bits32(opcode, 19, 16);3941registers = Bits32(opcode, 15, 0);3942registers = registers & 0xdfff; // Make sure bit 13 is zero.3943wback = BitIsSet(opcode, 21);39443945// if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then3946// UNPREDICTABLE;3947if ((n == 15) || (BitCount(registers) < 2) ||3948(BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))3949return false;39503951// if registers<15> == '1' && InITBlock() && !LastInITBlock() then3952// UNPREDICTABLE;3953if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())3954return false;39553956// if wback && registers<n> == '1' then UNPREDICTABLE;3957if (wback && BitIsSet(registers, n))3958return false;3959break;39603961case eEncodingA1:3962n = Bits32(opcode, 19, 16);3963registers = Bits32(opcode, 15, 0);3964wback = BitIsSet(opcode, 21);3965if ((n == 15) || (BitCount(registers) < 1))3966return false;3967break;3968default:3969return false;3970}39713972int32_t offset = 0;3973const addr_t base_address =3974ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);3975if (!success)3976return false;39773978EmulateInstruction::Context context;3979context.type = EmulateInstruction::eContextRegisterPlusOffset;3980std::optional<RegisterInfo> dwarf_reg =3981GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);3982context.SetRegisterPlusOffset(*dwarf_reg, offset);39833984for (int i = 0; i < 14; ++i) {3985if (BitIsSet(registers, i)) {3986context.type = EmulateInstruction::eContextRegisterPlusOffset;3987context.SetRegisterPlusOffset(*dwarf_reg, offset);3988if (wback && (n == 13)) // Pop Instruction3989{3990context.type = EmulateInstruction::eContextPopRegisterOffStack;3991context.SetAddress(base_address + offset);3992}39933994// R[i] = MemA [address, 4]; address = address + 4;3995uint32_t data = MemARead(context, base_address + offset, addr_byte_size,39960, &success);3997if (!success)3998return false;39994000if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,4001data))4002return false;40034004offset += addr_byte_size;4005}4006}40074008if (BitIsSet(registers, 15)) {4009// LoadWritePC (MemA [address, 4]);4010context.type = EmulateInstruction::eContextRegisterPlusOffset;4011context.SetRegisterPlusOffset(*dwarf_reg, offset);4012uint32_t data =4013MemARead(context, base_address + offset, addr_byte_size, 0, &success);4014if (!success)4015return false;4016// In ARMv5T and above, this is an interworking branch.4017if (!LoadWritePC(context, data))4018return false;4019}40204021if (wback && BitIsClear(registers, n)) {4022// R[n] = R[n] + 4 * BitCount (registers)4023int32_t offset = addr_byte_size * BitCount(registers);4024context.type = EmulateInstruction::eContextAdjustBaseRegister;4025context.SetRegisterPlusOffset(*dwarf_reg, offset);40264027if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4028base_address + offset))4029return false;4030}4031if (wback && BitIsSet(registers, n))4032// R[n] bits(32) UNKNOWN;4033return WriteBits32Unknown(n);4034}4035return true;4036}40374038// LDMDA loads multiple registers from consecutive memory locations using an4039// address from a base register.4040// The consecutive memory locations end at this address and the address just4041// below the lowest of those locations can optionally be written back to the4042// base register.4043bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,4044const ARMEncoding encoding) {4045#if 04046// ARM pseudo code...4047if ConditionPassed() then4048EncodingSpecificOperations();4049address = R[n] - 4*BitCount(registers) + 4;40504051for i = 0 to 144052if registers<i> == '1' then4053R[i] = MemA[address,4]; address = address + 4;40544055if registers<15> == '1' then4056LoadWritePC(MemA[address,4]);40574058if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);4059if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;4060#endif40614062bool success = false;40634064if (ConditionPassed(opcode)) {4065uint32_t n;4066uint32_t registers = 0;4067bool wback;4068const uint32_t addr_byte_size = GetAddressByteSize();40694070// EncodingSpecificOperations();4071switch (encoding) {4072case eEncodingA1:4073// n = UInt(Rn); registers = register_list; wback = (W == '1');4074n = Bits32(opcode, 19, 16);4075registers = Bits32(opcode, 15, 0);4076wback = BitIsSet(opcode, 21);40774078// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4079if ((n == 15) || (BitCount(registers) < 1))4080return false;40814082break;40834084default:4085return false;4086}4087// address = R[n] - 4*BitCount(registers) + 4;40884089int32_t offset = 0;4090addr_t Rn = ReadCoreReg(n, &success);40914092if (!success)4093return false;40944095addr_t address =4096Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;40974098EmulateInstruction::Context context;4099context.type = EmulateInstruction::eContextRegisterPlusOffset;4100std::optional<RegisterInfo> dwarf_reg =4101GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);4102context.SetRegisterPlusOffset(*dwarf_reg, offset);41034104// for i = 0 to 144105for (int i = 0; i < 14; ++i) {4106// if registers<i> == '1' then4107if (BitIsSet(registers, i)) {4108// R[i] = MemA[address,4]; address = address + 4;4109context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));4110uint32_t data =4111MemARead(context, address + offset, addr_byte_size, 0, &success);4112if (!success)4113return false;4114if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,4115data))4116return false;4117offset += addr_byte_size;4118}4119}41204121// if registers<15> == '1' then4122// LoadWritePC(MemA[address,4]);4123if (BitIsSet(registers, 15)) {4124context.SetRegisterPlusOffset(*dwarf_reg, offset);4125uint32_t data =4126MemARead(context, address + offset, addr_byte_size, 0, &success);4127if (!success)4128return false;4129// In ARMv5T and above, this is an interworking branch.4130if (!LoadWritePC(context, data))4131return false;4132}41334134// if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);4135if (wback && BitIsClear(registers, n)) {41364137offset = (addr_byte_size * BitCount(registers)) * -1;4138context.type = EmulateInstruction::eContextAdjustBaseRegister;4139context.SetImmediateSigned(offset);4140addr_t addr = Rn + offset;4141if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4142addr))4143return false;4144}41454146// if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;4147if (wback && BitIsSet(registers, n))4148return WriteBits32Unknown(n);4149}4150return true;4151}41524153// LDMDB loads multiple registers from consecutive memory locations using an4154// address from a base register. The4155// consecutive memory locations end just below this address, and the address of4156// the lowest of those locations can be optionally written back to the base4157// register.4158bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,4159const ARMEncoding encoding) {4160#if 04161// ARM pseudo code...4162if ConditionPassed() then4163EncodingSpecificOperations(); NullCheckIfThumbEE(n);4164address = R[n] - 4*BitCount(registers);41654166for i = 0 to 144167if registers<i> == '1' then4168R[i] = MemA[address,4]; address = address + 4;4169if registers<15> == '1' then4170LoadWritePC(MemA[address,4]);41714172if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);4173if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A14174#endif41754176bool success = false;41774178if (ConditionPassed(opcode)) {4179uint32_t n;4180uint32_t registers = 0;4181bool wback;4182const uint32_t addr_byte_size = GetAddressByteSize();4183switch (encoding) {4184case eEncodingT1:4185// n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');4186n = Bits32(opcode, 19, 16);4187registers = Bits32(opcode, 15, 0);4188registers = registers & 0xdfff; // Make sure bit 13 is a zero.4189wback = BitIsSet(opcode, 21);41904191// if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then4192// UNPREDICTABLE;4193if ((n == 15) || (BitCount(registers) < 2) ||4194(BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))4195return false;41964197// if registers<15> == '1' && InITBlock() && !LastInITBlock() then4198// UNPREDICTABLE;4199if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())4200return false;42014202// if wback && registers<n> == '1' then UNPREDICTABLE;4203if (wback && BitIsSet(registers, n))4204return false;42054206break;42074208case eEncodingA1:4209// n = UInt(Rn); registers = register_list; wback = (W == '1');4210n = Bits32(opcode, 19, 16);4211registers = Bits32(opcode, 15, 0);4212wback = BitIsSet(opcode, 21);42134214// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4215if ((n == 15) || (BitCount(registers) < 1))4216return false;42174218break;42194220default:4221return false;4222}42234224// address = R[n] - 4*BitCount(registers);42254226int32_t offset = 0;4227addr_t Rn =4228ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);42294230if (!success)4231return false;42324233addr_t address = Rn - (addr_byte_size * BitCount(registers));4234EmulateInstruction::Context context;4235context.type = EmulateInstruction::eContextRegisterPlusOffset;4236std::optional<RegisterInfo> dwarf_reg =4237GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);4238context.SetRegisterPlusOffset(*dwarf_reg, Rn - address);42394240for (int i = 0; i < 14; ++i) {4241if (BitIsSet(registers, i)) {4242// R[i] = MemA[address,4]; address = address + 4;4243context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));4244uint32_t data =4245MemARead(context, address + offset, addr_byte_size, 0, &success);4246if (!success)4247return false;42484249if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,4250data))4251return false;42524253offset += addr_byte_size;4254}4255}42564257// if registers<15> == '1' then4258// LoadWritePC(MemA[address,4]);4259if (BitIsSet(registers, 15)) {4260context.SetRegisterPlusOffset(*dwarf_reg, offset);4261uint32_t data =4262MemARead(context, address + offset, addr_byte_size, 0, &success);4263if (!success)4264return false;4265// In ARMv5T and above, this is an interworking branch.4266if (!LoadWritePC(context, data))4267return false;4268}42694270// if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);4271if (wback && BitIsClear(registers, n)) {42724273offset = (addr_byte_size * BitCount(registers)) * -1;4274context.type = EmulateInstruction::eContextAdjustBaseRegister;4275context.SetImmediateSigned(offset);4276addr_t addr = Rn + offset;4277if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4278addr))4279return false;4280}42814282// if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only4283// possible for encoding A14284if (wback && BitIsSet(registers, n))4285return WriteBits32Unknown(n);4286}4287return true;4288}42894290// LDMIB loads multiple registers from consecutive memory locations using an4291// address from a base register. The4292// consecutive memory locations start just above this address, and thea ddress4293// of the last of those locations can optinoally be written back to the base4294// register.4295bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,4296const ARMEncoding encoding) {4297#if 04298if ConditionPassed() then4299EncodingSpecificOperations();4300address = R[n] + 4;43014302for i = 0 to 144303if registers<i> == '1' then4304R[i] = MemA[address,4]; address = address + 4;4305if registers<15> == '1' then4306LoadWritePC(MemA[address,4]);43074308if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);4309if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;4310#endif43114312bool success = false;43134314if (ConditionPassed(opcode)) {4315uint32_t n;4316uint32_t registers = 0;4317bool wback;4318const uint32_t addr_byte_size = GetAddressByteSize();4319switch (encoding) {4320case eEncodingA1:4321// n = UInt(Rn); registers = register_list; wback = (W == '1');4322n = Bits32(opcode, 19, 16);4323registers = Bits32(opcode, 15, 0);4324wback = BitIsSet(opcode, 21);43254326// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4327if ((n == 15) || (BitCount(registers) < 1))4328return false;43294330break;4331default:4332return false;4333}4334// address = R[n] + 4;43354336int32_t offset = 0;4337addr_t Rn =4338ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);43394340if (!success)4341return false;43424343addr_t address = Rn + addr_byte_size;43444345EmulateInstruction::Context context;4346context.type = EmulateInstruction::eContextRegisterPlusOffset;4347std::optional<RegisterInfo> dwarf_reg =4348GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);4349context.SetRegisterPlusOffset(*dwarf_reg, offset);43504351for (int i = 0; i < 14; ++i) {4352if (BitIsSet(registers, i)) {4353// R[i] = MemA[address,4]; address = address + 4;43544355context.SetRegisterPlusOffset(*dwarf_reg, offset + addr_byte_size);4356uint32_t data =4357MemARead(context, address + offset, addr_byte_size, 0, &success);4358if (!success)4359return false;43604361if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,4362data))4363return false;43644365offset += addr_byte_size;4366}4367}43684369// if registers<15> == '1' then4370// LoadWritePC(MemA[address,4]);4371if (BitIsSet(registers, 15)) {4372context.SetRegisterPlusOffset(*dwarf_reg, offset);4373uint32_t data =4374MemARead(context, address + offset, addr_byte_size, 0, &success);4375if (!success)4376return false;4377// In ARMv5T and above, this is an interworking branch.4378if (!LoadWritePC(context, data))4379return false;4380}43814382// if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);4383if (wback && BitIsClear(registers, n)) {43844385offset = addr_byte_size * BitCount(registers);4386context.type = EmulateInstruction::eContextAdjustBaseRegister;4387context.SetImmediateSigned(offset);4388addr_t addr = Rn + offset;4389if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4390addr))4391return false;4392}43934394// if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only4395// possible for encoding A14396if (wback && BitIsSet(registers, n))4397return WriteBits32Unknown(n);4398}4399return true;4400}44014402// Load Register (immediate) calculates an address from a base register value4403// and an immediate offset, loads a word from memory, and writes to a register.4404// LDR (immediate, Thumb)4405bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,4406const ARMEncoding encoding) {4407#if 04408// ARM pseudo code...4409if (ConditionPassed())4410{4411EncodingSpecificOperations(); NullCheckIfThumbEE(15);4412offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);4413address = if index then offset_addr else R[n];4414data = MemU[address,4];4415if wback then R[n] = offset_addr;4416if t == 15 then4417if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;4418elsif UnalignedSupport() || address<1:0> = '00' then4419R[t] = data;4420else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv74421}4422#endif44234424bool success = false;44254426if (ConditionPassed(opcode)) {4427uint32_t Rt; // the destination register4428uint32_t Rn; // the base register4429uint32_t imm32; // the immediate offset used to form the address4430addr_t offset_addr; // the offset address4431addr_t address; // the calculated address4432uint32_t data; // the literal data value from memory load4433bool add, index, wback;4434switch (encoding) {4435case eEncodingT1:4436Rt = Bits32(opcode, 2, 0);4437Rn = Bits32(opcode, 5, 3);4438imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);4439// index = TRUE; add = TRUE; wback = FALSE4440add = true;4441index = true;4442wback = false;44434444break;44454446case eEncodingT2:4447// t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);4448Rt = Bits32(opcode, 10, 8);4449Rn = 13;4450imm32 = Bits32(opcode, 7, 0) << 2;44514452// index = TRUE; add = TRUE; wback = FALSE;4453index = true;4454add = true;4455wback = false;44564457break;44584459case eEncodingT3:4460// if Rn == '1111' then SEE LDR (literal);4461// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);4462Rt = Bits32(opcode, 15, 12);4463Rn = Bits32(opcode, 19, 16);4464imm32 = Bits32(opcode, 11, 0);44654466// index = TRUE; add = TRUE; wback = FALSE;4467index = true;4468add = true;4469wback = false;44704471// if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;4472if ((Rt == 15) && InITBlock() && !LastInITBlock())4473return false;44744475break;44764477case eEncodingT4:4478// if Rn == '1111' then SEE LDR (literal);4479// if P == '1' && U == '1' && W == '0' then SEE LDRT;4480// if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==4481// '00000100' then SEE POP;4482// if P == '0' && W == '0' then UNDEFINED;4483if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))4484return false;44854486// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);4487Rt = Bits32(opcode, 15, 12);4488Rn = Bits32(opcode, 19, 16);4489imm32 = Bits32(opcode, 7, 0);44904491// index = (P == '1'); add = (U == '1'); wback = (W == '1');4492index = BitIsSet(opcode, 10);4493add = BitIsSet(opcode, 9);4494wback = BitIsSet(opcode, 8);44954496// if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())4497// then UNPREDICTABLE;4498if ((wback && (Rn == Rt)) ||4499((Rt == 15) && InITBlock() && !LastInITBlock()))4500return false;45014502break;45034504default:4505return false;4506}4507uint32_t base = ReadCoreReg(Rn, &success);4508if (!success)4509return false;4510if (add)4511offset_addr = base + imm32;4512else4513offset_addr = base - imm32;45144515address = (index ? offset_addr : base);45164517std::optional<RegisterInfo> base_reg =4518GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn);4519if (wback) {4520EmulateInstruction::Context ctx;4521if (Rn == 13) {4522ctx.type = eContextAdjustStackPointer;4523ctx.SetImmediateSigned((int32_t)(offset_addr - base));4524} else if (Rn == GetFramePointerRegisterNumber()) {4525ctx.type = eContextSetFramePointer;4526ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));4527} else {4528ctx.type = EmulateInstruction::eContextAdjustBaseRegister;4529ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));4530}45314532if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn,4533offset_addr))4534return false;4535}45364537// Prepare to write to the Rt register.4538EmulateInstruction::Context context;4539context.type = EmulateInstruction::eContextRegisterLoad;4540context.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));45414542// Read memory from the address.4543data = MemURead(context, address, 4, 0, &success);4544if (!success)4545return false;45464547if (Rt == 15) {4548if (Bits32(address, 1, 0) == 0) {4549if (!LoadWritePC(context, data))4550return false;4551} else4552return false;4553} else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {4554if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,4555data))4556return false;4557} else4558WriteBits32Unknown(Rt);4559}4560return true;4561}45624563// STM (Store Multiple Increment After) stores multiple registers to consecutive4564// memory locations using an address4565// from a base register. The consecutive memory locations start at this4566// address, and the address just above the last of those locations can4567// optionally be written back to the base register.4568bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,4569const ARMEncoding encoding) {4570#if 04571if ConditionPassed() then4572EncodingSpecificOperations(); NullCheckIfThumbEE(n);4573address = R[n];45744575for i = 0 to 144576if registers<i> == '1' then4577if i == n && wback && i != LowestSetBit(registers) then4578MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A14579else4580MemA[address,4] = R[i];4581address = address + 4;45824583if registers<15> == '1' then // Only possible for encoding A14584MemA[address,4] = PCStoreValue();4585if wback then R[n] = R[n] + 4*BitCount(registers);4586#endif45874588bool success = false;45894590if (ConditionPassed(opcode)) {4591uint32_t n;4592uint32_t registers = 0;4593bool wback;4594const uint32_t addr_byte_size = GetAddressByteSize();45954596// EncodingSpecificOperations(); NullCheckIfThumbEE(n);4597switch (encoding) {4598case eEncodingT1:4599// n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;4600n = Bits32(opcode, 10, 8);4601registers = Bits32(opcode, 7, 0);4602registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.4603wback = true;46044605// if BitCount(registers) < 1 then UNPREDICTABLE;4606if (BitCount(registers) < 1)4607return false;46084609break;46104611case eEncodingT2:4612// n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');4613n = Bits32(opcode, 19, 16);4614registers = Bits32(opcode, 15, 0);4615registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.4616wback = BitIsSet(opcode, 21);46174618// if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;4619if ((n == 15) || (BitCount(registers) < 2))4620return false;46214622// if wback && registers<n> == '1' then UNPREDICTABLE;4623if (wback && BitIsSet(registers, n))4624return false;46254626break;46274628case eEncodingA1:4629// n = UInt(Rn); registers = register_list; wback = (W == '1');4630n = Bits32(opcode, 19, 16);4631registers = Bits32(opcode, 15, 0);4632wback = BitIsSet(opcode, 21);46334634// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4635if ((n == 15) || (BitCount(registers) < 1))4636return false;46374638break;46394640default:4641return false;4642}46434644// address = R[n];4645int32_t offset = 0;4646const addr_t address =4647ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);4648if (!success)4649return false;46504651EmulateInstruction::Context context;4652context.type = EmulateInstruction::eContextRegisterStore;4653std::optional<RegisterInfo> base_reg =4654GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);46554656// for i = 0 to 144657uint32_t lowest_set_bit = 14;4658for (uint32_t i = 0; i < 14; ++i) {4659// if registers<i> == '1' then4660if (BitIsSet(registers, i)) {4661if (i < lowest_set_bit)4662lowest_set_bit = i;4663// if i == n && wback && i != LowestSetBit(registers) then4664if ((i == n) && wback && (i != lowest_set_bit))4665// MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings4666// T1 and A14667WriteBits32UnknownToMemory(address + offset);4668else {4669// MemA[address,4] = R[i];4670uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,46710, &success);4672if (!success)4673return false;46744675std::optional<RegisterInfo> data_reg =4676GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);4677context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);4678if (!MemAWrite(context, address + offset, data, addr_byte_size))4679return false;4680}46814682// address = address + 4;4683offset += addr_byte_size;4684}4685}46864687// if registers<15> == '1' then // Only possible for encoding A14688// MemA[address,4] = PCStoreValue();4689if (BitIsSet(registers, 15)) {4690std::optional<RegisterInfo> pc_reg =4691GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);4692context.SetRegisterPlusOffset(*pc_reg, 8);4693const uint32_t pc = ReadCoreReg(PC_REG, &success);4694if (!success)4695return false;46964697if (!MemAWrite(context, address + offset, pc, addr_byte_size))4698return false;4699}47004701// if wback then R[n] = R[n] + 4*BitCount(registers);4702if (wback) {4703offset = addr_byte_size * BitCount(registers);4704context.type = EmulateInstruction::eContextAdjustBaseRegister;4705context.SetImmediateSigned(offset);4706addr_t data = address + offset;4707if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4708data))4709return false;4710}4711}4712return true;4713}47144715// STMDA (Store Multiple Decrement After) stores multiple registers to4716// consecutive memory locations using an address from a base register. The4717// consecutive memory locations end at this address, and the address just below4718// the lowest of those locations can optionally be written back to the base4719// register.4720bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,4721const ARMEncoding encoding) {4722#if 04723if ConditionPassed() then4724EncodingSpecificOperations();4725address = R[n] - 4*BitCount(registers) + 4;47264727for i = 0 to 144728if registers<i> == '1' then4729if i == n && wback && i != LowestSetBit(registers) then4730MemA[address,4] = bits(32) UNKNOWN;4731else4732MemA[address,4] = R[i];4733address = address + 4;47344735if registers<15> == '1' then4736MemA[address,4] = PCStoreValue();47374738if wback then R[n] = R[n] - 4*BitCount(registers);4739#endif47404741bool success = false;47424743if (ConditionPassed(opcode)) {4744uint32_t n;4745uint32_t registers = 0;4746bool wback;4747const uint32_t addr_byte_size = GetAddressByteSize();47484749// EncodingSpecificOperations();4750switch (encoding) {4751case eEncodingA1:4752// n = UInt(Rn); registers = register_list; wback = (W == '1');4753n = Bits32(opcode, 19, 16);4754registers = Bits32(opcode, 15, 0);4755wback = BitIsSet(opcode, 21);47564757// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4758if ((n == 15) || (BitCount(registers) < 1))4759return false;4760break;4761default:4762return false;4763}47644765// address = R[n] - 4*BitCount(registers) + 4;4766int32_t offset = 0;4767addr_t Rn = ReadCoreReg(n, &success);4768if (!success)4769return false;47704771addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;47724773EmulateInstruction::Context context;4774context.type = EmulateInstruction::eContextRegisterStore;4775std::optional<RegisterInfo> base_reg =4776GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);47774778// for i = 0 to 144779uint32_t lowest_bit_set = 14;4780for (uint32_t i = 0; i < 14; ++i) {4781// if registers<i> == '1' then4782if (BitIsSet(registers, i)) {4783if (i < lowest_bit_set)4784lowest_bit_set = i;4785// if i == n && wback && i != LowestSetBit(registers) then4786if ((i == n) && wback && (i != lowest_bit_set))4787// MemA[address,4] = bits(32) UNKNOWN;4788WriteBits32UnknownToMemory(address + offset);4789else {4790// MemA[address,4] = R[i];4791uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,47920, &success);4793if (!success)4794return false;47954796std::optional<RegisterInfo> data_reg =4797GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);4798context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,4799Rn - (address + offset));4800if (!MemAWrite(context, address + offset, data, addr_byte_size))4801return false;4802}48034804// address = address + 4;4805offset += addr_byte_size;4806}4807}48084809// if registers<15> == '1' then4810// MemA[address,4] = PCStoreValue();4811if (BitIsSet(registers, 15)) {4812std::optional<RegisterInfo> pc_reg =4813GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);4814context.SetRegisterPlusOffset(*pc_reg, 8);4815const uint32_t pc = ReadCoreReg(PC_REG, &success);4816if (!success)4817return false;48184819if (!MemAWrite(context, address + offset, pc, addr_byte_size))4820return false;4821}48224823// if wback then R[n] = R[n] - 4*BitCount(registers);4824if (wback) {4825offset = (addr_byte_size * BitCount(registers)) * -1;4826context.type = EmulateInstruction::eContextAdjustBaseRegister;4827context.SetImmediateSigned(offset);4828addr_t data = Rn + offset;4829if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4830data))4831return false;4832}4833}4834return true;4835}48364837// STMDB (Store Multiple Decrement Before) stores multiple registers to4838// consecutive memory locations using an address from a base register. The4839// consecutive memory locations end just below this address, and the address of4840// the first of those locations can optionally be written back to the base4841// register.4842bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,4843const ARMEncoding encoding) {4844#if 04845if ConditionPassed() then4846EncodingSpecificOperations(); NullCheckIfThumbEE(n);4847address = R[n] - 4*BitCount(registers);48484849for i = 0 to 144850if registers<i> == '1' then4851if i == n && wback && i != LowestSetBit(registers) then4852MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A14853else4854MemA[address,4] = R[i];4855address = address + 4;48564857if registers<15> == '1' then // Only possible for encoding A14858MemA[address,4] = PCStoreValue();48594860if wback then R[n] = R[n] - 4*BitCount(registers);4861#endif48624863bool success = false;48644865if (ConditionPassed(opcode)) {4866uint32_t n;4867uint32_t registers = 0;4868bool wback;4869const uint32_t addr_byte_size = GetAddressByteSize();48704871// EncodingSpecificOperations(); NullCheckIfThumbEE(n);4872switch (encoding) {4873case eEncodingT1:4874// if W == '1' && Rn == '1101' then SEE PUSH;4875if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {4876// See PUSH4877}4878// n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');4879n = Bits32(opcode, 19, 16);4880registers = Bits32(opcode, 15, 0);4881registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.4882wback = BitIsSet(opcode, 21);4883// if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;4884if ((n == 15) || BitCount(registers) < 2)4885return false;4886// if wback && registers<n> == '1' then UNPREDICTABLE;4887if (wback && BitIsSet(registers, n))4888return false;4889break;48904891case eEncodingA1:4892// if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE4893// PUSH;4894if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&4895BitCount(Bits32(opcode, 15, 0)) >= 2) {4896// See Push4897}4898// n = UInt(Rn); registers = register_list; wback = (W == '1');4899n = Bits32(opcode, 19, 16);4900registers = Bits32(opcode, 15, 0);4901wback = BitIsSet(opcode, 21);4902// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4903if ((n == 15) || BitCount(registers) < 1)4904return false;4905break;49064907default:4908return false;4909}49104911// address = R[n] - 4*BitCount(registers);49124913int32_t offset = 0;4914addr_t Rn =4915ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);4916if (!success)4917return false;49184919addr_t address = Rn - (addr_byte_size * BitCount(registers));49204921EmulateInstruction::Context context;4922context.type = EmulateInstruction::eContextRegisterStore;4923std::optional<RegisterInfo> base_reg =4924GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);49254926// for i = 0 to 144927uint32_t lowest_set_bit = 14;4928for (uint32_t i = 0; i < 14; ++i) {4929// if registers<i> == '1' then4930if (BitIsSet(registers, i)) {4931if (i < lowest_set_bit)4932lowest_set_bit = i;4933// if i == n && wback && i != LowestSetBit(registers) then4934if ((i == n) && wback && (i != lowest_set_bit))4935// MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding4936// A14937WriteBits32UnknownToMemory(address + offset);4938else {4939// MemA[address,4] = R[i];4940uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,49410, &success);4942if (!success)4943return false;49444945std::optional<RegisterInfo> data_reg =4946GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);4947context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,4948Rn - (address + offset));4949if (!MemAWrite(context, address + offset, data, addr_byte_size))4950return false;4951}49524953// address = address + 4;4954offset += addr_byte_size;4955}4956}49574958// if registers<15> == '1' then // Only possible for encoding A14959// MemA[address,4] = PCStoreValue();4960if (BitIsSet(registers, 15)) {4961std::optional<RegisterInfo> pc_reg =4962GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);4963context.SetRegisterPlusOffset(*pc_reg, 8);4964const uint32_t pc = ReadCoreReg(PC_REG, &success);4965if (!success)4966return false;49674968if (!MemAWrite(context, address + offset, pc, addr_byte_size))4969return false;4970}49714972// if wback then R[n] = R[n] - 4*BitCount(registers);4973if (wback) {4974offset = (addr_byte_size * BitCount(registers)) * -1;4975context.type = EmulateInstruction::eContextAdjustBaseRegister;4976context.SetImmediateSigned(offset);4977addr_t data = Rn + offset;4978if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4979data))4980return false;4981}4982}4983return true;4984}49854986// STMIB (Store Multiple Increment Before) stores multiple registers to4987// consecutive memory locations using an address from a base register. The4988// consecutive memory locations start just above this address, and the address4989// of the last of those locations can optionally be written back to the base4990// register.4991bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,4992const ARMEncoding encoding) {4993#if 04994if ConditionPassed() then4995EncodingSpecificOperations();4996address = R[n] + 4;49974998for i = 0 to 144999if registers<i> == '1' then5000if i == n && wback && i != LowestSetBit(registers) then5001MemA[address,4] = bits(32) UNKNOWN;5002else5003MemA[address,4] = R[i];5004address = address + 4;50055006if registers<15> == '1' then5007MemA[address,4] = PCStoreValue();50085009if wback then R[n] = R[n] + 4*BitCount(registers);5010#endif50115012bool success = false;50135014if (ConditionPassed(opcode)) {5015uint32_t n;5016uint32_t registers = 0;5017bool wback;5018const uint32_t addr_byte_size = GetAddressByteSize();50195020// EncodingSpecificOperations();5021switch (encoding) {5022case eEncodingA1:5023// n = UInt(Rn); registers = register_list; wback = (W == '1');5024n = Bits32(opcode, 19, 16);5025registers = Bits32(opcode, 15, 0);5026wback = BitIsSet(opcode, 21);50275028// if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;5029if ((n == 15) && (BitCount(registers) < 1))5030return false;5031break;5032default:5033return false;5034}5035// address = R[n] + 4;50365037int32_t offset = 0;5038addr_t Rn = ReadCoreReg(n, &success);5039if (!success)5040return false;50415042addr_t address = Rn + addr_byte_size;50435044EmulateInstruction::Context context;5045context.type = EmulateInstruction::eContextRegisterStore;5046std::optional<RegisterInfo> base_reg =5047GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);50485049uint32_t lowest_set_bit = 14;5050// for i = 0 to 145051for (uint32_t i = 0; i < 14; ++i) {5052// if registers<i> == '1' then5053if (BitIsSet(registers, i)) {5054if (i < lowest_set_bit)5055lowest_set_bit = i;5056// if i == n && wback && i != LowestSetBit(registers) then5057if ((i == n) && wback && (i != lowest_set_bit))5058// MemA[address,4] = bits(32) UNKNOWN;5059WriteBits32UnknownToMemory(address + offset);5060// else5061else {5062// MemA[address,4] = R[i];5063uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,50640, &success);5065if (!success)5066return false;50675068std::optional<RegisterInfo> data_reg =5069GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);5070context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,5071offset + addr_byte_size);5072if (!MemAWrite(context, address + offset, data, addr_byte_size))5073return false;5074}50755076// address = address + 4;5077offset += addr_byte_size;5078}5079}50805081// if registers<15> == '1' then5082// MemA[address,4] = PCStoreValue();5083if (BitIsSet(registers, 15)) {5084std::optional<RegisterInfo> pc_reg =5085GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);5086context.SetRegisterPlusOffset(*pc_reg, 8);5087const uint32_t pc = ReadCoreReg(PC_REG, &success);5088if (!success)5089return false;50905091if (!MemAWrite(context, address + offset, pc, addr_byte_size))5092return false;5093}50945095// if wback then R[n] = R[n] + 4*BitCount(registers);5096if (wback) {5097offset = addr_byte_size * BitCount(registers);5098context.type = EmulateInstruction::eContextAdjustBaseRegister;5099context.SetImmediateSigned(offset);5100addr_t data = Rn + offset;5101if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,5102data))5103return false;5104}5105}5106return true;5107}51085109// STR (store immediate) calculates an address from a base register value and an5110// immediate offset, and stores a word5111// from a register to memory. It can use offset, post-indexed, or pre-indexed5112// addressing.5113bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,5114const ARMEncoding encoding) {5115#if 05116if ConditionPassed() then5117EncodingSpecificOperations(); NullCheckIfThumbEE(n);5118offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);5119address = if index then offset_addr else R[n];5120if UnalignedSupport() || address<1:0> == '00' then5121MemU[address,4] = R[t];5122else // Can only occur before ARMv75123MemU[address,4] = bits(32) UNKNOWN;5124if wback then R[n] = offset_addr;5125#endif51265127bool success = false;51285129if (ConditionPassed(opcode)) {5130const uint32_t addr_byte_size = GetAddressByteSize();51315132uint32_t t;5133uint32_t n;5134uint32_t imm32;5135bool index;5136bool add;5137bool wback;5138// EncodingSpecificOperations (); NullCheckIfThumbEE(n);5139switch (encoding) {5140case eEncodingT1:5141// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);5142t = Bits32(opcode, 2, 0);5143n = Bits32(opcode, 5, 3);5144imm32 = Bits32(opcode, 10, 6) << 2;51455146// index = TRUE; add = TRUE; wback = FALSE;5147index = true;5148add = false;5149wback = false;5150break;51515152case eEncodingT2:5153// t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);5154t = Bits32(opcode, 10, 8);5155n = 13;5156imm32 = Bits32(opcode, 7, 0) << 2;51575158// index = TRUE; add = TRUE; wback = FALSE;5159index = true;5160add = true;5161wback = false;5162break;51635164case eEncodingT3:5165// if Rn == '1111' then UNDEFINED;5166if (Bits32(opcode, 19, 16) == 15)5167return false;51685169// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);5170t = Bits32(opcode, 15, 12);5171n = Bits32(opcode, 19, 16);5172imm32 = Bits32(opcode, 11, 0);51735174// index = TRUE; add = TRUE; wback = FALSE;5175index = true;5176add = true;5177wback = false;51785179// if t == 15 then UNPREDICTABLE;5180if (t == 15)5181return false;5182break;51835184case eEncodingT4:5185// if P == '1' && U == '1' && W == '0' then SEE STRT;5186// if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==5187// '00000100' then SEE PUSH;5188// if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;5189if ((Bits32(opcode, 19, 16) == 15) ||5190(BitIsClear(opcode, 10) && BitIsClear(opcode, 8)))5191return false;51925193// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);5194t = Bits32(opcode, 15, 12);5195n = Bits32(opcode, 19, 16);5196imm32 = Bits32(opcode, 7, 0);51975198// index = (P == '1'); add = (U == '1'); wback = (W == '1');5199index = BitIsSet(opcode, 10);5200add = BitIsSet(opcode, 9);5201wback = BitIsSet(opcode, 8);52025203// if t == 15 || (wback && n == t) then UNPREDICTABLE;5204if ((t == 15) || (wback && (n == t)))5205return false;5206break;52075208default:5209return false;5210}52115212addr_t offset_addr;5213addr_t address;52145215// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);5216uint32_t base_address = ReadCoreReg(n, &success);5217if (!success)5218return false;52195220if (add)5221offset_addr = base_address + imm32;5222else5223offset_addr = base_address - imm32;52245225// address = if index then offset_addr else R[n];5226if (index)5227address = offset_addr;5228else5229address = base_address;52305231EmulateInstruction::Context context;5232if (n == 13)5233context.type = eContextPushRegisterOnStack;5234else5235context.type = eContextRegisterStore;52365237std::optional<RegisterInfo> base_reg =5238GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);52395240// if UnalignedSupport() || address<1:0> == '00' then5241if (UnalignedSupport() ||5242(BitIsClear(address, 1) && BitIsClear(address, 0))) {5243// MemU[address,4] = R[t];5244uint32_t data =5245ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);5246if (!success)5247return false;52485249std::optional<RegisterInfo> data_reg =5250GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);5251int32_t offset = address - base_address;5252context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);5253if (!MemUWrite(context, address, data, addr_byte_size))5254return false;5255} else {5256// MemU[address,4] = bits(32) UNKNOWN;5257WriteBits32UnknownToMemory(address);5258}52595260// if wback then R[n] = offset_addr;5261if (wback) {5262if (n == 13)5263context.type = eContextAdjustStackPointer;5264else5265context.type = eContextAdjustBaseRegister;5266context.SetAddress(offset_addr);52675268if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,5269offset_addr))5270return false;5271}5272}5273return true;5274}52755276// STR (Store Register) calculates an address from a base register value and an5277// offset register value, stores a5278// word from a register to memory. The offset register value can optionally5279// be shifted.5280bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,5281const ARMEncoding encoding) {5282#if 05283if ConditionPassed() then5284EncodingSpecificOperations(); NullCheckIfThumbEE(n);5285offset = Shift(R[m], shift_t, shift_n, APSR.C);5286offset_addr = if add then (R[n] + offset) else (R[n] - offset);5287address = if index then offset_addr else R[n];5288if t == 15 then // Only possible for encoding A15289data = PCStoreValue();5290else5291data = R[t];5292if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then5293MemU[address,4] = data;5294else // Can only occur before ARMv75295MemU[address,4] = bits(32) UNKNOWN;5296if wback then R[n] = offset_addr;5297#endif52985299bool success = false;53005301if (ConditionPassed(opcode)) {5302const uint32_t addr_byte_size = GetAddressByteSize();53035304uint32_t t;5305uint32_t n;5306uint32_t m;5307ARM_ShifterType shift_t;5308uint32_t shift_n;5309bool index;5310bool add;5311bool wback;53125313// EncodingSpecificOperations (); NullCheckIfThumbEE(n);5314switch (encoding) {5315case eEncodingT1:5316// if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation5317// in ThumbEE";5318// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5319t = Bits32(opcode, 2, 0);5320n = Bits32(opcode, 5, 3);5321m = Bits32(opcode, 8, 6);53225323// index = TRUE; add = TRUE; wback = FALSE;5324index = true;5325add = true;5326wback = false;53275328// (shift_t, shift_n) = (SRType_LSL, 0);5329shift_t = SRType_LSL;5330shift_n = 0;5331break;53325333case eEncodingT2:5334// if Rn == '1111' then UNDEFINED;5335if (Bits32(opcode, 19, 16) == 15)5336return false;53375338// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5339t = Bits32(opcode, 15, 12);5340n = Bits32(opcode, 19, 16);5341m = Bits32(opcode, 3, 0);53425343// index = TRUE; add = TRUE; wback = FALSE;5344index = true;5345add = true;5346wback = false;53475348// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));5349shift_t = SRType_LSL;5350shift_n = Bits32(opcode, 5, 4);53515352// if t == 15 || BadReg(m) then UNPREDICTABLE;5353if ((t == 15) || (BadReg(m)))5354return false;5355break;53565357case eEncodingA1: {5358// if P == '0' && W == '1' then SEE STRT;5359// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5360t = Bits32(opcode, 15, 12);5361n = Bits32(opcode, 19, 16);5362m = Bits32(opcode, 3, 0);53635364// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||5365// (W == '1');5366index = BitIsSet(opcode, 24);5367add = BitIsSet(opcode, 23);5368wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));53695370// (shift_t, shift_n) = DecodeImmShift(type, imm5);5371uint32_t typ = Bits32(opcode, 6, 5);5372uint32_t imm5 = Bits32(opcode, 11, 7);5373shift_n = DecodeImmShift(typ, imm5, shift_t);53745375// if m == 15 then UNPREDICTABLE;5376if (m == 15)5377return false;53785379// if wback && (n == 15 || n == t) then UNPREDICTABLE;5380if (wback && ((n == 15) || (n == t)))5381return false;53825383break;5384}5385default:5386return false;5387}53885389addr_t offset_addr;5390addr_t address;5391int32_t offset = 0;53925393addr_t base_address =5394ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);5395if (!success)5396return false;53975398uint32_t Rm_data =5399ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);5400if (!success)5401return false;54025403// offset = Shift(R[m], shift_t, shift_n, APSR.C);5404offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success);5405if (!success)5406return false;54075408// offset_addr = if add then (R[n] + offset) else (R[n] - offset);5409if (add)5410offset_addr = base_address + offset;5411else5412offset_addr = base_address - offset;54135414// address = if index then offset_addr else R[n];5415if (index)5416address = offset_addr;5417else5418address = base_address;54195420uint32_t data;5421// if t == 15 then // Only possible for encoding A15422if (t == 15)5423// data = PCStoreValue();5424data = ReadCoreReg(PC_REG, &success);5425else5426// data = R[t];5427data =5428ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);54295430if (!success)5431return false;54325433EmulateInstruction::Context context;5434context.type = eContextRegisterStore;54355436// if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==5437// InstrSet_ARM then5438if (UnalignedSupport() ||5439(BitIsClear(address, 1) && BitIsClear(address, 0)) ||5440CurrentInstrSet() == eModeARM) {5441// MemU[address,4] = data;54425443std::optional<RegisterInfo> base_reg =5444GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);5445std::optional<RegisterInfo> data_reg =5446GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);54475448context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,5449address - base_address);5450if (!MemUWrite(context, address, data, addr_byte_size))5451return false;54525453} else5454// MemU[address,4] = bits(32) UNKNOWN;5455WriteBits32UnknownToMemory(address);54565457// if wback then R[n] = offset_addr;5458if (wback) {5459context.type = eContextRegisterLoad;5460context.SetAddress(offset_addr);5461if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,5462offset_addr))5463return false;5464}5465}5466return true;5467}54685469bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,5470const ARMEncoding encoding) {5471#if 05472if ConditionPassed() then5473EncodingSpecificOperations(); NullCheckIfThumbEE(n);5474offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);5475address = if index then offset_addr else R[n];5476MemU[address,1] = R[t]<7:0>;5477if wback then R[n] = offset_addr;5478#endif54795480bool success = false;54815482if (ConditionPassed(opcode)) {5483uint32_t t;5484uint32_t n;5485uint32_t imm32;5486bool index;5487bool add;5488bool wback;5489// EncodingSpecificOperations(); NullCheckIfThumbEE(n);5490switch (encoding) {5491case eEncodingT1:5492// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);5493t = Bits32(opcode, 2, 0);5494n = Bits32(opcode, 5, 3);5495imm32 = Bits32(opcode, 10, 6);54965497// index = TRUE; add = TRUE; wback = FALSE;5498index = true;5499add = true;5500wback = false;5501break;55025503case eEncodingT2:5504// if Rn == '1111' then UNDEFINED;5505if (Bits32(opcode, 19, 16) == 15)5506return false;55075508// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);5509t = Bits32(opcode, 15, 12);5510n = Bits32(opcode, 19, 16);5511imm32 = Bits32(opcode, 11, 0);55125513// index = TRUE; add = TRUE; wback = FALSE;5514index = true;5515add = true;5516wback = false;55175518// if BadReg(t) then UNPREDICTABLE;5519if (BadReg(t))5520return false;5521break;55225523case eEncodingT3:5524// if P == '1' && U == '1' && W == '0' then SEE STRBT;5525// if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;5526if (Bits32(opcode, 19, 16) == 15)5527return false;55285529// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);5530t = Bits32(opcode, 15, 12);5531n = Bits32(opcode, 19, 16);5532imm32 = Bits32(opcode, 7, 0);55335534// index = (P == '1'); add = (U == '1'); wback = (W == '1');5535index = BitIsSet(opcode, 10);5536add = BitIsSet(opcode, 9);5537wback = BitIsSet(opcode, 8);55385539// if BadReg(t) || (wback && n == t) then UNPREDICTABLE5540if ((BadReg(t)) || (wback && (n == t)))5541return false;5542break;55435544default:5545return false;5546}55475548addr_t offset_addr;5549addr_t address;5550addr_t base_address =5551ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);5552if (!success)5553return false;55545555// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);5556if (add)5557offset_addr = base_address + imm32;5558else5559offset_addr = base_address - imm32;55605561// address = if index then offset_addr else R[n];5562if (index)5563address = offset_addr;5564else5565address = base_address;55665567// MemU[address,1] = R[t]<7:0>5568std::optional<RegisterInfo> base_reg =5569GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);5570std::optional<RegisterInfo> data_reg =5571GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);55725573EmulateInstruction::Context context;5574context.type = eContextRegisterStore;5575context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,5576address - base_address);55775578uint32_t data =5579ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);5580if (!success)5581return false;55825583data = Bits32(data, 7, 0);55845585if (!MemUWrite(context, address, data, 1))5586return false;55875588// if wback then R[n] = offset_addr;5589if (wback) {5590context.type = eContextRegisterLoad;5591context.SetAddress(offset_addr);5592if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,5593offset_addr))5594return false;5595}5596}55975598return true;5599}56005601// STRH (register) calculates an address from a base register value and an5602// offset register value, and stores a5603// halfword from a register to memory. The offset register value can be5604// shifted left by 0, 1, 2, or 3 bits.5605bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,5606const ARMEncoding encoding) {5607#if 05608if ConditionPassed() then5609EncodingSpecificOperations(); NullCheckIfThumbEE(n);5610offset = Shift(R[m], shift_t, shift_n, APSR.C);5611offset_addr = if add then (R[n] + offset) else (R[n] - offset);5612address = if index then offset_addr else R[n];5613if UnalignedSupport() || address<0> == '0' then5614MemU[address,2] = R[t]<15:0>;5615else // Can only occur before ARMv75616MemU[address,2] = bits(16) UNKNOWN;5617if wback then R[n] = offset_addr;5618#endif56195620bool success = false;56215622if (ConditionPassed(opcode)) {5623uint32_t t;5624uint32_t n;5625uint32_t m;5626bool index;5627bool add;5628bool wback;5629ARM_ShifterType shift_t;5630uint32_t shift_n;56315632// EncodingSpecificOperations(); NullCheckIfThumbEE(n);5633switch (encoding) {5634case eEncodingT1:5635// if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation5636// in ThumbEE";5637// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5638t = Bits32(opcode, 2, 0);5639n = Bits32(opcode, 5, 3);5640m = Bits32(opcode, 8, 6);56415642// index = TRUE; add = TRUE; wback = FALSE;5643index = true;5644add = true;5645wback = false;56465647// (shift_t, shift_n) = (SRType_LSL, 0);5648shift_t = SRType_LSL;5649shift_n = 0;56505651break;56525653case eEncodingT2:5654// if Rn == '1111' then UNDEFINED;5655// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5656t = Bits32(opcode, 15, 12);5657n = Bits32(opcode, 19, 16);5658m = Bits32(opcode, 3, 0);5659if (n == 15)5660return false;56615662// index = TRUE; add = TRUE; wback = FALSE;5663index = true;5664add = true;5665wback = false;56665667// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));5668shift_t = SRType_LSL;5669shift_n = Bits32(opcode, 5, 4);56705671// if BadReg(t) || BadReg(m) then UNPREDICTABLE;5672if (BadReg(t) || BadReg(m))5673return false;56745675break;56765677case eEncodingA1:5678// if P == '0' && W == '1' then SEE STRHT;5679// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5680t = Bits32(opcode, 15, 12);5681n = Bits32(opcode, 19, 16);5682m = Bits32(opcode, 3, 0);56835684// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||5685// (W == '1');5686index = BitIsSet(opcode, 24);5687add = BitIsSet(opcode, 23);5688wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));56895690// (shift_t, shift_n) = (SRType_LSL, 0);5691shift_t = SRType_LSL;5692shift_n = 0;56935694// if t == 15 || m == 15 then UNPREDICTABLE;5695if ((t == 15) || (m == 15))5696return false;56975698// if wback && (n == 15 || n == t) then UNPREDICTABLE;5699if (wback && ((n == 15) || (n == t)))5700return false;57015702break;57035704default:5705return false;5706}57075708uint32_t Rm = ReadCoreReg(m, &success);5709if (!success)5710return false;57115712uint32_t Rn = ReadCoreReg(n, &success);5713if (!success)5714return false;57155716// offset = Shift(R[m], shift_t, shift_n, APSR.C);5717uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);5718if (!success)5719return false;57205721// offset_addr = if add then (R[n] + offset) else (R[n] - offset);5722addr_t offset_addr;5723if (add)5724offset_addr = Rn + offset;5725else5726offset_addr = Rn - offset;57275728// address = if index then offset_addr else R[n];5729addr_t address;5730if (index)5731address = offset_addr;5732else5733address = Rn;57345735EmulateInstruction::Context context;5736context.type = eContextRegisterStore;57375738// if UnalignedSupport() || address<0> == '0' then5739if (UnalignedSupport() || BitIsClear(address, 0)) {5740// MemU[address,2] = R[t]<15:0>;5741uint32_t Rt = ReadCoreReg(t, &success);5742if (!success)5743return false;57445745EmulateInstruction::Context context;5746context.type = eContextRegisterStore;5747std::optional<RegisterInfo> base_reg =5748GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);5749std::optional<RegisterInfo> offset_reg =5750GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);5751std::optional<RegisterInfo> data_reg =5752GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);5753context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,5754*data_reg);57555756if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2))5757return false;5758} else // Can only occur before ARMv75759{5760// MemU[address,2] = bits(16) UNKNOWN;5761}57625763// if wback then R[n] = offset_addr;5764if (wback) {5765context.type = eContextAdjustBaseRegister;5766context.SetAddress(offset_addr);5767if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,5768offset_addr))5769return false;5770}5771}57725773return true;5774}57755776// Add with Carry (immediate) adds an immediate value and the carry flag value5777// to a register value, and writes the result to the destination register. It5778// can optionally update the condition flags based on the result.5779bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,5780const ARMEncoding encoding) {5781#if 05782// ARM pseudo code...5783if ConditionPassed() then5784EncodingSpecificOperations();5785(result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);5786if d == 15 then // Can only occur for ARM encoding5787ALUWritePC(result); // setflags is always FALSE here5788else5789R[d] = result;5790if setflags then5791APSR.N = result<31>;5792APSR.Z = IsZeroBit(result);5793APSR.C = carry;5794APSR.V = overflow;5795#endif57965797bool success = false;57985799if (ConditionPassed(opcode)) {5800uint32_t Rd, Rn;5801uint32_t5802imm32; // the immediate value to be added to the value obtained from Rn5803bool setflags;5804switch (encoding) {5805case eEncodingT1:5806Rd = Bits32(opcode, 11, 8);5807Rn = Bits32(opcode, 19, 16);5808setflags = BitIsSet(opcode, 20);5809imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)5810if (BadReg(Rd) || BadReg(Rn))5811return false;5812break;5813case eEncodingA1:5814Rd = Bits32(opcode, 15, 12);5815Rn = Bits32(opcode, 19, 16);5816setflags = BitIsSet(opcode, 20);5817imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)58185819if (Rd == 15 && setflags)5820return EmulateSUBSPcLrEtc(opcode, encoding);5821break;5822default:5823return false;5824}58255826// Read the first operand.5827int32_t val1 = ReadCoreReg(Rn, &success);5828if (!success)5829return false;58305831AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);58325833EmulateInstruction::Context context;5834context.type = EmulateInstruction::eContextImmediate;5835context.SetNoArgs();58365837if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,5838res.carry_out, res.overflow))5839return false;5840}5841return true;5842}58435844// Add with Carry (register) adds a register value, the carry flag value, and5845// an optionally-shifted register value, and writes the result to the5846// destination register. It can optionally update the condition flags based on5847// the result.5848bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,5849const ARMEncoding encoding) {5850#if 05851// ARM pseudo code...5852if ConditionPassed() then5853EncodingSpecificOperations();5854shifted = Shift(R[m], shift_t, shift_n, APSR.C);5855(result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);5856if d == 15 then // Can only occur for ARM encoding5857ALUWritePC(result); // setflags is always FALSE here5858else5859R[d] = result;5860if setflags then5861APSR.N = result<31>;5862APSR.Z = IsZeroBit(result);5863APSR.C = carry;5864APSR.V = overflow;5865#endif58665867bool success = false;58685869if (ConditionPassed(opcode)) {5870uint32_t Rd, Rn, Rm;5871ARM_ShifterType shift_t;5872uint32_t shift_n; // the shift applied to the value read from Rm5873bool setflags;5874switch (encoding) {5875case eEncodingT1:5876Rd = Rn = Bits32(opcode, 2, 0);5877Rm = Bits32(opcode, 5, 3);5878setflags = !InITBlock();5879shift_t = SRType_LSL;5880shift_n = 0;5881break;5882case eEncodingT2:5883Rd = Bits32(opcode, 11, 8);5884Rn = Bits32(opcode, 19, 16);5885Rm = Bits32(opcode, 3, 0);5886setflags = BitIsSet(opcode, 20);5887shift_n = DecodeImmShiftThumb(opcode, shift_t);5888if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))5889return false;5890break;5891case eEncodingA1:5892Rd = Bits32(opcode, 15, 12);5893Rn = Bits32(opcode, 19, 16);5894Rm = Bits32(opcode, 3, 0);5895setflags = BitIsSet(opcode, 20);5896shift_n = DecodeImmShiftARM(opcode, shift_t);58975898if (Rd == 15 && setflags)5899return EmulateSUBSPcLrEtc(opcode, encoding);5900break;5901default:5902return false;5903}59045905// Read the first operand.5906int32_t val1 = ReadCoreReg(Rn, &success);5907if (!success)5908return false;59095910// Read the second operand.5911int32_t val2 = ReadCoreReg(Rm, &success);5912if (!success)5913return false;59145915uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);5916if (!success)5917return false;5918AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);59195920EmulateInstruction::Context context;5921context.type = EmulateInstruction::eContextImmediate;5922context.SetNoArgs();59235924if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,5925res.carry_out, res.overflow))5926return false;5927}5928return true;5929}59305931// This instruction adds an immediate value to the PC value to form a PC-5932// relative address, and writes the result to the destination register.5933bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,5934const ARMEncoding encoding) {5935#if 05936// ARM pseudo code...5937if ConditionPassed() then5938EncodingSpecificOperations();5939result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);5940if d == 15 then // Can only occur for ARM encodings5941ALUWritePC(result);5942else5943R[d] = result;5944#endif59455946bool success = false;59475948if (ConditionPassed(opcode)) {5949uint32_t Rd;5950uint32_t imm32; // the immediate value to be added/subtracted to/from the PC5951bool add;5952switch (encoding) {5953case eEncodingT1:5954Rd = Bits32(opcode, 10, 8);5955imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)5956add = true;5957break;5958case eEncodingT2:5959case eEncodingT3:5960Rd = Bits32(opcode, 11, 8);5961imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)5962add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB5963if (BadReg(Rd))5964return false;5965break;5966case eEncodingA1:5967case eEncodingA2:5968Rd = Bits32(opcode, 15, 12);5969imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)5970add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB5971break;5972default:5973return false;5974}59755976// Read the PC value.5977uint32_t pc = ReadCoreReg(PC_REG, &success);5978if (!success)5979return false;59805981uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);59825983EmulateInstruction::Context context;5984context.type = EmulateInstruction::eContextImmediate;5985context.SetNoArgs();59865987if (!WriteCoreReg(context, result, Rd))5988return false;5989}5990return true;5991}59925993// This instruction performs a bitwise AND of a register value and an immediate5994// value, and writes the result to the destination register. It can optionally5995// update the condition flags based on the result.5996bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,5997const ARMEncoding encoding) {5998#if 05999// ARM pseudo code...6000if ConditionPassed() then6001EncodingSpecificOperations();6002result = R[n] AND imm32;6003if d == 15 then // Can only occur for ARM encoding6004ALUWritePC(result); // setflags is always FALSE here6005else6006R[d] = result;6007if setflags then6008APSR.N = result<31>;6009APSR.Z = IsZeroBit(result);6010APSR.C = carry;6011// APSR.V unchanged6012#endif60136014bool success = false;60156016if (ConditionPassed(opcode)) {6017uint32_t Rd, Rn;6018uint32_t6019imm32; // the immediate value to be ANDed to the value obtained from Rn6020bool setflags;6021uint32_t carry; // the carry bit after ARM/Thumb Expand operation6022switch (encoding) {6023case eEncodingT1:6024Rd = Bits32(opcode, 11, 8);6025Rn = Bits32(opcode, 19, 16);6026setflags = BitIsSet(opcode, 20);6027imm32 = ThumbExpandImm_C(6028opcode, APSR_C,6029carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)6030// if Rd == '1111' && S == '1' then SEE TST (immediate);6031if (Rd == 15 && setflags)6032return EmulateTSTImm(opcode, eEncodingT1);6033if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))6034return false;6035break;6036case eEncodingA1:6037Rd = Bits32(opcode, 15, 12);6038Rn = Bits32(opcode, 19, 16);6039setflags = BitIsSet(opcode, 20);6040imm32 =6041ARMExpandImm_C(opcode, APSR_C,6042carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)60436044if (Rd == 15 && setflags)6045return EmulateSUBSPcLrEtc(opcode, encoding);6046break;6047default:6048return false;6049}60506051// Read the first operand.6052uint32_t val1 = ReadCoreReg(Rn, &success);6053if (!success)6054return false;60556056uint32_t result = val1 & imm32;60576058EmulateInstruction::Context context;6059context.type = EmulateInstruction::eContextImmediate;6060context.SetNoArgs();60616062if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))6063return false;6064}6065return true;6066}60676068// This instruction performs a bitwise AND of a register value and an6069// optionally-shifted register value, and writes the result to the destination6070// register. It can optionally update the condition flags based on the result.6071bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,6072const ARMEncoding encoding) {6073#if 06074// ARM pseudo code...6075if ConditionPassed() then6076EncodingSpecificOperations();6077(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);6078result = R[n] AND shifted;6079if d == 15 then // Can only occur for ARM encoding6080ALUWritePC(result); // setflags is always FALSE here6081else6082R[d] = result;6083if setflags then6084APSR.N = result<31>;6085APSR.Z = IsZeroBit(result);6086APSR.C = carry;6087// APSR.V unchanged6088#endif60896090bool success = false;60916092if (ConditionPassed(opcode)) {6093uint32_t Rd, Rn, Rm;6094ARM_ShifterType shift_t;6095uint32_t shift_n; // the shift applied to the value read from Rm6096bool setflags;6097uint32_t carry;6098switch (encoding) {6099case eEncodingT1:6100Rd = Rn = Bits32(opcode, 2, 0);6101Rm = Bits32(opcode, 5, 3);6102setflags = !InITBlock();6103shift_t = SRType_LSL;6104shift_n = 0;6105break;6106case eEncodingT2:6107Rd = Bits32(opcode, 11, 8);6108Rn = Bits32(opcode, 19, 16);6109Rm = Bits32(opcode, 3, 0);6110setflags = BitIsSet(opcode, 20);6111shift_n = DecodeImmShiftThumb(opcode, shift_t);6112// if Rd == '1111' && S == '1' then SEE TST (register);6113if (Rd == 15 && setflags)6114return EmulateTSTReg(opcode, eEncodingT2);6115if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))6116return false;6117break;6118case eEncodingA1:6119Rd = Bits32(opcode, 15, 12);6120Rn = Bits32(opcode, 19, 16);6121Rm = Bits32(opcode, 3, 0);6122setflags = BitIsSet(opcode, 20);6123shift_n = DecodeImmShiftARM(opcode, shift_t);61246125if (Rd == 15 && setflags)6126return EmulateSUBSPcLrEtc(opcode, encoding);6127break;6128default:6129return false;6130}61316132// Read the first operand.6133uint32_t val1 = ReadCoreReg(Rn, &success);6134if (!success)6135return false;61366137// Read the second operand.6138uint32_t val2 = ReadCoreReg(Rm, &success);6139if (!success)6140return false;61416142uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);6143if (!success)6144return false;6145uint32_t result = val1 & shifted;61466147EmulateInstruction::Context context;6148context.type = EmulateInstruction::eContextImmediate;6149context.SetNoArgs();61506151if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))6152return false;6153}6154return true;6155}61566157// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and6158// the complement of an immediate value, and writes the result to the6159// destination register. It can optionally update the condition flags based on6160// the result.6161bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,6162const ARMEncoding encoding) {6163#if 06164// ARM pseudo code...6165if ConditionPassed() then6166EncodingSpecificOperations();6167result = R[n] AND NOT(imm32);6168if d == 15 then // Can only occur for ARM encoding6169ALUWritePC(result); // setflags is always FALSE here6170else6171R[d] = result;6172if setflags then6173APSR.N = result<31>;6174APSR.Z = IsZeroBit(result);6175APSR.C = carry;6176// APSR.V unchanged6177#endif61786179bool success = false;61806181if (ConditionPassed(opcode)) {6182uint32_t Rd, Rn;6183uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to6184// the value obtained from Rn6185bool setflags;6186uint32_t carry; // the carry bit after ARM/Thumb Expand operation6187switch (encoding) {6188case eEncodingT1:6189Rd = Bits32(opcode, 11, 8);6190Rn = Bits32(opcode, 19, 16);6191setflags = BitIsSet(opcode, 20);6192imm32 = ThumbExpandImm_C(6193opcode, APSR_C,6194carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)6195if (BadReg(Rd) || BadReg(Rn))6196return false;6197break;6198case eEncodingA1:6199Rd = Bits32(opcode, 15, 12);6200Rn = Bits32(opcode, 19, 16);6201setflags = BitIsSet(opcode, 20);6202imm32 =6203ARMExpandImm_C(opcode, APSR_C,6204carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)62056206// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related6207// instructions;6208if (Rd == 15 && setflags)6209return EmulateSUBSPcLrEtc(opcode, encoding);6210break;6211default:6212return false;6213}62146215// Read the first operand.6216uint32_t val1 = ReadCoreReg(Rn, &success);6217if (!success)6218return false;62196220uint32_t result = val1 & ~imm32;62216222EmulateInstruction::Context context;6223context.type = EmulateInstruction::eContextImmediate;6224context.SetNoArgs();62256226if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))6227return false;6228}6229return true;6230}62316232// Bitwise Bit Clear (register) performs a bitwise AND of a register value and6233// the complement of an optionally-shifted register value, and writes the6234// result to the destination register. It can optionally update the condition6235// flags based on the result.6236bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,6237const ARMEncoding encoding) {6238#if 06239// ARM pseudo code...6240if ConditionPassed() then6241EncodingSpecificOperations();6242(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);6243result = R[n] AND NOT(shifted);6244if d == 15 then // Can only occur for ARM encoding6245ALUWritePC(result); // setflags is always FALSE here6246else6247R[d] = result;6248if setflags then6249APSR.N = result<31>;6250APSR.Z = IsZeroBit(result);6251APSR.C = carry;6252// APSR.V unchanged6253#endif62546255bool success = false;62566257if (ConditionPassed(opcode)) {6258uint32_t Rd, Rn, Rm;6259ARM_ShifterType shift_t;6260uint32_t shift_n; // the shift applied to the value read from Rm6261bool setflags;6262uint32_t carry;6263switch (encoding) {6264case eEncodingT1:6265Rd = Rn = Bits32(opcode, 2, 0);6266Rm = Bits32(opcode, 5, 3);6267setflags = !InITBlock();6268shift_t = SRType_LSL;6269shift_n = 0;6270break;6271case eEncodingT2:6272Rd = Bits32(opcode, 11, 8);6273Rn = Bits32(opcode, 19, 16);6274Rm = Bits32(opcode, 3, 0);6275setflags = BitIsSet(opcode, 20);6276shift_n = DecodeImmShiftThumb(opcode, shift_t);6277if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))6278return false;6279break;6280case eEncodingA1:6281Rd = Bits32(opcode, 15, 12);6282Rn = Bits32(opcode, 19, 16);6283Rm = Bits32(opcode, 3, 0);6284setflags = BitIsSet(opcode, 20);6285shift_n = DecodeImmShiftARM(opcode, shift_t);62866287// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related6288// instructions;6289if (Rd == 15 && setflags)6290return EmulateSUBSPcLrEtc(opcode, encoding);6291break;6292default:6293return false;6294}62956296// Read the first operand.6297uint32_t val1 = ReadCoreReg(Rn, &success);6298if (!success)6299return false;63006301// Read the second operand.6302uint32_t val2 = ReadCoreReg(Rm, &success);6303if (!success)6304return false;63056306uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);6307if (!success)6308return false;6309uint32_t result = val1 & ~shifted;63106311EmulateInstruction::Context context;6312context.type = EmulateInstruction::eContextImmediate;6313context.SetNoArgs();63146315if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))6316return false;6317}6318return true;6319}63206321// LDR (immediate, ARM) calculates an address from a base register value and an6322// immediate offset, loads a word6323// from memory, and writes it to a register. It can use offset, post-indexed,6324// or pre-indexed addressing.6325bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,6326const ARMEncoding encoding) {6327#if 06328if ConditionPassed() then6329EncodingSpecificOperations();6330offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);6331address = if index then offset_addr else R[n];6332data = MemU[address,4];6333if wback then R[n] = offset_addr;6334if t == 15 then6335if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;6336elsif UnalignedSupport() || address<1:0> = '00' then6337R[t] = data;6338else // Can only apply before ARMv76339R[t] = ROR(data, 8*UInt(address<1:0>));6340#endif63416342bool success = false;63436344if (ConditionPassed(opcode)) {6345const uint32_t addr_byte_size = GetAddressByteSize();63466347uint32_t t;6348uint32_t n;6349uint32_t imm32;6350bool index;6351bool add;6352bool wback;63536354switch (encoding) {6355case eEncodingA1:6356// if Rn == '1111' then SEE LDR (literal);6357// if P == '0' && W == '1' then SEE LDRT;6358// if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==6359// '000000000100' then SEE POP;6360// t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);6361t = Bits32(opcode, 15, 12);6362n = Bits32(opcode, 19, 16);6363imm32 = Bits32(opcode, 11, 0);63646365// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||6366// (W == '1');6367index = BitIsSet(opcode, 24);6368add = BitIsSet(opcode, 23);6369wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));63706371// if wback && n == t then UNPREDICTABLE;6372if (wback && (n == t))6373return false;63746375break;63766377default:6378return false;6379}63806381addr_t address;6382addr_t offset_addr;6383addr_t base_address = ReadCoreReg(n, &success);6384if (!success)6385return false;63866387// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);6388if (add)6389offset_addr = base_address + imm32;6390else6391offset_addr = base_address - imm32;63926393// address = if index then offset_addr else R[n];6394if (index)6395address = offset_addr;6396else6397address = base_address;63986399// data = MemU[address,4];64006401std::optional<RegisterInfo> base_reg =6402GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);6403EmulateInstruction::Context context;6404context.type = eContextRegisterLoad;6405context.SetRegisterPlusOffset(*base_reg, address - base_address);64066407uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);6408if (!success)6409return false;64106411// if wback then R[n] = offset_addr;6412if (wback) {6413context.type = eContextAdjustBaseRegister;6414context.SetAddress(offset_addr);6415if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,6416offset_addr))6417return false;6418}64196420// if t == 15 then6421if (t == 15) {6422// if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;6423if (BitIsClear(address, 1) && BitIsClear(address, 0)) {6424// LoadWritePC (data);6425context.type = eContextRegisterLoad;6426context.SetRegisterPlusOffset(*base_reg, address - base_address);6427LoadWritePC(context, data);6428} else6429return false;6430}6431// elsif UnalignedSupport() || address<1:0> = '00' then6432else if (UnalignedSupport() ||6433(BitIsClear(address, 1) && BitIsClear(address, 0))) {6434// R[t] = data;6435context.type = eContextRegisterLoad;6436context.SetRegisterPlusOffset(*base_reg, address - base_address);6437if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,6438data))6439return false;6440}6441// else // Can only apply before ARMv76442else {6443// R[t] = ROR(data, 8*UInt(address<1:0>));6444data = ROR(data, Bits32(address, 1, 0), &success);6445if (!success)6446return false;6447context.type = eContextRegisterLoad;6448context.SetImmediate(data);6449if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,6450data))6451return false;6452}6453}6454return true;6455}64566457// LDR (register) calculates an address from a base register value and an offset6458// register value, loads a word6459// from memory, and writes it to a register. The offset register value can6460// optionally be shifted.6461bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,6462const ARMEncoding encoding) {6463#if 06464if ConditionPassed() then6465EncodingSpecificOperations(); NullCheckIfThumbEE(n);6466offset = Shift(R[m], shift_t, shift_n, APSR.C);6467offset_addr = if add then (R[n] + offset) else (R[n] - offset);6468address = if index then offset_addr else R[n];6469data = MemU[address,4];6470if wback then R[n] = offset_addr;6471if t == 15 then6472if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;6473elsif UnalignedSupport() || address<1:0> = '00' then6474R[t] = data;6475else // Can only apply before ARMv76476if CurrentInstrSet() == InstrSet_ARM then6477R[t] = ROR(data, 8*UInt(address<1:0>));6478else6479R[t] = bits(32) UNKNOWN;6480#endif64816482bool success = false;64836484if (ConditionPassed(opcode)) {6485const uint32_t addr_byte_size = GetAddressByteSize();64866487uint32_t t;6488uint32_t n;6489uint32_t m;6490bool index;6491bool add;6492bool wback;6493ARM_ShifterType shift_t;6494uint32_t shift_n;64956496switch (encoding) {6497case eEncodingT1:6498// if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation6499// in ThumbEE";6500// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6501t = Bits32(opcode, 2, 0);6502n = Bits32(opcode, 5, 3);6503m = Bits32(opcode, 8, 6);65046505// index = TRUE; add = TRUE; wback = FALSE;6506index = true;6507add = true;6508wback = false;65096510// (shift_t, shift_n) = (SRType_LSL, 0);6511shift_t = SRType_LSL;6512shift_n = 0;65136514break;65156516case eEncodingT2:6517// if Rn == '1111' then SEE LDR (literal);6518// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6519t = Bits32(opcode, 15, 12);6520n = Bits32(opcode, 19, 16);6521m = Bits32(opcode, 3, 0);65226523// index = TRUE; add = TRUE; wback = FALSE;6524index = true;6525add = true;6526wback = false;65276528// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));6529shift_t = SRType_LSL;6530shift_n = Bits32(opcode, 5, 4);65316532// if BadReg(m) then UNPREDICTABLE;6533if (BadReg(m))6534return false;65356536// if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;6537if ((t == 15) && InITBlock() && !LastInITBlock())6538return false;65396540break;65416542case eEncodingA1: {6543// if P == '0' && W == '1' then SEE LDRT;6544// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6545t = Bits32(opcode, 15, 12);6546n = Bits32(opcode, 19, 16);6547m = Bits32(opcode, 3, 0);65486549// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||6550// (W == '1');6551index = BitIsSet(opcode, 24);6552add = BitIsSet(opcode, 23);6553wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));65546555// (shift_t, shift_n) = DecodeImmShift(type, imm5);6556uint32_t type = Bits32(opcode, 6, 5);6557uint32_t imm5 = Bits32(opcode, 11, 7);6558shift_n = DecodeImmShift(type, imm5, shift_t);65596560// if m == 15 then UNPREDICTABLE;6561if (m == 15)6562return false;65636564// if wback && (n == 15 || n == t) then UNPREDICTABLE;6565if (wback && ((n == 15) || (n == t)))6566return false;6567} break;65686569default:6570return false;6571}65726573uint32_t Rm =6574ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);6575if (!success)6576return false;65776578uint32_t Rn =6579ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);6580if (!success)6581return false;65826583addr_t offset_addr;6584addr_t address;65856586// offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is6587// an application level alias for the CPSR".6588addr_t offset =6589Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);6590if (!success)6591return false;65926593// offset_addr = if add then (R[n] + offset) else (R[n] - offset);6594if (add)6595offset_addr = Rn + offset;6596else6597offset_addr = Rn - offset;65986599// address = if index then offset_addr else R[n];6600if (index)6601address = offset_addr;6602else6603address = Rn;66046605// data = MemU[address,4];6606std::optional<RegisterInfo> base_reg =6607GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);6608EmulateInstruction::Context context;6609context.type = eContextRegisterLoad;6610context.SetRegisterPlusOffset(*base_reg, address - Rn);66116612uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);6613if (!success)6614return false;66156616// if wback then R[n] = offset_addr;6617if (wback) {6618context.type = eContextAdjustBaseRegister;6619context.SetAddress(offset_addr);6620if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,6621offset_addr))6622return false;6623}66246625// if t == 15 then6626if (t == 15) {6627// if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;6628if (BitIsClear(address, 1) && BitIsClear(address, 0)) {6629context.type = eContextRegisterLoad;6630context.SetRegisterPlusOffset(*base_reg, address - Rn);6631LoadWritePC(context, data);6632} else6633return false;6634}6635// elsif UnalignedSupport() || address<1:0> = '00' then6636else if (UnalignedSupport() ||6637(BitIsClear(address, 1) && BitIsClear(address, 0))) {6638// R[t] = data;6639context.type = eContextRegisterLoad;6640context.SetRegisterPlusOffset(*base_reg, address - Rn);6641if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,6642data))6643return false;6644} else // Can only apply before ARMv76645{6646// if CurrentInstrSet() == InstrSet_ARM then6647if (CurrentInstrSet() == eModeARM) {6648// R[t] = ROR(data, 8*UInt(address<1:0>));6649data = ROR(data, Bits32(address, 1, 0), &success);6650if (!success)6651return false;6652context.type = eContextRegisterLoad;6653context.SetImmediate(data);6654if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,6655data))6656return false;6657} else {6658// R[t] = bits(32) UNKNOWN;6659WriteBits32Unknown(t);6660}6661}6662}6663return true;6664}66656666// LDRB (immediate, Thumb)6667bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode,6668const ARMEncoding encoding) {6669#if 06670if ConditionPassed() then6671EncodingSpecificOperations(); NullCheckIfThumbEE(n);6672offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);6673address = if index then offset_addr else R[n];6674R[t] = ZeroExtend(MemU[address,1], 32);6675if wback then R[n] = offset_addr;6676#endif66776678bool success = false;66796680if (ConditionPassed(opcode)) {6681uint32_t t;6682uint32_t n;6683uint32_t imm32;6684bool index;6685bool add;6686bool wback;66876688// EncodingSpecificOperations(); NullCheckIfThumbEE(n);6689switch (encoding) {6690case eEncodingT1:6691// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);6692t = Bits32(opcode, 2, 0);6693n = Bits32(opcode, 5, 3);6694imm32 = Bits32(opcode, 10, 6);66956696// index = TRUE; add = TRUE; wback = FALSE;6697index = true;6698add = true;6699wback = false;67006701break;67026703case eEncodingT2:6704// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);6705t = Bits32(opcode, 15, 12);6706n = Bits32(opcode, 19, 16);6707imm32 = Bits32(opcode, 11, 0);67086709// index = TRUE; add = TRUE; wback = FALSE;6710index = true;6711add = true;6712wback = false;67136714// if Rt == '1111' then SEE PLD;6715if (t == 15)6716return false; // PLD is not implemented yet67176718// if Rn == '1111' then SEE LDRB (literal);6719if (n == 15)6720return EmulateLDRBLiteral(opcode, eEncodingT1);67216722// if t == 13 then UNPREDICTABLE;6723if (t == 13)6724return false;67256726break;67276728case eEncodingT3:6729// if P == '1' && U == '1' && W == '0' then SEE LDRBT;6730// if P == '0' && W == '0' then UNDEFINED;6731if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))6732return false;67336734// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);6735t = Bits32(opcode, 15, 12);6736n = Bits32(opcode, 19, 16);6737imm32 = Bits32(opcode, 7, 0);67386739// index = (P == '1'); add = (U == '1'); wback = (W == '1');6740index = BitIsSet(opcode, 10);6741add = BitIsSet(opcode, 9);6742wback = BitIsSet(opcode, 8);67436744// if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;6745if (t == 15)6746return false; // PLD is not implemented yet67476748// if Rn == '1111' then SEE LDRB (literal);6749if (n == 15)6750return EmulateLDRBLiteral(opcode, eEncodingT1);67516752// if BadReg(t) || (wback && n == t) then UNPREDICTABLE;6753if (BadReg(t) || (wback && (n == t)))6754return false;67556756break;67576758default:6759return false;6760}67616762uint32_t Rn =6763ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);6764if (!success)6765return false;67666767addr_t address;6768addr_t offset_addr;67696770// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);6771if (add)6772offset_addr = Rn + imm32;6773else6774offset_addr = Rn - imm32;67756776// address = if index then offset_addr else R[n];6777if (index)6778address = offset_addr;6779else6780address = Rn;67816782// R[t] = ZeroExtend(MemU[address,1], 32);6783std::optional<RegisterInfo> base_reg =6784GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);6785std::optional<RegisterInfo> data_reg =6786GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);67876788EmulateInstruction::Context context;6789context.type = eContextRegisterLoad;6790context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);67916792uint64_t data = MemURead(context, address, 1, 0, &success);6793if (!success)6794return false;67956796if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))6797return false;67986799// if wback then R[n] = offset_addr;6800if (wback) {6801context.type = eContextAdjustBaseRegister;6802context.SetAddress(offset_addr);6803if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,6804offset_addr))6805return false;6806}6807}6808return true;6809}68106811// LDRB (literal) calculates an address from the PC value and an immediate6812// offset, loads a byte from memory,6813// zero-extends it to form a 32-bit word and writes it to a register.6814bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,6815const ARMEncoding encoding) {6816#if 06817if ConditionPassed() then6818EncodingSpecificOperations(); NullCheckIfThumbEE(15);6819base = Align(PC,4);6820address = if add then (base + imm32) else (base - imm32);6821R[t] = ZeroExtend(MemU[address,1], 32);6822#endif68236824bool success = false;68256826if (ConditionPassed(opcode)) {6827uint32_t t;6828uint32_t imm32;6829bool add;6830switch (encoding) {6831case eEncodingT1:6832// t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');6833t = Bits32(opcode, 15, 12);6834imm32 = Bits32(opcode, 11, 0);6835add = BitIsSet(opcode, 23);68366837// if Rt == '1111' then SEE PLD;6838if (t == 15)6839return false; // PLD is not implemented yet68406841// if t == 13 then UNPREDICTABLE;6842if (t == 13)6843return false;68446845break;68466847case eEncodingA1:6848// t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');6849t = Bits32(opcode, 15, 12);6850imm32 = Bits32(opcode, 11, 0);6851add = BitIsSet(opcode, 23);68526853// if t == 15 then UNPREDICTABLE;6854if (t == 15)6855return false;6856break;68576858default:6859return false;6860}68616862// base = Align(PC,4);6863uint32_t pc_val = ReadCoreReg(PC_REG, &success);6864if (!success)6865return false;68666867uint32_t base = AlignPC(pc_val);68686869addr_t address;6870// address = if add then (base + imm32) else (base - imm32);6871if (add)6872address = base + imm32;6873else6874address = base - imm32;68756876// R[t] = ZeroExtend(MemU[address,1], 32);6877EmulateInstruction::Context context;6878context.type = eContextRelativeBranchImmediate;6879context.SetImmediate(address - base);68806881uint64_t data = MemURead(context, address, 1, 0, &success);6882if (!success)6883return false;68846885if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))6886return false;6887}6888return true;6889}68906891// LDRB (register) calculates an address from a base register value and an6892// offset rigister value, loads a byte from memory, zero-extends it to form a6893// 32-bit word, and writes it to a register. The offset register value can6894// optionally be shifted.6895bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,6896const ARMEncoding encoding) {6897#if 06898if ConditionPassed() then6899EncodingSpecificOperations(); NullCheckIfThumbEE(n);6900offset = Shift(R[m], shift_t, shift_n, APSR.C);6901offset_addr = if add then (R[n] + offset) else (R[n] - offset);6902address = if index then offset_addr else R[n];6903R[t] = ZeroExtend(MemU[address,1],32);6904if wback then R[n] = offset_addr;6905#endif69066907bool success = false;69086909if (ConditionPassed(opcode)) {6910uint32_t t;6911uint32_t n;6912uint32_t m;6913bool index;6914bool add;6915bool wback;6916ARM_ShifterType shift_t;6917uint32_t shift_n;69186919// EncodingSpecificOperations(); NullCheckIfThumbEE(n);6920switch (encoding) {6921case eEncodingT1:6922// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6923t = Bits32(opcode, 2, 0);6924n = Bits32(opcode, 5, 3);6925m = Bits32(opcode, 8, 6);69266927// index = TRUE; add = TRUE; wback = FALSE;6928index = true;6929add = true;6930wback = false;69316932// (shift_t, shift_n) = (SRType_LSL, 0);6933shift_t = SRType_LSL;6934shift_n = 0;6935break;69366937case eEncodingT2:6938// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6939t = Bits32(opcode, 15, 12);6940n = Bits32(opcode, 19, 16);6941m = Bits32(opcode, 3, 0);69426943// index = TRUE; add = TRUE; wback = FALSE;6944index = true;6945add = true;6946wback = false;69476948// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));6949shift_t = SRType_LSL;6950shift_n = Bits32(opcode, 5, 4);69516952// if Rt == '1111' then SEE PLD;6953if (t == 15)6954return false; // PLD is not implemented yet69556956// if Rn == '1111' then SEE LDRB (literal);6957if (n == 15)6958return EmulateLDRBLiteral(opcode, eEncodingT1);69596960// if t == 13 || BadReg(m) then UNPREDICTABLE;6961if ((t == 13) || BadReg(m))6962return false;6963break;69646965case eEncodingA1: {6966// if P == '0' && W == '1' then SEE LDRBT;6967// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6968t = Bits32(opcode, 15, 12);6969n = Bits32(opcode, 19, 16);6970m = Bits32(opcode, 3, 0);69716972// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||6973// (W == '1');6974index = BitIsSet(opcode, 24);6975add = BitIsSet(opcode, 23);6976wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));69776978// (shift_t, shift_n) = DecodeImmShift(type, imm5);6979uint32_t type = Bits32(opcode, 6, 5);6980uint32_t imm5 = Bits32(opcode, 11, 7);6981shift_n = DecodeImmShift(type, imm5, shift_t);69826983// if t == 15 || m == 15 then UNPREDICTABLE;6984if ((t == 15) || (m == 15))6985return false;69866987// if wback && (n == 15 || n == t) then UNPREDICTABLE;6988if (wback && ((n == 15) || (n == t)))6989return false;6990} break;69916992default:6993return false;6994}69956996addr_t offset_addr;6997addr_t address;69986999// offset = Shift(R[m], shift_t, shift_n, APSR.C);7000uint32_t Rm =7001ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);7002if (!success)7003return false;70047005addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);7006if (!success)7007return false;70087009// offset_addr = if add then (R[n] + offset) else (R[n] - offset);7010uint32_t Rn =7011ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);7012if (!success)7013return false;70147015if (add)7016offset_addr = Rn + offset;7017else7018offset_addr = Rn - offset;70197020// address = if index then offset_addr else R[n];7021if (index)7022address = offset_addr;7023else7024address = Rn;70257026// R[t] = ZeroExtend(MemU[address,1],32);7027std::optional<RegisterInfo> base_reg =7028GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);70297030EmulateInstruction::Context context;7031context.type = eContextRegisterLoad;7032context.SetRegisterPlusOffset(*base_reg, address - Rn);70337034uint64_t data = MemURead(context, address, 1, 0, &success);7035if (!success)7036return false;70377038if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))7039return false;70407041// if wback then R[n] = offset_addr;7042if (wback) {7043context.type = eContextAdjustBaseRegister;7044context.SetAddress(offset_addr);7045if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,7046offset_addr))7047return false;7048}7049}7050return true;7051}70527053// LDRH (immediate, Thumb) calculates an address from a base register value and7054// an immediate offset, loads a7055// halfword from memory, zero-extends it to form a 32-bit word, and writes it7056// to a register. It can use offset, post-indexed, or pre-indexed addressing.7057bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,7058const ARMEncoding encoding) {7059#if 07060if ConditionPassed() then7061EncodingSpecificOperations(); NullCheckIfThumbEE(n);7062offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);7063address = if index then offset_addr else R[n];7064data = MemU[address,2];7065if wback then R[n] = offset_addr;7066if UnalignedSupport() || address<0> = '0' then7067R[t] = ZeroExtend(data, 32);7068else // Can only apply before ARMv77069R[t] = bits(32) UNKNOWN;7070#endif70717072bool success = false;70737074if (ConditionPassed(opcode)) {7075uint32_t t;7076uint32_t n;7077uint32_t imm32;7078bool index;7079bool add;7080bool wback;70817082// EncodingSpecificOperations(); NullCheckIfThumbEE(n);7083switch (encoding) {7084case eEncodingT1:7085// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);7086t = Bits32(opcode, 2, 0);7087n = Bits32(opcode, 5, 3);7088imm32 = Bits32(opcode, 10, 6) << 1;70897090// index = TRUE; add = TRUE; wback = FALSE;7091index = true;7092add = true;7093wback = false;70947095break;70967097case eEncodingT2:7098// if Rt == '1111' then SEE "Unallocated memory hints";7099// if Rn == '1111' then SEE LDRH (literal);7100// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);7101t = Bits32(opcode, 15, 12);7102n = Bits32(opcode, 19, 16);7103imm32 = Bits32(opcode, 11, 0);71047105// index = TRUE; add = TRUE; wback = FALSE;7106index = true;7107add = true;7108wback = false;71097110// if t == 13 then UNPREDICTABLE;7111if (t == 13)7112return false;7113break;71147115case eEncodingT3:7116// if Rn == '1111' then SEE LDRH (literal);7117// if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE7118// "Unallocated memory hints";7119// if P == '1' && U == '1' && W == '0' then SEE LDRHT;7120// if P == '0' && W == '0' then UNDEFINED;7121if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))7122return false;71237124// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);7125t = Bits32(opcode, 15, 12);7126n = Bits32(opcode, 19, 16);7127imm32 = Bits32(opcode, 7, 0);71287129// index = (P == '1'); add = (U == '1'); wback = (W == '1');7130index = BitIsSet(opcode, 10);7131add = BitIsSet(opcode, 9);7132wback = BitIsSet(opcode, 8);71337134// if BadReg(t) || (wback && n == t) then UNPREDICTABLE;7135if (BadReg(t) || (wback && (n == t)))7136return false;7137break;71387139default:7140return false;7141}71427143// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);7144uint32_t Rn =7145ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);7146if (!success)7147return false;71487149addr_t offset_addr;7150addr_t address;71517152if (add)7153offset_addr = Rn + imm32;7154else7155offset_addr = Rn - imm32;71567157// address = if index then offset_addr else R[n];7158if (index)7159address = offset_addr;7160else7161address = Rn;71627163// data = MemU[address,2];7164std::optional<RegisterInfo> base_reg =7165GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);71667167EmulateInstruction::Context context;7168context.type = eContextRegisterLoad;7169context.SetRegisterPlusOffset(*base_reg, address - Rn);71707171uint64_t data = MemURead(context, address, 2, 0, &success);7172if (!success)7173return false;71747175// if wback then R[n] = offset_addr;7176if (wback) {7177context.type = eContextAdjustBaseRegister;7178context.SetAddress(offset_addr);7179if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,7180offset_addr))7181return false;7182}71837184// if UnalignedSupport() || address<0> = '0' then7185if (UnalignedSupport() || BitIsClear(address, 0)) {7186// R[t] = ZeroExtend(data, 32);7187context.type = eContextRegisterLoad;7188context.SetRegisterPlusOffset(*base_reg, address - Rn);7189if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7190data))7191return false;7192} else // Can only apply before ARMv77193{7194// R[t] = bits(32) UNKNOWN;7195WriteBits32Unknown(t);7196}7197}7198return true;7199}72007201// LDRH (literal) calculates an address from the PC value and an immediate7202// offset, loads a halfword from memory,7203// zero-extends it to form a 32-bit word, and writes it to a register.7204bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,7205const ARMEncoding encoding) {7206#if 07207if ConditionPassed() then7208EncodingSpecificOperations(); NullCheckIfThumbEE(15);7209base = Align(PC,4);7210address = if add then (base + imm32) else (base - imm32);7211data = MemU[address,2];7212if UnalignedSupport() || address<0> = '0' then7213R[t] = ZeroExtend(data, 32);7214else // Can only apply before ARMv77215R[t] = bits(32) UNKNOWN;7216#endif72177218bool success = false;72197220if (ConditionPassed(opcode)) {7221uint32_t t;7222uint32_t imm32;7223bool add;72247225// EncodingSpecificOperations(); NullCheckIfThumbEE(15);7226switch (encoding) {7227case eEncodingT1:7228// if Rt == '1111' then SEE "Unallocated memory hints";7229// t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');7230t = Bits32(opcode, 15, 12);7231imm32 = Bits32(opcode, 11, 0);7232add = BitIsSet(opcode, 23);72337234// if t == 13 then UNPREDICTABLE;7235if (t == 13)7236return false;72377238break;72397240case eEncodingA1: {7241uint32_t imm4H = Bits32(opcode, 11, 8);7242uint32_t imm4L = Bits32(opcode, 3, 0);72437244// t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');7245t = Bits32(opcode, 15, 12);7246imm32 = (imm4H << 4) | imm4L;7247add = BitIsSet(opcode, 23);72487249// if t == 15 then UNPREDICTABLE;7250if (t == 15)7251return false;7252break;7253}72547255default:7256return false;7257}72587259// base = Align(PC,4);7260uint64_t pc_value = ReadCoreReg(PC_REG, &success);7261if (!success)7262return false;72637264addr_t base = AlignPC(pc_value);7265addr_t address;72667267// address = if add then (base + imm32) else (base - imm32);7268if (add)7269address = base + imm32;7270else7271address = base - imm32;72727273// data = MemU[address,2];7274std::optional<RegisterInfo> base_reg =7275GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);72767277EmulateInstruction::Context context;7278context.type = eContextRegisterLoad;7279context.SetRegisterPlusOffset(*base_reg, address - base);72807281uint64_t data = MemURead(context, address, 2, 0, &success);7282if (!success)7283return false;72847285// if UnalignedSupport() || address<0> = '0' then7286if (UnalignedSupport() || BitIsClear(address, 0)) {7287// R[t] = ZeroExtend(data, 32);7288context.type = eContextRegisterLoad;7289context.SetRegisterPlusOffset(*base_reg, address - base);7290if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7291data))7292return false;72937294} else // Can only apply before ARMv77295{7296// R[t] = bits(32) UNKNOWN;7297WriteBits32Unknown(t);7298}7299}7300return true;7301}73027303// LDRH (literal) calculates an address from a base register value and an offset7304// register value, loads a halfword7305// from memory, zero-extends it to form a 32-bit word, and writes it to a7306// register. The offset register value can be shifted left by 0, 1, 2, or 37307// bits.7308bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,7309const ARMEncoding encoding) {7310#if 07311if ConditionPassed() then7312EncodingSpecificOperations(); NullCheckIfThumbEE(n);7313offset = Shift(R[m], shift_t, shift_n, APSR.C);7314offset_addr = if add then (R[n] + offset) else (R[n] - offset);7315address = if index then offset_addr else R[n];7316data = MemU[address,2];7317if wback then R[n] = offset_addr;7318if UnalignedSupport() || address<0> = '0' then7319R[t] = ZeroExtend(data, 32);7320else // Can only apply before ARMv77321R[t] = bits(32) UNKNOWN;7322#endif73237324bool success = false;73257326if (ConditionPassed(opcode)) {7327uint32_t t;7328uint32_t n;7329uint32_t m;7330bool index;7331bool add;7332bool wback;7333ARM_ShifterType shift_t;7334uint32_t shift_n;73357336// EncodingSpecificOperations(); NullCheckIfThumbEE(n);7337switch (encoding) {7338case eEncodingT1:7339// if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation7340// in ThumbEE";7341// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7342t = Bits32(opcode, 2, 0);7343n = Bits32(opcode, 5, 3);7344m = Bits32(opcode, 8, 6);73457346// index = TRUE; add = TRUE; wback = FALSE;7347index = true;7348add = true;7349wback = false;73507351// (shift_t, shift_n) = (SRType_LSL, 0);7352shift_t = SRType_LSL;7353shift_n = 0;73547355break;73567357case eEncodingT2:7358// if Rn == '1111' then SEE LDRH (literal);7359// if Rt == '1111' then SEE "Unallocated memory hints";7360// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7361t = Bits32(opcode, 15, 12);7362n = Bits32(opcode, 19, 16);7363m = Bits32(opcode, 3, 0);73647365// index = TRUE; add = TRUE; wback = FALSE;7366index = true;7367add = true;7368wback = false;73697370// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));7371shift_t = SRType_LSL;7372shift_n = Bits32(opcode, 5, 4);73737374// if t == 13 || BadReg(m) then UNPREDICTABLE;7375if ((t == 13) || BadReg(m))7376return false;7377break;73787379case eEncodingA1:7380// if P == '0' && W == '1' then SEE LDRHT;7381// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7382t = Bits32(opcode, 15, 12);7383n = Bits32(opcode, 19, 16);7384m = Bits32(opcode, 3, 0);73857386// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||7387// (W == '1');7388index = BitIsSet(opcode, 24);7389add = BitIsSet(opcode, 23);7390wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));73917392// (shift_t, shift_n) = (SRType_LSL, 0);7393shift_t = SRType_LSL;7394shift_n = 0;73957396// if t == 15 || m == 15 then UNPREDICTABLE;7397if ((t == 15) || (m == 15))7398return false;73997400// if wback && (n == 15 || n == t) then UNPREDICTABLE;7401if (wback && ((n == 15) || (n == t)))7402return false;74037404break;74057406default:7407return false;7408}74097410// offset = Shift(R[m], shift_t, shift_n, APSR.C);74117412uint64_t Rm =7413ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);7414if (!success)7415return false;74167417addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);7418if (!success)7419return false;74207421addr_t offset_addr;7422addr_t address;74237424// offset_addr = if add then (R[n] + offset) else (R[n] - offset);7425uint64_t Rn =7426ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);7427if (!success)7428return false;74297430if (add)7431offset_addr = Rn + offset;7432else7433offset_addr = Rn - offset;74347435// address = if index then offset_addr else R[n];7436if (index)7437address = offset_addr;7438else7439address = Rn;74407441// data = MemU[address,2];7442std::optional<RegisterInfo> base_reg =7443GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);7444std::optional<RegisterInfo> offset_reg =7445GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);74467447EmulateInstruction::Context context;7448context.type = eContextRegisterLoad;7449context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);7450uint64_t data = MemURead(context, address, 2, 0, &success);7451if (!success)7452return false;74537454// if wback then R[n] = offset_addr;7455if (wback) {7456context.type = eContextAdjustBaseRegister;7457context.SetAddress(offset_addr);7458if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,7459offset_addr))7460return false;7461}74627463// if UnalignedSupport() || address<0> = '0' then7464if (UnalignedSupport() || BitIsClear(address, 0)) {7465// R[t] = ZeroExtend(data, 32);7466context.type = eContextRegisterLoad;7467context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);7468if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7469data))7470return false;7471} else // Can only apply before ARMv77472{7473// R[t] = bits(32) UNKNOWN;7474WriteBits32Unknown(t);7475}7476}7477return true;7478}74797480// LDRSB (immediate) calculates an address from a base register value and an7481// immediate offset, loads a byte from7482// memory, sign-extends it to form a 32-bit word, and writes it to a register.7483// It can use offset, post-indexed, or pre-indexed addressing.7484bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,7485const ARMEncoding encoding) {7486#if 07487if ConditionPassed() then7488EncodingSpecificOperations(); NullCheckIfThumbEE(n);7489offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);7490address = if index then offset_addr else R[n];7491R[t] = SignExtend(MemU[address,1], 32);7492if wback then R[n] = offset_addr;7493#endif74947495bool success = false;74967497if (ConditionPassed(opcode)) {7498uint32_t t;7499uint32_t n;7500uint32_t imm32;7501bool index;7502bool add;7503bool wback;75047505// EncodingSpecificOperations(); NullCheckIfThumbEE(n);7506switch (encoding) {7507case eEncodingT1:7508// if Rt == '1111' then SEE PLI;7509// if Rn == '1111' then SEE LDRSB (literal);7510// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);7511t = Bits32(opcode, 15, 12);7512n = Bits32(opcode, 19, 16);7513imm32 = Bits32(opcode, 11, 0);75147515// index = TRUE; add = TRUE; wback = FALSE;7516index = true;7517add = true;7518wback = false;75197520// if t == 13 then UNPREDICTABLE;7521if (t == 13)7522return false;75237524break;75257526case eEncodingT2:7527// if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;7528// if Rn == '1111' then SEE LDRSB (literal);7529// if P == '1' && U == '1' && W == '0' then SEE LDRSBT;7530// if P == '0' && W == '0' then UNDEFINED;7531if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))7532return false;75337534// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);7535t = Bits32(opcode, 15, 12);7536n = Bits32(opcode, 19, 16);7537imm32 = Bits32(opcode, 7, 0);75387539// index = (P == '1'); add = (U == '1'); wback = (W == '1');7540index = BitIsSet(opcode, 10);7541add = BitIsSet(opcode, 9);7542wback = BitIsSet(opcode, 8);75437544// if BadReg(t) || (wback && n == t) then UNPREDICTABLE;7545if (((t == 13) ||7546((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) ||7547BitIsSet(opcode, 8)))) ||7548(wback && (n == t)))7549return false;75507551break;75527553case eEncodingA1: {7554// if Rn == '1111' then SEE LDRSB (literal);7555// if P == '0' && W == '1' then SEE LDRSBT;7556// t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);7557t = Bits32(opcode, 15, 12);7558n = Bits32(opcode, 19, 16);75597560uint32_t imm4H = Bits32(opcode, 11, 8);7561uint32_t imm4L = Bits32(opcode, 3, 0);7562imm32 = (imm4H << 4) | imm4L;75637564// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||7565// (W == '1');7566index = BitIsSet(opcode, 24);7567add = BitIsSet(opcode, 23);7568wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));75697570// if t == 15 || (wback && n == t) then UNPREDICTABLE;7571if ((t == 15) || (wback && (n == t)))7572return false;75737574break;7575}75767577default:7578return false;7579}75807581uint64_t Rn = ReadCoreReg(n, &success);7582if (!success)7583return false;75847585addr_t offset_addr;7586addr_t address;75877588// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);7589if (add)7590offset_addr = Rn + imm32;7591else7592offset_addr = Rn - imm32;75937594// address = if index then offset_addr else R[n];7595if (index)7596address = offset_addr;7597else7598address = Rn;75997600// R[t] = SignExtend(MemU[address,1], 32);7601std::optional<RegisterInfo> base_reg =7602GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);76037604EmulateInstruction::Context context;7605context.type = eContextRegisterLoad;7606context.SetRegisterPlusOffset(*base_reg, address - Rn);76077608uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);7609if (!success)7610return false;76117612int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);7613if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7614(uint64_t)signed_data))7615return false;76167617// if wback then R[n] = offset_addr;7618if (wback) {7619context.type = eContextAdjustBaseRegister;7620context.SetAddress(offset_addr);7621if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,7622offset_addr))7623return false;7624}7625}76267627return true;7628}76297630// LDRSB (literal) calculates an address from the PC value and an immediate7631// offset, loads a byte from memory,7632// sign-extends it to form a 32-bit word, and writes tit to a register.7633bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,7634const ARMEncoding encoding) {7635#if 07636if ConditionPassed() then7637EncodingSpecificOperations(); NullCheckIfThumbEE(15);7638base = Align(PC,4);7639address = if add then (base + imm32) else (base - imm32);7640R[t] = SignExtend(MemU[address,1], 32);7641#endif76427643bool success = false;76447645if (ConditionPassed(opcode)) {7646uint32_t t;7647uint32_t imm32;7648bool add;76497650// EncodingSpecificOperations(); NullCheckIfThumbEE(15);7651switch (encoding) {7652case eEncodingT1:7653// if Rt == '1111' then SEE PLI;7654// t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');7655t = Bits32(opcode, 15, 12);7656imm32 = Bits32(opcode, 11, 0);7657add = BitIsSet(opcode, 23);76587659// if t == 13 then UNPREDICTABLE;7660if (t == 13)7661return false;76627663break;76647665case eEncodingA1: {7666// t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');7667t = Bits32(opcode, 15, 12);7668uint32_t imm4H = Bits32(opcode, 11, 8);7669uint32_t imm4L = Bits32(opcode, 3, 0);7670imm32 = (imm4H << 4) | imm4L;7671add = BitIsSet(opcode, 23);76727673// if t == 15 then UNPREDICTABLE;7674if (t == 15)7675return false;76767677break;7678}76797680default:7681return false;7682}76837684// base = Align(PC,4);7685uint64_t pc_value = ReadCoreReg(PC_REG, &success);7686if (!success)7687return false;7688uint64_t base = AlignPC(pc_value);76897690// address = if add then (base + imm32) else (base - imm32);7691addr_t address;7692if (add)7693address = base + imm32;7694else7695address = base - imm32;76967697// R[t] = SignExtend(MemU[address,1], 32);7698std::optional<RegisterInfo> base_reg =7699GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);77007701EmulateInstruction::Context context;7702context.type = eContextRegisterLoad;7703context.SetRegisterPlusOffset(*base_reg, address - base);77047705uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);7706if (!success)7707return false;77087709int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);7710if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7711(uint64_t)signed_data))7712return false;7713}7714return true;7715}77167717// LDRSB (register) calculates an address from a base register value and an7718// offset register value, loadsa byte from7719// memory, sign-extends it to form a 32-bit word, and writes it to a register.7720// The offset register value can be shifted left by 0, 1, 2, or 3 bits.7721bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,7722const ARMEncoding encoding) {7723#if 07724if ConditionPassed() then7725EncodingSpecificOperations(); NullCheckIfThumbEE(n);7726offset = Shift(R[m], shift_t, shift_n, APSR.C);7727offset_addr = if add then (R[n] + offset) else (R[n] - offset);7728address = if index then offset_addr else R[n];7729R[t] = SignExtend(MemU[address,1], 32);7730if wback then R[n] = offset_addr;7731#endif77327733bool success = false;77347735if (ConditionPassed(opcode)) {7736uint32_t t;7737uint32_t n;7738uint32_t m;7739bool index;7740bool add;7741bool wback;7742ARM_ShifterType shift_t;7743uint32_t shift_n;77447745// EncodingSpecificOperations(); NullCheckIfThumbEE(n);7746switch (encoding) {7747case eEncodingT1:7748// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7749t = Bits32(opcode, 2, 0);7750n = Bits32(opcode, 5, 3);7751m = Bits32(opcode, 8, 6);77527753// index = TRUE; add = TRUE; wback = FALSE;7754index = true;7755add = true;7756wback = false;77577758// (shift_t, shift_n) = (SRType_LSL, 0);7759shift_t = SRType_LSL;7760shift_n = 0;77617762break;77637764case eEncodingT2:7765// if Rt == '1111' then SEE PLI;7766// if Rn == '1111' then SEE LDRSB (literal);7767// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7768t = Bits32(opcode, 15, 12);7769n = Bits32(opcode, 19, 16);7770m = Bits32(opcode, 3, 0);77717772// index = TRUE; add = TRUE; wback = FALSE;7773index = true;7774add = true;7775wback = false;77767777// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));7778shift_t = SRType_LSL;7779shift_n = Bits32(opcode, 5, 4);77807781// if t == 13 || BadReg(m) then UNPREDICTABLE;7782if ((t == 13) || BadReg(m))7783return false;7784break;77857786case eEncodingA1:7787// if P == '0' && W == '1' then SEE LDRSBT;7788// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7789t = Bits32(opcode, 15, 12);7790n = Bits32(opcode, 19, 16);7791m = Bits32(opcode, 3, 0);77927793// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||7794// (W == '1');7795index = BitIsSet(opcode, 24);7796add = BitIsSet(opcode, 23);7797wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);77987799// (shift_t, shift_n) = (SRType_LSL, 0);7800shift_t = SRType_LSL;7801shift_n = 0;78027803// if t == 15 || m == 15 then UNPREDICTABLE;7804if ((t == 15) || (m == 15))7805return false;78067807// if wback && (n == 15 || n == t) then UNPREDICTABLE;7808if (wback && ((n == 15) || (n == t)))7809return false;7810break;78117812default:7813return false;7814}78157816uint64_t Rm =7817ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);7818if (!success)7819return false;78207821// offset = Shift(R[m], shift_t, shift_n, APSR.C);7822addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);7823if (!success)7824return false;78257826addr_t offset_addr;7827addr_t address;78287829// offset_addr = if add then (R[n] + offset) else (R[n] - offset);7830uint64_t Rn =7831ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);7832if (!success)7833return false;78347835if (add)7836offset_addr = Rn + offset;7837else7838offset_addr = Rn - offset;78397840// address = if index then offset_addr else R[n];7841if (index)7842address = offset_addr;7843else7844address = Rn;78457846// R[t] = SignExtend(MemU[address,1], 32);7847std::optional<RegisterInfo> base_reg =7848GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);7849std::optional<RegisterInfo> offset_reg =7850GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);78517852EmulateInstruction::Context context;7853context.type = eContextRegisterLoad;7854context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);78557856uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);7857if (!success)7858return false;78597860int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);7861if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7862(uint64_t)signed_data))7863return false;78647865// if wback then R[n] = offset_addr;7866if (wback) {7867context.type = eContextAdjustBaseRegister;7868context.SetAddress(offset_addr);7869if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,7870offset_addr))7871return false;7872}7873}7874return true;7875}78767877// LDRSH (immediate) calculates an address from a base register value and an7878// immediate offset, loads a halfword from7879// memory, sign-extends it to form a 32-bit word, and writes it to a register.7880// It can use offset, post-indexed, or pre-indexed addressing.7881bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,7882const ARMEncoding encoding) {7883#if 07884if ConditionPassed() then7885EncodingSpecificOperations(); NullCheckIfThumbEE(n);7886offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);7887address = if index then offset_addr else R[n];7888data = MemU[address,2];7889if wback then R[n] = offset_addr;7890if UnalignedSupport() || address<0> = '0' then7891R[t] = SignExtend(data, 32);7892else // Can only apply before ARMv77893R[t] = bits(32) UNKNOWN;7894#endif78957896bool success = false;78977898if (ConditionPassed(opcode)) {7899uint32_t t;7900uint32_t n;7901uint32_t imm32;7902bool index;7903bool add;7904bool wback;79057906// EncodingSpecificOperations(); NullCheckIfThumbEE(n);7907switch (encoding) {7908case eEncodingT1:7909// if Rn == '1111' then SEE LDRSH (literal);7910// if Rt == '1111' then SEE "Unallocated memory hints";7911// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);7912t = Bits32(opcode, 15, 12);7913n = Bits32(opcode, 19, 16);7914imm32 = Bits32(opcode, 11, 0);79157916// index = TRUE; add = TRUE; wback = FALSE;7917index = true;7918add = true;7919wback = false;79207921// if t == 13 then UNPREDICTABLE;7922if (t == 13)7923return false;79247925break;79267927case eEncodingT2:7928// if Rn == '1111' then SEE LDRSH (literal);7929// if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE7930// "Unallocated memory hints";7931// if P == '1' && U == '1' && W == '0' then SEE LDRSHT;7932// if P == '0' && W == '0' then UNDEFINED;7933if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))7934return false;79357936// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);7937t = Bits32(opcode, 15, 12);7938n = Bits32(opcode, 19, 16);7939imm32 = Bits32(opcode, 7, 0);79407941// index = (P == '1'); add = (U == '1'); wback = (W == '1');7942index = BitIsSet(opcode, 10);7943add = BitIsSet(opcode, 9);7944wback = BitIsSet(opcode, 8);79457946// if BadReg(t) || (wback && n == t) then UNPREDICTABLE;7947if (BadReg(t) || (wback && (n == t)))7948return false;79497950break;79517952case eEncodingA1: {7953// if Rn == '1111' then SEE LDRSH (literal);7954// if P == '0' && W == '1' then SEE LDRSHT;7955// t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);7956t = Bits32(opcode, 15, 12);7957n = Bits32(opcode, 19, 16);7958uint32_t imm4H = Bits32(opcode, 11, 8);7959uint32_t imm4L = Bits32(opcode, 3, 0);7960imm32 = (imm4H << 4) | imm4L;79617962// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||7963// (W == '1');7964index = BitIsSet(opcode, 24);7965add = BitIsSet(opcode, 23);7966wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);79677968// if t == 15 || (wback && n == t) then UNPREDICTABLE;7969if ((t == 15) || (wback && (n == t)))7970return false;79717972break;7973}79747975default:7976return false;7977}79787979// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);7980uint64_t Rn =7981ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);7982if (!success)7983return false;79847985addr_t offset_addr;7986if (add)7987offset_addr = Rn + imm32;7988else7989offset_addr = Rn - imm32;79907991// address = if index then offset_addr else R[n];7992addr_t address;7993if (index)7994address = offset_addr;7995else7996address = Rn;79977998// data = MemU[address,2];7999std::optional<RegisterInfo> base_reg =8000GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);80018002EmulateInstruction::Context context;8003context.type = eContextRegisterLoad;8004context.SetRegisterPlusOffset(*base_reg, address - Rn);80058006uint64_t data = MemURead(context, address, 2, 0, &success);8007if (!success)8008return false;80098010// if wback then R[n] = offset_addr;8011if (wback) {8012context.type = eContextAdjustBaseRegister;8013context.SetAddress(offset_addr);8014if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,8015offset_addr))8016return false;8017}80188019// if UnalignedSupport() || address<0> = '0' then8020if (UnalignedSupport() || BitIsClear(address, 0)) {8021// R[t] = SignExtend(data, 32);8022int64_t signed_data = llvm::SignExtend64<16>(data);8023context.type = eContextRegisterLoad;8024context.SetRegisterPlusOffset(*base_reg, address - Rn);8025if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,8026(uint64_t)signed_data))8027return false;8028} else // Can only apply before ARMv78029{8030// R[t] = bits(32) UNKNOWN;8031WriteBits32Unknown(t);8032}8033}8034return true;8035}80368037// LDRSH (literal) calculates an address from the PC value and an immediate8038// offset, loads a halfword from memory,8039// sign-extends it to from a 32-bit word, and writes it to a register.8040bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,8041const ARMEncoding encoding) {8042#if 08043if ConditionPassed() then8044EncodingSpecificOperations(); NullCheckIfThumbEE(15);8045base = Align(PC,4);8046address = if add then (base + imm32) else (base - imm32);8047data = MemU[address,2];8048if UnalignedSupport() || address<0> = '0' then8049R[t] = SignExtend(data, 32);8050else // Can only apply before ARMv78051R[t] = bits(32) UNKNOWN;8052#endif80538054bool success = false;80558056if (ConditionPassed(opcode)) {8057uint32_t t;8058uint32_t imm32;8059bool add;80608061// EncodingSpecificOperations(); NullCheckIfThumbEE(15);8062switch (encoding) {8063case eEncodingT1:8064// if Rt == '1111' then SEE "Unallocated memory hints";8065// t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');8066t = Bits32(opcode, 15, 12);8067imm32 = Bits32(opcode, 11, 0);8068add = BitIsSet(opcode, 23);80698070// if t == 13 then UNPREDICTABLE;8071if (t == 13)8072return false;80738074break;80758076case eEncodingA1: {8077// t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');8078t = Bits32(opcode, 15, 12);8079uint32_t imm4H = Bits32(opcode, 11, 8);8080uint32_t imm4L = Bits32(opcode, 3, 0);8081imm32 = (imm4H << 4) | imm4L;8082add = BitIsSet(opcode, 23);80838084// if t == 15 then UNPREDICTABLE;8085if (t == 15)8086return false;80878088break;8089}8090default:8091return false;8092}80938094// base = Align(PC,4);8095uint64_t pc_value = ReadCoreReg(PC_REG, &success);8096if (!success)8097return false;80988099uint64_t base = AlignPC(pc_value);81008101addr_t address;8102// address = if add then (base + imm32) else (base - imm32);8103if (add)8104address = base + imm32;8105else8106address = base - imm32;81078108// data = MemU[address,2];8109std::optional<RegisterInfo> base_reg =8110GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);81118112EmulateInstruction::Context context;8113context.type = eContextRegisterLoad;8114context.SetRegisterPlusOffset(*base_reg, imm32);81158116uint64_t data = MemURead(context, address, 2, 0, &success);8117if (!success)8118return false;81198120// if UnalignedSupport() || address<0> = '0' then8121if (UnalignedSupport() || BitIsClear(address, 0)) {8122// R[t] = SignExtend(data, 32);8123int64_t signed_data = llvm::SignExtend64<16>(data);8124if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,8125(uint64_t)signed_data))8126return false;8127} else // Can only apply before ARMv78128{8129// R[t] = bits(32) UNKNOWN;8130WriteBits32Unknown(t);8131}8132}8133return true;8134}81358136// LDRSH (register) calculates an address from a base register value and an8137// offset register value, loads a halfword8138// from memory, sign-extends it to form a 32-bit word, and writes it to a8139// register. The offset register value can be shifted left by 0, 1, 2, or 38140// bits.8141bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,8142const ARMEncoding encoding) {8143#if 08144if ConditionPassed() then8145EncodingSpecificOperations(); NullCheckIfThumbEE(n);8146offset = Shift(R[m], shift_t, shift_n, APSR.C);8147offset_addr = if add then (R[n] + offset) else (R[n] - offset);8148address = if index then offset_addr else R[n];8149data = MemU[address,2];8150if wback then R[n] = offset_addr;8151if UnalignedSupport() || address<0> = '0' then8152R[t] = SignExtend(data, 32);8153else // Can only apply before ARMv78154R[t] = bits(32) UNKNOWN;8155#endif81568157bool success = false;81588159if (ConditionPassed(opcode)) {8160uint32_t t;8161uint32_t n;8162uint32_t m;8163bool index;8164bool add;8165bool wback;8166ARM_ShifterType shift_t;8167uint32_t shift_n;81688169// EncodingSpecificOperations(); NullCheckIfThumbEE(n);8170switch (encoding) {8171case eEncodingT1:8172// if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation8173// in ThumbEE";8174// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);8175t = Bits32(opcode, 2, 0);8176n = Bits32(opcode, 5, 3);8177m = Bits32(opcode, 8, 6);81788179// index = TRUE; add = TRUE; wback = FALSE;8180index = true;8181add = true;8182wback = false;81838184// (shift_t, shift_n) = (SRType_LSL, 0);8185shift_t = SRType_LSL;8186shift_n = 0;81878188break;81898190case eEncodingT2:8191// if Rn == '1111' then SEE LDRSH (literal);8192// if Rt == '1111' then SEE "Unallocated memory hints";8193// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);8194t = Bits32(opcode, 15, 12);8195n = Bits32(opcode, 19, 16);8196m = Bits32(opcode, 3, 0);81978198// index = TRUE; add = TRUE; wback = FALSE;8199index = true;8200add = true;8201wback = false;82028203// (shift_t, shift_n) = (SRType_LSL, UInt(imm2));8204shift_t = SRType_LSL;8205shift_n = Bits32(opcode, 5, 4);82068207// if t == 13 || BadReg(m) then UNPREDICTABLE;8208if ((t == 13) || BadReg(m))8209return false;82108211break;82128213case eEncodingA1:8214// if P == '0' && W == '1' then SEE LDRSHT;8215// t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);8216t = Bits32(opcode, 15, 12);8217n = Bits32(opcode, 19, 16);8218m = Bits32(opcode, 3, 0);82198220// index = (P == '1'); add = (U == '1'); wback = (P == '0') ||8221// (W == '1');8222index = BitIsSet(opcode, 24);8223add = BitIsSet(opcode, 23);8224wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);82258226// (shift_t, shift_n) = (SRType_LSL, 0);8227shift_t = SRType_LSL;8228shift_n = 0;82298230// if t == 15 || m == 15 then UNPREDICTABLE;8231if ((t == 15) || (m == 15))8232return false;82338234// if wback && (n == 15 || n == t) then UNPREDICTABLE;8235if (wback && ((n == 15) || (n == t)))8236return false;82378238break;82398240default:8241return false;8242}82438244uint64_t Rm =8245ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);8246if (!success)8247return false;82488249uint64_t Rn =8250ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);8251if (!success)8252return false;82538254// offset = Shift(R[m], shift_t, shift_n, APSR.C);8255addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);8256if (!success)8257return false;82588259addr_t offset_addr;8260addr_t address;82618262// offset_addr = if add then (R[n] + offset) else (R[n] - offset);8263if (add)8264offset_addr = Rn + offset;8265else8266offset_addr = Rn - offset;82678268// address = if index then offset_addr else R[n];8269if (index)8270address = offset_addr;8271else8272address = Rn;82738274// data = MemU[address,2];8275std::optional<RegisterInfo> base_reg =8276GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);8277std::optional<RegisterInfo> offset_reg =8278GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);82798280EmulateInstruction::Context context;8281context.type = eContextRegisterLoad;8282context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);82838284uint64_t data = MemURead(context, address, 2, 0, &success);8285if (!success)8286return false;82878288// if wback then R[n] = offset_addr;8289if (wback) {8290context.type = eContextAdjustBaseRegister;8291context.SetAddress(offset_addr);8292if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,8293offset_addr))8294return false;8295}82968297// if UnalignedSupport() || address<0> = '0' then8298if (UnalignedSupport() || BitIsClear(address, 0)) {8299// R[t] = SignExtend(data, 32);8300context.type = eContextRegisterLoad;8301context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);83028303int64_t signed_data = llvm::SignExtend64<16>(data);8304if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,8305(uint64_t)signed_data))8306return false;8307} else // Can only apply before ARMv78308{8309// R[t] = bits(32) UNKNOWN;8310WriteBits32Unknown(t);8311}8312}8313return true;8314}83158316// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and8317// writes the result to the destination8318// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before8319// extracting the 8-bit value.8320bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode,8321const ARMEncoding encoding) {8322#if 08323if ConditionPassed() then8324EncodingSpecificOperations();8325rotated = ROR(R[m], rotation);8326R[d] = SignExtend(rotated<7:0>, 32);8327#endif83288329bool success = false;83308331if (ConditionPassed(opcode)) {8332uint32_t d;8333uint32_t m;8334uint32_t rotation;83358336// EncodingSpecificOperations();8337switch (encoding) {8338case eEncodingT1:8339// d = UInt(Rd); m = UInt(Rm); rotation = 0;8340d = Bits32(opcode, 2, 0);8341m = Bits32(opcode, 5, 3);8342rotation = 0;83438344break;83458346case eEncodingT2:8347// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8348d = Bits32(opcode, 11, 8);8349m = Bits32(opcode, 3, 0);8350rotation = Bits32(opcode, 5, 4) << 3;83518352// if BadReg(d) || BadReg(m) then UNPREDICTABLE;8353if (BadReg(d) || BadReg(m))8354return false;83558356break;83578358case eEncodingA1:8359// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8360d = Bits32(opcode, 15, 12);8361m = Bits32(opcode, 3, 0);8362rotation = Bits32(opcode, 11, 10) << 3;83638364// if d == 15 || m == 15 then UNPREDICTABLE;8365if ((d == 15) || (m == 15))8366return false;83678368break;83698370default:8371return false;8372}83738374uint64_t Rm =8375ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);8376if (!success)8377return false;83788379// rotated = ROR(R[m], rotation);8380uint64_t rotated = ROR(Rm, rotation, &success);8381if (!success)8382return false;83838384// R[d] = SignExtend(rotated<7:0>, 32);8385int64_t data = llvm::SignExtend64<8>(rotated);83868387std::optional<RegisterInfo> source_reg =8388GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);83898390EmulateInstruction::Context context;8391context.type = eContextRegisterLoad;8392context.SetRegister(*source_reg);83938394if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,8395(uint64_t)data))8396return false;8397}8398return true;8399}84008401// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and8402// writes the result to the destination8403// register. You can specify a rotation by 0, 8, 16, or 24 bits before8404// extracting the 16-bit value.8405bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode,8406const ARMEncoding encoding) {8407#if 08408if ConditionPassed() then8409EncodingSpecificOperations();8410rotated = ROR(R[m], rotation);8411R[d] = SignExtend(rotated<15:0>, 32);8412#endif84138414bool success = false;84158416if (ConditionPassed(opcode)) {8417uint32_t d;8418uint32_t m;8419uint32_t rotation;84208421// EncodingSpecificOperations();8422switch (encoding) {8423case eEncodingT1:8424// d = UInt(Rd); m = UInt(Rm); rotation = 0;8425d = Bits32(opcode, 2, 0);8426m = Bits32(opcode, 5, 3);8427rotation = 0;84288429break;84308431case eEncodingT2:8432// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8433d = Bits32(opcode, 11, 8);8434m = Bits32(opcode, 3, 0);8435rotation = Bits32(opcode, 5, 4) << 3;84368437// if BadReg(d) || BadReg(m) then UNPREDICTABLE;8438if (BadReg(d) || BadReg(m))8439return false;84408441break;84428443case eEncodingA1:8444// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8445d = Bits32(opcode, 15, 12);8446m = Bits32(opcode, 3, 0);8447rotation = Bits32(opcode, 11, 10) << 3;84488449// if d == 15 || m == 15 then UNPREDICTABLE;8450if ((d == 15) || (m == 15))8451return false;84528453break;84548455default:8456return false;8457}84588459uint64_t Rm =8460ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);8461if (!success)8462return false;84638464// rotated = ROR(R[m], rotation);8465uint64_t rotated = ROR(Rm, rotation, &success);8466if (!success)8467return false;84688469// R[d] = SignExtend(rotated<15:0>, 32);8470std::optional<RegisterInfo> source_reg =8471GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);84728473EmulateInstruction::Context context;8474context.type = eContextRegisterLoad;8475context.SetRegister(*source_reg);84768477int64_t data = llvm::SignExtend64<16>(rotated);8478if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,8479(uint64_t)data))8480return false;8481}84828483return true;8484}84858486// UXTB extracts an 8-bit value from a register, zero-extends it to 32 bits, and8487// writes the result to the destination8488// register. You can specify a rotation by 0, 8, 16, or 24 bits before8489// extracting the 8-bit value.8490bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode,8491const ARMEncoding encoding) {8492#if 08493if ConditionPassed() then8494EncodingSpecificOperations();8495rotated = ROR(R[m], rotation);8496R[d] = ZeroExtend(rotated<7:0>, 32);8497#endif84988499bool success = false;85008501if (ConditionPassed(opcode)) {8502uint32_t d;8503uint32_t m;8504uint32_t rotation;85058506// EncodingSpecificOperations();8507switch (encoding) {8508case eEncodingT1:8509// d = UInt(Rd); m = UInt(Rm); rotation = 0;8510d = Bits32(opcode, 2, 0);8511m = Bits32(opcode, 5, 3);8512rotation = 0;85138514break;85158516case eEncodingT2:8517// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8518d = Bits32(opcode, 11, 8);8519m = Bits32(opcode, 3, 0);8520rotation = Bits32(opcode, 5, 4) << 3;85218522// if BadReg(d) || BadReg(m) then UNPREDICTABLE;8523if (BadReg(d) || BadReg(m))8524return false;85258526break;85278528case eEncodingA1:8529// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8530d = Bits32(opcode, 15, 12);8531m = Bits32(opcode, 3, 0);8532rotation = Bits32(opcode, 11, 10) << 3;85338534// if d == 15 || m == 15 then UNPREDICTABLE;8535if ((d == 15) || (m == 15))8536return false;85378538break;85398540default:8541return false;8542}85438544uint64_t Rm =8545ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);8546if (!success)8547return false;85488549// rotated = ROR(R[m], rotation);8550uint64_t rotated = ROR(Rm, rotation, &success);8551if (!success)8552return false;85538554// R[d] = ZeroExtend(rotated<7:0>, 32);8555std::optional<RegisterInfo> source_reg =8556GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);85578558EmulateInstruction::Context context;8559context.type = eContextRegisterLoad;8560context.SetRegister(*source_reg);85618562if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,8563Bits32(rotated, 7, 0)))8564return false;8565}8566return true;8567}85688569// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and8570// writes the result to the destination8571// register. You can specify a rotation by 0, 8, 16, or 24 bits before8572// extracting the 16-bit value.8573bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode,8574const ARMEncoding encoding) {8575#if 08576if ConditionPassed() then8577EncodingSpecificOperations();8578rotated = ROR(R[m], rotation);8579R[d] = ZeroExtend(rotated<15:0>, 32);8580#endif85818582bool success = false;85838584if (ConditionPassed(opcode)) {8585uint32_t d;8586uint32_t m;8587uint32_t rotation;85888589switch (encoding) {8590case eEncodingT1:8591// d = UInt(Rd); m = UInt(Rm); rotation = 0;8592d = Bits32(opcode, 2, 0);8593m = Bits32(opcode, 5, 3);8594rotation = 0;85958596break;85978598case eEncodingT2:8599// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8600d = Bits32(opcode, 11, 8);8601m = Bits32(opcode, 3, 0);8602rotation = Bits32(opcode, 5, 4) << 3;86038604// if BadReg(d) || BadReg(m) then UNPREDICTABLE;8605if (BadReg(d) || BadReg(m))8606return false;86078608break;86098610case eEncodingA1:8611// d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8612d = Bits32(opcode, 15, 12);8613m = Bits32(opcode, 3, 0);8614rotation = Bits32(opcode, 11, 10) << 3;86158616// if d == 15 || m == 15 then UNPREDICTABLE;8617if ((d == 15) || (m == 15))8618return false;86198620break;86218622default:8623return false;8624}86258626uint64_t Rm =8627ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);8628if (!success)8629return false;86308631// rotated = ROR(R[m], rotation);8632uint64_t rotated = ROR(Rm, rotation, &success);8633if (!success)8634return false;86358636// R[d] = ZeroExtend(rotated<15:0>, 32);8637std::optional<RegisterInfo> source_reg =8638GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);86398640EmulateInstruction::Context context;8641context.type = eContextRegisterLoad;8642context.SetRegister(*source_reg);86438644if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,8645Bits32(rotated, 15, 0)))8646return false;8647}8648return true;8649}86508651// RFE (Return From Exception) loads the PC and the CPSR from the word at the8652// specified address and the following8653// word respectively.8654bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,8655const ARMEncoding encoding) {8656#if 08657if ConditionPassed() then8658EncodingSpecificOperations();8659if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then8660UNPREDICTABLE;8661else8662address = if increment then R[n] else R[n]-8;8663if wordhigher then address = address+4;8664CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);8665BranchWritePC(MemA[address,4]);8666if wback then R[n] = if increment then R[n]+8 else R[n]-8;8667#endif86688669bool success = false;86708671if (ConditionPassed(opcode)) {8672uint32_t n;8673bool wback;8674bool increment;8675bool wordhigher;86768677// EncodingSpecificOperations();8678switch (encoding) {8679case eEncodingT1:8680// n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =8681// FALSE;8682n = Bits32(opcode, 19, 16);8683wback = BitIsSet(opcode, 21);8684increment = false;8685wordhigher = false;86868687// if n == 15 then UNPREDICTABLE;8688if (n == 15)8689return false;86908691// if InITBlock() && !LastInITBlock() then UNPREDICTABLE;8692if (InITBlock() && !LastInITBlock())8693return false;86948695break;86968697case eEncodingT2:8698// n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;8699n = Bits32(opcode, 19, 16);8700wback = BitIsSet(opcode, 21);8701increment = true;8702wordhigher = false;87038704// if n == 15 then UNPREDICTABLE;8705if (n == 15)8706return false;87078708// if InITBlock() && !LastInITBlock() then UNPREDICTABLE;8709if (InITBlock() && !LastInITBlock())8710return false;87118712break;87138714case eEncodingA1:8715// n = UInt(Rn);8716n = Bits32(opcode, 19, 16);87178718// wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);8719wback = BitIsSet(opcode, 21);8720increment = BitIsSet(opcode, 23);8721wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23));87228723// if n == 15 then UNPREDICTABLE;8724if (n == 15)8725return false;87268727break;87288729default:8730return false;8731}87328733// if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE8734// then8735if (!CurrentModeIsPrivileged())8736// UNPREDICTABLE;8737return false;8738else {8739uint64_t Rn =8740ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);8741if (!success)8742return false;87438744addr_t address;8745// address = if increment then R[n] else R[n]-8;8746if (increment)8747address = Rn;8748else8749address = Rn - 8;87508751// if wordhigher then address = address+4;8752if (wordhigher)8753address = address + 4;87548755// CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);8756std::optional<RegisterInfo> base_reg =8757GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);87588759EmulateInstruction::Context context;8760context.type = eContextReturnFromException;8761context.SetRegisterPlusOffset(*base_reg, address - Rn);87628763uint64_t data = MemARead(context, address + 4, 4, 0, &success);8764if (!success)8765return false;87668767CPSRWriteByInstr(data, 15, true);87688769// BranchWritePC(MemA[address,4]);8770uint64_t data2 = MemARead(context, address, 4, 0, &success);8771if (!success)8772return false;87738774BranchWritePC(context, data2);87758776// if wback then R[n] = if increment then R[n]+8 else R[n]-8;8777if (wback) {8778context.type = eContextAdjustBaseRegister;8779if (increment) {8780context.SetOffset(8);8781if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,8782Rn + 8))8783return false;8784} else {8785context.SetOffset(-8);8786if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,8787Rn - 8))8788return false;8789}8790} // if wback8791}8792} // if ConditionPassed()8793return true;8794}87958796// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a8797// register value and an immediate value, and writes the result to the8798// destination register. It can optionally update the condition flags based on8799// the result.8800bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,8801const ARMEncoding encoding) {8802#if 08803// ARM pseudo code...8804if ConditionPassed() then8805EncodingSpecificOperations();8806result = R[n] EOR imm32;8807if d == 15 then // Can only occur for ARM encoding8808ALUWritePC(result); // setflags is always FALSE here8809else8810R[d] = result;8811if setflags then8812APSR.N = result<31>;8813APSR.Z = IsZeroBit(result);8814APSR.C = carry;8815// APSR.V unchanged8816#endif88178818bool success = false;88198820if (ConditionPassed(opcode)) {8821uint32_t Rd, Rn;8822uint32_t8823imm32; // the immediate value to be ORed to the value obtained from Rn8824bool setflags;8825uint32_t carry; // the carry bit after ARM/Thumb Expand operation8826switch (encoding) {8827case eEncodingT1:8828Rd = Bits32(opcode, 11, 8);8829Rn = Bits32(opcode, 19, 16);8830setflags = BitIsSet(opcode, 20);8831imm32 = ThumbExpandImm_C(8832opcode, APSR_C,8833carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)8834// if Rd == '1111' && S == '1' then SEE TEQ (immediate);8835if (Rd == 15 && setflags)8836return EmulateTEQImm(opcode, eEncodingT1);8837if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))8838return false;8839break;8840case eEncodingA1:8841Rd = Bits32(opcode, 15, 12);8842Rn = Bits32(opcode, 19, 16);8843setflags = BitIsSet(opcode, 20);8844imm32 =8845ARMExpandImm_C(opcode, APSR_C,8846carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)88478848// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related8849// instructions;8850if (Rd == 15 && setflags)8851return EmulateSUBSPcLrEtc(opcode, encoding);8852break;8853default:8854return false;8855}88568857// Read the first operand.8858uint32_t val1 = ReadCoreReg(Rn, &success);8859if (!success)8860return false;88618862uint32_t result = val1 ^ imm32;88638864EmulateInstruction::Context context;8865context.type = EmulateInstruction::eContextImmediate;8866context.SetNoArgs();88678868if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))8869return false;8870}8871return true;8872}88738874// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a8875// register value and an optionally-shifted register value, and writes the8876// result to the destination register. It can optionally update the condition8877// flags based on the result.8878bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,8879const ARMEncoding encoding) {8880#if 08881// ARM pseudo code...8882if ConditionPassed() then8883EncodingSpecificOperations();8884(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);8885result = R[n] EOR shifted;8886if d == 15 then // Can only occur for ARM encoding8887ALUWritePC(result); // setflags is always FALSE here8888else8889R[d] = result;8890if setflags then8891APSR.N = result<31>;8892APSR.Z = IsZeroBit(result);8893APSR.C = carry;8894// APSR.V unchanged8895#endif88968897bool success = false;88988899if (ConditionPassed(opcode)) {8900uint32_t Rd, Rn, Rm;8901ARM_ShifterType shift_t;8902uint32_t shift_n; // the shift applied to the value read from Rm8903bool setflags;8904uint32_t carry;8905switch (encoding) {8906case eEncodingT1:8907Rd = Rn = Bits32(opcode, 2, 0);8908Rm = Bits32(opcode, 5, 3);8909setflags = !InITBlock();8910shift_t = SRType_LSL;8911shift_n = 0;8912break;8913case eEncodingT2:8914Rd = Bits32(opcode, 11, 8);8915Rn = Bits32(opcode, 19, 16);8916Rm = Bits32(opcode, 3, 0);8917setflags = BitIsSet(opcode, 20);8918shift_n = DecodeImmShiftThumb(opcode, shift_t);8919// if Rd == '1111' && S == '1' then SEE TEQ (register);8920if (Rd == 15 && setflags)8921return EmulateTEQReg(opcode, eEncodingT1);8922if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))8923return false;8924break;8925case eEncodingA1:8926Rd = Bits32(opcode, 15, 12);8927Rn = Bits32(opcode, 19, 16);8928Rm = Bits32(opcode, 3, 0);8929setflags = BitIsSet(opcode, 20);8930shift_n = DecodeImmShiftARM(opcode, shift_t);89318932// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related8933// instructions;8934if (Rd == 15 && setflags)8935return EmulateSUBSPcLrEtc(opcode, encoding);8936break;8937default:8938return false;8939}89408941// Read the first operand.8942uint32_t val1 = ReadCoreReg(Rn, &success);8943if (!success)8944return false;89458946// Read the second operand.8947uint32_t val2 = ReadCoreReg(Rm, &success);8948if (!success)8949return false;89508951uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);8952if (!success)8953return false;8954uint32_t result = val1 ^ shifted;89558956EmulateInstruction::Context context;8957context.type = EmulateInstruction::eContextImmediate;8958context.SetNoArgs();89598960if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))8961return false;8962}8963return true;8964}89658966// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value8967// and an immediate value, and writes the result to the destination register.8968// It can optionally update the condition flags based on the result.8969bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,8970const ARMEncoding encoding) {8971#if 08972// ARM pseudo code...8973if ConditionPassed() then8974EncodingSpecificOperations();8975result = R[n] OR imm32;8976if d == 15 then // Can only occur for ARM encoding8977ALUWritePC(result); // setflags is always FALSE here8978else8979R[d] = result;8980if setflags then8981APSR.N = result<31>;8982APSR.Z = IsZeroBit(result);8983APSR.C = carry;8984// APSR.V unchanged8985#endif89868987bool success = false;89888989if (ConditionPassed(opcode)) {8990uint32_t Rd, Rn;8991uint32_t8992imm32; // the immediate value to be ORed to the value obtained from Rn8993bool setflags;8994uint32_t carry; // the carry bit after ARM/Thumb Expand operation8995switch (encoding) {8996case eEncodingT1:8997Rd = Bits32(opcode, 11, 8);8998Rn = Bits32(opcode, 19, 16);8999setflags = BitIsSet(opcode, 20);9000imm32 = ThumbExpandImm_C(9001opcode, APSR_C,9002carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)9003// if Rn == '1111' then SEE MOV (immediate);9004if (Rn == 15)9005return EmulateMOVRdImm(opcode, eEncodingT2);9006if (BadReg(Rd) || Rn == 13)9007return false;9008break;9009case eEncodingA1:9010Rd = Bits32(opcode, 15, 12);9011Rn = Bits32(opcode, 19, 16);9012setflags = BitIsSet(opcode, 20);9013imm32 =9014ARMExpandImm_C(opcode, APSR_C,9015carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)90169017if (Rd == 15 && setflags)9018return EmulateSUBSPcLrEtc(opcode, encoding);9019break;9020default:9021return false;9022}90239024// Read the first operand.9025uint32_t val1 = ReadCoreReg(Rn, &success);9026if (!success)9027return false;90289029uint32_t result = val1 | imm32;90309031EmulateInstruction::Context context;9032context.type = EmulateInstruction::eContextImmediate;9033context.SetNoArgs();90349035if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))9036return false;9037}9038return true;9039}90409041// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value9042// and an optionally-shifted register value, and writes the result to the9043// destination register. It can optionally update the condition flags based on9044// the result.9045bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,9046const ARMEncoding encoding) {9047#if 09048// ARM pseudo code...9049if ConditionPassed() then9050EncodingSpecificOperations();9051(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);9052result = R[n] OR shifted;9053if d == 15 then // Can only occur for ARM encoding9054ALUWritePC(result); // setflags is always FALSE here9055else9056R[d] = result;9057if setflags then9058APSR.N = result<31>;9059APSR.Z = IsZeroBit(result);9060APSR.C = carry;9061// APSR.V unchanged9062#endif90639064bool success = false;90659066if (ConditionPassed(opcode)) {9067uint32_t Rd, Rn, Rm;9068ARM_ShifterType shift_t;9069uint32_t shift_n; // the shift applied to the value read from Rm9070bool setflags;9071uint32_t carry;9072switch (encoding) {9073case eEncodingT1:9074Rd = Rn = Bits32(opcode, 2, 0);9075Rm = Bits32(opcode, 5, 3);9076setflags = !InITBlock();9077shift_t = SRType_LSL;9078shift_n = 0;9079break;9080case eEncodingT2:9081Rd = Bits32(opcode, 11, 8);9082Rn = Bits32(opcode, 19, 16);9083Rm = Bits32(opcode, 3, 0);9084setflags = BitIsSet(opcode, 20);9085shift_n = DecodeImmShiftThumb(opcode, shift_t);9086// if Rn == '1111' then SEE MOV (register);9087if (Rn == 15)9088return EmulateMOVRdRm(opcode, eEncodingT3);9089if (BadReg(Rd) || Rn == 13 || BadReg(Rm))9090return false;9091break;9092case eEncodingA1:9093Rd = Bits32(opcode, 15, 12);9094Rn = Bits32(opcode, 19, 16);9095Rm = Bits32(opcode, 3, 0);9096setflags = BitIsSet(opcode, 20);9097shift_n = DecodeImmShiftARM(opcode, shift_t);90989099if (Rd == 15 && setflags)9100return EmulateSUBSPcLrEtc(opcode, encoding);9101break;9102default:9103return false;9104}91059106// Read the first operand.9107uint32_t val1 = ReadCoreReg(Rn, &success);9108if (!success)9109return false;91109111// Read the second operand.9112uint32_t val2 = ReadCoreReg(Rm, &success);9113if (!success)9114return false;91159116uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);9117if (!success)9118return false;9119uint32_t result = val1 | shifted;91209121EmulateInstruction::Context context;9122context.type = EmulateInstruction::eContextImmediate;9123context.SetNoArgs();91249125if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))9126return false;9127}9128return true;9129}91309131// Reverse Subtract (immediate) subtracts a register value from an immediate9132// value, and writes the result to the destination register. It can optionally9133// update the condition flags based on the result.9134bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,9135const ARMEncoding encoding) {9136#if 09137// ARM pseudo code...9138if ConditionPassed() then9139EncodingSpecificOperations();9140(result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');9141if d == 15 then // Can only occur for ARM encoding9142ALUWritePC(result); // setflags is always FALSE here9143else9144R[d] = result;9145if setflags then9146APSR.N = result<31>;9147APSR.Z = IsZeroBit(result);9148APSR.C = carry;9149APSR.V = overflow;9150#endif91519152bool success = false;91539154uint32_t Rd; // the destination register9155uint32_t Rn; // the first operand9156bool setflags;9157uint32_t9158imm32; // the immediate value to be added to the value obtained from Rn9159switch (encoding) {9160case eEncodingT1:9161Rd = Bits32(opcode, 2, 0);9162Rn = Bits32(opcode, 5, 3);9163setflags = !InITBlock();9164imm32 = 0;9165break;9166case eEncodingT2:9167Rd = Bits32(opcode, 11, 8);9168Rn = Bits32(opcode, 19, 16);9169setflags = BitIsSet(opcode, 20);9170imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)9171if (BadReg(Rd) || BadReg(Rn))9172return false;9173break;9174case eEncodingA1:9175Rd = Bits32(opcode, 15, 12);9176Rn = Bits32(opcode, 19, 16);9177setflags = BitIsSet(opcode, 20);9178imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)91799180// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9181// instructions;9182if (Rd == 15 && setflags)9183return EmulateSUBSPcLrEtc(opcode, encoding);9184break;9185default:9186return false;9187}9188// Read the register value from the operand register Rn.9189uint32_t reg_val = ReadCoreReg(Rn, &success);9190if (!success)9191return false;91929193AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);91949195EmulateInstruction::Context context;9196context.type = EmulateInstruction::eContextImmediate;9197context.SetNoArgs();91989199return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9200res.carry_out, res.overflow);9201}92029203// Reverse Subtract (register) subtracts a register value from an optionally-9204// shifted register value, and writes the result to the destination register.9205// It can optionally update the condition flags based on the result.9206bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,9207const ARMEncoding encoding) {9208#if 09209// ARM pseudo code...9210if ConditionPassed() then9211EncodingSpecificOperations();9212shifted = Shift(R[m], shift_t, shift_n, APSR.C);9213(result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');9214if d == 15 then // Can only occur for ARM encoding9215ALUWritePC(result); // setflags is always FALSE here9216else9217R[d] = result;9218if setflags then9219APSR.N = result<31>;9220APSR.Z = IsZeroBit(result);9221APSR.C = carry;9222APSR.V = overflow;9223#endif92249225bool success = false;92269227uint32_t Rd; // the destination register9228uint32_t Rn; // the first operand9229uint32_t Rm; // the second operand9230bool setflags;9231ARM_ShifterType shift_t;9232uint32_t shift_n; // the shift applied to the value read from Rm9233switch (encoding) {9234case eEncodingT1:9235Rd = Bits32(opcode, 11, 8);9236Rn = Bits32(opcode, 19, 16);9237Rm = Bits32(opcode, 3, 0);9238setflags = BitIsSet(opcode, 20);9239shift_n = DecodeImmShiftThumb(opcode, shift_t);9240// if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;9241if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))9242return false;9243break;9244case eEncodingA1:9245Rd = Bits32(opcode, 15, 12);9246Rn = Bits32(opcode, 19, 16);9247Rm = Bits32(opcode, 3, 0);9248setflags = BitIsSet(opcode, 20);9249shift_n = DecodeImmShiftARM(opcode, shift_t);92509251// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9252// instructions;9253if (Rd == 15 && setflags)9254return EmulateSUBSPcLrEtc(opcode, encoding);9255break;9256default:9257return false;9258}9259// Read the register value from register Rn.9260uint32_t val1 = ReadCoreReg(Rn, &success);9261if (!success)9262return false;92639264// Read the register value from register Rm.9265uint32_t val2 = ReadCoreReg(Rm, &success);9266if (!success)9267return false;92689269uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);9270if (!success)9271return false;9272AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);92739274EmulateInstruction::Context context;9275context.type = EmulateInstruction::eContextImmediate;9276context.SetNoArgs();9277return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9278res.carry_out, res.overflow);9279}92809281// Reverse Subtract with Carry (immediate) subtracts a register value and the9282// value of NOT (Carry flag) from an immediate value, and writes the result to9283// the destination register. It can optionally update the condition flags based9284// on the result.9285bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,9286const ARMEncoding encoding) {9287#if 09288// ARM pseudo code...9289if ConditionPassed() then9290EncodingSpecificOperations();9291(result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);9292if d == 15 then9293ALUWritePC(result); // setflags is always FALSE here9294else9295R[d] = result;9296if setflags then9297APSR.N = result<31>;9298APSR.Z = IsZeroBit(result);9299APSR.C = carry;9300APSR.V = overflow;9301#endif93029303bool success = false;93049305uint32_t Rd; // the destination register9306uint32_t Rn; // the first operand9307bool setflags;9308uint32_t9309imm32; // the immediate value to be added to the value obtained from Rn9310switch (encoding) {9311case eEncodingA1:9312Rd = Bits32(opcode, 15, 12);9313Rn = Bits32(opcode, 19, 16);9314setflags = BitIsSet(opcode, 20);9315imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)93169317// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9318// instructions;9319if (Rd == 15 && setflags)9320return EmulateSUBSPcLrEtc(opcode, encoding);9321break;9322default:9323return false;9324}9325// Read the register value from the operand register Rn.9326uint32_t reg_val = ReadCoreReg(Rn, &success);9327if (!success)9328return false;93299330AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);93319332EmulateInstruction::Context context;9333context.type = EmulateInstruction::eContextImmediate;9334context.SetNoArgs();93359336return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9337res.carry_out, res.overflow);9338}93399340// Reverse Subtract with Carry (register) subtracts a register value and the9341// value of NOT (Carry flag) from an optionally-shifted register value, and9342// writes the result to the destination register. It can optionally update the9343// condition flags based on the result.9344bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,9345const ARMEncoding encoding) {9346#if 09347// ARM pseudo code...9348if ConditionPassed() then9349EncodingSpecificOperations();9350shifted = Shift(R[m], shift_t, shift_n, APSR.C);9351(result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);9352if d == 15 then9353ALUWritePC(result); // setflags is always FALSE here9354else9355R[d] = result;9356if setflags then9357APSR.N = result<31>;9358APSR.Z = IsZeroBit(result);9359APSR.C = carry;9360APSR.V = overflow;9361#endif93629363bool success = false;93649365uint32_t Rd; // the destination register9366uint32_t Rn; // the first operand9367uint32_t Rm; // the second operand9368bool setflags;9369ARM_ShifterType shift_t;9370uint32_t shift_n; // the shift applied to the value read from Rm9371switch (encoding) {9372case eEncodingA1:9373Rd = Bits32(opcode, 15, 12);9374Rn = Bits32(opcode, 19, 16);9375Rm = Bits32(opcode, 3, 0);9376setflags = BitIsSet(opcode, 20);9377shift_n = DecodeImmShiftARM(opcode, shift_t);93789379// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9380// instructions;9381if (Rd == 15 && setflags)9382return EmulateSUBSPcLrEtc(opcode, encoding);9383break;9384default:9385return false;9386}9387// Read the register value from register Rn.9388uint32_t val1 = ReadCoreReg(Rn, &success);9389if (!success)9390return false;93919392// Read the register value from register Rm.9393uint32_t val2 = ReadCoreReg(Rm, &success);9394if (!success)9395return false;93969397uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);9398if (!success)9399return false;9400AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);94019402EmulateInstruction::Context context;9403context.type = EmulateInstruction::eContextImmediate;9404context.SetNoArgs();9405return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9406res.carry_out, res.overflow);9407}94089409// Subtract with Carry (immediate) subtracts an immediate value and the value9410// of9411// NOT (Carry flag) from a register value, and writes the result to the9412// destination register.9413// It can optionally update the condition flags based on the result.9414bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,9415const ARMEncoding encoding) {9416#if 09417// ARM pseudo code...9418if ConditionPassed() then9419EncodingSpecificOperations();9420(result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);9421if d == 15 then // Can only occur for ARM encoding9422ALUWritePC(result); // setflags is always FALSE here9423else9424R[d] = result;9425if setflags then9426APSR.N = result<31>;9427APSR.Z = IsZeroBit(result);9428APSR.C = carry;9429APSR.V = overflow;9430#endif94319432bool success = false;94339434uint32_t Rd; // the destination register9435uint32_t Rn; // the first operand9436bool setflags;9437uint32_t9438imm32; // the immediate value to be added to the value obtained from Rn9439switch (encoding) {9440case eEncodingT1:9441Rd = Bits32(opcode, 11, 8);9442Rn = Bits32(opcode, 19, 16);9443setflags = BitIsSet(opcode, 20);9444imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)9445if (BadReg(Rd) || BadReg(Rn))9446return false;9447break;9448case eEncodingA1:9449Rd = Bits32(opcode, 15, 12);9450Rn = Bits32(opcode, 19, 16);9451setflags = BitIsSet(opcode, 20);9452imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)94539454// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9455// instructions;9456if (Rd == 15 && setflags)9457return EmulateSUBSPcLrEtc(opcode, encoding);9458break;9459default:9460return false;9461}9462// Read the register value from the operand register Rn.9463uint32_t reg_val = ReadCoreReg(Rn, &success);9464if (!success)9465return false;94669467AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);94689469EmulateInstruction::Context context;9470context.type = EmulateInstruction::eContextImmediate;9471context.SetNoArgs();94729473return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9474res.carry_out, res.overflow);9475}94769477// Subtract with Carry (register) subtracts an optionally-shifted register9478// value and the value of9479// NOT (Carry flag) from a register value, and writes the result to the9480// destination register.9481// It can optionally update the condition flags based on the result.9482bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,9483const ARMEncoding encoding) {9484#if 09485// ARM pseudo code...9486if ConditionPassed() then9487EncodingSpecificOperations();9488shifted = Shift(R[m], shift_t, shift_n, APSR.C);9489(result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);9490if d == 15 then // Can only occur for ARM encoding9491ALUWritePC(result); // setflags is always FALSE here9492else9493R[d] = result;9494if setflags then9495APSR.N = result<31>;9496APSR.Z = IsZeroBit(result);9497APSR.C = carry;9498APSR.V = overflow;9499#endif95009501bool success = false;95029503uint32_t Rd; // the destination register9504uint32_t Rn; // the first operand9505uint32_t Rm; // the second operand9506bool setflags;9507ARM_ShifterType shift_t;9508uint32_t shift_n; // the shift applied to the value read from Rm9509switch (encoding) {9510case eEncodingT1:9511Rd = Rn = Bits32(opcode, 2, 0);9512Rm = Bits32(opcode, 5, 3);9513setflags = !InITBlock();9514shift_t = SRType_LSL;9515shift_n = 0;9516break;9517case eEncodingT2:9518Rd = Bits32(opcode, 11, 8);9519Rn = Bits32(opcode, 19, 16);9520Rm = Bits32(opcode, 3, 0);9521setflags = BitIsSet(opcode, 20);9522shift_n = DecodeImmShiftThumb(opcode, shift_t);9523if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))9524return false;9525break;9526case eEncodingA1:9527Rd = Bits32(opcode, 15, 12);9528Rn = Bits32(opcode, 19, 16);9529Rm = Bits32(opcode, 3, 0);9530setflags = BitIsSet(opcode, 20);9531shift_n = DecodeImmShiftARM(opcode, shift_t);95329533// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9534// instructions;9535if (Rd == 15 && setflags)9536return EmulateSUBSPcLrEtc(opcode, encoding);9537break;9538default:9539return false;9540}9541// Read the register value from register Rn.9542uint32_t val1 = ReadCoreReg(Rn, &success);9543if (!success)9544return false;95459546// Read the register value from register Rm.9547uint32_t val2 = ReadCoreReg(Rm, &success);9548if (!success)9549return false;95509551uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);9552if (!success)9553return false;9554AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);95559556EmulateInstruction::Context context;9557context.type = EmulateInstruction::eContextImmediate;9558context.SetNoArgs();9559return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9560res.carry_out, res.overflow);9561}95629563// This instruction subtracts an immediate value from a register value, and9564// writes the result to the destination register. It can optionally update the9565// condition flags based on the result.9566bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,9567const ARMEncoding encoding) {9568#if 09569// ARM pseudo code...9570if ConditionPassed() then9571EncodingSpecificOperations();9572(result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');9573R[d] = result;9574if setflags then9575APSR.N = result<31>;9576APSR.Z = IsZeroBit(result);9577APSR.C = carry;9578APSR.V = overflow;9579#endif95809581bool success = false;95829583uint32_t Rd; // the destination register9584uint32_t Rn; // the first operand9585bool setflags;9586uint32_t imm32; // the immediate value to be subtracted from the value9587// obtained from Rn9588switch (encoding) {9589case eEncodingT1:9590Rd = Bits32(opcode, 2, 0);9591Rn = Bits32(opcode, 5, 3);9592setflags = !InITBlock();9593imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)9594break;9595case eEncodingT2:9596Rd = Rn = Bits32(opcode, 10, 8);9597setflags = !InITBlock();9598imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)9599break;9600case eEncodingT3:9601Rd = Bits32(opcode, 11, 8);9602Rn = Bits32(opcode, 19, 16);9603setflags = BitIsSet(opcode, 20);9604imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)96059606// if Rd == '1111' && S == '1' then SEE CMP (immediate);9607if (Rd == 15 && setflags)9608return EmulateCMPImm(opcode, eEncodingT2);96099610// if Rn == '1101' then SEE SUB (SP minus immediate);9611if (Rn == 13)9612return EmulateSUBSPImm(opcode, eEncodingT2);96139614// if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;9615if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)9616return false;9617break;9618case eEncodingT4:9619Rd = Bits32(opcode, 11, 8);9620Rn = Bits32(opcode, 19, 16);9621setflags = BitIsSet(opcode, 20);9622imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)96239624// if Rn == '1111' then SEE ADR;9625if (Rn == 15)9626return EmulateADR(opcode, eEncodingT2);96279628// if Rn == '1101' then SEE SUB (SP minus immediate);9629if (Rn == 13)9630return EmulateSUBSPImm(opcode, eEncodingT3);96319632if (BadReg(Rd))9633return false;9634break;9635default:9636return false;9637}9638// Read the register value from the operand register Rn.9639uint32_t reg_val = ReadCoreReg(Rn, &success);9640if (!success)9641return false;96429643AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);96449645EmulateInstruction::Context context;9646context.type = EmulateInstruction::eContextImmediate;9647context.SetNoArgs();96489649return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9650res.carry_out, res.overflow);9651}96529653// This instruction subtracts an immediate value from a register value, and9654// writes the result to the destination register. It can optionally update the9655// condition flags based on the result.9656bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,9657const ARMEncoding encoding) {9658#if 09659// ARM pseudo code...9660if ConditionPassed() then9661EncodingSpecificOperations();9662(result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');9663if d == 15 then9664ALUWritePC(result); // setflags is always FALSE here9665else9666R[d] = result;9667if setflags then9668APSR.N = result<31>;9669APSR.Z = IsZeroBit(result);9670APSR.C = carry;9671APSR.V = overflow;9672#endif96739674bool success = false;96759676if (ConditionPassed(opcode)) {9677uint32_t Rd; // the destination register9678uint32_t Rn; // the first operand9679bool setflags;9680uint32_t imm32; // the immediate value to be subtracted from the value9681// obtained from Rn9682switch (encoding) {9683case eEncodingA1:9684Rd = Bits32(opcode, 15, 12);9685Rn = Bits32(opcode, 19, 16);9686setflags = BitIsSet(opcode, 20);9687imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)96889689// if Rn == '1111' && S == '0' then SEE ADR;9690if (Rn == 15 && !setflags)9691return EmulateADR(opcode, eEncodingA2);96929693// if Rn == '1101' then SEE SUB (SP minus immediate);9694if (Rn == 13)9695return EmulateSUBSPImm(opcode, eEncodingA1);96969697// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9698// instructions;9699if (Rd == 15 && setflags)9700return EmulateSUBSPcLrEtc(opcode, encoding);9701break;9702default:9703return false;9704}9705// Read the register value from the operand register Rn.9706uint32_t reg_val = ReadCoreReg(Rn, &success);9707if (!success)9708return false;97099710AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);97119712EmulateInstruction::Context context;9713if (Rd == 13)9714context.type = EmulateInstruction::eContextAdjustStackPointer;9715else9716context.type = EmulateInstruction::eContextRegisterPlusOffset;97179718std::optional<RegisterInfo> dwarf_reg =9719GetRegisterInfo(eRegisterKindDWARF, Rn);9720int64_t imm32_signed = imm32;9721context.SetRegisterPlusOffset(*dwarf_reg, -imm32_signed);97229723if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9724res.carry_out, res.overflow))9725return false;9726}9727return true;9728}97299730// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a9731// register value and an immediate value. It updates the condition flags based9732// on the result, and discards the result.9733bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,9734const ARMEncoding encoding) {9735#if 09736// ARM pseudo code...9737if ConditionPassed() then9738EncodingSpecificOperations();9739result = R[n] EOR imm32;9740APSR.N = result<31>;9741APSR.Z = IsZeroBit(result);9742APSR.C = carry;9743// APSR.V unchanged9744#endif97459746bool success = false;97479748if (ConditionPassed(opcode)) {9749uint32_t Rn;9750uint32_t9751imm32; // the immediate value to be ANDed to the value obtained from Rn9752uint32_t carry; // the carry bit after ARM/Thumb Expand operation9753switch (encoding) {9754case eEncodingT1:9755Rn = Bits32(opcode, 19, 16);9756imm32 = ThumbExpandImm_C(9757opcode, APSR_C,9758carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)9759if (BadReg(Rn))9760return false;9761break;9762case eEncodingA1:9763Rn = Bits32(opcode, 19, 16);9764imm32 =9765ARMExpandImm_C(opcode, APSR_C,9766carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)9767break;9768default:9769return false;9770}97719772// Read the first operand.9773uint32_t val1 = ReadCoreReg(Rn, &success);9774if (!success)9775return false;97769777uint32_t result = val1 ^ imm32;97789779EmulateInstruction::Context context;9780context.type = EmulateInstruction::eContextImmediate;9781context.SetNoArgs();97829783if (!WriteFlags(context, result, carry))9784return false;9785}9786return true;9787}97889789// Test Equivalence (register) performs a bitwise exclusive OR operation on a9790// register value and an optionally-shifted register value. It updates the9791// condition flags based on the result, and discards the result.9792bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,9793const ARMEncoding encoding) {9794#if 09795// ARM pseudo code...9796if ConditionPassed() then9797EncodingSpecificOperations();9798(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);9799result = R[n] EOR shifted;9800APSR.N = result<31>;9801APSR.Z = IsZeroBit(result);9802APSR.C = carry;9803// APSR.V unchanged9804#endif98059806bool success = false;98079808if (ConditionPassed(opcode)) {9809uint32_t Rn, Rm;9810ARM_ShifterType shift_t;9811uint32_t shift_n; // the shift applied to the value read from Rm9812uint32_t carry;9813switch (encoding) {9814case eEncodingT1:9815Rn = Bits32(opcode, 19, 16);9816Rm = Bits32(opcode, 3, 0);9817shift_n = DecodeImmShiftThumb(opcode, shift_t);9818if (BadReg(Rn) || BadReg(Rm))9819return false;9820break;9821case eEncodingA1:9822Rn = Bits32(opcode, 19, 16);9823Rm = Bits32(opcode, 3, 0);9824shift_n = DecodeImmShiftARM(opcode, shift_t);9825break;9826default:9827return false;9828}98299830// Read the first operand.9831uint32_t val1 = ReadCoreReg(Rn, &success);9832if (!success)9833return false;98349835// Read the second operand.9836uint32_t val2 = ReadCoreReg(Rm, &success);9837if (!success)9838return false;98399840uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);9841if (!success)9842return false;9843uint32_t result = val1 ^ shifted;98449845EmulateInstruction::Context context;9846context.type = EmulateInstruction::eContextImmediate;9847context.SetNoArgs();98489849if (!WriteFlags(context, result, carry))9850return false;9851}9852return true;9853}98549855// Test (immediate) performs a bitwise AND operation on a register value and an9856// immediate value. It updates the condition flags based on the result, and9857// discards the result.9858bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,9859const ARMEncoding encoding) {9860#if 09861// ARM pseudo code...9862if ConditionPassed() then9863EncodingSpecificOperations();9864result = R[n] AND imm32;9865APSR.N = result<31>;9866APSR.Z = IsZeroBit(result);9867APSR.C = carry;9868// APSR.V unchanged9869#endif98709871bool success = false;98729873if (ConditionPassed(opcode)) {9874uint32_t Rn;9875uint32_t9876imm32; // the immediate value to be ANDed to the value obtained from Rn9877uint32_t carry; // the carry bit after ARM/Thumb Expand operation9878switch (encoding) {9879case eEncodingT1:9880Rn = Bits32(opcode, 19, 16);9881imm32 = ThumbExpandImm_C(9882opcode, APSR_C,9883carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)9884if (BadReg(Rn))9885return false;9886break;9887case eEncodingA1:9888Rn = Bits32(opcode, 19, 16);9889imm32 =9890ARMExpandImm_C(opcode, APSR_C,9891carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)9892break;9893default:9894return false;9895}98969897// Read the first operand.9898uint32_t val1 = ReadCoreReg(Rn, &success);9899if (!success)9900return false;99019902uint32_t result = val1 & imm32;99039904EmulateInstruction::Context context;9905context.type = EmulateInstruction::eContextImmediate;9906context.SetNoArgs();99079908if (!WriteFlags(context, result, carry))9909return false;9910}9911return true;9912}99139914// Test (register) performs a bitwise AND operation on a register value and an9915// optionally-shifted register value. It updates the condition flags based on9916// the result, and discards the result.9917bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,9918const ARMEncoding encoding) {9919#if 09920// ARM pseudo code...9921if ConditionPassed() then9922EncodingSpecificOperations();9923(shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);9924result = R[n] AND shifted;9925APSR.N = result<31>;9926APSR.Z = IsZeroBit(result);9927APSR.C = carry;9928// APSR.V unchanged9929#endif99309931bool success = false;99329933if (ConditionPassed(opcode)) {9934uint32_t Rn, Rm;9935ARM_ShifterType shift_t;9936uint32_t shift_n; // the shift applied to the value read from Rm9937uint32_t carry;9938switch (encoding) {9939case eEncodingT1:9940Rn = Bits32(opcode, 2, 0);9941Rm = Bits32(opcode, 5, 3);9942shift_t = SRType_LSL;9943shift_n = 0;9944break;9945case eEncodingT2:9946Rn = Bits32(opcode, 19, 16);9947Rm = Bits32(opcode, 3, 0);9948shift_n = DecodeImmShiftThumb(opcode, shift_t);9949if (BadReg(Rn) || BadReg(Rm))9950return false;9951break;9952case eEncodingA1:9953Rn = Bits32(opcode, 19, 16);9954Rm = Bits32(opcode, 3, 0);9955shift_n = DecodeImmShiftARM(opcode, shift_t);9956break;9957default:9958return false;9959}99609961// Read the first operand.9962uint32_t val1 = ReadCoreReg(Rn, &success);9963if (!success)9964return false;99659966// Read the second operand.9967uint32_t val2 = ReadCoreReg(Rm, &success);9968if (!success)9969return false;99709971uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);9972if (!success)9973return false;9974uint32_t result = val1 & shifted;99759976EmulateInstruction::Context context;9977context.type = EmulateInstruction::eContextImmediate;9978context.SetNoArgs();99799980if (!WriteFlags(context, result, carry))9981return false;9982}9983return true;9984}99859986// A8.6.216 SUB (SP minus register)9987bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode,9988const ARMEncoding encoding) {9989#if 09990if ConditionPassed() then9991EncodingSpecificOperations();9992shifted = Shift(R[m], shift_t, shift_n, APSR.C);9993(result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');9994if d == 15 then // Can only occur for ARM encoding9995ALUWritePC(result); // setflags is always FALSE here9996else9997R[d] = result;9998if setflags then9999APSR.N = result<31>;10000APSR.Z = IsZeroBit(result);10001APSR.C = carry;10002APSR.V = overflow;10003#endif1000410005bool success = false;1000610007if (ConditionPassed(opcode)) {10008uint32_t d;10009uint32_t m;10010bool setflags;10011ARM_ShifterType shift_t;10012uint32_t shift_n;1001310014switch (encoding) {10015case eEncodingT1:10016// d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');10017d = Bits32(opcode, 11, 8);10018m = Bits32(opcode, 3, 0);10019setflags = BitIsSet(opcode, 20);1002010021// (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);10022shift_n = DecodeImmShiftThumb(opcode, shift_t);1002310024// if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then10025// UNPREDICTABLE;10026if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))10027return false;1002810029// if d == 15 || BadReg(m) then UNPREDICTABLE;10030if ((d == 15) || BadReg(m))10031return false;10032break;1003310034case eEncodingA1:10035// d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');10036d = Bits32(opcode, 15, 12);10037m = Bits32(opcode, 3, 0);10038setflags = BitIsSet(opcode, 20);1003910040// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related10041// instructions;10042if (d == 15 && setflags)10043EmulateSUBSPcLrEtc(opcode, encoding);1004410045// (shift_t, shift_n) = DecodeImmShift(type, imm5);10046shift_n = DecodeImmShiftARM(opcode, shift_t);10047break;1004810049default:10050return false;10051}1005210053// shifted = Shift(R[m], shift_t, shift_n, APSR.C);10054uint32_t Rm = ReadCoreReg(m, &success);10055if (!success)10056return false;1005710058uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);10059if (!success)10060return false;1006110062// (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');10063uint32_t sp_val = ReadCoreReg(SP_REG, &success);10064if (!success)10065return false;1006610067AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1);1006810069EmulateInstruction::Context context;10070context.type = eContextArithmetic;10071std::optional<RegisterInfo> sp_reg =10072GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);10073std::optional<RegisterInfo> dwarf_reg =10074GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);10075context.SetRegisterRegisterOperands(*sp_reg, *dwarf_reg);1007610077if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,10078res.carry_out, res.overflow))10079return false;10080}10081return true;10082}1008310084// A8.6.7 ADD (register-shifted register)10085bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode,10086const ARMEncoding encoding) {10087#if 010088if ConditionPassed() then10089EncodingSpecificOperations();10090shift_n = UInt(R[s]<7:0>);10091shifted = Shift(R[m], shift_t, shift_n, APSR.C);10092(result, carry, overflow) = AddWithCarry(R[n], shifted, '0');10093R[d] = result;10094if setflags then10095APSR.N = result<31>;10096APSR.Z = IsZeroBit(result);10097APSR.C = carry;10098APSR.V = overflow;10099#endif1010010101bool success = false;1010210103if (ConditionPassed(opcode)) {10104uint32_t d;10105uint32_t n;10106uint32_t m;10107uint32_t s;10108bool setflags;10109ARM_ShifterType shift_t;1011010111switch (encoding) {10112case eEncodingA1:10113// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);10114d = Bits32(opcode, 15, 12);10115n = Bits32(opcode, 19, 16);10116m = Bits32(opcode, 3, 0);10117s = Bits32(opcode, 11, 8);1011810119// setflags = (S == '1'); shift_t = DecodeRegShift(type);10120setflags = BitIsSet(opcode, 20);10121shift_t = DecodeRegShift(Bits32(opcode, 6, 5));1012210123// if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;10124if ((d == 15) || (n == 15) || (m == 15) || (s == 15))10125return false;10126break;1012710128default:10129return false;10130}1013110132// shift_n = UInt(R[s]<7:0>);10133uint32_t Rs = ReadCoreReg(s, &success);10134if (!success)10135return false;1013610137uint32_t shift_n = Bits32(Rs, 7, 0);1013810139// shifted = Shift(R[m], shift_t, shift_n, APSR.C);10140uint32_t Rm = ReadCoreReg(m, &success);10141if (!success)10142return false;1014310144uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);10145if (!success)10146return false;1014710148// (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');10149uint32_t Rn = ReadCoreReg(n, &success);10150if (!success)10151return false;1015210153AddWithCarryResult res = AddWithCarry(Rn, shifted, 0);1015410155// R[d] = result;10156EmulateInstruction::Context context;10157context.type = eContextArithmetic;10158std::optional<RegisterInfo> reg_n =10159GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10160std::optional<RegisterInfo> reg_m =10161GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);1016210163context.SetRegisterRegisterOperands(*reg_n, *reg_m);1016410165if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,10166res.result))10167return false;1016810169// if setflags then10170// APSR.N = result<31>;10171// APSR.Z = IsZeroBit(result);10172// APSR.C = carry;10173// APSR.V = overflow;10174if (setflags)10175return WriteFlags(context, res.result, res.carry_out, res.overflow);10176}10177return true;10178}1017910180// A8.6.213 SUB (register)10181bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,10182const ARMEncoding encoding) {10183#if 010184if ConditionPassed() then10185EncodingSpecificOperations();10186shifted = Shift(R[m], shift_t, shift_n, APSR.C);10187(result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');10188if d == 15 then // Can only occur for ARM encoding10189ALUWritePC(result); // setflags is always FALSE here10190else10191R[d] = result;10192if setflags then10193APSR.N = result<31>;10194APSR.Z = IsZeroBit(result);10195APSR.C = carry;10196APSR.V = overflow;10197#endif1019810199bool success = false;1020010201if (ConditionPassed(opcode)) {10202uint32_t d;10203uint32_t n;10204uint32_t m;10205bool setflags;10206ARM_ShifterType shift_t;10207uint32_t shift_n;1020810209switch (encoding) {10210case eEncodingT1:10211// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();10212d = Bits32(opcode, 2, 0);10213n = Bits32(opcode, 5, 3);10214m = Bits32(opcode, 8, 6);10215setflags = !InITBlock();1021610217// (shift_t, shift_n) = (SRType_LSL, 0);10218shift_t = SRType_LSL;10219shift_n = 0;1022010221break;1022210223case eEncodingT2:10224// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");10225d = Bits32(opcode, 11, 8);10226n = Bits32(opcode, 19, 16);10227m = Bits32(opcode, 3, 0);10228setflags = BitIsSet(opcode, 20);1022910230// if Rd == "1111" && S == "1" then SEE CMP (register);10231if (d == 15 && setflags == 1)10232return EmulateCMPImm(opcode, eEncodingT3);1023310234// if Rn == "1101" then SEE SUB (SP minus register);10235if (n == 13)10236return EmulateSUBSPReg(opcode, eEncodingT1);1023710238// (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);10239shift_n = DecodeImmShiftThumb(opcode, shift_t);1024010241// if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then10242// UNPREDICTABLE;10243if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) ||10244BadReg(m))10245return false;1024610247break;1024810249case eEncodingA1:10250// if Rn == '1101' then SEE SUB (SP minus register);10251// d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');10252d = Bits32(opcode, 15, 12);10253n = Bits32(opcode, 19, 16);10254m = Bits32(opcode, 3, 0);10255setflags = BitIsSet(opcode, 20);1025610257// if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related10258// instructions;10259if ((d == 15) && setflags)10260EmulateSUBSPcLrEtc(opcode, encoding);1026110262// (shift_t, shift_n) = DecodeImmShift(type, imm5);10263shift_n = DecodeImmShiftARM(opcode, shift_t);1026410265break;1026610267default:10268return false;10269}1027010271// shifted = Shift(R[m], shift_t, shift_n, APSR.C);10272uint32_t Rm = ReadCoreReg(m, &success);10273if (!success)10274return false;1027510276uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);10277if (!success)10278return false;1027910280// (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');10281uint32_t Rn = ReadCoreReg(n, &success);10282if (!success)10283return false;1028410285AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);1028610287// if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);10288// // setflags is always FALSE here else10289// R[d] = result;10290// if setflags then10291// APSR.N = result<31>;10292// APSR.Z = IsZeroBit(result);10293// APSR.C = carry;10294// APSR.V = overflow;1029510296EmulateInstruction::Context context;10297context.type = eContextArithmetic;10298std::optional<RegisterInfo> reg_n =10299GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10300std::optional<RegisterInfo> reg_m =10301GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);10302context.SetRegisterRegisterOperands(*reg_n, *reg_m);1030310304if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,10305res.carry_out, res.overflow))10306return false;10307}10308return true;10309}1031010311// A8.6.202 STREX10312// Store Register Exclusive calculates an address from a base register value10313// and an immediate offset, and stores a word from a register to memory if the10314// executing processor has exclusive access to the memory addressed.10315bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,10316const ARMEncoding encoding) {10317#if 010318if ConditionPassed() then10319EncodingSpecificOperations(); NullCheckIfThumbEE(n);10320address = R[n] + imm32;10321if ExclusiveMonitorsPass(address,4) then10322MemA[address,4] = R[t];10323R[d] = 0;10324else10325R[d] = 1;10326#endif1032710328bool success = false;1032910330if (ConditionPassed(opcode)) {10331uint32_t d;10332uint32_t t;10333uint32_t n;10334uint32_t imm32;10335const uint32_t addr_byte_size = GetAddressByteSize();1033610337switch (encoding) {10338case eEncodingT1:10339// d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =10340// ZeroExtend(imm8:'00',10341// 32);10342d = Bits32(opcode, 11, 8);10343t = Bits32(opcode, 15, 12);10344n = Bits32(opcode, 19, 16);10345imm32 = Bits32(opcode, 7, 0) << 2;1034610347// if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;10348if (BadReg(d) || BadReg(t) || (n == 15))10349return false;1035010351// if d == n || d == t then UNPREDICTABLE;10352if ((d == n) || (d == t))10353return false;1035410355break;1035610357case eEncodingA1:10358// d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero10359// offset10360d = Bits32(opcode, 15, 12);10361t = Bits32(opcode, 3, 0);10362n = Bits32(opcode, 19, 16);10363imm32 = 0;1036410365// if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;10366if ((d == 15) || (t == 15) || (n == 15))10367return false;1036810369// if d == n || d == t then UNPREDICTABLE;10370if ((d == n) || (d == t))10371return false;1037210373break;1037410375default:10376return false;10377}1037810379// address = R[n] + imm32;10380uint32_t Rn = ReadCoreReg(n, &success);10381if (!success)10382return false;1038310384addr_t address = Rn + imm32;1038510386std::optional<RegisterInfo> base_reg =10387GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10388std::optional<RegisterInfo> data_reg =10389GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);10390EmulateInstruction::Context context;10391context.type = eContextRegisterStore;10392context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, imm32);1039310394// if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass10395// (address, addr_byte_size)) -- For now, for the sake of emulation, we10396// will say this10397// always return10398// true.10399if (true) {10400// MemA[address,4] = R[t];10401uint32_t Rt =10402ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);10403if (!success)10404return false;1040510406if (!MemAWrite(context, address, Rt, addr_byte_size))10407return false;1040810409// R[d] = 0;10410if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0))10411return false;10412}10413#if 0 // unreachable because if true10414else10415{10416// R[d] = 1;10417if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))10418return false;10419}10420#endif // unreachable because if true10421}10422return true;10423}1042410425// A8.6.197 STRB (immediate, ARM)10426bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode,10427const ARMEncoding encoding) {10428#if 010429if ConditionPassed() then10430EncodingSpecificOperations();10431offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10432address = if index then offset_addr else R[n];10433MemU[address,1] = R[t]<7:0>;10434if wback then R[n] = offset_addr;10435#endif1043610437bool success = false;1043810439if (ConditionPassed(opcode)) {10440uint32_t t;10441uint32_t n;10442uint32_t imm32;10443bool index;10444bool add;10445bool wback;1044610447switch (encoding) {10448case eEncodingA1:10449// if P == '0' && W == '1' then SEE STRBT;10450// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);10451t = Bits32(opcode, 15, 12);10452n = Bits32(opcode, 19, 16);10453imm32 = Bits32(opcode, 11, 0);1045410455// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');10456index = BitIsSet(opcode, 24);10457add = BitIsSet(opcode, 23);10458wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);1045910460// if t == 15 then UNPREDICTABLE;10461if (t == 15)10462return false;1046310464// if wback && (n == 15 || n == t) then UNPREDICTABLE;10465if (wback && ((n == 15) || (n == t)))10466return false;1046710468break;1046910470default:10471return false;10472}1047310474// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10475uint32_t Rn = ReadCoreReg(n, &success);10476if (!success)10477return false;1047810479addr_t offset_addr;10480if (add)10481offset_addr = Rn + imm32;10482else10483offset_addr = Rn - imm32;1048410485// address = if index then offset_addr else R[n];10486addr_t address;10487if (index)10488address = offset_addr;10489else10490address = Rn;1049110492// MemU[address,1] = R[t]<7:0>;10493uint32_t Rt = ReadCoreReg(t, &success);10494if (!success)10495return false;1049610497std::optional<RegisterInfo> base_reg =10498GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10499std::optional<RegisterInfo> data_reg =10500GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);10501EmulateInstruction::Context context;10502context.type = eContextRegisterStore;10503context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);1050410505if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1))10506return false;1050710508// if wback then R[n] = offset_addr;10509if (wback) {10510if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,10511offset_addr))10512return false;10513}10514}10515return true;10516}1051710518// A8.6.194 STR (immediate, ARM)10519bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,10520const ARMEncoding encoding) {10521#if 010522if ConditionPassed() then10523EncodingSpecificOperations();10524offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10525address = if index then offset_addr else R[n];10526MemU[address,4] = if t == 15 then PCStoreValue() else R[t];10527if wback then R[n] = offset_addr;10528#endif1052910530bool success = false;1053110532if (ConditionPassed(opcode)) {10533uint32_t t;10534uint32_t n;10535uint32_t imm32;10536bool index;10537bool add;10538bool wback;1053910540const uint32_t addr_byte_size = GetAddressByteSize();1054110542switch (encoding) {10543case eEncodingA1:10544// if P == '0' && W == '1' then SEE STRT;10545// if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==10546// '000000000100' then SEE PUSH;10547// t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);10548t = Bits32(opcode, 15, 12);10549n = Bits32(opcode, 19, 16);10550imm32 = Bits32(opcode, 11, 0);1055110552// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');10553index = BitIsSet(opcode, 24);10554add = BitIsSet(opcode, 23);10555wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);1055610557// if wback && (n == 15 || n == t) then UNPREDICTABLE;10558if (wback && ((n == 15) || (n == t)))10559return false;1056010561break;1056210563default:10564return false;10565}1056610567// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10568uint32_t Rn = ReadCoreReg(n, &success);10569if (!success)10570return false;1057110572addr_t offset_addr;10573if (add)10574offset_addr = Rn + imm32;10575else10576offset_addr = Rn - imm32;1057710578// address = if index then offset_addr else R[n];10579addr_t address;10580if (index)10581address = offset_addr;10582else10583address = Rn;1058410585std::optional<RegisterInfo> base_reg =10586GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10587std::optional<RegisterInfo> data_reg =10588GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);10589EmulateInstruction::Context context;10590context.type = eContextRegisterStore;10591context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);1059210593// MemU[address,4] = if t == 15 then PCStoreValue() else R[t];10594uint32_t Rt = ReadCoreReg(t, &success);10595if (!success)10596return false;1059710598if (t == 15) {10599uint32_t pc_value = ReadCoreReg(PC_REG, &success);10600if (!success)10601return false;1060210603if (!MemUWrite(context, address, pc_value, addr_byte_size))10604return false;10605} else {10606if (!MemUWrite(context, address, Rt, addr_byte_size))10607return false;10608}1060910610// if wback then R[n] = offset_addr;10611if (wback) {10612context.type = eContextAdjustBaseRegister;10613context.SetImmediate(offset_addr);1061410615if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,10616offset_addr))10617return false;10618}10619}10620return true;10621}1062210623// A8.6.66 LDRD (immediate)10624// Load Register Dual (immediate) calculates an address from a base register10625// value and an immediate offset, loads two words from memory, and writes them10626// to two registers. It can use offset, post-indexed, or pre-indexed10627// addressing.10628bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,10629const ARMEncoding encoding) {10630#if 010631if ConditionPassed() then10632EncodingSpecificOperations(); NullCheckIfThumbEE(n);10633offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10634address = if index then offset_addr else R[n];10635R[t] = MemA[address,4];10636R[t2] = MemA[address+4,4];10637if wback then R[n] = offset_addr;10638#endif1063910640bool success = false;1064110642if (ConditionPassed(opcode)) {10643uint32_t t;10644uint32_t t2;10645uint32_t n;10646uint32_t imm32;10647bool index;10648bool add;10649bool wback;1065010651switch (encoding) {10652case eEncodingT1:10653// if P == '0' && W == '0' then SEE 'Related encodings';10654// if Rn == '1111' then SEE LDRD (literal);10655// t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =10656// ZeroExtend(imm8:'00', 32);10657t = Bits32(opcode, 15, 12);10658t2 = Bits32(opcode, 11, 8);10659n = Bits32(opcode, 19, 16);10660imm32 = Bits32(opcode, 7, 0) << 2;1066110662// index = (P == '1'); add = (U == '1'); wback = (W == '1');10663index = BitIsSet(opcode, 24);10664add = BitIsSet(opcode, 23);10665wback = BitIsSet(opcode, 21);1066610667// if wback && (n == t || n == t2) then UNPREDICTABLE;10668if (wback && ((n == t) || (n == t2)))10669return false;1067010671// if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;10672if (BadReg(t) || BadReg(t2) || (t == t2))10673return false;1067410675break;1067610677case eEncodingA1:10678// if Rn == '1111' then SEE LDRD (literal);10679// if Rt<0> == '1' then UNPREDICTABLE;10680// t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,10681// 32);10682t = Bits32(opcode, 15, 12);10683if (BitIsSet(t, 0))10684return false;10685t2 = t + 1;10686n = Bits32(opcode, 19, 16);10687imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);1068810689// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');10690index = BitIsSet(opcode, 24);10691add = BitIsSet(opcode, 23);10692wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);1069310694// if P == '0' && W == '1' then UNPREDICTABLE;10695if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))10696return false;1069710698// if wback && (n == t || n == t2) then UNPREDICTABLE;10699if (wback && ((n == t) || (n == t2)))10700return false;1070110702// if t2 == 15 then UNPREDICTABLE;10703if (t2 == 15)10704return false;1070510706break;1070710708default:10709return false;10710}1071110712// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10713uint32_t Rn = ReadCoreReg(n, &success);10714if (!success)10715return false;1071610717addr_t offset_addr;10718if (add)10719offset_addr = Rn + imm32;10720else10721offset_addr = Rn - imm32;1072210723// address = if index then offset_addr else R[n];10724addr_t address;10725if (index)10726address = offset_addr;10727else10728address = Rn;1072910730// R[t] = MemA[address,4];1073110732EmulateInstruction::Context context;10733if (n == 13)10734context.type = eContextPopRegisterOffStack;10735else10736context.type = eContextRegisterLoad;10737context.SetAddress(address);1073810739const uint32_t addr_byte_size = GetAddressByteSize();10740uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);10741if (!success)10742return false;1074310744if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))10745return false;1074610747// R[t2] = MemA[address+4,4];10748context.SetAddress(address + 4);10749data = MemARead(context, address + 4, addr_byte_size, 0, &success);10750if (!success)10751return false;1075210753if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,10754data))10755return false;1075610757// if wback then R[n] = offset_addr;10758if (wback) {10759context.type = eContextAdjustBaseRegister;10760context.SetAddress(offset_addr);1076110762if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,10763offset_addr))10764return false;10765}10766}10767return true;10768}1076910770// A8.6.68 LDRD (register)10771// Load Register Dual (register) calculates an address from a base register10772// value and a register offset, loads two words from memory, and writes them to10773// two registers. It can use offset, post-indexed or pre-indexed addressing.10774bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,10775const ARMEncoding encoding) {10776#if 010777if ConditionPassed() then10778EncodingSpecificOperations();10779offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);10780address = if index then offset_addr else R[n];10781R[t] = MemA[address,4];10782R[t2] = MemA[address+4,4];10783if wback then R[n] = offset_addr;10784#endif1078510786bool success = false;1078710788if (ConditionPassed(opcode)) {10789uint32_t t;10790uint32_t t2;10791uint32_t n;10792uint32_t m;10793bool index;10794bool add;10795bool wback;1079610797switch (encoding) {10798case eEncodingA1:10799// if Rt<0> == '1' then UNPREDICTABLE;10800// t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);10801t = Bits32(opcode, 15, 12);10802if (BitIsSet(t, 0))10803return false;10804t2 = t + 1;10805n = Bits32(opcode, 19, 16);10806m = Bits32(opcode, 3, 0);1080710808// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');10809index = BitIsSet(opcode, 24);10810add = BitIsSet(opcode, 23);10811wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);1081210813// if P == '0' && W == '1' then UNPREDICTABLE;10814if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))10815return false;1081610817// if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;10818if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))10819return false;1082010821// if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;10822if (wback && ((n == 15) || (n == t) || (n == t2)))10823return false;1082410825// if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;10826if ((ArchVersion() < 6) && wback && (m == n))10827return false;10828break;1082910830default:10831return false;10832}1083310834uint32_t Rn = ReadCoreReg(n, &success);10835if (!success)10836return false;1083710838uint32_t Rm = ReadCoreReg(m, &success);10839if (!success)10840return false;1084110842// offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);10843addr_t offset_addr;10844if (add)10845offset_addr = Rn + Rm;10846else10847offset_addr = Rn - Rm;1084810849// address = if index then offset_addr else R[n];10850addr_t address;10851if (index)10852address = offset_addr;10853else10854address = Rn;1085510856EmulateInstruction::Context context;10857if (n == 13)10858context.type = eContextPopRegisterOffStack;10859else10860context.type = eContextRegisterLoad;10861context.SetAddress(address);1086210863// R[t] = MemA[address,4];10864const uint32_t addr_byte_size = GetAddressByteSize();10865uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);10866if (!success)10867return false;1086810869if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))10870return false;1087110872// R[t2] = MemA[address+4,4];1087310874data = MemARead(context, address + 4, addr_byte_size, 0, &success);10875if (!success)10876return false;1087710878if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,10879data))10880return false;1088110882// if wback then R[n] = offset_addr;10883if (wback) {10884context.type = eContextAdjustBaseRegister;10885context.SetAddress(offset_addr);1088610887if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,10888offset_addr))10889return false;10890}10891}10892return true;10893}1089410895// A8.6.200 STRD (immediate)10896// Store Register Dual (immediate) calculates an address from a base register10897// value and an immediate offset, and stores two words from two registers to10898// memory. It can use offset, post-indexed, or pre-indexed addressing.10899bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,10900const ARMEncoding encoding) {10901#if 010902if ConditionPassed() then10903EncodingSpecificOperations(); NullCheckIfThumbEE(n);10904offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10905address = if index then offset_addr else R[n];10906MemA[address,4] = R[t];10907MemA[address+4,4] = R[t2];10908if wback then R[n] = offset_addr;10909#endif1091010911bool success = false;1091210913if (ConditionPassed(opcode)) {10914uint32_t t;10915uint32_t t2;10916uint32_t n;10917uint32_t imm32;10918bool index;10919bool add;10920bool wback;1092110922switch (encoding) {10923case eEncodingT1:10924// if P == '0' && W == '0' then SEE 'Related encodings';10925// t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =10926// ZeroExtend(imm8:'00', 32);10927t = Bits32(opcode, 15, 12);10928t2 = Bits32(opcode, 11, 8);10929n = Bits32(opcode, 19, 16);10930imm32 = Bits32(opcode, 7, 0) << 2;1093110932// index = (P == '1'); add = (U == '1'); wback = (W == '1');10933index = BitIsSet(opcode, 24);10934add = BitIsSet(opcode, 23);10935wback = BitIsSet(opcode, 21);1093610937// if wback && (n == t || n == t2) then UNPREDICTABLE;10938if (wback && ((n == t) || (n == t2)))10939return false;1094010941// if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;10942if ((n == 15) || BadReg(t) || BadReg(t2))10943return false;1094410945break;1094610947case eEncodingA1:10948// if Rt<0> == '1' then UNPREDICTABLE;10949// t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,10950// 32);10951t = Bits32(opcode, 15, 12);10952if (BitIsSet(t, 0))10953return false;1095410955t2 = t + 1;10956n = Bits32(opcode, 19, 16);10957imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);1095810959// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');10960index = BitIsSet(opcode, 24);10961add = BitIsSet(opcode, 23);10962wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);1096310964// if P == '0' && W == '1' then UNPREDICTABLE;10965if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))10966return false;1096710968// if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;10969if (wback && ((n == 15) || (n == t) || (n == t2)))10970return false;1097110972// if t2 == 15 then UNPREDICTABLE;10973if (t2 == 15)10974return false;1097510976break;1097710978default:10979return false;10980}1098110982std::optional<RegisterInfo> base_reg =10983GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);1098410985uint32_t Rn = ReadCoreReg(n, &success);10986if (!success)10987return false;1098810989// offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10990addr_t offset_addr;10991if (add)10992offset_addr = Rn + imm32;10993else10994offset_addr = Rn - imm32;1099510996// address = if index then offset_addr else R[n];10997addr_t address;10998if (index)10999address = offset_addr;11000else11001address = Rn;1100211003// MemA[address,4] = R[t];11004std::optional<RegisterInfo> data_reg =11005GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);1100611007uint32_t data = ReadCoreReg(t, &success);11008if (!success)11009return false;1101011011EmulateInstruction::Context context;11012if (n == 13)11013context.type = eContextPushRegisterOnStack;11014else11015context.type = eContextRegisterStore;11016context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);1101711018const uint32_t addr_byte_size = GetAddressByteSize();1101911020if (!MemAWrite(context, address, data, addr_byte_size))11021return false;1102211023// MemA[address+4,4] = R[t2];11024data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2);11025context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11026(address + 4) - Rn);1102711028data = ReadCoreReg(t2, &success);11029if (!success)11030return false;1103111032if (!MemAWrite(context, address + 4, data, addr_byte_size))11033return false;1103411035// if wback then R[n] = offset_addr;11036if (wback) {11037if (n == 13)11038context.type = eContextAdjustStackPointer;11039else11040context.type = eContextAdjustBaseRegister;11041context.SetAddress(offset_addr);1104211043if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,11044offset_addr))11045return false;11046}11047}11048return true;11049}1105011051// A8.6.201 STRD (register)11052bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,11053const ARMEncoding encoding) {11054#if 011055if ConditionPassed() then11056EncodingSpecificOperations();11057offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);11058address = if index then offset_addr else R[n];11059MemA[address,4] = R[t];11060MemA[address+4,4] = R[t2];11061if wback then R[n] = offset_addr;11062#endif1106311064bool success = false;1106511066if (ConditionPassed(opcode)) {11067uint32_t t;11068uint32_t t2;11069uint32_t n;11070uint32_t m;11071bool index;11072bool add;11073bool wback;1107411075switch (encoding) {11076case eEncodingA1:11077// if Rt<0> == '1' then UNPREDICTABLE;11078// t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);11079t = Bits32(opcode, 15, 12);11080if (BitIsSet(t, 0))11081return false;1108211083t2 = t + 1;11084n = Bits32(opcode, 19, 16);11085m = Bits32(opcode, 3, 0);1108611087// index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');11088index = BitIsSet(opcode, 24);11089add = BitIsSet(opcode, 23);11090wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);1109111092// if P == '0' && W == '1' then UNPREDICTABLE;11093if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))11094return false;1109511096// if t2 == 15 || m == 15 then UNPREDICTABLE;11097if ((t2 == 15) || (m == 15))11098return false;1109911100// if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;11101if (wback && ((n == 15) || (n == t) || (n == t2)))11102return false;1110311104// if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;11105if ((ArchVersion() < 6) && wback && (m == n))11106return false;1110711108break;1110911110default:11111return false;11112}1111311114uint32_t Rn = ReadCoreReg(n, &success);11115if (!success)11116return false;1111711118uint32_t Rm = ReadCoreReg(m, &success);11119if (!success)11120return false;1112111122// offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);11123addr_t offset_addr;11124if (add)11125offset_addr = Rn + Rm;11126else11127offset_addr = Rn - Rm;1112811129// address = if index then offset_addr else R[n];11130addr_t address;11131if (index)11132address = offset_addr;11133else11134address = Rn;11135// MemA[address,4] = R[t];11136uint32_t Rt = ReadCoreReg(t, &success);11137if (!success)11138return false;1113911140EmulateInstruction::Context context;11141if (t == 13)11142context.type = eContextPushRegisterOnStack;11143else11144context.type = eContextRegisterStore;1114511146std::optional<RegisterInfo> base_reg =11147GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);11148std::optional<RegisterInfo> offset_reg =11149GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);11150std::optional<RegisterInfo> data_reg =11151GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);11152context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,11153*data_reg);1115411155const uint32_t addr_byte_size = GetAddressByteSize();1115611157if (!MemAWrite(context, address, Rt, addr_byte_size))11158return false;1115911160// MemA[address+4,4] = R[t2];11161uint32_t Rt2 = ReadCoreReg(t2, &success);11162if (!success)11163return false;1116411165data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2);1116611167context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,11168*data_reg);1116911170if (!MemAWrite(context, address + 4, Rt2, addr_byte_size))11171return false;1117211173// if wback then R[n] = offset_addr;11174if (wback) {11175context.type = eContextAdjustBaseRegister;11176context.SetAddress(offset_addr);1117711178if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,11179offset_addr))11180return false;11181}11182}11183return true;11184}1118511186// A8.6.319 VLDM11187// Vector Load Multiple loads multiple extension registers from consecutive11188// memory locations using an address from an ARM core register.11189bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,11190const ARMEncoding encoding) {11191#if 011192if ConditionPassed() then11193EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);11194address = if add then R[n] else R[n]-imm32;11195if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;11196for r = 0 to regs-111197if single_regs then11198S[d+r] = MemA[address,4]; address = address+4;11199else11200word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;11201// Combine the word-aligned words in the correct order for11202// current endianness.11203D[d+r] = if BigEndian() then word1:word2 else word2:word1;11204#endif1120511206bool success = false;1120711208if (ConditionPassed(opcode)) {11209bool single_regs;11210bool add;11211bool wback;11212uint32_t d;11213uint32_t n;11214uint32_t imm32;11215uint32_t regs;1121611217switch (encoding) {11218case eEncodingT1:11219case eEncodingA1:11220// if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';11221// if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;11222// if P == '1' && W == '0' then SEE VLDR;11223// if P == U && W == '1' then UNDEFINED;11224if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))11225return false;1122611227// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with11228// !), 101 (DB with !)11229// single_regs = FALSE; add = (U == '1'); wback = (W == '1');11230single_regs = false;11231add = BitIsSet(opcode, 23);11232wback = BitIsSet(opcode, 21);1123311234// d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);11235d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);11236n = Bits32(opcode, 19, 16);11237imm32 = Bits32(opcode, 7, 0) << 2;1123811239// regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.11240regs = Bits32(opcode, 7, 0) / 2;1124111242// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then11243// UNPREDICTABLE;11244if (n == 15 && (wback || CurrentInstrSet() != eModeARM))11245return false;1124611247// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;11248if ((regs == 0) || (regs > 16) || ((d + regs) > 32))11249return false;1125011251break;1125211253case eEncodingT2:11254case eEncodingA2:11255// if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';11256// if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;11257// if P == '1' && W == '0' then SEE VLDR;11258// if P == U && W == '1' then UNDEFINED;11259if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))11260return false;1126111262// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with11263// !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W11264// == '1'); d =11265// UInt(Vd:D); n = UInt(Rn);11266single_regs = true;11267add = BitIsSet(opcode, 23);11268wback = BitIsSet(opcode, 21);11269d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);11270n = Bits32(opcode, 19, 16);1127111272// imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);11273imm32 = Bits32(opcode, 7, 0) << 2;11274regs = Bits32(opcode, 7, 0);1127511276// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then11277// UNPREDICTABLE;11278if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))11279return false;1128011281// if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;11282if ((regs == 0) || ((d + regs) > 32))11283return false;11284break;1128511286default:11287return false;11288}1128911290uint32_t Rn = ReadCoreReg(n, &success);11291if (!success)11292return false;1129311294// address = if add then R[n] else R[n]-imm32;11295addr_t address;11296if (add)11297address = Rn;11298else11299address = Rn - imm32;1130011301// if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;11302EmulateInstruction::Context context;1130311304if (wback) {11305uint32_t value;11306if (add)11307value = Rn + imm32;11308else11309value = Rn - imm32;1131011311context.type = eContextAdjustBaseRegister;11312context.SetImmediateSigned(value - Rn);11313if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,11314value))11315return false;11316}1131711318const uint32_t addr_byte_size = GetAddressByteSize();11319uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;1132011321context.type = eContextRegisterLoad;1132211323std::optional<RegisterInfo> base_reg =11324GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);1132511326// for r = 0 to regs-111327for (uint32_t r = 0; r < regs; ++r) {11328if (single_regs) {11329// S[d+r] = MemA[address,4]; address = address+4;11330context.SetRegisterPlusOffset(*base_reg, address - Rn);1133111332uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);11333if (!success)11334return false;1133511336if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,11337start_reg + d + r, data))11338return false;1133911340address = address + 4;11341} else {11342// word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =11343// address+8;11344context.SetRegisterPlusOffset(*base_reg, address - Rn);11345uint32_t word1 =11346MemARead(context, address, addr_byte_size, 0, &success);11347if (!success)11348return false;1134911350context.SetRegisterPlusOffset(*base_reg, (address + 4) - Rn);11351uint32_t word2 =11352MemARead(context, address + 4, addr_byte_size, 0, &success);11353if (!success)11354return false;1135511356address = address + 8;11357// // Combine the word-aligned words in the correct order for current11358// endianness.11359// D[d+r] = if BigEndian() then word1:word2 else word2:word1;11360uint64_t data;11361if (GetByteOrder() == eByteOrderBig) {11362data = word1;11363data = (data << 32) | word2;11364} else {11365data = word2;11366data = (data << 32) | word1;11367}1136811369if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,11370start_reg + d + r, data))11371return false;11372}11373}11374}11375return true;11376}1137711378// A8.6.399 VSTM11379// Vector Store Multiple stores multiple extension registers to consecutive11380// memory locations using an address from an11381// ARM core register.11382bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,11383const ARMEncoding encoding) {11384#if 011385if ConditionPassed() then11386EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);11387address = if add then R[n] else R[n]-imm32;11388if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;11389for r = 0 to regs-111390if single_regs then11391MemA[address,4] = S[d+r]; address = address+4;11392else11393// Store as two word-aligned words in the correct order for11394// current endianness.11395MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;11396MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;11397address = address+8;11398#endif1139911400bool success = false;1140111402if (ConditionPassed(opcode)) {11403bool single_regs;11404bool add;11405bool wback;11406uint32_t d;11407uint32_t n;11408uint32_t imm32;11409uint32_t regs;1141011411switch (encoding) {11412case eEncodingT1:11413case eEncodingA1:11414// if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';11415// if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;11416// if P == '1' && W == '0' then SEE VSTR;11417// if P == U && W == '1' then UNDEFINED;11418if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))11419return false;1142011421// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with11422// !), 101 (DB with !)11423// single_regs = FALSE; add = (U == '1'); wback = (W == '1');11424single_regs = false;11425add = BitIsSet(opcode, 23);11426wback = BitIsSet(opcode, 21);1142711428// d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);11429d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);11430n = Bits32(opcode, 19, 16);11431imm32 = Bits32(opcode, 7, 0) << 2;1143211433// regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.11434regs = Bits32(opcode, 7, 0) / 2;1143511436// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then11437// UNPREDICTABLE;11438if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))11439return false;1144011441// if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;11442if ((regs == 0) || (regs > 16) || ((d + regs) > 32))11443return false;1144411445break;1144611447case eEncodingT2:11448case eEncodingA2:11449// if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';11450// if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;11451// if P == '1' && W == '0' then SEE VSTR;11452// if P == U && W == '1' then UNDEFINED;11453if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))11454return false;1145511456// // Remaining combinations are PUW = 010 (IA without !), 011 (IA with11457// !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W11458// == '1'); d =11459// UInt(Vd:D); n = UInt(Rn);11460single_regs = true;11461add = BitIsSet(opcode, 23);11462wback = BitIsSet(opcode, 21);11463d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);11464n = Bits32(opcode, 19, 16);1146511466// imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);11467imm32 = Bits32(opcode, 7, 0) << 2;11468regs = Bits32(opcode, 7, 0);1146911470// if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then11471// UNPREDICTABLE;11472if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))11473return false;1147411475// if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;11476if ((regs == 0) || ((d + regs) > 32))11477return false;1147811479break;1148011481default:11482return false;11483}1148411485std::optional<RegisterInfo> base_reg =11486GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);1148711488uint32_t Rn = ReadCoreReg(n, &success);11489if (!success)11490return false;1149111492// address = if add then R[n] else R[n]-imm32;11493addr_t address;11494if (add)11495address = Rn;11496else11497address = Rn - imm32;1149811499EmulateInstruction::Context context;11500// if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;11501if (wback) {11502uint32_t value;11503if (add)11504value = Rn + imm32;11505else11506value = Rn - imm32;1150711508context.type = eContextAdjustBaseRegister;11509context.SetRegisterPlusOffset(*base_reg, value - Rn);1151011511if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,11512value))11513return false;11514}1151511516const uint32_t addr_byte_size = GetAddressByteSize();11517uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;1151811519context.type = eContextRegisterStore;11520// for r = 0 to regs-111521for (uint32_t r = 0; r < regs; ++r) {1152211523if (single_regs) {11524// MemA[address,4] = S[d+r]; address = address+4;11525uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF,11526start_reg + d + r, 0, &success);11527if (!success)11528return false;1152911530std::optional<RegisterInfo> data_reg =11531GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r);11532context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11533address - Rn);11534if (!MemAWrite(context, address, data, addr_byte_size))11535return false;1153611537address = address + 4;11538} else {11539// // Store as two word-aligned words in the correct order for current11540// endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else11541// D[d+r]<31:0>;11542// MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else11543// D[d+r]<63:32>;11544uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF,11545start_reg + d + r, 0, &success);11546if (!success)11547return false;1154811549std::optional<RegisterInfo> data_reg =11550GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r);1155111552if (GetByteOrder() == eByteOrderBig) {11553context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11554address - Rn);11555if (!MemAWrite(context, address, Bits64(data, 63, 32),11556addr_byte_size))11557return false;1155811559context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11560(address + 4) - Rn);11561if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),11562addr_byte_size))11563return false;11564} else {11565context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11566address - Rn);11567if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))11568return false;1156911570context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11571(address + 4) - Rn);11572if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),11573addr_byte_size))11574return false;11575}11576// address = address+8;11577address = address + 8;11578}11579}11580}11581return true;11582}1158311584// A8.6.32011585// This instruction loads a single extension register from memory, using an11586// address from an ARM core register, with an optional offset.11587bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,11588ARMEncoding encoding) {11589#if 011590if ConditionPassed() then11591EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);11592base = if n == 15 then Align(PC,4) else R[n];11593address = if add then (base + imm32) else (base - imm32);11594if single_reg then11595S[d] = MemA[address,4];11596else11597word1 = MemA[address,4]; word2 = MemA[address+4,4];11598// Combine the word-aligned words in the correct order for current11599// endianness.11600D[d] = if BigEndian() then word1:word2 else word2:word1;11601#endif1160211603bool success = false;1160411605if (ConditionPassed(opcode)) {11606bool single_reg;11607bool add;11608uint32_t imm32;11609uint32_t d;11610uint32_t n;1161111612switch (encoding) {11613case eEncodingT1:11614case eEncodingA1:11615// single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',11616// 32);11617single_reg = false;11618add = BitIsSet(opcode, 23);11619imm32 = Bits32(opcode, 7, 0) << 2;1162011621// d = UInt(D:Vd); n = UInt(Rn);11622d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);11623n = Bits32(opcode, 19, 16);1162411625break;1162611627case eEncodingT2:11628case eEncodingA2:11629// single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);11630single_reg = true;11631add = BitIsSet(opcode, 23);11632imm32 = Bits32(opcode, 7, 0) << 2;1163311634// d = UInt(Vd:D); n = UInt(Rn);11635d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);11636n = Bits32(opcode, 19, 16);1163711638break;1163911640default:11641return false;11642}11643std::optional<RegisterInfo> base_reg =11644GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);1164511646uint32_t Rn = ReadCoreReg(n, &success);11647if (!success)11648return false;1164911650// base = if n == 15 then Align(PC,4) else R[n];11651uint32_t base;11652if (n == 15)11653base = AlignPC(Rn);11654else11655base = Rn;1165611657// address = if add then (base + imm32) else (base - imm32);11658addr_t address;11659if (add)11660address = base + imm32;11661else11662address = base - imm32;1166311664const uint32_t addr_byte_size = GetAddressByteSize();11665uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;1166611667EmulateInstruction::Context context;11668context.type = eContextRegisterLoad;11669context.SetRegisterPlusOffset(*base_reg, address - base);1167011671if (single_reg) {11672// S[d] = MemA[address,4];11673uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);11674if (!success)11675return false;1167611677if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,11678data))11679return false;11680} else {11681// word1 = MemA[address,4]; word2 = MemA[address+4,4];11682uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success);11683if (!success)11684return false;1168511686context.SetRegisterPlusOffset(*base_reg, (address + 4) - base);11687uint32_t word2 =11688MemARead(context, address + 4, addr_byte_size, 0, &success);11689if (!success)11690return false;11691// // Combine the word-aligned words in the correct order for current11692// endianness.11693// D[d] = if BigEndian() then word1:word2 else word2:word1;11694uint64_t data64;11695if (GetByteOrder() == eByteOrderBig) {11696data64 = word1;11697data64 = (data64 << 32) | word2;11698} else {11699data64 = word2;11700data64 = (data64 << 32) | word1;11701}1170211703if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,11704data64))11705return false;11706}11707}11708return true;11709}1171011711// A8.6.400 VSTR11712// This instruction stores a signle extension register to memory, using an11713// address from an ARM core register, with an optional offset.11714bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,11715ARMEncoding encoding) {11716#if 011717if ConditionPassed() then11718EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);11719address = if add then (R[n] + imm32) else (R[n] - imm32);11720if single_reg then11721MemA[address,4] = S[d];11722else11723// Store as two word-aligned words in the correct order for current11724// endianness.11725MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;11726MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;11727#endif1172811729bool success = false;1173011731if (ConditionPassed(opcode)) {11732bool single_reg;11733bool add;11734uint32_t imm32;11735uint32_t d;11736uint32_t n;1173711738switch (encoding) {11739case eEncodingT1:11740case eEncodingA1:11741// single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',11742// 32);11743single_reg = false;11744add = BitIsSet(opcode, 23);11745imm32 = Bits32(opcode, 7, 0) << 2;1174611747// d = UInt(D:Vd); n = UInt(Rn);11748d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);11749n = Bits32(opcode, 19, 16);1175011751// if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;11752if ((n == 15) && (CurrentInstrSet() != eModeARM))11753return false;1175411755break;1175611757case eEncodingT2:11758case eEncodingA2:11759// single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);11760single_reg = true;11761add = BitIsSet(opcode, 23);11762imm32 = Bits32(opcode, 7, 0) << 2;1176311764// d = UInt(Vd:D); n = UInt(Rn);11765d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);11766n = Bits32(opcode, 19, 16);1176711768// if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;11769if ((n == 15) && (CurrentInstrSet() != eModeARM))11770return false;1177111772break;1177311774default:11775return false;11776}1177711778uint32_t Rn = ReadCoreReg(n, &success);11779if (!success)11780return false;1178111782// address = if add then (R[n] + imm32) else (R[n] - imm32);11783addr_t address;11784if (add)11785address = Rn + imm32;11786else11787address = Rn - imm32;1178811789const uint32_t addr_byte_size = GetAddressByteSize();11790uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;1179111792std::optional<RegisterInfo> base_reg =11793GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);11794std::optional<RegisterInfo> data_reg =11795GetRegisterInfo(eRegisterKindDWARF, start_reg + d);11796EmulateInstruction::Context context;11797context.type = eContextRegisterStore;11798context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);1179911800if (single_reg) {11801// MemA[address,4] = S[d];11802uint32_t data =11803ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);11804if (!success)11805return false;1180611807if (!MemAWrite(context, address, data, addr_byte_size))11808return false;11809} else {11810// // Store as two word-aligned words in the correct order for current11811// endianness.11812// MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;11813// MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;11814uint64_t data =11815ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);11816if (!success)11817return false;1181811819if (GetByteOrder() == eByteOrderBig) {11820if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size))11821return false;1182211823context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11824(address + 4) - Rn);11825if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),11826addr_byte_size))11827return false;11828} else {11829if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))11830return false;1183111832context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11833(address + 4) - Rn);11834if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),11835addr_byte_size))11836return false;11837}11838}11839}11840return true;11841}1184211843// A8.6.307 VLDI1 (multiple single elements) This instruction loads elements11844// from memory into one, two, three or four registers, without de-interleaving.11845// Every element of each register is loaded.11846bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,11847ARMEncoding encoding) {11848#if 011849if ConditionPassed() then11850EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);11851address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();11852if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);11853for r = 0 to regs-111854for e = 0 to elements-111855Elem[D[d+r],e,esize] = MemU[address,ebytes];11856address = address + ebytes;11857#endif1185811859bool success = false;1186011861if (ConditionPassed(opcode)) {11862uint32_t regs;11863uint32_t alignment;11864uint32_t ebytes;11865uint32_t esize;11866uint32_t elements;11867uint32_t d;11868uint32_t n;11869uint32_t m;11870bool wback;11871bool register_index;1187211873switch (encoding) {11874case eEncodingT1:11875case eEncodingA1: {11876// case type of11877// when '0111'11878// regs = 1; if align<1> == '1' then UNDEFINED;11879// when '1010'11880// regs = 2; if align == '11' then UNDEFINED;11881// when '0110'11882// regs = 3; if align<1> == '1' then UNDEFINED;11883// when '0010'11884// regs = 4;11885// otherwise11886// SEE 'Related encodings';11887uint32_t type = Bits32(opcode, 11, 8);11888uint32_t align = Bits32(opcode, 5, 4);11889if (type == 7) // '0111'11890{11891regs = 1;11892if (BitIsSet(align, 1))11893return false;11894} else if (type == 10) // '1010'11895{11896regs = 2;11897if (align == 3)11898return false;1189911900} else if (type == 6) // '0110'11901{11902regs = 3;11903if (BitIsSet(align, 1))11904return false;11905} else if (type == 2) // '0010'11906{11907regs = 4;11908} else11909return false;1191011911// alignment = if align == '00' then 1 else 4 << UInt(align);11912if (align == 0)11913alignment = 1;11914else11915alignment = 4 << align;1191611917// ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;11918ebytes = 1 << Bits32(opcode, 7, 6);11919esize = 8 * ebytes;11920elements = 8 / ebytes;1192111922// d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);11923d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);11924n = Bits32(opcode, 19, 15);11925m = Bits32(opcode, 3, 0);1192611927// wback = (m != 15); register_index = (m != 15 && m != 13);11928wback = (m != 15);11929register_index = ((m != 15) && (m != 13));1193011931// if d+regs > 32 then UNPREDICTABLE;11932if ((d + regs) > 32)11933return false;11934} break;1193511936default:11937return false;11938}1193911940std::optional<RegisterInfo> base_reg =11941GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);1194211943uint32_t Rn = ReadCoreReg(n, &success);11944if (!success)11945return false;1194611947// address = R[n]; if (address MOD alignment) != 0 then11948// GenerateAlignmentException();11949addr_t address = Rn;11950if ((address % alignment) != 0)11951return false;1195211953EmulateInstruction::Context context;11954// if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);11955if (wback) {11956uint32_t Rm = ReadCoreReg(m, &success);11957if (!success)11958return false;1195911960uint32_t offset;11961if (register_index)11962offset = Rm;11963else11964offset = 8 * regs;1196511966uint32_t value = Rn + offset;11967context.type = eContextAdjustBaseRegister;11968context.SetRegisterPlusOffset(*base_reg, offset);1196911970if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,11971value))11972return false;11973}1197411975// for r = 0 to regs-111976for (uint32_t r = 0; r < regs; ++r) {11977// for e = 0 to elements-111978uint64_t assembled_data = 0;11979for (uint32_t e = 0; e < elements; ++e) {11980// Elem[D[d+r],e,esize] = MemU[address,ebytes];11981context.type = eContextRegisterLoad;11982context.SetRegisterPlusOffset(*base_reg, address - Rn);11983uint64_t data = MemURead(context, address, ebytes, 0, &success);11984if (!success)11985return false;1198611987assembled_data =11988(data << (e * esize)) |11989assembled_data; // New data goes to the left of existing data1199011991// address = address + ebytes;11992address = address + ebytes;11993}11994if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,11995assembled_data))11996return false;11997}11998}11999return true;12000}1200112002// A8.6.308 VLD1 (single element to one lane)12003//12004bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,12005const ARMEncoding encoding) {12006#if 012007if ConditionPassed() then12008EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);12009address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();12010if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12011Elem[D[d],index,esize] = MemU[address,ebytes];12012#endif1201312014bool success = false;1201512016if (ConditionPassed(opcode)) {12017uint32_t ebytes;12018uint32_t esize;12019uint32_t index;12020uint32_t alignment;12021uint32_t d;12022uint32_t n;12023uint32_t m;12024bool wback;12025bool register_index;1202612027switch (encoding) {12028case eEncodingT1:12029case eEncodingA1: {12030uint32_t size = Bits32(opcode, 11, 10);12031uint32_t index_align = Bits32(opcode, 7, 4);12032// if size == '11' then SEE VLD1 (single element to all lanes);12033if (size == 3)12034return EmulateVLD1SingleAll(opcode, encoding);12035// case size of12036if (size == 0) // when '00'12037{12038// if index_align<0> != '0' then UNDEFINED;12039if (BitIsClear(index_align, 0))12040return false;1204112042// ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;12043ebytes = 1;12044esize = 8;12045index = Bits32(index_align, 3, 1);12046alignment = 1;12047} else if (size == 1) // when '01'12048{12049// if index_align<1> != '0' then UNDEFINED;12050if (BitIsClear(index_align, 1))12051return false;1205212053// ebytes = 2; esize = 16; index = UInt(index_align<3:2>);12054ebytes = 2;12055esize = 16;12056index = Bits32(index_align, 3, 2);1205712058// alignment = if index_align<0> == '0' then 1 else 2;12059if (BitIsClear(index_align, 0))12060alignment = 1;12061else12062alignment = 2;12063} else if (size == 2) // when '10'12064{12065// if index_align<2> != '0' then UNDEFINED;12066if (BitIsClear(index_align, 2))12067return false;1206812069// if index_align<1:0> != '00' && index_align<1:0> != '11' then12070// UNDEFINED;12071if ((Bits32(index_align, 1, 0) != 0) &&12072(Bits32(index_align, 1, 0) != 3))12073return false;1207412075// ebytes = 4; esize = 32; index = UInt(index_align<3>);12076ebytes = 4;12077esize = 32;12078index = Bit32(index_align, 3);1207912080// alignment = if index_align<1:0> == '00' then 1 else 4;12081if (Bits32(index_align, 1, 0) == 0)12082alignment = 1;12083else12084alignment = 4;12085} else {12086return false;12087}12088// d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);12089d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);12090n = Bits32(opcode, 19, 16);12091m = Bits32(opcode, 3, 0);1209212093// wback = (m != 15); register_index = (m != 15 && m != 13); if n == 1512094// then UNPREDICTABLE;12095wback = (m != 15);12096register_index = ((m != 15) && (m != 13));1209712098if (n == 15)12099return false;1210012101} break;1210212103default:12104return false;12105}1210612107uint32_t Rn = ReadCoreReg(n, &success);12108if (!success)12109return false;1211012111// address = R[n]; if (address MOD alignment) != 0 then12112// GenerateAlignmentException();12113addr_t address = Rn;12114if ((address % alignment) != 0)12115return false;1211612117EmulateInstruction::Context context;12118// if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12119if (wback) {12120uint32_t Rm = ReadCoreReg(m, &success);12121if (!success)12122return false;1212312124uint32_t offset;12125if (register_index)12126offset = Rm;12127else12128offset = ebytes;1212912130uint32_t value = Rn + offset;1213112132context.type = eContextAdjustBaseRegister;12133std::optional<RegisterInfo> base_reg =12134GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);12135context.SetRegisterPlusOffset(*base_reg, offset);1213612137if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,12138value))12139return false;12140}1214112142// Elem[D[d],index,esize] = MemU[address,ebytes];12143uint32_t element = MemURead(context, address, esize, 0, &success);12144if (!success)12145return false;1214612147element = element << (index * esize);1214812149uint64_t reg_data =12150ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);12151if (!success)12152return false;1215312154uint64_t all_ones = -1;12155uint64_t mask = all_ones12156<< ((index + 1) * esize); // mask is all 1's to left of12157// where 'element' goes, & all 0's12158// at element & to the right of element.12159if (index > 0)12160mask = mask | Bits64(all_ones, (index * esize) - 1,121610); // add 1's to the right of where 'element' goes.12162// now mask should be 0's where element goes & 1's everywhere else.1216312164uint64_t masked_reg =12165reg_data & mask; // Take original reg value & zero out 'element' bits12166reg_data =12167masked_reg & element; // Put 'element' into those bits in reg_data.1216812169context.type = eContextRegisterLoad;12170if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,12171reg_data))12172return false;12173}12174return true;12175}1217612177// A8.6.391 VST1 (multiple single elements) Vector Store (multiple single12178// elements) stores elements to memory from one, two, three, or four registers,12179// without interleaving. Every element of each register is stored.12180bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,12181ARMEncoding encoding) {12182#if 012183if ConditionPassed() then12184EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);12185address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();12186if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);12187for r = 0 to regs-112188for e = 0 to elements-112189MemU[address,ebytes] = Elem[D[d+r],e,esize];12190address = address + ebytes;12191#endif1219212193bool success = false;1219412195if (ConditionPassed(opcode)) {12196uint32_t regs;12197uint32_t alignment;12198uint32_t ebytes;12199uint32_t esize;12200uint32_t elements;12201uint32_t d;12202uint32_t n;12203uint32_t m;12204bool wback;12205bool register_index;1220612207switch (encoding) {12208case eEncodingT1:12209case eEncodingA1: {12210uint32_t type = Bits32(opcode, 11, 8);12211uint32_t align = Bits32(opcode, 5, 4);1221212213// case type of12214if (type == 7) // when '0111'12215{12216// regs = 1; if align<1> == '1' then UNDEFINED;12217regs = 1;12218if (BitIsSet(align, 1))12219return false;12220} else if (type == 10) // when '1010'12221{12222// regs = 2; if align == '11' then UNDEFINED;12223regs = 2;12224if (align == 3)12225return false;12226} else if (type == 6) // when '0110'12227{12228// regs = 3; if align<1> == '1' then UNDEFINED;12229regs = 3;12230if (BitIsSet(align, 1))12231return false;12232} else if (type == 2) // when '0010'12233// regs = 4;12234regs = 4;12235else // otherwise12236// SEE 'Related encodings';12237return false;1223812239// alignment = if align == '00' then 1 else 4 << UInt(align);12240if (align == 0)12241alignment = 1;12242else12243alignment = 4 << align;1224412245// ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;12246ebytes = 1 << Bits32(opcode, 7, 6);12247esize = 8 * ebytes;12248elements = 8 / ebytes;1224912250// d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);12251d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);12252n = Bits32(opcode, 19, 16);12253m = Bits32(opcode, 3, 0);1225412255// wback = (m != 15); register_index = (m != 15 && m != 13);12256wback = (m != 15);12257register_index = ((m != 15) && (m != 13));1225812259// if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;12260if ((d + regs) > 32)12261return false;1226212263if (n == 15)12264return false;1226512266} break;1226712268default:12269return false;12270}1227112272std::optional<RegisterInfo> base_reg =12273GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);1227412275uint32_t Rn = ReadCoreReg(n, &success);12276if (!success)12277return false;1227812279// address = R[n]; if (address MOD alignment) != 0 then12280// GenerateAlignmentException();12281addr_t address = Rn;12282if ((address % alignment) != 0)12283return false;1228412285EmulateInstruction::Context context;12286// if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);12287if (wback) {12288uint32_t Rm = ReadCoreReg(m, &success);12289if (!success)12290return false;1229112292uint32_t offset;12293if (register_index)12294offset = Rm;12295else12296offset = 8 * regs;1229712298context.type = eContextAdjustBaseRegister;12299context.SetRegisterPlusOffset(*base_reg, offset);1230012301if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,12302Rn + offset))12303return false;12304}1230512306context.type = eContextRegisterStore;12307// for r = 0 to regs-112308for (uint32_t r = 0; r < regs; ++r) {12309std::optional<RegisterInfo> data_reg =12310GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r);12311uint64_t register_data = ReadRegisterUnsigned(12312eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);12313if (!success)12314return false;1231512316// for e = 0 to elements-112317for (uint32_t e = 0; e < elements; ++e) {12318// MemU[address,ebytes] = Elem[D[d+r],e,esize];12319uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize);1232012321context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,12322address - Rn);12323if (!MemUWrite(context, address, word, ebytes))12324return false;1232512326// address = address + ebytes;12327address = address + ebytes;12328}12329}12330}12331return true;12332}1233312334// A8.6.392 VST1 (single element from one lane) This instruction stores one12335// element to memory from one element of a register.12336bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,12337ARMEncoding encoding) {12338#if 012339if ConditionPassed() then12340EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);12341address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();12342if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12343MemU[address,ebytes] = Elem[D[d],index,esize];12344#endif1234512346bool success = false;1234712348if (ConditionPassed(opcode)) {12349uint32_t ebytes;12350uint32_t esize;12351uint32_t index;12352uint32_t alignment;12353uint32_t d;12354uint32_t n;12355uint32_t m;12356bool wback;12357bool register_index;1235812359switch (encoding) {12360case eEncodingT1:12361case eEncodingA1: {12362uint32_t size = Bits32(opcode, 11, 10);12363uint32_t index_align = Bits32(opcode, 7, 4);1236412365// if size == '11' then UNDEFINED;12366if (size == 3)12367return false;1236812369// case size of12370if (size == 0) // when '00'12371{12372// if index_align<0> != '0' then UNDEFINED;12373if (BitIsClear(index_align, 0))12374return false;12375// ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;12376ebytes = 1;12377esize = 8;12378index = Bits32(index_align, 3, 1);12379alignment = 1;12380} else if (size == 1) // when '01'12381{12382// if index_align<1> != '0' then UNDEFINED;12383if (BitIsClear(index_align, 1))12384return false;1238512386// ebytes = 2; esize = 16; index = UInt(index_align<3:2>);12387ebytes = 2;12388esize = 16;12389index = Bits32(index_align, 3, 2);1239012391// alignment = if index_align<0> == '0' then 1 else 2;12392if (BitIsClear(index_align, 0))12393alignment = 1;12394else12395alignment = 2;12396} else if (size == 2) // when '10'12397{12398// if index_align<2> != '0' then UNDEFINED;12399if (BitIsClear(index_align, 2))12400return false;1240112402// if index_align<1:0> != '00' && index_align<1:0> != '11' then12403// UNDEFINED;12404if ((Bits32(index_align, 1, 0) != 0) &&12405(Bits32(index_align, 1, 0) != 3))12406return false;1240712408// ebytes = 4; esize = 32; index = UInt(index_align<3>);12409ebytes = 4;12410esize = 32;12411index = Bit32(index_align, 3);1241212413// alignment = if index_align<1:0> == '00' then 1 else 4;12414if (Bits32(index_align, 1, 0) == 0)12415alignment = 1;12416else12417alignment = 4;12418} else {12419return false;12420}12421// d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);12422d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);12423n = Bits32(opcode, 19, 16);12424m = Bits32(opcode, 3, 0);1242512426// wback = (m != 15); register_index = (m != 15 && m != 13); if n == 1512427// then UNPREDICTABLE;12428wback = (m != 15);12429register_index = ((m != 15) && (m != 13));1243012431if (n == 15)12432return false;12433} break;1243412435default:12436return false;12437}1243812439std::optional<RegisterInfo> base_reg =12440GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);1244112442uint32_t Rn = ReadCoreReg(n, &success);12443if (!success)12444return false;1244512446// address = R[n]; if (address MOD alignment) != 0 then12447// GenerateAlignmentException();12448addr_t address = Rn;12449if ((address % alignment) != 0)12450return false;1245112452EmulateInstruction::Context context;12453// if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12454if (wback) {12455uint32_t Rm = ReadCoreReg(m, &success);12456if (!success)12457return false;1245812459uint32_t offset;12460if (register_index)12461offset = Rm;12462else12463offset = ebytes;1246412465context.type = eContextAdjustBaseRegister;12466context.SetRegisterPlusOffset(*base_reg, offset);1246712468if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,12469Rn + offset))12470return false;12471}1247212473// MemU[address,ebytes] = Elem[D[d],index,esize];12474uint64_t register_data =12475ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);12476if (!success)12477return false;1247812479uint64_t word =12480Bits64(register_data, ((index + 1) * esize) - 1, index * esize);1248112482std::optional<RegisterInfo> data_reg =12483GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d);12484context.type = eContextRegisterStore;12485context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);1248612487if (!MemUWrite(context, address, word, ebytes))12488return false;12489}12490return true;12491}1249212493// A8.6.309 VLD1 (single element to all lanes) This instruction loads one12494// element from memory into every element of one or two vectors.12495bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,12496const ARMEncoding encoding) {12497#if 012498if ConditionPassed() then12499EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);12500address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();12501if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12502replicated_element = Replicate(MemU[address,ebytes], elements);12503for r = 0 to regs-112504D[d+r] = replicated_element;12505#endif1250612507bool success = false;1250812509if (ConditionPassed(opcode)) {12510uint32_t ebytes;12511uint32_t elements;12512uint32_t regs;12513uint32_t alignment;12514uint32_t d;12515uint32_t n;12516uint32_t m;12517bool wback;12518bool register_index;1251912520switch (encoding) {12521case eEncodingT1:12522case eEncodingA1: {12523// if size == '11' || (size == '00' && a == '1') then UNDEFINED;12524uint32_t size = Bits32(opcode, 7, 6);12525if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4)))12526return false;1252712528// ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'12529// then 1 else 2;12530ebytes = 1 << size;12531elements = 8 / ebytes;12532if (BitIsClear(opcode, 5))12533regs = 1;12534else12535regs = 2;1253612537// alignment = if a == '0' then 1 else ebytes;12538if (BitIsClear(opcode, 4))12539alignment = 1;12540else12541alignment = ebytes;1254212543// d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);12544d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);12545n = Bits32(opcode, 19, 16);12546m = Bits32(opcode, 3, 0);1254712548// wback = (m != 15); register_index = (m != 15 && m != 13);12549wback = (m != 15);12550register_index = ((m != 15) && (m != 13));1255112552// if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;12553if ((d + regs) > 32)12554return false;1255512556if (n == 15)12557return false;12558} break;1255912560default:12561return false;12562}1256312564uint32_t Rn = ReadCoreReg(n, &success);12565if (!success)12566return false;1256712568// address = R[n]; if (address MOD alignment) != 0 then12569// GenerateAlignmentException();12570addr_t address = Rn;12571if ((address % alignment) != 0)12572return false;1257312574EmulateInstruction::Context context;12575// if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12576if (wback) {12577uint32_t Rm = ReadCoreReg(m, &success);12578if (!success)12579return false;1258012581uint32_t offset;12582if (register_index)12583offset = Rm;12584else12585offset = ebytes;1258612587context.type = eContextAdjustBaseRegister;12588std::optional<RegisterInfo> base_reg =12589GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);12590context.SetRegisterPlusOffset(*base_reg, offset);1259112592if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,12593Rn + offset))12594return false;12595}1259612597// replicated_element = Replicate(MemU[address,ebytes], elements);1259812599context.type = eContextRegisterLoad;12600uint64_t word = MemURead(context, address, ebytes, 0, &success);12601if (!success)12602return false;1260312604uint64_t replicated_element = 0;12605uint32_t esize = ebytes * 8;12606for (uint32_t e = 0; e < elements; ++e)12607replicated_element =12608(replicated_element << esize) | Bits64(word, esize - 1, 0);1260912610// for r = 0 to regs-112611for (uint32_t r = 0; r < regs; ++r) {12612// D[d+r] = replicated_element;12613if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,12614replicated_element))12615return false;12616}12617}12618return true;12619}1262012621// B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?12622// instruction provides an exception return without the use of the stack. It12623// subtracts the immediate constant from the LR, branches to the resulting12624// address, and also copies the SPSR to the CPSR.12625bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,12626const ARMEncoding encoding) {12627#if 012628if ConditionPassed() then12629EncodingSpecificOperations();12630if CurrentInstrSet() == InstrSet_ThumbEE then12631UNPREDICTABLE;12632operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;12633case opcode of12634when '0000' result = R[n] AND operand2; // AND12635when '0001' result = R[n] EOR operand2; // EOR12636when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB12637when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB12638when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD12639when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC12640when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC12641when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC12642when '1100' result = R[n] OR operand2; // ORR12643when '1101' result = operand2; // MOV12644when '1110' result = R[n] AND NOT(operand2); // BIC12645when '1111' result = NOT(operand2); // MVN12646CPSRWriteByInstr(SPSR[], '1111', TRUE);12647BranchWritePC(result);12648#endif1264912650bool success = false;1265112652if (ConditionPassed(opcode)) {12653uint32_t n;12654uint32_t m;12655uint32_t imm32;12656bool register_form;12657ARM_ShifterType shift_t;12658uint32_t shift_n;12659uint32_t code;1266012661switch (encoding) {12662case eEncodingT1:12663// if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;12664// imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';12665// // = SUB12666n = 14;12667imm32 = Bits32(opcode, 7, 0);12668register_form = false;12669code = 2;1267012671// if InITBlock() && !LastInITBlock() then UNPREDICTABLE;12672if (InITBlock() && !LastInITBlock())12673return false;1267412675break;1267612677case eEncodingA1:12678// n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;12679n = Bits32(opcode, 19, 16);12680imm32 = ARMExpandImm(opcode);12681register_form = false;12682code = Bits32(opcode, 24, 21);1268312684break;1268512686case eEncodingA2:12687// n = UInt(Rn); m = UInt(Rm); register_form = TRUE;12688n = Bits32(opcode, 19, 16);12689m = Bits32(opcode, 3, 0);12690register_form = true;1269112692// (shift_t, shift_n) = DecodeImmShift(type, imm5);12693shift_n = DecodeImmShiftARM(opcode, shift_t);1269412695break;1269612697default:12698return false;12699}1270012701// operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)12702// else imm32;12703uint32_t operand2;12704if (register_form) {12705uint32_t Rm = ReadCoreReg(m, &success);12706if (!success)12707return false;1270812709operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success);12710if (!success)12711return false;12712} else {12713operand2 = imm32;12714}1271512716uint32_t Rn = ReadCoreReg(n, &success);12717if (!success)12718return false;1271912720AddWithCarryResult result;1272112722// case opcode of12723switch (code) {12724case 0: // when '0000'12725// result = R[n] AND operand2; // AND12726result.result = Rn & operand2;12727break;1272812729case 1: // when '0001'12730// result = R[n] EOR operand2; // EOR12731result.result = Rn ^ operand2;12732break;1273312734case 2: // when '0010'12735// (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB12736result = AddWithCarry(Rn, ~(operand2), 1);12737break;1273812739case 3: // when '0011'12740// (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB12741result = AddWithCarry(~(Rn), operand2, 1);12742break;1274312744case 4: // when '0100'12745// (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD12746result = AddWithCarry(Rn, operand2, 0);12747break;1274812749case 5: // when '0101'12750// (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC12751result = AddWithCarry(Rn, operand2, APSR_C);12752break;1275312754case 6: // when '0110'12755// (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC12756result = AddWithCarry(Rn, ~(operand2), APSR_C);12757break;1275812759case 7: // when '0111'12760// (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC12761result = AddWithCarry(~(Rn), operand2, APSR_C);12762break;1276312764case 10: // when '1100'12765// result = R[n] OR operand2; // ORR12766result.result = Rn | operand2;12767break;1276812769case 11: // when '1101'12770// result = operand2; // MOV12771result.result = operand2;12772break;1277312774case 12: // when '1110'12775// result = R[n] AND NOT(operand2); // BIC12776result.result = Rn & ~(operand2);12777break;1277812779case 15: // when '1111'12780// result = NOT(operand2); // MVN12781result.result = ~(operand2);12782break;1278312784default:12785return false;12786}12787// CPSRWriteByInstr(SPSR[], '1111', TRUE);1278812789// For now, in emulation mode, we don't have access to the SPSR, so we will12790// use the CPSR instead, and hope for the best.12791uint32_t spsr =12792ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);12793if (!success)12794return false;1279512796CPSRWriteByInstr(spsr, 15, true);1279712798// BranchWritePC(result);12799EmulateInstruction::Context context;12800context.type = eContextAdjustPC;12801context.SetImmediate(result.result);1280212803BranchWritePC(context, result.result);12804}12805return true;12806}1280712808EmulateInstructionARM::ARMOpcode *12809EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,12810uint32_t arm_isa) {12811static ARMOpcode g_arm_opcodes[] = {12812// Prologue instructions1281312814// push register(s)12815{0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12816&EmulateInstructionARM::EmulatePUSH, "push <registers>"},12817{0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,12818&EmulateInstructionARM::EmulatePUSH, "push <register>"},1281912820// set r7 to point to a stack offset12821{0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32,12822&EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"},12823{0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32,12824&EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},12825// copy the stack pointer to ip12826{0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32,12827&EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"},12828{0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,12829&EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"},12830{0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,12831&EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},1283212833// adjust the stack pointer12834{0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32,12835&EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},12836{0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12837&EmulateInstructionARM::EmulateSUBSPReg,12838"sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},1283912840// push one register12841// if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;12842{0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12843&EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"},1284412845// vector push consecutive extension register(s)12846{0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,12847&EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},12848{0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,12849&EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},1285012851// Epilogue instructions1285212853{0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12854&EmulateInstructionARM::EmulatePOP, "pop <registers>"},12855{0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,12856&EmulateInstructionARM::EmulatePOP, "pop <register>"},12857{0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,12858&EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},12859{0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,12860&EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},1286112862// Supervisor Call (previously Software Interrupt)12863{0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32,12864&EmulateInstructionARM::EmulateSVC, "svc #imm24"},1286512866// Branch instructions12867// To resolve ambiguity, "blx <label>" should come before "b #imm24" and12868// "bl <label>".12869{0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32,12870&EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},12871{0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32,12872&EmulateInstructionARM::EmulateB, "b #imm24"},12873{0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32,12874&EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},12875{0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32,12876&EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},12877// for example, "bx lr"12878{0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32,12879&EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},12880// bxj12881{0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32,12882&EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},1288312884// Data-processing instructions12885// adc (immediate)12886{0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12887&EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},12888// adc (register)12889{0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12890&EmulateInstructionARM::EmulateADCReg,12891"adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12892// add (immediate)12893{0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32,12894&EmulateInstructionARM::EmulateADDImmARM,12895"add{s}<c> <Rd>, <Rn>, #const"},12896// add (register)12897{0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32,12898&EmulateInstructionARM::EmulateADDReg,12899"add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12900// add (register-shifted register)12901{0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32,12902&EmulateInstructionARM::EmulateADDRegShift,12903"add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},12904// adr12905{0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12906&EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},12907{0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32,12908&EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},12909// and (immediate)12910{0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32,12911&EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},12912// and (register)12913{0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32,12914&EmulateInstructionARM::EmulateANDReg,12915"and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12916// bic (immediate)12917{0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12918&EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},12919// bic (register)12920{0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12921&EmulateInstructionARM::EmulateBICReg,12922"bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12923// eor (immediate)12924{0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32,12925&EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},12926// eor (register)12927{0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32,12928&EmulateInstructionARM::EmulateEORReg,12929"eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12930// orr (immediate)12931{0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32,12932&EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},12933// orr (register)12934{0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32,12935&EmulateInstructionARM::EmulateORRReg,12936"orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12937// rsb (immediate)12938{0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32,12939&EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},12940// rsb (register)12941{0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32,12942&EmulateInstructionARM::EmulateRSBReg,12943"rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12944// rsc (immediate)12945{0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12946&EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},12947// rsc (register)12948{0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12949&EmulateInstructionARM::EmulateRSCReg,12950"rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12951// sbc (immediate)12952{0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12953&EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},12954// sbc (register)12955{0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12956&EmulateInstructionARM::EmulateSBCReg,12957"sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12958// sub (immediate, ARM)12959{0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32,12960&EmulateInstructionARM::EmulateSUBImmARM,12961"sub{s}<c> <Rd>, <Rn>, #<const>"},12962// sub (sp minus immediate)12963{0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12964&EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},12965// sub (register)12966{0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32,12967&EmulateInstructionARM::EmulateSUBReg,12968"sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},12969// teq (immediate)12970{0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32,12971&EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},12972// teq (register)12973{0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32,12974&EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},12975// tst (immediate)12976{0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32,12977&EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},12978// tst (register)12979{0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32,12980&EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},1298112982// mov (immediate)12983{0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12984&EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},12985{0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,12986&EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"},12987// mov (register)12988{0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12989&EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},12990// mvn (immediate)12991{0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12992&EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},12993// mvn (register)12994{0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12995&EmulateInstructionARM::EmulateMVNReg,12996"mvn{s}<c> <Rd>, <Rm> {,<shift>}"},12997// cmn (immediate)12998{0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32,12999&EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},13000// cmn (register)13001{0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32,13002&EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},13003// cmp (immediate)13004{0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32,13005&EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},13006// cmp (register)13007{0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32,13008&EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},13009// asr (immediate)13010{0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32,13011&EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},13012// asr (register)13013{0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,13014&EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},13015// lsl (immediate)13016{0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,13017&EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},13018// lsl (register)13019{0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32,13020&EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},13021// lsr (immediate)13022{0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32,13023&EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},13024// lsr (register)13025{0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,13026&EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},13027// rrx is a special case encoding of ror (immediate)13028{0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,13029&EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},13030// ror (immediate)13031{0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,13032&EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},13033// ror (register)13034{0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32,13035&EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},13036// mul13037{0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32,13038&EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"},1303913040// subs pc, lr and related instructions13041{0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32,13042&EmulateInstructionARM::EmulateSUBSPcLrEtc,13043"<opc>S<c> PC,#<const> | <Rn>,#<const>"},13044{0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32,13045&EmulateInstructionARM::EmulateSUBSPcLrEtc,13046"<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},1304713048// Load instructions13049{0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32,13050&EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},13051{0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32,13052&EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"},13053{0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32,13054&EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},13055{0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32,13056&EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"},13057{0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32,13058&EmulateInstructionARM::EmulateLDRImmediateARM,13059"ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},13060{0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32,13061&EmulateInstructionARM::EmulateLDRRegister,13062"ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},13063{0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,13064&EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},13065{0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32,13066&EmulateInstructionARM::EmulateLDRBRegister,13067"ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},13068{0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32,13069&EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},13070{0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,13071&EmulateInstructionARM::EmulateLDRHRegister,13072"ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},13073{0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,13074&EmulateInstructionARM::EmulateLDRSBImmediate,13075"ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},13076{0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32,13077&EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"},13078{0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,13079&EmulateInstructionARM::EmulateLDRSBRegister,13080"ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},13081{0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,13082&EmulateInstructionARM::EmulateLDRSHImmediate,13083"ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},13084{0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32,13085&EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},13086{0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,13087&EmulateInstructionARM::EmulateLDRSHRegister,13088"ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},13089{0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,13090&EmulateInstructionARM::EmulateLDRDImmediate,13091"ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},13092{0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,13093&EmulateInstructionARM::EmulateLDRDRegister,13094"ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},13095{0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,13096&EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},13097{0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,13098&EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},13099{0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,13100&EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},13101{0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,13102&EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},13103{0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,13104&EmulateInstructionARM::EmulateVLD1Multiple,13105"vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13106{0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,13107&EmulateInstructionARM::EmulateVLD1Single,13108"vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13109{0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,13110&EmulateInstructionARM::EmulateVLD1SingleAll,13111"vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},1311213113// Store instructions13114{0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32,13115&EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},13116{0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32,13117&EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"},13118{0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32,13119&EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},13120{0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32,13121&EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"},13122{0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32,13123&EmulateInstructionARM::EmulateSTRRegister,13124"str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},13125{0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,13126&EmulateInstructionARM::EmulateSTRHRegister,13127"strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},13128{0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13129&EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},13130{0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32,13131&EmulateInstructionARM::EmulateSTRBImmARM,13132"strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},13133{0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32,13134&EmulateInstructionARM::EmulateSTRImmARM,13135"str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},13136{0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,13137&EmulateInstructionARM::EmulateSTRDImm,13138"strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},13139{0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,13140&EmulateInstructionARM::EmulateSTRDReg,13141"strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},13142{0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,13143&EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},13144{0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,13145&EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},13146{0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,13147&EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},13148{0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,13149&EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},13150{0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,13151&EmulateInstructionARM::EmulateVST1Multiple,13152"vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13153{0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,13154&EmulateInstructionARM::EmulateVST1Single,13155"vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},1315613157// Other instructions13158{0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13159&EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},13160{0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13161&EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"},13162{0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13163&EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},13164{0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13165&EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"},13166{0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13167&EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"}1316813169};13170static const size_t k_num_arm_opcodes = std::size(g_arm_opcodes);1317113172for (size_t i = 0; i < k_num_arm_opcodes; ++i) {13173if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&13174(g_arm_opcodes[i].variants & arm_isa) != 0)13175return &g_arm_opcodes[i];13176}13177return nullptr;13178}1317913180EmulateInstructionARM::ARMOpcode *13181EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,13182uint32_t arm_isa) {1318313184static ARMOpcode g_thumb_opcodes[] = {13185// Prologue instructions1318613187// push register(s)13188{0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16,13189&EmulateInstructionARM::EmulatePUSH, "push <registers>"},13190{0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13191&EmulateInstructionARM::EmulatePUSH, "push.w <registers>"},13192{0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13193&EmulateInstructionARM::EmulatePUSH, "push.w <register>"},1319413195// set r7 to point to a stack offset13196{0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16,13197&EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"},13198// copy the stack pointer to r713199{0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16,13200&EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"},13201// move from high register to low register (comes after "mov r7, sp" to13202// resolve ambiguity)13203{0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16,13204&EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"},1320513206// PC-relative load into register (see also EmulateADDSPRm)13207{0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16,13208&EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},1320913210// adjust the stack pointer13211{0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16,13212&EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},13213{0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16,13214&EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},13215{0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13216&EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},13217{0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13218&EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},13219{0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13220&EmulateInstructionARM::EmulateSUBSPReg,13221"sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},1322213223// vector push consecutive extension register(s)13224{0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13225&EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},13226{0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13227&EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},1322813229// Epilogue instructions1323013231{0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13232&EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},13233{0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16,13234&EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},13235{0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16,13236&EmulateInstructionARM::EmulatePOP, "pop <registers>"},13237{0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13238&EmulateInstructionARM::EmulatePOP, "pop.w <registers>"},13239{0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13240&EmulateInstructionARM::EmulatePOP, "pop.w <register>"},13241{0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13242&EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},13243{0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13244&EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},1324513246// Supervisor Call (previously Software Interrupt)13247{0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16,13248&EmulateInstructionARM::EmulateSVC, "svc #imm8"},1324913250// If Then makes up to four following instructions conditional.13251// The next 5 opcode _must_ come before the if then instruction13252{0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,13253&EmulateInstructionARM::EmulateNop, "nop"},13254{0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,13255&EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},13256{0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,13257&EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},13258{0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,13259&EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},13260{0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,13261&EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},13262{0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,13263&EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},1326413265// Branch instructions13266// To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".13267{0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16,13268&EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},13269{0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16,13270&EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},13271{0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13272&EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},13273{0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,13274&EmulateInstructionARM::EmulateB,13275"b<c>.w #imm8 (outside or last in IT)"},13276// J1 == J2 == 113277{0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32,13278&EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},13279// J1 == J2 == 113280{0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32,13281&EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},13282{0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16,13283&EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},13284// for example, "bx lr"13285{0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32,13286&EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},13287// bxj13288{0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32,13289&EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},13290// compare and branch13291{0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,13292&EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},13293// table branch byte13294{0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13295&EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},13296// table branch halfword13297{0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13298&EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},1329913300// Data-processing instructions13301// adc (immediate)13302{0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13303&EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},13304// adc (register)13305{0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16,13306&EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},13307{0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13308&EmulateInstructionARM::EmulateADCReg,13309"adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13310// add (register)13311{0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16,13312&EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},13313// Make sure "add sp, <Rm>" comes before this instruction, so there's no13314// ambiguity decoding the two.13315{0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16,13316&EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},13317// adr13318{0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16,13319&EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},13320{0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13321&EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},13322{0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13323&EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},13324// and (immediate)13325{0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13326&EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},13327// and (register)13328{0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16,13329&EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},13330{0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13331&EmulateInstructionARM::EmulateANDReg,13332"and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13333// bic (immediate)13334{0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13335&EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},13336// bic (register)13337{0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16,13338&EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},13339{0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13340&EmulateInstructionARM::EmulateBICReg,13341"bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13342// eor (immediate)13343{0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13344&EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},13345// eor (register)13346{0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16,13347&EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},13348{0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13349&EmulateInstructionARM::EmulateEORReg,13350"eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13351// orr (immediate)13352{0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13353&EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},13354// orr (register)13355{0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16,13356&EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},13357{0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13358&EmulateInstructionARM::EmulateORRReg,13359"orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13360// rsb (immediate)13361{0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16,13362&EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},13363{0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13364&EmulateInstructionARM::EmulateRSBImm,13365"rsb{s}<c>.w <Rd>, <Rn>, #<const>"},13366// rsb (register)13367{0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13368&EmulateInstructionARM::EmulateRSBReg,13369"rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13370// sbc (immediate)13371{0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13372&EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},13373// sbc (register)13374{0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16,13375&EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},13376{0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13377&EmulateInstructionARM::EmulateSBCReg,13378"sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13379// add (immediate, Thumb)13380{0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13381&EmulateInstructionARM::EmulateADDImmThumb,13382"adds|add<c> <Rd>,<Rn>,#<imm3>"},13383{0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,13384&EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"},13385{0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13386&EmulateInstructionARM::EmulateADDImmThumb,13387"add{s}<c>.w <Rd>,<Rn>,#<const>"},13388{0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,13389&EmulateInstructionARM::EmulateADDImmThumb,13390"addw<c> <Rd>,<Rn>,#<imm12>"},13391// sub (immediate, Thumb)13392{0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16,13393&EmulateInstructionARM::EmulateSUBImmThumb,13394"subs|sub<c> <Rd>, <Rn> #imm3"},13395{0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16,13396&EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},13397{0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13398&EmulateInstructionARM::EmulateSUBImmThumb,13399"sub{s}<c>.w <Rd>, <Rn>, #<const>"},13400{0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,13401&EmulateInstructionARM::EmulateSUBImmThumb,13402"subw<c> <Rd>, <Rn>, #imm12"},13403// sub (sp minus immediate)13404{0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13405&EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},13406{0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13407&EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},13408// sub (register)13409{0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13410&EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},13411{0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13412&EmulateInstructionARM::EmulateSUBReg,13413"sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},13414// teq (immediate)13415{0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13416&EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},13417// teq (register)13418{0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13419&EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},13420// tst (immediate)13421{0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13422&EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},13423// tst (register)13424{0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16,13425&EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},13426{0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13427&EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},1342813429// move from high register to high register13430{0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16,13431&EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},13432// move from low register to low register13433{0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16,13434&EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},13435// mov{s}<c>.w <Rd>, <Rm>13436{0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13437&EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},13438// move immediate13439{0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16,13440&EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},13441{0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13442&EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},13443{0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13444&EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},13445// mvn (immediate)13446{0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13447&EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},13448// mvn (register)13449{0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16,13450&EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},13451{0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13452&EmulateInstructionARM::EmulateMVNReg,13453"mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},13454// cmn (immediate)13455{0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13456&EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},13457// cmn (register)13458{0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16,13459&EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},13460{0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13461&EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},13462// cmp (immediate)13463{0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16,13464&EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},13465{0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13466&EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},13467// cmp (register) (Rn and Rm both from r0-r7)13468{0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16,13469&EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},13470// cmp (register) (Rn and Rm not both from r0-r7)13471{0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16,13472&EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},13473{0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16,13474&EmulateInstructionARM::EmulateCMPReg,13475"cmp<c>.w <Rn>, <Rm> {, <shift>}"},13476// asr (immediate)13477{0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16,13478&EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},13479{0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13480&EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},13481// asr (register)13482{0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16,13483&EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},13484{0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13485&EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},13486// lsl (immediate)13487{0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16,13488&EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},13489{0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13490&EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},13491// lsl (register)13492{0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16,13493&EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},13494{0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13495&EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},13496// lsr (immediate)13497{0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16,13498&EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},13499{0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13500&EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},13501// lsr (register)13502{0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16,13503&EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},13504{0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13505&EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},13506// rrx is a special case encoding of ror (immediate)13507{0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13508&EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},13509// ror (immediate)13510{0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13511&EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},13512// ror (register)13513{0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16,13514&EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},13515{0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13516&EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},13517// mul13518{0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13519&EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"},13520// mul13521{0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13522&EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"},1352313524// subs pc, lr and related instructions13525{0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13526&EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"},1352713528// RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE13529// LDM.. Instructions in this table;13530// otherwise the wrong instructions will be selected.1353113532{0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13533&EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"},13534{0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13535&EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"},1353613537// Load instructions13538{0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13539&EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},13540{0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13541&EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"},13542{0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13543&EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},13544{0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13545&EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},13546{0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,13547&EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},13548{0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13549&EmulateInstructionARM::EmulateLDRRtRnImm,13550"ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},13551{0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,13552&EmulateInstructionARM::EmulateLDRRtRnImm,13553"ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},13554// Thumb2 PC-relative load into register13555{0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13556&EmulateInstructionARM::EmulateLDRRtPCRelative,13557"ldr<c>.w <Rt>, [PC, +/-#imm}]"},13558{0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13559&EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"},13560{0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13561&EmulateInstructionARM::EmulateLDRRegister,13562"ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},13563{0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13564&EmulateInstructionARM::EmulateLDRBImmediate,13565"ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},13566{0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13567&EmulateInstructionARM::EmulateLDRBImmediate,13568"ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},13569{0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13570&EmulateInstructionARM::EmulateLDRBImmediate,13571"ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},13572{0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13573&EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"},13574{0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,13575&EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},13576{0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13577&EmulateInstructionARM::EmulateLDRBRegister,13578"ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},13579{0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13580&EmulateInstructionARM::EmulateLDRHImmediate,13581"ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},13582{0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13583&EmulateInstructionARM::EmulateLDRHImmediate,13584"ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},13585{0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13586&EmulateInstructionARM::EmulateLDRHImmediate,13587"ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},13588{0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13589&EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},13590{0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13591&EmulateInstructionARM::EmulateLDRHRegister,13592"ldrh<c> <Rt>, [<Rn>,<Rm>]"},13593{0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13594&EmulateInstructionARM::EmulateLDRHRegister,13595"ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},13596{0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13597&EmulateInstructionARM::EmulateLDRSBImmediate,13598"ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},13599{0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13600&EmulateInstructionARM::EmulateLDRSBImmediate,13601"ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},13602{0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13603&EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"},13604{0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13605&EmulateInstructionARM::EmulateLDRSBRegister,13606"ldrsb<c> <Rt>,[<Rn>,<Rm>]"},13607{0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13608&EmulateInstructionARM::EmulateLDRSBRegister,13609"ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},13610{0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13611&EmulateInstructionARM::EmulateLDRSHImmediate,13612"ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},13613{0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13614&EmulateInstructionARM::EmulateLDRSHImmediate,13615"ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},13616{0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13617&EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},13618{0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13619&EmulateInstructionARM::EmulateLDRSHRegister,13620"ldrsh<c> <Rt>,[<Rn>,<Rm>]"},13621{0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13622&EmulateInstructionARM::EmulateLDRSHRegister,13623"ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},13624{0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13625&EmulateInstructionARM::EmulateLDRDImmediate,13626"ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},13627{0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,13628&EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},13629{0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,13630&EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},13631{0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,13632&EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},13633{0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,13634&EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},13635{0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,13636&EmulateInstructionARM::EmulateVLD1Multiple,13637"vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},13638{0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,13639&EmulateInstructionARM::EmulateVLD1Single,13640"vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},13641{0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,13642&EmulateInstructionARM::EmulateVLD1SingleAll,13643"vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},1364413645// Store instructions13646{0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13647&EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},13648{0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13649&EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"},13650{0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13651&EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},13652{0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13653&EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"},13654{0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,13655&EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"},13656{0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13657&EmulateInstructionARM::EmulateSTRThumb,13658"str<c>.w <Rt>, [<Rn>,#<imm12>]"},13659{0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,13660&EmulateInstructionARM::EmulateSTRThumb,13661"str<c> <Rt>, [<Rn>,#+/-<imm8>]"},13662{0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13663&EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"},13664{0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13665&EmulateInstructionARM::EmulateSTRRegister,13666"str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},13667{0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13668&EmulateInstructionARM::EmulateSTRBThumb,13669"strb<c> <Rt>, [<Rn>, #<imm5>]"},13670{0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13671&EmulateInstructionARM::EmulateSTRBThumb,13672"strb<c>.w <Rt>, [<Rn>, #<imm12>]"},13673{0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13674&EmulateInstructionARM::EmulateSTRBThumb,13675"strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},13676{0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13677&EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"},13678{0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13679&EmulateInstructionARM::EmulateSTRHRegister,13680"strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},13681{0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13682&EmulateInstructionARM::EmulateSTREX,13683"strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},13684{0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13685&EmulateInstructionARM::EmulateSTRDImm,13686"strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},13687{0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,13688&EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},13689{0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,13690&EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},13691{0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,13692&EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},13693{0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,13694&EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},13695{0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,13696&EmulateInstructionARM::EmulateVST1Multiple,13697"vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13698{0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,13699&EmulateInstructionARM::EmulateVST1Single,13700"vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},1370113702// Other instructions13703{0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,13704&EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"},13705{0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32,13706&EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},13707{0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,13708&EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"},13709{0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13710&EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},13711{0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,13712&EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"},13713{0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13714&EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},13715{0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,13716&EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"},13717{0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13718&EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},13719};1372013721const size_t k_num_thumb_opcodes = std::size(g_thumb_opcodes);13722for (size_t i = 0; i < k_num_thumb_opcodes; ++i) {13723if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&13724(g_thumb_opcodes[i].variants & arm_isa) != 0)13725return &g_thumb_opcodes[i];13726}13727return nullptr;13728}1372913730bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) {13731m_arch = arch;13732m_arm_isa = 0;13733llvm::StringRef arch_cstr = arch.GetArchitectureName();13734if (arch_cstr.equals_insensitive("armv4t"))13735m_arm_isa = ARMv4T;13736else if (arch_cstr.equals_insensitive("armv5tej"))13737m_arm_isa = ARMv5TEJ;13738else if (arch_cstr.equals_insensitive("armv5te"))13739m_arm_isa = ARMv5TE;13740else if (arch_cstr.equals_insensitive("armv5t"))13741m_arm_isa = ARMv5T;13742else if (arch_cstr.equals_insensitive("armv6k"))13743m_arm_isa = ARMv6K;13744else if (arch_cstr.equals_insensitive("armv6t2"))13745m_arm_isa = ARMv6T2;13746else if (arch_cstr.equals_insensitive("armv7s"))13747m_arm_isa = ARMv7S;13748else if (arch_cstr.equals_insensitive("arm"))13749m_arm_isa = ARMvAll;13750else if (arch_cstr.equals_insensitive("thumb"))13751m_arm_isa = ARMvAll;13752else if (arch_cstr.starts_with_insensitive("armv4"))13753m_arm_isa = ARMv4;13754else if (arch_cstr.starts_with_insensitive("armv6"))13755m_arm_isa = ARMv6;13756else if (arch_cstr.starts_with_insensitive("armv7"))13757m_arm_isa = ARMv7;13758else if (arch_cstr.starts_with_insensitive("armv8"))13759m_arm_isa = ARMv8;13760return m_arm_isa != 0;13761}1376213763bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,13764const Address &inst_addr,13765Target *target) {13766if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {13767if (m_arch.GetTriple().getArch() == llvm::Triple::thumb ||13768m_arch.IsAlwaysThumbInstructions())13769m_opcode_mode = eModeThumb;13770else {13771AddressClass addr_class = inst_addr.GetAddressClass();1377213773if ((addr_class == AddressClass::eCode) ||13774(addr_class == AddressClass::eUnknown))13775m_opcode_mode = eModeARM;13776else if (addr_class == AddressClass::eCodeAlternateISA)13777m_opcode_mode = eModeThumb;13778else13779return false;13780}13781if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions())13782m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;13783else13784m_opcode_cpsr = CPSR_MODE_USR;13785return true;13786}13787return false;13788}1378913790bool EmulateInstructionARM::ReadInstruction() {13791bool success = false;13792m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric,13793LLDB_REGNUM_GENERIC_FLAGS, 0, &success);13794if (success) {13795addr_t pc =13796ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,13797LLDB_INVALID_ADDRESS, &success);13798if (success) {13799Context read_inst_context;13800read_inst_context.type = eContextReadOpcode;13801read_inst_context.SetNoArgs();1380213803if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {13804m_opcode_mode = eModeThumb;13805uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);1380613807if (success) {13808if ((thumb_opcode & 0xe000) != 0xe000 ||13809((thumb_opcode & 0x1800u) == 0)) {13810m_opcode.SetOpcode16(thumb_opcode, GetByteOrder());13811} else {13812m_opcode.SetOpcode32(13813(thumb_opcode << 16) |13814MemARead(read_inst_context, pc + 2, 2, 0, &success),13815GetByteOrder());13816}13817}13818} else {13819m_opcode_mode = eModeARM;13820m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success),13821GetByteOrder());13822}1382313824if (!m_ignore_conditions) {13825// If we are not ignoreing the conditions then init the it session from13826// the current value of cpsr.13827uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |13828Bits32(m_opcode_cpsr, 26, 25);13829if (it != 0)13830m_it_session.InitIT(it);13831}13832}13833}13834if (!success) {13835m_opcode_mode = eModeInvalid;13836m_addr = LLDB_INVALID_ADDRESS;13837}13838return success;13839}1384013841uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }1384213843bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {13844// If we are ignoring conditions, then always return true. this allows us to13845// iterate over disassembly code and still emulate an instruction even if we13846// don't have all the right bits set in the CPSR register...13847if (m_ignore_conditions)13848return true;1384913850const uint32_t cond = CurrentCond(opcode);13851if (cond == UINT32_MAX)13852return false;1385313854bool result = false;13855switch (UnsignedBits(cond, 3, 1)) {13856case 0:13857if (m_opcode_cpsr == 0)13858result = true;13859else13860result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;13861break;13862case 1:13863if (m_opcode_cpsr == 0)13864result = true;13865else13866result = (m_opcode_cpsr & MASK_CPSR_C) != 0;13867break;13868case 2:13869if (m_opcode_cpsr == 0)13870result = true;13871else13872result = (m_opcode_cpsr & MASK_CPSR_N) != 0;13873break;13874case 3:13875if (m_opcode_cpsr == 0)13876result = true;13877else13878result = (m_opcode_cpsr & MASK_CPSR_V) != 0;13879break;13880case 4:13881if (m_opcode_cpsr == 0)13882result = true;13883else13884result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) &&13885((m_opcode_cpsr & MASK_CPSR_Z) == 0);13886break;13887case 5:13888if (m_opcode_cpsr == 0)13889result = true;13890else {13891bool n = (m_opcode_cpsr & MASK_CPSR_N);13892bool v = (m_opcode_cpsr & MASK_CPSR_V);13893result = n == v;13894}13895break;13896case 6:13897if (m_opcode_cpsr == 0)13898result = true;13899else {13900bool n = (m_opcode_cpsr & MASK_CPSR_N);13901bool v = (m_opcode_cpsr & MASK_CPSR_V);13902result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);13903}13904break;13905case 7:13906// Always execute (cond == 0b1110, or the special 0b1111 which gives13907// opcodes different meanings, but always means execution happens.13908return true;13909}1391013911if (cond & 1)13912result = !result;13913return result;13914}1391513916uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {13917switch (m_opcode_mode) {13918case eModeInvalid:13919break;1392013921case eModeARM:13922return UnsignedBits(opcode, 31, 28);1392313924case eModeThumb:13925// For T1 and T3 encodings of the Branch instruction, it returns the 4-bit13926// 'cond' field of the encoding.13927{13928const uint32_t byte_size = m_opcode.GetByteSize();13929if (byte_size == 2) {13930if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)13931return Bits32(opcode, 11, 8);13932} else if (byte_size == 4) {13933if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 &&13934Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) {13935return Bits32(opcode, 25, 22);13936}13937} else13938// We have an invalid thumb instruction, let's bail out.13939break;1394013941return m_it_session.GetCond();13942}13943}13944return UINT32_MAX; // Return invalid value13945}1394613947bool EmulateInstructionARM::InITBlock() {13948return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();13949}1395013951bool EmulateInstructionARM::LastInITBlock() {13952return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();13953}1395413955bool EmulateInstructionARM::BadMode(uint32_t mode) {1395613957switch (mode) {13958case 16:13959return false; // '10000'13960case 17:13961return false; // '10001'13962case 18:13963return false; // '10010'13964case 19:13965return false; // '10011'13966case 22:13967return false; // '10110'13968case 23:13969return false; // '10111'13970case 27:13971return false; // '11011'13972case 31:13973return false; // '11111'13974default:13975return true;13976}13977return true;13978}1397913980bool EmulateInstructionARM::CurrentModeIsPrivileged() {13981uint32_t mode = Bits32(m_opcode_cpsr, 4, 0);1398213983if (BadMode(mode))13984return false;1398513986if (mode == 16)13987return false;1398813989return true;13990}1399113992void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,13993bool affect_execstate) {13994bool privileged = CurrentModeIsPrivileged();1399513996uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20;1399713998if (BitIsSet(bytemask, 3)) {13999tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27);14000if (affect_execstate)14001tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24);14002}1400314004if (BitIsSet(bytemask, 2)) {14005tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16);14006}1400714008if (BitIsSet(bytemask, 1)) {14009if (affect_execstate)14010tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10);14011tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9);14012if (privileged)14013tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8);14014}1401514016if (BitIsSet(bytemask, 0)) {14017if (privileged)14018tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6);14019if (affect_execstate)14020tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5);14021if (privileged)14022tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0);14023}1402414025m_opcode_cpsr = tmp_cpsr;14026}1402714028bool EmulateInstructionARM::BranchWritePC(const Context &context,14029uint32_t addr) {14030addr_t target;1403114032// Check the current instruction set.14033if (CurrentInstrSet() == eModeARM)14034target = addr & 0xfffffffc;14035else14036target = addr & 0xfffffffe;1403714038return WriteRegisterUnsigned(context, eRegisterKindGeneric,14039LLDB_REGNUM_GENERIC_PC, target);14040}1404114042// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by14043// inspecting addr.14044bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {14045addr_t target;14046// If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,14047// we want to record it and issue a WriteRegister callback so the clients can14048// track the mode changes accordingly.14049bool cpsr_changed = false;1405014051if (BitIsSet(addr, 0)) {14052if (CurrentInstrSet() != eModeThumb) {14053SelectInstrSet(eModeThumb);14054cpsr_changed = true;14055}14056target = addr & 0xfffffffe;14057context.SetISA(eModeThumb);14058} else if (BitIsClear(addr, 1)) {14059if (CurrentInstrSet() != eModeARM) {14060SelectInstrSet(eModeARM);14061cpsr_changed = true;14062}14063target = addr & 0xfffffffc;14064context.SetISA(eModeARM);14065} else14066return false; // address<1:0> == '10' => UNPREDICTABLE1406714068if (cpsr_changed) {14069if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,14070LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))14071return false;14072}14073return WriteRegisterUnsigned(context, eRegisterKindGeneric,14074LLDB_REGNUM_GENERIC_PC, target);14075}1407614077// Dispatches to either BXWritePC or BranchWritePC based on architecture14078// versions.14079bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {14080if (ArchVersion() >= ARMv5T)14081return BXWritePC(context, addr);14082else14083return BranchWritePC((const Context)context, addr);14084}1408514086// Dispatches to either BXWritePC or BranchWritePC based on architecture14087// versions and current instruction set.14088bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {14089if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)14090return BXWritePC(context, addr);14091else14092return BranchWritePC((const Context)context, addr);14093}1409414095EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {14096return m_opcode_mode;14097}1409814099// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next14100// ReadInstruction() is performed. This function has a side effect of updating14101// the m_new_inst_cpsr member variable if necessary.14102bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) {14103m_new_inst_cpsr = m_opcode_cpsr;14104switch (arm_or_thumb) {14105default:14106return false;14107case eModeARM:14108// Clear the T bit.14109m_new_inst_cpsr &= ~MASK_CPSR_T;14110break;14111case eModeThumb:14112// Set the T bit.14113m_new_inst_cpsr |= MASK_CPSR_T;14114break;14115}14116return true;14117}1411814119// This function returns TRUE if the processor currently provides support for14120// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,14121// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.14122bool EmulateInstructionARM::UnalignedSupport() {14123return (ArchVersion() >= ARMv7);14124}1412514126// The main addition and subtraction instructions can produce status14127// information about both unsigned carry and signed overflow conditions. This14128// status information can be used to synthesize multi-word additions and14129// subtractions.14130EmulateInstructionARM::AddWithCarryResult14131EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {14132uint32_t result;14133uint8_t carry_out;14134uint8_t overflow;1413514136uint64_t unsigned_sum = x + y + carry_in;14137int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;1413814139result = UnsignedBits(unsigned_sum, 31, 0);14140// carry_out = (result == unsigned_sum ? 0 : 1);14141overflow = ((int32_t)result == signed_sum ? 0 : 1);1414214143if (carry_in)14144carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0;14145else14146carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0;1414714148AddWithCarryResult res = {result, carry_out, overflow};14149return res;14150}1415114152uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {14153lldb::RegisterKind reg_kind;14154uint32_t reg_num;14155switch (num) {14156case SP_REG:14157reg_kind = eRegisterKindGeneric;14158reg_num = LLDB_REGNUM_GENERIC_SP;14159break;14160case LR_REG:14161reg_kind = eRegisterKindGeneric;14162reg_num = LLDB_REGNUM_GENERIC_RA;14163break;14164case PC_REG:14165reg_kind = eRegisterKindGeneric;14166reg_num = LLDB_REGNUM_GENERIC_PC;14167break;14168default:14169if (num < SP_REG) {14170reg_kind = eRegisterKindDWARF;14171reg_num = dwarf_r0 + num;14172} else {14173// assert(0 && "Invalid register number");14174*success = false;14175return UINT32_MAX;14176}14177break;14178}1417914180// Read our register.14181uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);1418214183// When executing an ARM instruction , PC reads as the address of the current14184// instruction plus 8. When executing a Thumb instruction , PC reads as the14185// address of the current instruction plus 4.14186if (num == 15) {14187if (CurrentInstrSet() == eModeARM)14188val += 8;14189else14190val += 4;14191}1419214193return val;14194}1419514196// Write the result to the ARM core register Rd, and optionally update the14197// condition flags based on the result.14198//14199// This helper method tries to encapsulate the following pseudocode from the14200// ARM Architecture Reference Manual:14201//14202// if d == 15 then // Can only occur for encoding A114203// ALUWritePC(result); // setflags is always FALSE here14204// else14205// R[d] = result;14206// if setflags then14207// APSR.N = result<31>;14208// APSR.Z = IsZeroBit(result);14209// APSR.C = carry;14210// // APSR.V unchanged14211//14212// In the above case, the API client does not pass in the overflow arg, which14213// defaults to ~0u.14214bool EmulateInstructionARM::WriteCoreRegOptionalFlags(14215Context &context, const uint32_t result, const uint32_t Rd, bool setflags,14216const uint32_t carry, const uint32_t overflow) {14217if (Rd == 15) {14218if (!ALUWritePC(context, result))14219return false;14220} else {14221lldb::RegisterKind reg_kind;14222uint32_t reg_num;14223switch (Rd) {14224case SP_REG:14225reg_kind = eRegisterKindGeneric;14226reg_num = LLDB_REGNUM_GENERIC_SP;14227break;14228case LR_REG:14229reg_kind = eRegisterKindGeneric;14230reg_num = LLDB_REGNUM_GENERIC_RA;14231break;14232default:14233reg_kind = eRegisterKindDWARF;14234reg_num = dwarf_r0 + Rd;14235}14236if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result))14237return false;14238if (setflags)14239return WriteFlags(context, result, carry, overflow);14240}14241return true;14242}1424314244// This helper method tries to encapsulate the following pseudocode from the14245// ARM Architecture Reference Manual:14246//14247// APSR.N = result<31>;14248// APSR.Z = IsZeroBit(result);14249// APSR.C = carry;14250// APSR.V = overflow14251//14252// Default arguments can be specified for carry and overflow parameters, which14253// means not to update the respective flags.14254bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,14255const uint32_t carry,14256const uint32_t overflow) {14257m_new_inst_cpsr = m_opcode_cpsr;14258SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));14259SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);14260if (carry != ~0u)14261SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);14262if (overflow != ~0u)14263SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);14264if (m_new_inst_cpsr != m_opcode_cpsr) {14265if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,14266LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))14267return false;14268}14269return true;14270}1427114272bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {14273ARMOpcode *opcode_data = nullptr;1427414275if (m_opcode_mode == eModeThumb)14276opcode_data =14277GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);14278else if (m_opcode_mode == eModeARM)14279opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);1428014281const bool auto_advance_pc =14282evaluate_options & eEmulateInstructionOptionAutoAdvancePC;14283m_ignore_conditions =14284evaluate_options & eEmulateInstructionOptionIgnoreConditions;1428514286bool success = false;14287if (m_opcode_cpsr == 0 || !m_ignore_conditions) {14288m_opcode_cpsr =14289ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);14290}1429114292// Only return false if we are unable to read the CPSR if we care about14293// conditions14294if (!success && !m_ignore_conditions)14295return false;1429614297uint32_t orig_pc_value = 0;14298if (auto_advance_pc) {14299orig_pc_value =14300ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);14301if (!success)14302return false;14303}1430414305// Call the Emulate... function if we managed to decode the opcode.14306if (opcode_data) {14307success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(),14308opcode_data->encoding);14309if (!success)14310return false;14311}1431214313// Advance the ITSTATE bits to their values for the next instruction if we14314// haven't just executed an IT instruction what initialized it.14315if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&14316(opcode_data == nullptr ||14317opcode_data->callback != &EmulateInstructionARM::EmulateIT))14318m_it_session.ITAdvance();1431914320if (auto_advance_pc) {14321uint32_t after_pc_value =14322ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);14323if (!success)14324return false;1432514326if (after_pc_value == orig_pc_value) {14327after_pc_value += m_opcode.GetByteSize();1432814329EmulateInstruction::Context context;14330context.type = eContextAdvancePC;14331context.SetNoArgs();14332if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc,14333after_pc_value))14334return false;14335}14336}14337return true;14338}1433914340EmulateInstruction::InstructionCondition14341EmulateInstructionARM::GetInstructionCondition() {14342const uint32_t cond = CurrentCond(m_opcode.GetOpcode32());14343if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)14344return EmulateInstruction::UnconditionalCondition;14345return cond;14346}1434714348bool EmulateInstructionARM::TestEmulation(Stream &out_stream, ArchSpec &arch,14349OptionValueDictionary *test_data) {14350if (!test_data) {14351out_stream.Printf("TestEmulation: Missing test data.\n");14352return false;14353}1435414355static constexpr llvm::StringLiteral opcode_key("opcode");14356static constexpr llvm::StringLiteral before_key("before_state");14357static constexpr llvm::StringLiteral after_key("after_state");1435814359OptionValueSP value_sp = test_data->GetValueForKey(opcode_key);1436014361uint32_t test_opcode;14362if ((value_sp.get() == nullptr) ||14363(value_sp->GetType() != OptionValue::eTypeUInt64)) {14364out_stream.Printf("TestEmulation: Error reading opcode from test file.\n");14365return false;14366}14367test_opcode = value_sp->GetValueAs<uint64_t>().value_or(0);1436814369if (arch.GetTriple().getArch() == llvm::Triple::thumb ||14370arch.IsAlwaysThumbInstructions()) {14371m_opcode_mode = eModeThumb;14372if (test_opcode < 0x10000)14373m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder());14374else14375m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());14376} else if (arch.GetTriple().getArch() == llvm::Triple::arm) {14377m_opcode_mode = eModeARM;14378m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());14379} else {14380out_stream.Printf("TestEmulation: Invalid arch.\n");14381return false;14382}1438314384EmulationStateARM before_state;14385EmulationStateARM after_state;1438614387value_sp = test_data->GetValueForKey(before_key);14388if ((value_sp.get() == nullptr) ||14389(value_sp->GetType() != OptionValue::eTypeDictionary)) {14390out_stream.Printf("TestEmulation: Failed to find 'before' state.\n");14391return false;14392}1439314394OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();14395if (!before_state.LoadStateFromDictionary(state_dictionary)) {14396out_stream.Printf("TestEmulation: Failed loading 'before' state.\n");14397return false;14398}1439914400value_sp = test_data->GetValueForKey(after_key);14401if ((value_sp.get() == nullptr) ||14402(value_sp->GetType() != OptionValue::eTypeDictionary)) {14403out_stream.Printf("TestEmulation: Failed to find 'after' state.\n");14404return false;14405}1440614407state_dictionary = value_sp->GetAsDictionary();14408if (!after_state.LoadStateFromDictionary(state_dictionary)) {14409out_stream.Printf("TestEmulation: Failed loading 'after' state.\n");14410return false;14411}1441214413SetBaton((void *)&before_state);14414SetCallbacks(&EmulationStateARM::ReadPseudoMemory,14415&EmulationStateARM::WritePseudoMemory,14416&EmulationStateARM::ReadPseudoRegister,14417&EmulationStateARM::WritePseudoRegister);1441814419bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);14420if (!success) {14421out_stream.Printf("TestEmulation: EvaluateInstruction() failed.\n");14422return false;14423}1442414425success = before_state.CompareState(after_state, out_stream);14426if (!success)14427out_stream.Printf("TestEmulation: State after emulation does not match "14428"'after' state.\n");1442914430return success;14431}14432//14433//14434// const char *14435// EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)14436//{14437// if (reg_kind == eRegisterKindGeneric)14438// {14439// switch (reg_num)14440// {14441// case LLDB_REGNUM_GENERIC_PC: return "pc";14442// case LLDB_REGNUM_GENERIC_SP: return "sp";14443// case LLDB_REGNUM_GENERIC_FP: return "fp";14444// case LLDB_REGNUM_GENERIC_RA: return "lr";14445// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";14446// default: return NULL;14447// }14448// }14449// else if (reg_kind == eRegisterKindDWARF)14450// {14451// return GetARMDWARFRegisterName (reg_num);14452// }14453// return NULL;14454//}14455//14456bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {14457unwind_plan.Clear();14458unwind_plan.SetRegisterKind(eRegisterKindDWARF);1445914460UnwindPlan::RowSP row(new UnwindPlan::Row);1446114462// Our previous Call Frame Address is the stack pointer14463row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0);1446414465unwind_plan.AppendRow(row);14466unwind_plan.SetSourceName("EmulateInstructionARM");14467unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);14468unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);14469unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);14470unwind_plan.SetReturnAddressRegister(dwarf_lr);14471return true;14472}144731447414475