brintos

brintos / llvm-project-archived public Read only

0
0
Text · 461.1 KiB · f5f077f Raw
14493 lines · cpp
1//===-- EmulateInstructionARM.cpp -----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <cstdlib>10#include <optional>11 12#include "EmulateInstructionARM.h"13#include "EmulationStateARM.h"14#include "lldb/Core/Address.h"15#include "lldb/Core/PluginManager.h"16#include "lldb/Host/PosixApi.h"17#include "lldb/Interpreter/OptionValueArray.h"18#include "lldb/Interpreter/OptionValueDictionary.h"19#include "lldb/Symbol/UnwindPlan.h"20#include "lldb/Utility/ArchSpec.h"21#include "lldb/Utility/Stream.h"22 23#include "Plugins/Process/Utility/ARMDefines.h"24#include "Plugins/Process/Utility/ARMUtils.h"25#include "Utility/ARM_DWARF_Registers.h"26 27#include "llvm/ADT/STLExtras.h"28#include "llvm/Support/MathExtras.h"29 30using namespace lldb;31using namespace lldb_private;32 33LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM, InstructionARM)34 35// Convenient macro definitions.36#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)37#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)38 39#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)40 41//42// ITSession implementation43//44 45static std::optional<RegisterInfo> GetARMDWARFRegisterInfo(unsigned reg_num) {46  RegisterInfo reg_info;47  ::memset(&reg_info, 0, sizeof(RegisterInfo));48  ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));49 50  if (reg_num >= dwarf_q0 && reg_num <= dwarf_q15) {51    reg_info.byte_size = 16;52    reg_info.format = eFormatVectorOfUInt8;53    reg_info.encoding = eEncodingVector;54  }55 56  if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) {57    reg_info.byte_size = 8;58    reg_info.format = eFormatFloat;59    reg_info.encoding = eEncodingIEEE754;60  } else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) {61    reg_info.byte_size = 4;62    reg_info.format = eFormatFloat;63    reg_info.encoding = eEncodingIEEE754;64  } else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) {65    reg_info.byte_size = 12;66    reg_info.format = eFormatFloat;67    reg_info.encoding = eEncodingIEEE754;68  } else {69    reg_info.byte_size = 4;70    reg_info.format = eFormatHex;71    reg_info.encoding = eEncodingUint;72  }73 74  reg_info.kinds[eRegisterKindDWARF] = reg_num;75 76  switch (reg_num) {77  case dwarf_r0:78    reg_info.name = "r0";79    break;80  case dwarf_r1:81    reg_info.name = "r1";82    break;83  case dwarf_r2:84    reg_info.name = "r2";85    break;86  case dwarf_r3:87    reg_info.name = "r3";88    break;89  case dwarf_r4:90    reg_info.name = "r4";91    break;92  case dwarf_r5:93    reg_info.name = "r5";94    break;95  case dwarf_r6:96    reg_info.name = "r6";97    break;98  case dwarf_r7:99    reg_info.name = "r7";100    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;101    break;102  case dwarf_r8:103    reg_info.name = "r8";104    break;105  case dwarf_r9:106    reg_info.name = "r9";107    break;108  case dwarf_r10:109    reg_info.name = "r10";110    break;111  case dwarf_r11:112    reg_info.name = "r11";113    break;114  case dwarf_r12:115    reg_info.name = "r12";116    break;117  case dwarf_sp:118    reg_info.name = "sp";119    reg_info.alt_name = "r13";120    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;121    break;122  case dwarf_lr:123    reg_info.name = "lr";124    reg_info.alt_name = "r14";125    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;126    break;127  case dwarf_pc:128    reg_info.name = "pc";129    reg_info.alt_name = "r15";130    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;131    break;132  case dwarf_cpsr:133    reg_info.name = "cpsr";134    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;135    break;136 137  case dwarf_s0:138    reg_info.name = "s0";139    break;140  case dwarf_s1:141    reg_info.name = "s1";142    break;143  case dwarf_s2:144    reg_info.name = "s2";145    break;146  case dwarf_s3:147    reg_info.name = "s3";148    break;149  case dwarf_s4:150    reg_info.name = "s4";151    break;152  case dwarf_s5:153    reg_info.name = "s5";154    break;155  case dwarf_s6:156    reg_info.name = "s6";157    break;158  case dwarf_s7:159    reg_info.name = "s7";160    break;161  case dwarf_s8:162    reg_info.name = "s8";163    break;164  case dwarf_s9:165    reg_info.name = "s9";166    break;167  case dwarf_s10:168    reg_info.name = "s10";169    break;170  case dwarf_s11:171    reg_info.name = "s11";172    break;173  case dwarf_s12:174    reg_info.name = "s12";175    break;176  case dwarf_s13:177    reg_info.name = "s13";178    break;179  case dwarf_s14:180    reg_info.name = "s14";181    break;182  case dwarf_s15:183    reg_info.name = "s15";184    break;185  case dwarf_s16:186    reg_info.name = "s16";187    break;188  case dwarf_s17:189    reg_info.name = "s17";190    break;191  case dwarf_s18:192    reg_info.name = "s18";193    break;194  case dwarf_s19:195    reg_info.name = "s19";196    break;197  case dwarf_s20:198    reg_info.name = "s20";199    break;200  case dwarf_s21:201    reg_info.name = "s21";202    break;203  case dwarf_s22:204    reg_info.name = "s22";205    break;206  case dwarf_s23:207    reg_info.name = "s23";208    break;209  case dwarf_s24:210    reg_info.name = "s24";211    break;212  case dwarf_s25:213    reg_info.name = "s25";214    break;215  case dwarf_s26:216    reg_info.name = "s26";217    break;218  case dwarf_s27:219    reg_info.name = "s27";220    break;221  case dwarf_s28:222    reg_info.name = "s28";223    break;224  case dwarf_s29:225    reg_info.name = "s29";226    break;227  case dwarf_s30:228    reg_info.name = "s30";229    break;230  case dwarf_s31:231    reg_info.name = "s31";232    break;233 234  // FPA Registers 0-7235  case dwarf_f0:236    reg_info.name = "f0";237    break;238  case dwarf_f1:239    reg_info.name = "f1";240    break;241  case dwarf_f2:242    reg_info.name = "f2";243    break;244  case dwarf_f3:245    reg_info.name = "f3";246    break;247  case dwarf_f4:248    reg_info.name = "f4";249    break;250  case dwarf_f5:251    reg_info.name = "f5";252    break;253  case dwarf_f6:254    reg_info.name = "f6";255    break;256  case dwarf_f7:257    reg_info.name = "f7";258    break;259 260  // Intel wireless MMX general purpose registers 0 - 7 XScale accumulator261  // register 0 - 7 (they do overlap with wCGR0 - wCGR7)262  case dwarf_wCGR0:263    reg_info.name = "wCGR0/ACC0";264    break;265  case dwarf_wCGR1:266    reg_info.name = "wCGR1/ACC1";267    break;268  case dwarf_wCGR2:269    reg_info.name = "wCGR2/ACC2";270    break;271  case dwarf_wCGR3:272    reg_info.name = "wCGR3/ACC3";273    break;274  case dwarf_wCGR4:275    reg_info.name = "wCGR4/ACC4";276    break;277  case dwarf_wCGR5:278    reg_info.name = "wCGR5/ACC5";279    break;280  case dwarf_wCGR6:281    reg_info.name = "wCGR6/ACC6";282    break;283  case dwarf_wCGR7:284    reg_info.name = "wCGR7/ACC7";285    break;286 287  // Intel wireless MMX data registers 0 - 15288  case dwarf_wR0:289    reg_info.name = "wR0";290    break;291  case dwarf_wR1:292    reg_info.name = "wR1";293    break;294  case dwarf_wR2:295    reg_info.name = "wR2";296    break;297  case dwarf_wR3:298    reg_info.name = "wR3";299    break;300  case dwarf_wR4:301    reg_info.name = "wR4";302    break;303  case dwarf_wR5:304    reg_info.name = "wR5";305    break;306  case dwarf_wR6:307    reg_info.name = "wR6";308    break;309  case dwarf_wR7:310    reg_info.name = "wR7";311    break;312  case dwarf_wR8:313    reg_info.name = "wR8";314    break;315  case dwarf_wR9:316    reg_info.name = "wR9";317    break;318  case dwarf_wR10:319    reg_info.name = "wR10";320    break;321  case dwarf_wR11:322    reg_info.name = "wR11";323    break;324  case dwarf_wR12:325    reg_info.name = "wR12";326    break;327  case dwarf_wR13:328    reg_info.name = "wR13";329    break;330  case dwarf_wR14:331    reg_info.name = "wR14";332    break;333  case dwarf_wR15:334    reg_info.name = "wR15";335    break;336 337  case dwarf_spsr:338    reg_info.name = "spsr";339    break;340  case dwarf_spsr_fiq:341    reg_info.name = "spsr_fiq";342    break;343  case dwarf_spsr_irq:344    reg_info.name = "spsr_irq";345    break;346  case dwarf_spsr_abt:347    reg_info.name = "spsr_abt";348    break;349  case dwarf_spsr_und:350    reg_info.name = "spsr_und";351    break;352  case dwarf_spsr_svc:353    reg_info.name = "spsr_svc";354    break;355 356  case dwarf_r8_usr:357    reg_info.name = "r8_usr";358    break;359  case dwarf_r9_usr:360    reg_info.name = "r9_usr";361    break;362  case dwarf_r10_usr:363    reg_info.name = "r10_usr";364    break;365  case dwarf_r11_usr:366    reg_info.name = "r11_usr";367    break;368  case dwarf_r12_usr:369    reg_info.name = "r12_usr";370    break;371  case dwarf_r13_usr:372    reg_info.name = "r13_usr";373    break;374  case dwarf_r14_usr:375    reg_info.name = "r14_usr";376    break;377  case dwarf_r8_fiq:378    reg_info.name = "r8_fiq";379    break;380  case dwarf_r9_fiq:381    reg_info.name = "r9_fiq";382    break;383  case dwarf_r10_fiq:384    reg_info.name = "r10_fiq";385    break;386  case dwarf_r11_fiq:387    reg_info.name = "r11_fiq";388    break;389  case dwarf_r12_fiq:390    reg_info.name = "r12_fiq";391    break;392  case dwarf_r13_fiq:393    reg_info.name = "r13_fiq";394    break;395  case dwarf_r14_fiq:396    reg_info.name = "r14_fiq";397    break;398  case dwarf_r13_irq:399    reg_info.name = "r13_irq";400    break;401  case dwarf_r14_irq:402    reg_info.name = "r14_irq";403    break;404  case dwarf_r13_abt:405    reg_info.name = "r13_abt";406    break;407  case dwarf_r14_abt:408    reg_info.name = "r14_abt";409    break;410  case dwarf_r13_und:411    reg_info.name = "r13_und";412    break;413  case dwarf_r14_und:414    reg_info.name = "r14_und";415    break;416  case dwarf_r13_svc:417    reg_info.name = "r13_svc";418    break;419  case dwarf_r14_svc:420    reg_info.name = "r14_svc";421    break;422 423  // Intel wireless MMX control register in co-processor 0 - 7424  case dwarf_wC0:425    reg_info.name = "wC0";426    break;427  case dwarf_wC1:428    reg_info.name = "wC1";429    break;430  case dwarf_wC2:431    reg_info.name = "wC2";432    break;433  case dwarf_wC3:434    reg_info.name = "wC3";435    break;436  case dwarf_wC4:437    reg_info.name = "wC4";438    break;439  case dwarf_wC5:440    reg_info.name = "wC5";441    break;442  case dwarf_wC6:443    reg_info.name = "wC6";444    break;445  case dwarf_wC7:446    reg_info.name = "wC7";447    break;448 449  // VFP-v3/Neon450  case dwarf_d0:451    reg_info.name = "d0";452    break;453  case dwarf_d1:454    reg_info.name = "d1";455    break;456  case dwarf_d2:457    reg_info.name = "d2";458    break;459  case dwarf_d3:460    reg_info.name = "d3";461    break;462  case dwarf_d4:463    reg_info.name = "d4";464    break;465  case dwarf_d5:466    reg_info.name = "d5";467    break;468  case dwarf_d6:469    reg_info.name = "d6";470    break;471  case dwarf_d7:472    reg_info.name = "d7";473    break;474  case dwarf_d8:475    reg_info.name = "d8";476    break;477  case dwarf_d9:478    reg_info.name = "d9";479    break;480  case dwarf_d10:481    reg_info.name = "d10";482    break;483  case dwarf_d11:484    reg_info.name = "d11";485    break;486  case dwarf_d12:487    reg_info.name = "d12";488    break;489  case dwarf_d13:490    reg_info.name = "d13";491    break;492  case dwarf_d14:493    reg_info.name = "d14";494    break;495  case dwarf_d15:496    reg_info.name = "d15";497    break;498  case dwarf_d16:499    reg_info.name = "d16";500    break;501  case dwarf_d17:502    reg_info.name = "d17";503    break;504  case dwarf_d18:505    reg_info.name = "d18";506    break;507  case dwarf_d19:508    reg_info.name = "d19";509    break;510  case dwarf_d20:511    reg_info.name = "d20";512    break;513  case dwarf_d21:514    reg_info.name = "d21";515    break;516  case dwarf_d22:517    reg_info.name = "d22";518    break;519  case dwarf_d23:520    reg_info.name = "d23";521    break;522  case dwarf_d24:523    reg_info.name = "d24";524    break;525  case dwarf_d25:526    reg_info.name = "d25";527    break;528  case dwarf_d26:529    reg_info.name = "d26";530    break;531  case dwarf_d27:532    reg_info.name = "d27";533    break;534  case dwarf_d28:535    reg_info.name = "d28";536    break;537  case dwarf_d29:538    reg_info.name = "d29";539    break;540  case dwarf_d30:541    reg_info.name = "d30";542    break;543  case dwarf_d31:544    reg_info.name = "d31";545    break;546 547  // NEON 128-bit vector registers (overlays the d registers)548  case dwarf_q0:549    reg_info.name = "q0";550    break;551  case dwarf_q1:552    reg_info.name = "q1";553    break;554  case dwarf_q2:555    reg_info.name = "q2";556    break;557  case dwarf_q3:558    reg_info.name = "q3";559    break;560  case dwarf_q4:561    reg_info.name = "q4";562    break;563  case dwarf_q5:564    reg_info.name = "q5";565    break;566  case dwarf_q6:567    reg_info.name = "q6";568    break;569  case dwarf_q7:570    reg_info.name = "q7";571    break;572  case dwarf_q8:573    reg_info.name = "q8";574    break;575  case dwarf_q9:576    reg_info.name = "q9";577    break;578  case dwarf_q10:579    reg_info.name = "q10";580    break;581  case dwarf_q11:582    reg_info.name = "q11";583    break;584  case dwarf_q12:585    reg_info.name = "q12";586    break;587  case dwarf_q13:588    reg_info.name = "q13";589    break;590  case dwarf_q14:591    reg_info.name = "q14";592    break;593  case dwarf_q15:594    reg_info.name = "q15";595    break;596 597  default:598    return {};599  }600  return reg_info;601}602 603// A8.6.50604// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.605static uint32_t CountITSize(uint32_t ITMask) {606  // First count the trailing zeros of the IT mask.607  uint32_t TZ = llvm::countr_zero(ITMask);608  if (TZ > 3) {609    return 0;610  }611  return (4 - TZ);612}613 614// Init ITState.  Note that at least one bit is always 1 in mask.615bool ITSession::InitIT(uint32_t bits7_0) {616  ITCounter = CountITSize(Bits32(bits7_0, 3, 0));617  if (ITCounter == 0)618    return false;619 620  // A8.6.50 IT621  unsigned short FirstCond = Bits32(bits7_0, 7, 4);622  if (FirstCond == 0xF) {623    return false;624  }625  if (FirstCond == 0xE && ITCounter != 1) {626    return false;627  }628 629  ITState = bits7_0;630  return true;631}632 633// Update ITState if necessary.634void ITSession::ITAdvance() {635  // assert(ITCounter);636  --ITCounter;637  if (ITCounter == 0)638    ITState = 0;639  else {640    unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;641    SetBits32(ITState, 4, 0, NewITState4_0);642  }643}644 645// Return true if we're inside an IT Block.646bool ITSession::InITBlock() { return ITCounter != 0; }647 648// Return true if we're the last instruction inside an IT Block.649bool ITSession::LastInITBlock() { return ITCounter == 1; }650 651// Get condition bits for the current thumb instruction.652uint32_t ITSession::GetCond() {653  if (InITBlock())654    return Bits32(ITState, 7, 4);655  else656    return COND_AL;657}658 659// ARM constants used during decoding660#define REG_RD 0661#define LDM_REGLIST 1662#define SP_REG 13663#define LR_REG 14664#define PC_REG 15665#define PC_REGLIST_BIT 0x8000666 667#define ARMv4 (1u << 0)668#define ARMv4T (1u << 1)669#define ARMv5T (1u << 2)670#define ARMv5TE (1u << 3)671#define ARMv5TEJ (1u << 4)672#define ARMv6 (1u << 5)673#define ARMv6K (1u << 6)674#define ARMv6T2 (1u << 7)675#define ARMv7 (1u << 8)676#define ARMv7S (1u << 9)677#define ARMv8 (1u << 10)678#define ARMvAll (0xffffffffu)679 680#define ARMV4T_ABOVE                                                           \681  (ARMv4T | ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 |   \682   ARMv7S | ARMv8)683#define ARMV5_ABOVE                                                            \684  (ARMv5T | ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S |   \685   ARMv8)686#define ARMV5TE_ABOVE                                                          \687  (ARMv5TE | ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)688#define ARMV5J_ABOVE                                                           \689  (ARMv5TEJ | ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)690#define ARMV6_ABOVE (ARMv6 | ARMv6K | ARMv6T2 | ARMv7 | ARMv7S | ARMv8)691#define ARMV6T2_ABOVE (ARMv6T2 | ARMv7 | ARMv7S | ARMv8)692#define ARMV7_ABOVE (ARMv7 | ARMv7S | ARMv8)693 694#define No_VFP 0695#define VFPv1 (1u << 1)696#define VFPv2 (1u << 2)697#define VFPv3 (1u << 3)698#define AdvancedSIMD (1u << 4)699 700#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)701#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)702#define VFPv2v3 (VFPv2 | VFPv3)703 704//705// EmulateInstructionARM implementation706//707 708void EmulateInstructionARM::Initialize() {709  PluginManager::RegisterPlugin(GetPluginNameStatic(),710                                GetPluginDescriptionStatic(), CreateInstance);711}712 713void EmulateInstructionARM::Terminate() {714  PluginManager::UnregisterPlugin(CreateInstance);715}716 717llvm::StringRef EmulateInstructionARM::GetPluginDescriptionStatic() {718  return "Emulate instructions for the ARM architecture.";719}720 721EmulateInstruction *722EmulateInstructionARM::CreateInstance(const ArchSpec &arch,723                                      InstructionType inst_type) {724  if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic(725          inst_type)) {726    if (arch.GetTriple().getArch() == llvm::Triple::arm) {727      std::unique_ptr<EmulateInstructionARM> emulate_insn_up(728          new EmulateInstructionARM(arch));729 730      if (emulate_insn_up)731        return emulate_insn_up.release();732    } else if (arch.GetTriple().getArch() == llvm::Triple::thumb) {733      std::unique_ptr<EmulateInstructionARM> emulate_insn_up(734          new EmulateInstructionARM(arch));735 736      if (emulate_insn_up)737        return emulate_insn_up.release();738    }739  }740 741  return nullptr;742}743 744bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) {745  if (arch.GetTriple().getArch() == llvm::Triple::arm)746    return true;747  else if (arch.GetTriple().getArch() == llvm::Triple::thumb)748    return true;749 750  return false;751}752 753// Write "bits (32) UNKNOWN" to memory address "address".  Helper function for754// many ARM instructions.755bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) {756  EmulateInstruction::Context context;757  context.type = EmulateInstruction::eContextWriteMemoryRandomBits;758  context.SetNoArgs();759 760  uint32_t random_data = rand();761  const uint32_t addr_byte_size = GetAddressByteSize();762 763  return MemAWrite(context, address, random_data, addr_byte_size);764}765 766// Write "bits (32) UNKNOWN" to register n.  Helper function for many ARM767// instructions.768bool EmulateInstructionARM::WriteBits32Unknown(int n) {769  EmulateInstruction::Context context;770  context.type = EmulateInstruction::eContextWriteRegisterRandomBits;771  context.SetNoArgs();772 773  bool success;774  uint32_t data =775      ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);776 777  if (!success)778    return false;779 780  if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data))781    return false;782 783  return true;784}785 786std::optional<RegisterInfo>787EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind,788                                       uint32_t reg_num) {789  if (reg_kind == eRegisterKindGeneric) {790    switch (reg_num) {791    case LLDB_REGNUM_GENERIC_PC:792      reg_kind = eRegisterKindDWARF;793      reg_num = dwarf_pc;794      break;795    case LLDB_REGNUM_GENERIC_SP:796      reg_kind = eRegisterKindDWARF;797      reg_num = dwarf_sp;798      break;799    case LLDB_REGNUM_GENERIC_FP:800      reg_kind = eRegisterKindDWARF;801      reg_num = dwarf_r7;802      break;803    case LLDB_REGNUM_GENERIC_RA:804      reg_kind = eRegisterKindDWARF;805      reg_num = dwarf_lr;806      break;807    case LLDB_REGNUM_GENERIC_FLAGS:808      reg_kind = eRegisterKindDWARF;809      reg_num = dwarf_cpsr;810      break;811    default:812      return {};813    }814  }815 816  if (reg_kind == eRegisterKindDWARF)817    return GetARMDWARFRegisterInfo(reg_num);818  return {};819}820 821uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {822  if (m_arch.GetTriple().isAndroid())823    return LLDB_INVALID_REGNUM; // Don't use frame pointer on android824  bool is_apple = false;825  if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)826    is_apple = true;827  switch (m_arch.GetTriple().getOS()) {828  case llvm::Triple::Darwin:829  case llvm::Triple::MacOSX:830  case llvm::Triple::IOS:831  case llvm::Triple::TvOS:832  case llvm::Triple::WatchOS:833  case llvm::Triple::XROS:834  case llvm::Triple::BridgeOS:835    is_apple = true;836    break;837  default:838    break;839  }840 841  /* On Apple iOS et al, the frame pointer register is always r7.842   * Typically on other ARM systems, thumb code uses r7; arm code uses r11.843   * Windows on ARM, which is in thumb mode, uses r11 though.844   */845 846  uint32_t fp_regnum = 11;847 848  if (is_apple)849    fp_regnum = 7;850 851  if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())852    fp_regnum = 7;853 854  return fp_regnum;855}856 857uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const {858  bool is_apple = false;859  if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)860    is_apple = true;861  switch (m_arch.GetTriple().getOS()) {862  case llvm::Triple::Darwin:863  case llvm::Triple::MacOSX:864  case llvm::Triple::IOS:865    is_apple = true;866    break;867  default:868    break;869  }870 871  /* On Apple iOS et al, the frame pointer register is always r7.872   * Typically on other ARM systems, thumb code uses r7; arm code uses r11.873   * Windows on ARM, which is in thumb mode, uses r11 though.874   */875 876  uint32_t fp_regnum = dwarf_r11;877 878  if (is_apple)879    fp_regnum = dwarf_r7;880 881  if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows())882    fp_regnum = dwarf_r7;883 884  return fp_regnum;885}886 887// Push Multiple Registers stores multiple registers to the stack, storing to888// consecutive memory locations ending just below the address in SP, and889// updates890// SP to point to the start of the stored data.891bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode,892                                        const ARMEncoding encoding) {893#if 0894    // ARM pseudo code...895    if (ConditionPassed())896    {897        EncodingSpecificOperations(); 898        NullCheckIfThumbEE(13); 899        address = SP - 4*BitCount(registers);900 901        for (i = 0 to 14)902        {903            if (registers<i> == '1')904            {905                if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1 906                    MemA[address,4] = bits(32) UNKNOWN;907                else 908                    MemA[address,4] = R[i];909                address = address + 4;910            }911        }912 913        if (registers<15> == '1') // Only possible for encoding A1 or A2 914            MemA[address,4] = PCStoreValue();915        916        SP = SP - 4*BitCount(registers);917    }918#endif919 920  bool success = false;921  if (ConditionPassed(opcode)) {922    const uint32_t addr_byte_size = GetAddressByteSize();923    const addr_t sp = ReadCoreReg(SP_REG, &success);924    if (!success)925      return false;926    uint32_t registers = 0;927    uint32_t Rt; // the source register928    switch (encoding) {929    case eEncodingT1:930      registers = Bits32(opcode, 7, 0);931      // The M bit represents LR.932      if (Bit32(opcode, 8))933        registers |= (1u << 14);934      // if BitCount(registers) < 1 then UNPREDICTABLE;935      if (BitCount(registers) < 1)936        return false;937      break;938    case eEncodingT2:939      // Ignore bits 15 & 13.940      registers = Bits32(opcode, 15, 0) & ~0xa000;941      // if BitCount(registers) < 2 then UNPREDICTABLE;942      if (BitCount(registers) < 2)943        return false;944      break;945    case eEncodingT3:946      Rt = Bits32(opcode, 15, 12);947      // if BadReg(t) then UNPREDICTABLE;948      if (BadReg(Rt))949        return false;950      registers = (1u << Rt);951      break;952    case eEncodingA1:953      registers = Bits32(opcode, 15, 0);954      // Instead of return false, let's handle the following case as well,955      // which amounts to pushing one reg onto the full descending stacks.956      // if BitCount(register_list) < 2 then SEE STMDB / STMFD;957      break;958    case eEncodingA2:959      Rt = Bits32(opcode, 15, 12);960      // if t == 13 then UNPREDICTABLE;961      if (Rt == dwarf_sp)962        return false;963      registers = (1u << Rt);964      break;965    default:966      return false;967    }968    addr_t sp_offset = addr_byte_size * BitCount(registers);969    addr_t addr = sp - sp_offset;970    uint32_t i;971 972    EmulateInstruction::Context context;973    context.type = EmulateInstruction::eContextPushRegisterOnStack;974    std::optional<RegisterInfo> sp_reg =975        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);976    for (i = 0; i < 15; ++i) {977      if (BitIsSet(registers, i)) {978        std::optional<RegisterInfo> reg_info =979            GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);980        context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);981        uint32_t reg_value = ReadCoreReg(i, &success);982        if (!success)983          return false;984        if (!MemAWrite(context, addr, reg_value, addr_byte_size))985          return false;986        addr += addr_byte_size;987      }988    }989 990    if (BitIsSet(registers, 15)) {991      std::optional<RegisterInfo> reg_info =992          GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);993      context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp);994      const uint32_t pc = ReadCoreReg(PC_REG, &success);995      if (!success)996        return false;997      if (!MemAWrite(context, addr, pc, addr_byte_size))998        return false;999    }1000 1001    context.type = EmulateInstruction::eContextAdjustStackPointer;1002    context.SetImmediateSigned(-sp_offset);1003 1004    if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,1005                               LLDB_REGNUM_GENERIC_SP, sp - sp_offset))1006      return false;1007  }1008  return true;1009}1010 1011// Pop Multiple Registers loads multiple registers from the stack, loading from1012// consecutive memory locations staring at the address in SP, and updates1013// SP to point just above the loaded data.1014bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode,1015                                       const ARMEncoding encoding) {1016#if 01017    // ARM pseudo code...1018    if (ConditionPassed())1019    {1020        EncodingSpecificOperations(); NullCheckIfThumbEE(13);1021        address = SP;1022        for i = 0 to 141023            if registers<i> == '1' then1024                R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;1025        if registers<15> == '1' then1026            if UnalignedAllowed then1027                LoadWritePC(MemU[address,4]);1028            else 1029                LoadWritePC(MemA[address,4]);1030        if registers<13> == '0' then SP = SP + 4*BitCount(registers);1031        if registers<13> == '1' then SP = bits(32) UNKNOWN;1032    }1033#endif1034 1035  bool success = false;1036 1037  if (ConditionPassed(opcode)) {1038    const uint32_t addr_byte_size = GetAddressByteSize();1039    const addr_t sp = ReadCoreReg(SP_REG, &success);1040    if (!success)1041      return false;1042    uint32_t registers = 0;1043    uint32_t Rt; // the destination register1044    switch (encoding) {1045    case eEncodingT1:1046      registers = Bits32(opcode, 7, 0);1047      // The P bit represents PC.1048      if (Bit32(opcode, 8))1049        registers |= (1u << 15);1050      // if BitCount(registers) < 1 then UNPREDICTABLE;1051      if (BitCount(registers) < 1)1052        return false;1053      break;1054    case eEncodingT2:1055      // Ignore bit 13.1056      registers = Bits32(opcode, 15, 0) & ~0x2000;1057      // if BitCount(registers) < 2 || (P == '1' && M == '1') then1058      // UNPREDICTABLE;1059      if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))1060        return false;1061      // if registers<15> == '1' && InITBlock() && !LastInITBlock() then1062      // UNPREDICTABLE;1063      if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())1064        return false;1065      break;1066    case eEncodingT3:1067      Rt = Bits32(opcode, 15, 12);1068      // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then1069      // UNPREDICTABLE;1070      if (Rt == 13)1071        return false;1072      if (Rt == 15 && InITBlock() && !LastInITBlock())1073        return false;1074      registers = (1u << Rt);1075      break;1076    case eEncodingA1:1077      registers = Bits32(opcode, 15, 0);1078      // Instead of return false, let's handle the following case as well,1079      // which amounts to popping one reg from the full descending stacks.1080      // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;1081 1082      // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;1083      if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)1084        return false;1085      break;1086    case eEncodingA2:1087      Rt = Bits32(opcode, 15, 12);1088      // if t == 13 then UNPREDICTABLE;1089      if (Rt == dwarf_sp)1090        return false;1091      registers = (1u << Rt);1092      break;1093    default:1094      return false;1095    }1096    addr_t sp_offset = addr_byte_size * BitCount(registers);1097    addr_t addr = sp;1098    uint32_t i, data;1099 1100    EmulateInstruction::Context context;1101    context.type = EmulateInstruction::eContextPopRegisterOffStack;1102 1103    std::optional<RegisterInfo> sp_reg =1104        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);1105 1106    for (i = 0; i < 15; ++i) {1107      if (BitIsSet(registers, i)) {1108        context.SetAddress(addr);1109        data = MemARead(context, addr, 4, 0, &success);1110        if (!success)1111          return false;1112        if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,1113                                   data))1114          return false;1115        addr += addr_byte_size;1116      }1117    }1118 1119    if (BitIsSet(registers, 15)) {1120      context.SetRegisterPlusOffset(*sp_reg, addr - sp);1121      data = MemARead(context, addr, 4, 0, &success);1122      if (!success)1123        return false;1124      // In ARMv5T and above, this is an interworking branch.1125      if (!LoadWritePC(context, data))1126        return false;1127      // addr += addr_byte_size;1128    }1129 1130    context.type = EmulateInstruction::eContextAdjustStackPointer;1131    context.SetImmediateSigned(sp_offset);1132 1133    if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,1134                               LLDB_REGNUM_GENERIC_SP, sp + sp_offset))1135      return false;1136  }1137  return true;1138}1139 1140// Set r7 or ip to point to saved value residing within the stack.1141// ADD (SP plus immediate)1142bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode,1143                                              const ARMEncoding encoding) {1144#if 01145    // ARM pseudo code...1146    if (ConditionPassed())1147    {1148        EncodingSpecificOperations();1149        (result, carry, overflow) = AddWithCarry(SP, imm32, '0');1150        if d == 15 then1151           ALUWritePC(result); // setflags is always FALSE here1152        else1153            R[d] = result;1154            if setflags then1155                APSR.N = result<31>;1156                APSR.Z = IsZeroBit(result);1157                APSR.C = carry;1158                APSR.V = overflow;1159    }1160#endif1161 1162  bool success = false;1163 1164  if (ConditionPassed(opcode)) {1165    const addr_t sp = ReadCoreReg(SP_REG, &success);1166    if (!success)1167      return false;1168    uint32_t Rd; // the destination register1169    uint32_t imm32;1170    switch (encoding) {1171    case eEncodingT1:1172      Rd = 7;1173      imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)1174      break;1175    case eEncodingA1:1176      Rd = Bits32(opcode, 15, 12);1177      imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)1178      break;1179    default:1180      return false;1181    }1182    addr_t sp_offset = imm32;1183    addr_t addr = sp + sp_offset; // a pointer to the stack area1184 1185    EmulateInstruction::Context context;1186    if (Rd == GetFramePointerRegisterNumber())1187      context.type = eContextSetFramePointer;1188    else1189      context.type = EmulateInstruction::eContextRegisterPlusOffset;1190    std::optional<RegisterInfo> sp_reg =1191        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);1192    context.SetRegisterPlusOffset(*sp_reg, sp_offset);1193 1194    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd,1195                               addr))1196      return false;1197  }1198  return true;1199}1200 1201// Set r7 or ip to the current stack pointer.1202// MOV (register)1203bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode,1204                                           const ARMEncoding encoding) {1205#if 01206    // ARM pseudo code...1207    if (ConditionPassed())1208    {1209        EncodingSpecificOperations();1210        result = R[m];1211        if d == 15 then1212            ALUWritePC(result); // setflags is always FALSE here1213        else1214            R[d] = result;1215            if setflags then1216                APSR.N = result<31>;1217                APSR.Z = IsZeroBit(result);1218                // APSR.C unchanged1219                // APSR.V unchanged1220    }1221#endif1222 1223  bool success = false;1224 1225  if (ConditionPassed(opcode)) {1226    const addr_t sp = ReadCoreReg(SP_REG, &success);1227    if (!success)1228      return false;1229    uint32_t Rd; // the destination register1230    switch (encoding) {1231    case eEncodingT1:1232      Rd = 7;1233      break;1234    case eEncodingA1:1235      Rd = 12;1236      break;1237    default:1238      return false;1239    }1240 1241    EmulateInstruction::Context context;1242    if (Rd == GetFramePointerRegisterNumber())1243      context.type = EmulateInstruction::eContextSetFramePointer;1244    else1245      context.type = EmulateInstruction::eContextRegisterPlusOffset;1246    std::optional<RegisterInfo> sp_reg =1247        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);1248    context.SetRegisterPlusOffset(*sp_reg, 0);1249 1250    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))1251      return false;1252  }1253  return true;1254}1255 1256// Move from high register (r8-r15) to low register (r0-r7).1257// MOV (register)1258bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode,1259                                              const ARMEncoding encoding) {1260  return EmulateMOVRdRm(opcode, encoding);1261}1262 1263// Move from register to register.1264// MOV (register)1265bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode,1266                                           const ARMEncoding encoding) {1267#if 01268    // ARM pseudo code...1269    if (ConditionPassed())1270    {1271        EncodingSpecificOperations();1272        result = R[m];1273        if d == 15 then1274            ALUWritePC(result); // setflags is always FALSE here1275        else1276            R[d] = result;1277            if setflags then1278                APSR.N = result<31>;1279                APSR.Z = IsZeroBit(result);1280                // APSR.C unchanged1281                // APSR.V unchanged1282    }1283#endif1284 1285  bool success = false;1286 1287  if (ConditionPassed(opcode)) {1288    uint32_t Rm; // the source register1289    uint32_t Rd; // the destination register1290    bool setflags;1291    switch (encoding) {1292    case eEncodingT1:1293      Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);1294      Rm = Bits32(opcode, 6, 3);1295      setflags = false;1296      if (Rd == 15 && InITBlock() && !LastInITBlock())1297        return false;1298      break;1299    case eEncodingT2:1300      Rd = Bits32(opcode, 2, 0);1301      Rm = Bits32(opcode, 5, 3);1302      setflags = true;1303      if (InITBlock())1304        return false;1305      break;1306    case eEncodingT3:1307      Rd = Bits32(opcode, 11, 8);1308      Rm = Bits32(opcode, 3, 0);1309      setflags = BitIsSet(opcode, 20);1310      // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;1311      if (setflags && (BadReg(Rd) || BadReg(Rm)))1312        return false;1313      // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then1314      // UNPREDICTABLE;1315      if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))1316        return false;1317      break;1318    case eEncodingA1:1319      Rd = Bits32(opcode, 15, 12);1320      Rm = Bits32(opcode, 3, 0);1321      setflags = BitIsSet(opcode, 20);1322 1323      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related1324      // instructions;1325      if (Rd == 15 && setflags)1326        return EmulateSUBSPcLrEtc(opcode, encoding);1327      break;1328    default:1329      return false;1330    }1331    uint32_t result = ReadCoreReg(Rm, &success);1332    if (!success)1333      return false;1334 1335    // The context specifies that Rm is to be moved into Rd.1336    EmulateInstruction::Context context;1337    if (Rd == 13)1338      context.type = EmulateInstruction::eContextAdjustStackPointer;1339    else if (Rd == GetFramePointerRegisterNumber() && Rm == 13)1340      context.type = EmulateInstruction::eContextSetFramePointer;1341    else1342      context.type = EmulateInstruction::eContextRegisterPlusOffset;1343    std::optional<RegisterInfo> dwarf_reg =1344        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);1345    context.SetRegisterPlusOffset(*dwarf_reg, 0);1346 1347    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))1348      return false;1349  }1350  return true;1351}1352 1353// Move (immediate) writes an immediate value to the destination register.  It1354// can optionally update the condition flags based on the value.1355// MOV (immediate)1356bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode,1357                                            const ARMEncoding encoding) {1358#if 01359    // ARM pseudo code...1360    if (ConditionPassed())1361    {1362        EncodingSpecificOperations();1363        result = imm32;1364        if d == 15 then         // Can only occur for ARM encoding1365            ALUWritePC(result); // setflags is always FALSE here1366        else1367            R[d] = result;1368            if setflags then1369                APSR.N = result<31>;1370                APSR.Z = IsZeroBit(result);1371                APSR.C = carry;1372                // APSR.V unchanged1373    }1374#endif1375 1376  if (ConditionPassed(opcode)) {1377    uint32_t Rd;    // the destination register1378    uint32_t imm32; // the immediate value to be written to Rd1379    uint32_t carry =1380        0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.1381           // for setflags == false, this value is a don't care initialized to1382           // 0 to silence the static analyzer1383    bool setflags;1384    switch (encoding) {1385    case eEncodingT1:1386      Rd = Bits32(opcode, 10, 8);1387      setflags = !InITBlock();1388      imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)1389      carry = APSR_C;1390 1391      break;1392 1393    case eEncodingT2:1394      Rd = Bits32(opcode, 11, 8);1395      setflags = BitIsSet(opcode, 20);1396      imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);1397      if (BadReg(Rd))1398        return false;1399 1400      break;1401 1402    case eEncodingT3: {1403      // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8,1404      // 32);1405      Rd = Bits32(opcode, 11, 8);1406      setflags = false;1407      uint32_t imm4 = Bits32(opcode, 19, 16);1408      uint32_t imm3 = Bits32(opcode, 14, 12);1409      uint32_t i = Bit32(opcode, 26);1410      uint32_t imm8 = Bits32(opcode, 7, 0);1411      imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;1412 1413      // if BadReg(d) then UNPREDICTABLE;1414      if (BadReg(Rd))1415        return false;1416    } break;1417 1418    case eEncodingA1:1419      // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) =1420      // ARMExpandImm_C(imm12, APSR.C);1421      Rd = Bits32(opcode, 15, 12);1422      setflags = BitIsSet(opcode, 20);1423      imm32 = ARMExpandImm_C(opcode, APSR_C, carry);1424 1425      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related1426      // instructions;1427      if ((Rd == 15) && setflags)1428        return EmulateSUBSPcLrEtc(opcode, encoding);1429 1430      break;1431 1432    case eEncodingA2: {1433      // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);1434      Rd = Bits32(opcode, 15, 12);1435      setflags = false;1436      uint32_t imm4 = Bits32(opcode, 19, 16);1437      uint32_t imm12 = Bits32(opcode, 11, 0);1438      imm32 = (imm4 << 12) | imm12;1439 1440      // if d == 15 then UNPREDICTABLE;1441      if (Rd == 15)1442        return false;1443    } break;1444 1445    default:1446      return false;1447    }1448    uint32_t result = imm32;1449 1450    // The context specifies that an immediate is to be moved into Rd.1451    EmulateInstruction::Context context;1452    context.type = EmulateInstruction::eContextImmediate;1453    context.SetNoArgs();1454 1455    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))1456      return false;1457  }1458  return true;1459}1460 1461// MUL multiplies two register values.  The least significant 32 bits of the1462// result are written to the destination1463// register.  These 32 bits do not depend on whether the source register values1464// are considered to be signed values or unsigned values.1465//1466// Optionally, it can update the condition flags based on the result.  In the1467// Thumb instruction set, this option is limited to only a few forms of the1468// instruction.1469bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode,1470                                       const ARMEncoding encoding) {1471#if 01472    if ConditionPassed() then 1473        EncodingSpecificOperations(); 1474        operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 1475        operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 1476        result = operand1 * operand2; 1477        R[d] = result<31:0>; 1478        if setflags then1479            APSR.N = result<31>; 1480            APSR.Z = IsZeroBit(result); 1481            if ArchVersion() == 4 then1482                APSR.C = bit UNKNOWN; 1483            // else APSR.C unchanged 1484            // APSR.V always unchanged1485#endif1486 1487  if (ConditionPassed(opcode)) {1488    uint32_t d;1489    uint32_t n;1490    uint32_t m;1491    bool setflags;1492 1493    // EncodingSpecificOperations();1494    switch (encoding) {1495    case eEncodingT1:1496      // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock();1497      d = Bits32(opcode, 2, 0);1498      n = Bits32(opcode, 5, 3);1499      m = Bits32(opcode, 2, 0);1500      setflags = !InITBlock();1501 1502      // if ArchVersion() < 6 && d == n then UNPREDICTABLE;1503      if ((ArchVersion() < ARMv6) && (d == n))1504        return false;1505 1506      break;1507 1508    case eEncodingT2:1509      // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE;1510      d = Bits32(opcode, 11, 8);1511      n = Bits32(opcode, 19, 16);1512      m = Bits32(opcode, 3, 0);1513      setflags = false;1514 1515      // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;1516      if (BadReg(d) || BadReg(n) || BadReg(m))1517        return false;1518 1519      break;1520 1521    case eEncodingA1:1522      // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');1523      d = Bits32(opcode, 19, 16);1524      n = Bits32(opcode, 3, 0);1525      m = Bits32(opcode, 11, 8);1526      setflags = BitIsSet(opcode, 20);1527 1528      // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;1529      if ((d == 15) || (n == 15) || (m == 15))1530        return false;1531 1532      // if ArchVersion() < 6 && d == n then UNPREDICTABLE;1533      if ((ArchVersion() < ARMv6) && (d == n))1534        return false;1535 1536      break;1537 1538    default:1539      return false;1540    }1541 1542    bool success = false;1543 1544    // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final1545    // results1546    uint64_t operand1 =1547        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);1548    if (!success)1549      return false;1550 1551    // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final1552    // results1553    uint64_t operand2 =1554        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);1555    if (!success)1556      return false;1557 1558    // result = operand1 * operand2;1559    uint64_t result = operand1 * operand2;1560 1561    // R[d] = result<31:0>;1562    std::optional<RegisterInfo> op1_reg =1563        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);1564    std::optional<RegisterInfo> op2_reg =1565        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);1566 1567    EmulateInstruction::Context context;1568    context.type = eContextArithmetic;1569    context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);1570 1571    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,1572                               (0x0000ffff & result)))1573      return false;1574 1575    // if setflags then1576    if (setflags) {1577      // APSR.N = result<31>;1578      // APSR.Z = IsZeroBit(result);1579      m_new_inst_cpsr = m_opcode_cpsr;1580      SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31));1581      SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);1582      if (m_new_inst_cpsr != m_opcode_cpsr) {1583        if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,1584                                   LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))1585          return false;1586      }1587 1588      // if ArchVersion() == 4 then1589      // APSR.C = bit UNKNOWN;1590    }1591  }1592  return true;1593}1594 1595// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to1596// the destination register. It can optionally update the condition flags based1597// on the value.1598bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode,1599                                          const ARMEncoding encoding) {1600#if 01601    // ARM pseudo code...1602    if (ConditionPassed())1603    {1604        EncodingSpecificOperations();1605        result = NOT(imm32);1606        if d == 15 then         // Can only occur for ARM encoding1607            ALUWritePC(result); // setflags is always FALSE here1608        else1609            R[d] = result;1610            if setflags then1611                APSR.N = result<31>;1612                APSR.Z = IsZeroBit(result);1613                APSR.C = carry;1614                // APSR.V unchanged1615    }1616#endif1617 1618  if (ConditionPassed(opcode)) {1619    uint32_t Rd;    // the destination register1620    uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C1621    uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C1622    bool setflags;1623    switch (encoding) {1624    case eEncodingT1:1625      Rd = Bits32(opcode, 11, 8);1626      setflags = BitIsSet(opcode, 20);1627      imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);1628      break;1629    case eEncodingA1:1630      Rd = Bits32(opcode, 15, 12);1631      setflags = BitIsSet(opcode, 20);1632      imm32 = ARMExpandImm_C(opcode, APSR_C, carry);1633 1634      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related1635      // instructions;1636      if (Rd == 15 && setflags)1637        return EmulateSUBSPcLrEtc(opcode, encoding);1638      break;1639    default:1640      return false;1641    }1642    uint32_t result = ~imm32;1643 1644    // The context specifies that an immediate is to be moved into Rd.1645    EmulateInstruction::Context context;1646    context.type = EmulateInstruction::eContextImmediate;1647    context.SetNoArgs();1648 1649    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))1650      return false;1651  }1652  return true;1653}1654 1655// Bitwise NOT (register) writes the bitwise inverse of a register value to the1656// destination register. It can optionally update the condition flags based on1657// the result.1658bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode,1659                                          const ARMEncoding encoding) {1660#if 01661    // ARM pseudo code...1662    if (ConditionPassed())1663    {1664        EncodingSpecificOperations();1665        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);1666        result = NOT(shifted);1667        if d == 15 then         // Can only occur for ARM encoding1668            ALUWritePC(result); // setflags is always FALSE here1669        else1670            R[d] = result;1671            if setflags then1672                APSR.N = result<31>;1673                APSR.Z = IsZeroBit(result);1674                APSR.C = carry;1675                // APSR.V unchanged1676    }1677#endif1678 1679  if (ConditionPassed(opcode)) {1680    uint32_t Rm; // the source register1681    uint32_t Rd; // the destination register1682    ARM_ShifterType shift_t;1683    uint32_t shift_n; // the shift applied to the value read from Rm1684    bool setflags;1685    uint32_t carry; // the carry bit after the shift operation1686    switch (encoding) {1687    case eEncodingT1:1688      Rd = Bits32(opcode, 2, 0);1689      Rm = Bits32(opcode, 5, 3);1690      setflags = !InITBlock();1691      shift_t = SRType_LSL;1692      shift_n = 0;1693      if (InITBlock())1694        return false;1695      break;1696    case eEncodingT2:1697      Rd = Bits32(opcode, 11, 8);1698      Rm = Bits32(opcode, 3, 0);1699      setflags = BitIsSet(opcode, 20);1700      shift_n = DecodeImmShiftThumb(opcode, shift_t);1701      // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;1702      if (BadReg(Rd) || BadReg(Rm))1703        return false;1704      break;1705    case eEncodingA1:1706      Rd = Bits32(opcode, 15, 12);1707      Rm = Bits32(opcode, 3, 0);1708      setflags = BitIsSet(opcode, 20);1709      shift_n = DecodeImmShiftARM(opcode, shift_t);1710      break;1711    default:1712      return false;1713    }1714    bool success = false;1715    uint32_t value = ReadCoreReg(Rm, &success);1716    if (!success)1717      return false;1718 1719    uint32_t shifted =1720        Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);1721    if (!success)1722      return false;1723    uint32_t result = ~shifted;1724 1725    // The context specifies that an immediate is to be moved into Rd.1726    EmulateInstruction::Context context;1727    context.type = EmulateInstruction::eContextImmediate;1728    context.SetNoArgs();1729 1730    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))1731      return false;1732  }1733  return true;1734}1735 1736// PC relative immediate load into register, possibly followed by ADD (SP plus1737// register).1738// LDR (literal)1739bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode,1740                                                   const ARMEncoding encoding) {1741#if 01742    // ARM pseudo code...1743    if (ConditionPassed())1744    {1745        EncodingSpecificOperations(); NullCheckIfThumbEE(15);1746        base = Align(PC,4);1747        address = if add then (base + imm32) else (base - imm32);1748        data = MemU[address,4];1749        if t == 15 then1750            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;1751        elsif UnalignedSupport() || address<1:0> = '00' then1752            R[t] = data;1753        else // Can only apply before ARMv71754            if CurrentInstrSet() == InstrSet_ARM then1755                R[t] = ROR(data, 8*UInt(address<1:0>));1756            else1757                R[t] = bits(32) UNKNOWN;1758    }1759#endif1760 1761  if (ConditionPassed(opcode)) {1762    bool success = false;1763    const uint32_t pc = ReadCoreReg(PC_REG, &success);1764    if (!success)1765      return false;1766 1767    // PC relative immediate load context1768    EmulateInstruction::Context context;1769    context.type = EmulateInstruction::eContextRegisterPlusOffset;1770    std::optional<RegisterInfo> pc_reg =1771        GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);1772    context.SetRegisterPlusOffset(*pc_reg, 0);1773 1774    uint32_t Rt;    // the destination register1775    uint32_t imm32; // immediate offset from the PC1776    bool add;       // +imm32 or -imm32?1777    addr_t base;    // the base address1778    addr_t address; // the PC relative address1779    uint32_t data;  // the literal data value from the PC relative load1780    switch (encoding) {1781    case eEncodingT1:1782      Rt = Bits32(opcode, 10, 8);1783      imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);1784      add = true;1785      break;1786    case eEncodingT2:1787      Rt = Bits32(opcode, 15, 12);1788      imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);1789      add = BitIsSet(opcode, 23);1790      if (Rt == 15 && InITBlock() && !LastInITBlock())1791        return false;1792      break;1793    default:1794      return false;1795    }1796 1797    base = Align(pc, 4);1798    if (add)1799      address = base + imm32;1800    else1801      address = base - imm32;1802 1803    context.SetRegisterPlusOffset(*pc_reg, address - base);1804    data = MemURead(context, address, 4, 0, &success);1805    if (!success)1806      return false;1807 1808    if (Rt == 15) {1809      if (Bits32(address, 1, 0) == 0) {1810        // In ARMv5T and above, this is an interworking branch.1811        if (!LoadWritePC(context, data))1812          return false;1813      } else1814        return false;1815    } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {1816      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,1817                                 data))1818        return false;1819    } else // We don't handle ARM for now.1820      return false;1821  }1822  return true;1823}1824 1825// An add operation to adjust the SP.1826// ADD (SP plus immediate)1827bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode,1828                                            const ARMEncoding encoding) {1829#if 01830    // ARM pseudo code...1831    if (ConditionPassed())1832    {1833        EncodingSpecificOperations();1834        (result, carry, overflow) = AddWithCarry(SP, imm32, '0');1835        if d == 15 then // Can only occur for ARM encoding1836            ALUWritePC(result); // setflags is always FALSE here1837        else1838            R[d] = result;1839            if setflags then1840                APSR.N = result<31>;1841                APSR.Z = IsZeroBit(result);1842                APSR.C = carry;1843                APSR.V = overflow;1844    }1845#endif1846 1847  bool success = false;1848 1849  if (ConditionPassed(opcode)) {1850    const addr_t sp = ReadCoreReg(SP_REG, &success);1851    if (!success)1852      return false;1853    uint32_t imm32; // the immediate operand1854    uint32_t d;1855    bool setflags;1856    switch (encoding) {1857    case eEncodingT1:1858      // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);1859      d = Bits32(opcode, 10, 8);1860      imm32 = (Bits32(opcode, 7, 0) << 2);1861      setflags = false;1862      break;1863 1864    case eEncodingT2:1865      // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);1866      d = 13;1867      imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)1868      setflags = false;1869      break;1870 1871    case eEncodingT3:1872      // d = UInt(Rd); setflags = (S == "1"); imm32 =1873      // ThumbExpandImm(i:imm3:imm8);1874      d = Bits32(opcode, 11, 8);1875      imm32 = ThumbExpandImm(opcode);1876      setflags = Bit32(opcode, 20);1877 1878      // if Rd == "1111" && S == "1" then SEE CMN (immediate);1879      if (d == 15 && setflags == 1)1880        return false; // CMN (immediate) not yet supported1881 1882      // if d == 15 && S == "0" then UNPREDICTABLE;1883      if (d == 15 && setflags == 0)1884        return false;1885      break;1886 1887    case eEncodingT4: {1888      // if Rn == '1111' then SEE ADR;1889      // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32);1890      d = Bits32(opcode, 11, 8);1891      setflags = false;1892      uint32_t i = Bit32(opcode, 26);1893      uint32_t imm3 = Bits32(opcode, 14, 12);1894      uint32_t imm8 = Bits32(opcode, 7, 0);1895      imm32 = (i << 11) | (imm3 << 8) | imm8;1896 1897      // if d == 15 then UNPREDICTABLE;1898      if (d == 15)1899        return false;1900    } break;1901 1902    default:1903      return false;1904    }1905    // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');1906    AddWithCarryResult res = AddWithCarry(sp, imm32, 0);1907 1908    EmulateInstruction::Context context;1909    if (d == 13)1910      context.type = EmulateInstruction::eContextAdjustStackPointer;1911    else1912      context.type = EmulateInstruction::eContextRegisterPlusOffset;1913 1914    std::optional<RegisterInfo> sp_reg =1915        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);1916    context.SetRegisterPlusOffset(*sp_reg, res.result - sp);1917 1918    if (d == 15) {1919      if (!ALUWritePC(context, res.result))1920        return false;1921    } else {1922      // R[d] = result;1923      // if setflags then1924      //     APSR.N = result<31>;1925      //     APSR.Z = IsZeroBit(result);1926      //     APSR.C = carry;1927      //     APSR.V = overflow;1928      if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,1929                                     res.carry_out, res.overflow))1930        return false;1931    }1932  }1933  return true;1934}1935 1936// An add operation to adjust the SP.1937// ADD (SP plus register)1938bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode,1939                                           const ARMEncoding encoding) {1940#if 01941    // ARM pseudo code...1942    if (ConditionPassed())1943    {1944        EncodingSpecificOperations();1945        shifted = Shift(R[m], shift_t, shift_n, APSR.C);1946        (result, carry, overflow) = AddWithCarry(SP, shifted, '0');1947        if d == 15 then1948            ALUWritePC(result); // setflags is always FALSE here1949        else1950            R[d] = result;1951            if setflags then1952                APSR.N = result<31>;1953                APSR.Z = IsZeroBit(result);1954                APSR.C = carry;1955                APSR.V = overflow;1956    }1957#endif1958 1959  bool success = false;1960 1961  if (ConditionPassed(opcode)) {1962    const addr_t sp = ReadCoreReg(SP_REG, &success);1963    if (!success)1964      return false;1965    uint32_t Rm; // the second operand1966    switch (encoding) {1967    case eEncodingT2:1968      Rm = Bits32(opcode, 6, 3);1969      break;1970    default:1971      return false;1972    }1973    int32_t reg_value = ReadCoreReg(Rm, &success);1974    if (!success)1975      return false;1976 1977    addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value1978 1979    EmulateInstruction::Context context;1980    context.type = eContextArithmetic;1981    std::optional<RegisterInfo> sp_reg =1982        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);1983    std::optional<RegisterInfo> other_reg =1984        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);1985    context.SetRegisterRegisterOperands(*sp_reg, *other_reg);1986 1987    if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,1988                               LLDB_REGNUM_GENERIC_SP, addr))1989      return false;1990  }1991  return true;1992}1993 1994// Branch with Link and Exchange Instruction Sets (immediate) calls a1995// subroutine at a PC-relative address, and changes instruction set from ARM to1996// Thumb, or from Thumb to ARM.1997// BLX (immediate)1998bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode,1999                                                const ARMEncoding encoding) {2000#if 02001    // ARM pseudo code...2002    if (ConditionPassed())2003    {2004        EncodingSpecificOperations();2005        if CurrentInstrSet() == InstrSet_ARM then2006            LR = PC - 4;2007        else2008            LR = PC<31:1> : '1';2009        if targetInstrSet == InstrSet_ARM then2010            targetAddress = Align(PC,4) + imm32;2011        else2012            targetAddress = PC + imm32;2013        SelectInstrSet(targetInstrSet);2014        BranchWritePC(targetAddress);2015    }2016#endif2017 2018  bool success = true;2019 2020  if (ConditionPassed(opcode)) {2021    EmulateInstruction::Context context;2022    context.type = EmulateInstruction::eContextRelativeBranchImmediate;2023    const uint32_t pc = ReadCoreReg(PC_REG, &success);2024    if (!success)2025      return false;2026    addr_t lr;     // next instruction address2027    addr_t target; // target address2028    int32_t imm32; // PC-relative offset2029    switch (encoding) {2030    case eEncodingT1: {2031      lr = pc | 1u; // return address2032      uint32_t S = Bit32(opcode, 26);2033      uint32_t imm10 = Bits32(opcode, 25, 16);2034      uint32_t J1 = Bit32(opcode, 13);2035      uint32_t J2 = Bit32(opcode, 11);2036      uint32_t imm11 = Bits32(opcode, 10, 0);2037      uint32_t I1 = !(J1 ^ S);2038      uint32_t I2 = !(J2 ^ S);2039      uint32_t imm25 =2040          (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);2041      imm32 = llvm::SignExtend32<25>(imm25);2042      target = pc + imm32;2043      SelectInstrSet(eModeThumb);2044      context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2045      if (InITBlock() && !LastInITBlock())2046        return false;2047      break;2048    }2049    case eEncodingT2: {2050      lr = pc | 1u; // return address2051      uint32_t S = Bit32(opcode, 26);2052      uint32_t imm10H = Bits32(opcode, 25, 16);2053      uint32_t J1 = Bit32(opcode, 13);2054      uint32_t J2 = Bit32(opcode, 11);2055      uint32_t imm10L = Bits32(opcode, 10, 1);2056      uint32_t I1 = !(J1 ^ S);2057      uint32_t I2 = !(J2 ^ S);2058      uint32_t imm25 =2059          (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);2060      imm32 = llvm::SignExtend32<25>(imm25);2061      target = Align(pc, 4) + imm32;2062      SelectInstrSet(eModeARM);2063      context.SetISAAndImmediateSigned(eModeARM, 4 + imm32);2064      if (InITBlock() && !LastInITBlock())2065        return false;2066      break;2067    }2068    case eEncodingA1:2069      lr = pc - 4; // return address2070      imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);2071      target = Align(pc, 4) + imm32;2072      SelectInstrSet(eModeARM);2073      context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);2074      break;2075    case eEncodingA2:2076      lr = pc - 4; // return address2077      imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 |2078                                     Bits32(opcode, 24, 24) << 1);2079      target = pc + imm32;2080      SelectInstrSet(eModeThumb);2081      context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32);2082      break;2083    default:2084      return false;2085    }2086    if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2087                               LLDB_REGNUM_GENERIC_RA, lr))2088      return false;2089    if (!BranchWritePC(context, target))2090      return false;2091    if (m_opcode_cpsr != m_new_inst_cpsr)2092      if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2093                                 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))2094        return false;2095  }2096  return true;2097}2098 2099// Branch with Link and Exchange (register) calls a subroutine at an address2100// and instruction set specified by a register.2101// BLX (register)2102bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode,2103                                         const ARMEncoding encoding) {2104#if 02105    // ARM pseudo code...2106    if (ConditionPassed())2107    {2108        EncodingSpecificOperations();2109        target = R[m];2110        if CurrentInstrSet() == InstrSet_ARM then2111            next_instr_addr = PC - 4;2112            LR = next_instr_addr;2113        else2114            next_instr_addr = PC - 2;2115            LR = next_instr_addr<31:1> : '1';2116        BXWritePC(target);2117    }2118#endif2119 2120  bool success = false;2121 2122  if (ConditionPassed(opcode)) {2123    EmulateInstruction::Context context;2124    context.type = EmulateInstruction::eContextAbsoluteBranchRegister;2125    const uint32_t pc = ReadCoreReg(PC_REG, &success);2126    addr_t lr; // next instruction address2127    if (!success)2128      return false;2129    uint32_t Rm; // the register with the target address2130    switch (encoding) {2131    case eEncodingT1:2132      lr = (pc - 2) | 1u; // return address2133      Rm = Bits32(opcode, 6, 3);2134      // if m == 15 then UNPREDICTABLE;2135      if (Rm == 15)2136        return false;2137      if (InITBlock() && !LastInITBlock())2138        return false;2139      break;2140    case eEncodingA1:2141      lr = pc - 4; // return address2142      Rm = Bits32(opcode, 3, 0);2143      // if m == 15 then UNPREDICTABLE;2144      if (Rm == 15)2145        return false;2146      break;2147    default:2148      return false;2149    }2150    addr_t target = ReadCoreReg(Rm, &success);2151    if (!success)2152      return false;2153    std::optional<RegisterInfo> dwarf_reg =2154        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);2155    context.SetRegister(*dwarf_reg);2156    if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2157                               LLDB_REGNUM_GENERIC_RA, lr))2158      return false;2159    if (!BXWritePC(context, target))2160      return false;2161  }2162  return true;2163}2164 2165// Branch and Exchange causes a branch to an address and instruction set2166// specified by a register.2167bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode,2168                                        const ARMEncoding encoding) {2169#if 02170    // ARM pseudo code...2171    if (ConditionPassed())2172    {2173        EncodingSpecificOperations();2174        BXWritePC(R[m]);2175    }2176#endif2177 2178  if (ConditionPassed(opcode)) {2179    EmulateInstruction::Context context;2180    context.type = EmulateInstruction::eContextAbsoluteBranchRegister;2181    uint32_t Rm; // the register with the target address2182    switch (encoding) {2183    case eEncodingT1:2184      Rm = Bits32(opcode, 6, 3);2185      if (InITBlock() && !LastInITBlock())2186        return false;2187      break;2188    case eEncodingA1:2189      Rm = Bits32(opcode, 3, 0);2190      break;2191    default:2192      return false;2193    }2194    bool success = false;2195    addr_t target = ReadCoreReg(Rm, &success);2196    if (!success)2197      return false;2198 2199    std::optional<RegisterInfo> dwarf_reg =2200        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);2201    context.SetRegister(*dwarf_reg);2202    if (!BXWritePC(context, target))2203      return false;2204  }2205  return true;2206}2207 2208// Branch and Exchange Jazelle attempts to change to Jazelle state. If the2209// attempt fails, it branches to an address and instruction set specified by a2210// register as though it were a BX instruction.2211//2212// TODO: Emulate Jazelle architecture?2213//       We currently assume that switching to Jazelle state fails, thus2214//       treating BXJ as a BX operation.2215bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode,2216                                         const ARMEncoding encoding) {2217#if 02218    // ARM pseudo code...2219    if (ConditionPassed())2220    {2221        EncodingSpecificOperations();2222        if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then2223            BXWritePC(R[m]);2224        else2225            if JazelleAcceptsExecution() then2226                SwitchToJazelleExecution();2227            else2228                SUBARCHITECTURE_DEFINED handler call;2229    }2230#endif2231 2232  if (ConditionPassed(opcode)) {2233    EmulateInstruction::Context context;2234    context.type = EmulateInstruction::eContextAbsoluteBranchRegister;2235    uint32_t Rm; // the register with the target address2236    switch (encoding) {2237    case eEncodingT1:2238      Rm = Bits32(opcode, 19, 16);2239      if (BadReg(Rm))2240        return false;2241      if (InITBlock() && !LastInITBlock())2242        return false;2243      break;2244    case eEncodingA1:2245      Rm = Bits32(opcode, 3, 0);2246      if (Rm == 15)2247        return false;2248      break;2249    default:2250      return false;2251    }2252    bool success = false;2253    addr_t target = ReadCoreReg(Rm, &success);2254    if (!success)2255      return false;2256 2257    std::optional<RegisterInfo> dwarf_reg =2258        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);2259    context.SetRegister(*dwarf_reg);2260    if (!BXWritePC(context, target))2261      return false;2262  }2263  return true;2264}2265 2266// Set r7 to point to some ip offset.2267// SUB (immediate)2268bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode,2269                                              const ARMEncoding encoding) {2270#if 02271    // ARM pseudo code...2272    if (ConditionPassed())2273    {2274        EncodingSpecificOperations();2275        (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');2276        if d == 15 then // Can only occur for ARM encoding2277           ALUWritePC(result); // setflags is always FALSE here2278        else2279            R[d] = result;2280            if setflags then2281                APSR.N = result<31>;2282                APSR.Z = IsZeroBit(result);2283                APSR.C = carry;2284                APSR.V = overflow;2285    }2286#endif2287 2288  if (ConditionPassed(opcode)) {2289    bool success = false;2290    const addr_t ip = ReadCoreReg(12, &success);2291    if (!success)2292      return false;2293    uint32_t imm32;2294    switch (encoding) {2295    case eEncodingA1:2296      imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)2297      break;2298    default:2299      return false;2300    }2301    addr_t ip_offset = imm32;2302    addr_t addr = ip - ip_offset; // the adjusted ip value2303 2304    EmulateInstruction::Context context;2305    context.type = EmulateInstruction::eContextRegisterPlusOffset;2306    std::optional<RegisterInfo> dwarf_reg =2307        GetRegisterInfo(eRegisterKindDWARF, dwarf_r12);2308    context.SetRegisterPlusOffset(*dwarf_reg, -ip_offset);2309 2310    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr))2311      return false;2312  }2313  return true;2314}2315 2316// Set ip to point to some stack offset.2317// SUB (SP minus immediate)2318bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode,2319                                              const ARMEncoding encoding) {2320#if 02321    // ARM pseudo code...2322    if (ConditionPassed())2323    {2324        EncodingSpecificOperations();2325        (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');2326        if d == 15 then // Can only occur for ARM encoding2327           ALUWritePC(result); // setflags is always FALSE here2328        else2329            R[d] = result;2330            if setflags then2331                APSR.N = result<31>;2332                APSR.Z = IsZeroBit(result);2333                APSR.C = carry;2334                APSR.V = overflow;2335    }2336#endif2337 2338  if (ConditionPassed(opcode)) {2339    bool success = false;2340    const addr_t sp = ReadCoreReg(SP_REG, &success);2341    if (!success)2342      return false;2343    uint32_t imm32;2344    switch (encoding) {2345    case eEncodingA1:2346      imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)2347      break;2348    default:2349      return false;2350    }2351    addr_t sp_offset = imm32;2352    addr_t addr = sp - sp_offset; // the adjusted stack pointer value2353 2354    EmulateInstruction::Context context;2355    context.type = EmulateInstruction::eContextRegisterPlusOffset;2356    std::optional<RegisterInfo> dwarf_reg =2357        GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);2358    context.SetRegisterPlusOffset(*dwarf_reg, -sp_offset);2359 2360    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr))2361      return false;2362  }2363  return true;2364}2365 2366// This instruction subtracts an immediate value from the SP value, and writes2367// the result to the destination register.2368//2369// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local2370// storage.2371bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode,2372                                            const ARMEncoding encoding) {2373#if 02374    // ARM pseudo code...2375    if (ConditionPassed())2376    {2377        EncodingSpecificOperations();2378        (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');2379        if d == 15 then        // Can only occur for ARM encoding2380           ALUWritePC(result); // setflags is always FALSE here2381        else2382            R[d] = result;2383            if setflags then2384                APSR.N = result<31>;2385                APSR.Z = IsZeroBit(result);2386                APSR.C = carry;2387                APSR.V = overflow;2388    }2389#endif2390 2391  bool success = false;2392  if (ConditionPassed(opcode)) {2393    const addr_t sp = ReadCoreReg(SP_REG, &success);2394    if (!success)2395      return false;2396 2397    uint32_t Rd;2398    bool setflags;2399    uint32_t imm32;2400    switch (encoding) {2401    case eEncodingT1:2402      Rd = 13;2403      setflags = false;2404      imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)2405      break;2406    case eEncodingT2:2407      Rd = Bits32(opcode, 11, 8);2408      setflags = BitIsSet(opcode, 20);2409      imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)2410      if (Rd == 15 && setflags)2411        return EmulateCMPImm(opcode, eEncodingT2);2412      if (Rd == 15 && !setflags)2413        return false;2414      break;2415    case eEncodingT3:2416      Rd = Bits32(opcode, 11, 8);2417      setflags = false;2418      imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)2419      if (Rd == 15)2420        return false;2421      break;2422    case eEncodingA1:2423      Rd = Bits32(opcode, 15, 12);2424      setflags = BitIsSet(opcode, 20);2425      imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)2426 2427      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related2428      // instructions;2429      if (Rd == 15 && setflags)2430        return EmulateSUBSPcLrEtc(opcode, encoding);2431      break;2432    default:2433      return false;2434    }2435    AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);2436 2437    EmulateInstruction::Context context;2438    if (Rd == 13) {2439      uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting2440                              // to negate it, or the wrong2441      // value gets passed down to context.SetImmediateSigned.2442      context.type = EmulateInstruction::eContextAdjustStackPointer;2443      context.SetImmediateSigned(-imm64); // the stack pointer offset2444    } else {2445      context.type = EmulateInstruction::eContextImmediate;2446      context.SetNoArgs();2447    }2448 2449    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,2450                                   res.carry_out, res.overflow))2451      return false;2452  }2453  return true;2454}2455 2456// A store operation to the stack that also updates the SP.2457bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode,2458                                           const ARMEncoding encoding) {2459#if 02460    // ARM pseudo code...2461    if (ConditionPassed())2462    {2463        EncodingSpecificOperations();2464        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);2465        address = if index then offset_addr else R[n];2466        MemU[address,4] = if t == 15 then PCStoreValue() else R[t];2467        if wback then R[n] = offset_addr;2468    }2469#endif2470 2471  bool success = false;2472  if (ConditionPassed(opcode)) {2473    const uint32_t addr_byte_size = GetAddressByteSize();2474    const addr_t sp = ReadCoreReg(SP_REG, &success);2475    if (!success)2476      return false;2477    uint32_t Rt; // the source register2478    uint32_t imm12;2479    uint32_t2480        Rn; // This function assumes Rn is the SP, but we should verify that.2481 2482    bool index;2483    bool add;2484    bool wback;2485    switch (encoding) {2486    case eEncodingA1:2487      Rt = Bits32(opcode, 15, 12);2488      imm12 = Bits32(opcode, 11, 0);2489      Rn = Bits32(opcode, 19, 16);2490 2491      if (Rn != 13) // 13 is the SP reg on ARM.  Verify that Rn == SP.2492        return false;2493 2494      index = BitIsSet(opcode, 24);2495      add = BitIsSet(opcode, 23);2496      wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));2497 2498      if (wback && ((Rn == 15) || (Rn == Rt)))2499        return false;2500      break;2501    default:2502      return false;2503    }2504    addr_t offset_addr;2505    if (add)2506      offset_addr = sp + imm12;2507    else2508      offset_addr = sp - imm12;2509 2510    addr_t addr;2511    if (index)2512      addr = offset_addr;2513    else2514      addr = sp;2515 2516    EmulateInstruction::Context context;2517    context.type = EmulateInstruction::eContextPushRegisterOnStack;2518    std::optional<RegisterInfo> sp_reg =2519        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);2520    std::optional<RegisterInfo> dwarf_reg =2521        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt);2522 2523    context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);2524    if (Rt != 15) {2525      uint32_t reg_value = ReadCoreReg(Rt, &success);2526      if (!success)2527        return false;2528      if (!MemUWrite(context, addr, reg_value, addr_byte_size))2529        return false;2530    } else {2531      const uint32_t pc = ReadCoreReg(PC_REG, &success);2532      if (!success)2533        return false;2534      if (!MemUWrite(context, addr, pc, addr_byte_size))2535        return false;2536    }2537 2538    if (wback) {2539      context.type = EmulateInstruction::eContextAdjustStackPointer;2540      context.SetImmediateSigned(addr - sp);2541      if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2542                                 LLDB_REGNUM_GENERIC_SP, offset_addr))2543        return false;2544    }2545  }2546  return true;2547}2548 2549// Vector Push stores multiple extension registers to the stack. It also2550// updates SP to point to the start of the stored data.2551bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode,2552                                         const ARMEncoding encoding) {2553#if 02554    // ARM pseudo code...2555    if (ConditionPassed())2556    {2557        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);2558        address = SP - imm32;2559        SP = SP - imm32;2560        if single_regs then2561            for r = 0 to regs-12562                MemA[address,4] = S[d+r]; address = address+4;2563        else2564            for r = 0 to regs-12565                // Store as two word-aligned words in the correct order for2566                // current endianness.2567                MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;2568                MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;2569                address = address+8;2570    }2571#endif2572 2573  bool success = false;2574  if (ConditionPassed(opcode)) {2575    const uint32_t addr_byte_size = GetAddressByteSize();2576    const addr_t sp = ReadCoreReg(SP_REG, &success);2577    if (!success)2578      return false;2579    bool single_regs;2580    uint32_t d;     // UInt(D:Vd) or UInt(Vd:D) starting register2581    uint32_t imm32; // stack offset2582    uint32_t regs;  // number of registers2583    switch (encoding) {2584    case eEncodingT1:2585    case eEncodingA1:2586      single_regs = false;2587      d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);2588      imm32 = Bits32(opcode, 7, 0) * addr_byte_size;2589      // If UInt(imm8) is odd, see "FSTMX".2590      regs = Bits32(opcode, 7, 0) / 2;2591      // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;2592      if (regs == 0 || regs > 16 || (d + regs) > 32)2593        return false;2594      break;2595    case eEncodingT2:2596    case eEncodingA2:2597      single_regs = true;2598      d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);2599      imm32 = Bits32(opcode, 7, 0) * addr_byte_size;2600      regs = Bits32(opcode, 7, 0);2601      // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;2602      if (regs == 0 || regs > 16 || (d + regs) > 32)2603        return false;2604      break;2605    default:2606      return false;2607    }2608    uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;2609    uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;2610    addr_t sp_offset = imm32;2611    addr_t addr = sp - sp_offset;2612    uint32_t i;2613 2614    EmulateInstruction::Context context;2615    context.type = EmulateInstruction::eContextPushRegisterOnStack;2616 2617    std::optional<RegisterInfo> sp_reg =2618        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);2619    for (i = 0; i < regs; ++i) {2620      std::optional<RegisterInfo> dwarf_reg =2621          GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);2622      context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp);2623      // uint64_t to accommodate 64-bit registers.2624      uint64_t reg_value = ReadRegisterUnsigned(*dwarf_reg, 0, &success);2625      if (!success)2626        return false;2627      if (!MemAWrite(context, addr, reg_value, reg_byte_size))2628        return false;2629      addr += reg_byte_size;2630    }2631 2632    context.type = EmulateInstruction::eContextAdjustStackPointer;2633    context.SetImmediateSigned(-sp_offset);2634 2635    if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2636                               LLDB_REGNUM_GENERIC_SP, sp - sp_offset))2637      return false;2638  }2639  return true;2640}2641 2642// Vector Pop loads multiple extension registers from the stack. It also2643// updates SP to point just above the loaded data.2644bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode,2645                                        const ARMEncoding encoding) {2646#if 02647    // ARM pseudo code...2648    if (ConditionPassed())2649    {2650        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);2651        address = SP;2652        SP = SP + imm32;2653        if single_regs then2654            for r = 0 to regs-12655                S[d+r] = MemA[address,4]; address = address+4;2656        else2657            for r = 0 to regs-12658                word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;2659                // Combine the word-aligned words in the correct order for2660                // current endianness.2661                D[d+r] = if BigEndian() then word1:word2 else word2:word1;2662    }2663#endif2664 2665  bool success = false;2666  if (ConditionPassed(opcode)) {2667    const uint32_t addr_byte_size = GetAddressByteSize();2668    const addr_t sp = ReadCoreReg(SP_REG, &success);2669    if (!success)2670      return false;2671    bool single_regs;2672    uint32_t d;     // UInt(D:Vd) or UInt(Vd:D) starting register2673    uint32_t imm32; // stack offset2674    uint32_t regs;  // number of registers2675    switch (encoding) {2676    case eEncodingT1:2677    case eEncodingA1:2678      single_regs = false;2679      d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);2680      imm32 = Bits32(opcode, 7, 0) * addr_byte_size;2681      // If UInt(imm8) is odd, see "FLDMX".2682      regs = Bits32(opcode, 7, 0) / 2;2683      // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;2684      if (regs == 0 || regs > 16 || (d + regs) > 32)2685        return false;2686      break;2687    case eEncodingT2:2688    case eEncodingA2:2689      single_regs = true;2690      d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);2691      imm32 = Bits32(opcode, 7, 0) * addr_byte_size;2692      regs = Bits32(opcode, 7, 0);2693      // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;2694      if (regs == 0 || regs > 16 || (d + regs) > 32)2695        return false;2696      break;2697    default:2698      return false;2699    }2700    uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;2701    uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;2702    addr_t sp_offset = imm32;2703    addr_t addr = sp;2704    uint32_t i;2705    uint64_t data; // uint64_t to accommodate 64-bit registers.2706 2707    EmulateInstruction::Context context;2708    context.type = EmulateInstruction::eContextPopRegisterOffStack;2709 2710    for (i = 0; i < regs; ++i) {2711      std::optional<RegisterInfo> dwarf_reg =2712          GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i);2713      context.SetAddress(addr);2714      data = MemARead(context, addr, reg_byte_size, 0, &success);2715      if (!success)2716        return false;2717      if (!WriteRegisterUnsigned(context, *dwarf_reg, data))2718        return false;2719      addr += reg_byte_size;2720    }2721 2722    context.type = EmulateInstruction::eContextAdjustStackPointer;2723    context.SetImmediateSigned(sp_offset);2724 2725    if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2726                               LLDB_REGNUM_GENERIC_SP, sp + sp_offset))2727      return false;2728  }2729  return true;2730}2731 2732// SVC (previously SWI)2733bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode,2734                                       const ARMEncoding encoding) {2735#if 02736    // ARM pseudo code...2737    if (ConditionPassed())2738    {2739        EncodingSpecificOperations();2740        CallSupervisor();2741    }2742#endif2743 2744  bool success = false;2745 2746  if (ConditionPassed(opcode)) {2747    const uint32_t pc = ReadCoreReg(PC_REG, &success);2748    addr_t lr; // next instruction address2749    if (!success)2750      return false;2751    uint32_t imm32; // the immediate constant2752    uint32_t mode;  // ARM or Thumb mode2753    switch (encoding) {2754    case eEncodingT1:2755      lr = (pc + 2) | 1u; // return address2756      imm32 = Bits32(opcode, 7, 0);2757      mode = eModeThumb;2758      break;2759    case eEncodingA1:2760      lr = pc + 4; // return address2761      imm32 = Bits32(opcode, 23, 0);2762      mode = eModeARM;2763      break;2764    default:2765      return false;2766    }2767 2768    EmulateInstruction::Context context;2769    context.type = EmulateInstruction::eContextSupervisorCall;2770    context.SetISAAndImmediate(mode, imm32);2771    if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,2772                               LLDB_REGNUM_GENERIC_RA, lr))2773      return false;2774  }2775  return true;2776}2777 2778// If Then makes up to four following instructions (the IT block) conditional.2779bool EmulateInstructionARM::EmulateIT(const uint32_t opcode,2780                                      const ARMEncoding encoding) {2781#if 02782    // ARM pseudo code...2783    EncodingSpecificOperations();2784    ITSTATE.IT<7:0> = firstcond:mask;2785#endif2786 2787  m_it_session.InitIT(Bits32(opcode, 7, 0));2788  return true;2789}2790 2791bool EmulateInstructionARM::EmulateNop(const uint32_t opcode,2792                                       const ARMEncoding encoding) {2793  // NOP, nothing to do...2794  return true;2795}2796 2797// Branch causes a branch to a target address.2798bool EmulateInstructionARM::EmulateB(const uint32_t opcode,2799                                     const ARMEncoding encoding) {2800#if 02801    // ARM pseudo code...2802    if (ConditionPassed())2803    {2804        EncodingSpecificOperations();2805        BranchWritePC(PC + imm32);2806    }2807#endif2808 2809  bool success = false;2810 2811  if (ConditionPassed(opcode)) {2812    EmulateInstruction::Context context;2813    context.type = EmulateInstruction::eContextRelativeBranchImmediate;2814    const uint32_t pc = ReadCoreReg(PC_REG, &success);2815    if (!success)2816      return false;2817    addr_t target; // target address2818    int32_t imm32; // PC-relative offset2819    switch (encoding) {2820    case eEncodingT1:2821      // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().2822      imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);2823      target = pc + imm32;2824      context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2825      break;2826    case eEncodingT2:2827      imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1);2828      target = pc + imm32;2829      context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2830      break;2831    case eEncodingT3:2832      // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().2833      {2834        if (Bits32(opcode, 25, 23) == 7)2835          return false; // See Branches and miscellaneous control on page2836                        // A6-235.2837 2838        uint32_t S = Bit32(opcode, 26);2839        uint32_t imm6 = Bits32(opcode, 21, 16);2840        uint32_t J1 = Bit32(opcode, 13);2841        uint32_t J2 = Bit32(opcode, 11);2842        uint32_t imm11 = Bits32(opcode, 10, 0);2843        uint32_t imm21 =2844            (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);2845        imm32 = llvm::SignExtend32<21>(imm21);2846        target = pc + imm32;2847        context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2848        break;2849      }2850    case eEncodingT4: {2851      uint32_t S = Bit32(opcode, 26);2852      uint32_t imm10 = Bits32(opcode, 25, 16);2853      uint32_t J1 = Bit32(opcode, 13);2854      uint32_t J2 = Bit32(opcode, 11);2855      uint32_t imm11 = Bits32(opcode, 10, 0);2856      uint32_t I1 = !(J1 ^ S);2857      uint32_t I2 = !(J2 ^ S);2858      uint32_t imm25 =2859          (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);2860      imm32 = llvm::SignExtend32<25>(imm25);2861      target = pc + imm32;2862      context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2863      break;2864    }2865    case eEncodingA1:2866      imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);2867      target = pc + imm32;2868      context.SetISAAndImmediateSigned(eModeARM, 8 + imm32);2869      break;2870    default:2871      return false;2872    }2873    if (!BranchWritePC(context, target))2874      return false;2875  }2876  return true;2877}2878 2879// Compare and Branch on Nonzero and Compare and Branch on Zero compare the2880// value in a register with zero and conditionally branch forward a constant2881// value.  They do not affect the condition flags. CBNZ, CBZ2882bool EmulateInstructionARM::EmulateCB(const uint32_t opcode,2883                                      const ARMEncoding encoding) {2884#if 02885    // ARM pseudo code...2886    EncodingSpecificOperations();2887    if nonzero ^ IsZero(R[n]) then2888        BranchWritePC(PC + imm32);2889#endif2890 2891  bool success = false;2892 2893  // Read the register value from the operand register Rn.2894  uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);2895  if (!success)2896    return false;2897 2898  EmulateInstruction::Context context;2899  context.type = EmulateInstruction::eContextRelativeBranchImmediate;2900  const uint32_t pc = ReadCoreReg(PC_REG, &success);2901  if (!success)2902    return false;2903 2904  addr_t target;  // target address2905  uint32_t imm32; // PC-relative offset to branch forward2906  bool nonzero;2907  switch (encoding) {2908  case eEncodingT1:2909    imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;2910    nonzero = BitIsSet(opcode, 11);2911    target = pc + imm32;2912    context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32);2913    break;2914  default:2915    return false;2916  }2917  if (m_ignore_conditions || (nonzero ^ (reg_val == 0)))2918    if (!BranchWritePC(context, target))2919      return false;2920 2921  return true;2922}2923 2924// Table Branch Byte causes a PC-relative forward branch using a table of2925// single byte offsets.2926// A base register provides a pointer to the table, and a second register2927// supplies an index into the table.2928// The branch length is twice the value of the byte returned from the table.2929//2930// Table Branch Halfword causes a PC-relative forward branch using a table of2931// single halfword offsets.2932// A base register provides a pointer to the table, and a second register2933// supplies an index into the table.2934// The branch length is twice the value of the halfword returned from the2935// table. TBB, TBH2936bool EmulateInstructionARM::EmulateTB(const uint32_t opcode,2937                                      const ARMEncoding encoding) {2938#if 02939    // ARM pseudo code...2940    EncodingSpecificOperations(); NullCheckIfThumbEE(n);2941    if is_tbh then2942        halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);2943    else2944        halfwords = UInt(MemU[R[n]+R[m], 1]);2945    BranchWritePC(PC + 2*halfwords);2946#endif2947 2948  bool success = false;2949 2950  if (ConditionPassed(opcode)) {2951    uint32_t Rn; // the base register which contains the address of the table of2952                 // branch lengths2953    uint32_t Rm; // the index register which contains an integer pointing to a2954                 // byte/halfword in the table2955    bool is_tbh; // true if table branch halfword2956    switch (encoding) {2957    case eEncodingT1:2958      Rn = Bits32(opcode, 19, 16);2959      Rm = Bits32(opcode, 3, 0);2960      is_tbh = BitIsSet(opcode, 4);2961      if (Rn == 13 || BadReg(Rm))2962        return false;2963      if (InITBlock() && !LastInITBlock())2964        return false;2965      break;2966    default:2967      return false;2968    }2969 2970    // Read the address of the table from the operand register Rn. The PC can2971    // be used, in which case the table immediately follows this instruction.2972    uint32_t base = ReadCoreReg(Rn, &success);2973    if (!success)2974      return false;2975 2976    // the table index2977    uint32_t index = ReadCoreReg(Rm, &success);2978    if (!success)2979      return false;2980 2981    // the offsetted table address2982    addr_t addr = base + (is_tbh ? index * 2 : index);2983 2984    // PC-relative offset to branch forward2985    EmulateInstruction::Context context;2986    context.type = EmulateInstruction::eContextTableBranchReadMemory;2987    uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;2988    if (!success)2989      return false;2990 2991    const uint32_t pc = ReadCoreReg(PC_REG, &success);2992    if (!success)2993      return false;2994 2995    // target address2996    addr_t target = pc + offset;2997    context.type = EmulateInstruction::eContextRelativeBranchImmediate;2998    context.SetISAAndImmediateSigned(eModeThumb, 4 + offset);2999 3000    if (!BranchWritePC(context, target))3001      return false;3002  }3003 3004  return true;3005}3006 3007// This instruction adds an immediate value to a register value, and writes the3008// result to the destination register. It can optionally update the condition3009// flags based on the result.3010bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode,3011                                               const ARMEncoding encoding) {3012#if 03013    if ConditionPassed() then 3014        EncodingSpecificOperations(); 3015        (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 3016        R[d] = result; 3017        if setflags then3018            APSR.N = result<31>;3019            APSR.Z = IsZeroBit(result);3020            APSR.C = carry;3021            APSR.V = overflow;3022#endif3023 3024  bool success = false;3025 3026  if (ConditionPassed(opcode)) {3027    uint32_t d;3028    uint32_t n;3029    bool setflags;3030    uint32_t imm32;3031    uint32_t carry_out;3032 3033    // EncodingSpecificOperations();3034    switch (encoding) {3035    case eEncodingT1:3036      // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 =3037      // ZeroExtend(imm3, 32);3038      d = Bits32(opcode, 2, 0);3039      n = Bits32(opcode, 5, 3);3040      setflags = !InITBlock();3041      imm32 = Bits32(opcode, 8, 6);3042 3043      break;3044 3045    case eEncodingT2:3046      // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 =3047      // ZeroExtend(imm8, 32);3048      d = Bits32(opcode, 10, 8);3049      n = Bits32(opcode, 10, 8);3050      setflags = !InITBlock();3051      imm32 = Bits32(opcode, 7, 0);3052 3053      break;3054 3055    case eEncodingT3:3056      // if Rd == '1111' && S == '1' then SEE CMN (immediate);3057      // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 =3058      // ThumbExpandImm(i:imm3:imm8);3059      d = Bits32(opcode, 11, 8);3060      n = Bits32(opcode, 19, 16);3061      setflags = BitIsSet(opcode, 20);3062      imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out);3063 3064      // if Rn == '1101' then SEE ADD (SP plus immediate);3065      if (n == 13)3066        return EmulateADDSPImm(opcode, eEncodingT3);3067 3068      // if BadReg(d) || n == 15 then UNPREDICTABLE;3069      if (BadReg(d) || (n == 15))3070        return false;3071 3072      break;3073 3074    case eEncodingT4: {3075      // if Rn == '1111' then SEE ADR;3076      // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 =3077      // ZeroExtend(i:imm3:imm8, 32);3078      d = Bits32(opcode, 11, 8);3079      n = Bits32(opcode, 19, 16);3080      setflags = false;3081      uint32_t i = Bit32(opcode, 26);3082      uint32_t imm3 = Bits32(opcode, 14, 12);3083      uint32_t imm8 = Bits32(opcode, 7, 0);3084      imm32 = (i << 11) | (imm3 << 8) | imm8;3085 3086      // if Rn == '1101' then SEE ADD (SP plus immediate);3087      if (n == 13)3088        return EmulateADDSPImm(opcode, eEncodingT4);3089 3090      // if BadReg(d) then UNPREDICTABLE;3091      if (BadReg(d))3092        return false;3093 3094      break;3095    }3096 3097    default:3098      return false;3099    }3100 3101    uint64_t Rn =3102        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);3103    if (!success)3104      return false;3105 3106    //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0');3107    AddWithCarryResult res = AddWithCarry(Rn, imm32, 0);3108 3109    std::optional<RegisterInfo> reg_n =3110        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);3111    EmulateInstruction::Context context;3112    context.type = eContextArithmetic;3113    context.SetRegisterPlusOffset(*reg_n, imm32);3114 3115    // R[d] = result;3116    // if setflags then3117    // APSR.N = result<31>;3118    // APSR.Z = IsZeroBit(result);3119    // APSR.C = carry;3120    // APSR.V = overflow;3121    if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags,3122                                   res.carry_out, res.overflow))3123      return false;3124  }3125  return true;3126}3127 3128// This instruction adds an immediate value to a register value, and writes the3129// result to the destination register.  It can optionally update the condition3130// flags based on the result.3131bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode,3132                                             const ARMEncoding encoding) {3133#if 03134    // ARM pseudo code...3135    if ConditionPassed() then3136        EncodingSpecificOperations();3137        (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');3138        if d == 15 then3139            ALUWritePC(result); // setflags is always FALSE here3140        else3141            R[d] = result;3142            if setflags then3143                APSR.N = result<31>;3144                APSR.Z = IsZeroBit(result);3145                APSR.C = carry;3146                APSR.V = overflow;3147#endif3148 3149  bool success = false;3150 3151  if (ConditionPassed(opcode)) {3152    uint32_t Rd, Rn;3153    uint32_t3154        imm32; // the immediate value to be added to the value obtained from Rn3155    bool setflags;3156    switch (encoding) {3157    case eEncodingA1:3158      Rd = Bits32(opcode, 15, 12);3159      Rn = Bits32(opcode, 19, 16);3160      setflags = BitIsSet(opcode, 20);3161      imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)3162      break;3163    default:3164      return false;3165    }3166 3167    // Read the first operand.3168    uint32_t val1 = ReadCoreReg(Rn, &success);3169    if (!success)3170      return false;3171 3172    AddWithCarryResult res = AddWithCarry(val1, imm32, 0);3173 3174    EmulateInstruction::Context context;3175    if (Rd == 13)3176      context.type = EmulateInstruction::eContextAdjustStackPointer;3177    else if (Rd == GetFramePointerRegisterNumber())3178      context.type = EmulateInstruction::eContextSetFramePointer;3179    else3180      context.type = EmulateInstruction::eContextRegisterPlusOffset;3181 3182    std::optional<RegisterInfo> dwarf_reg =3183        GetRegisterInfo(eRegisterKindDWARF, Rn);3184    context.SetRegisterPlusOffset(*dwarf_reg, imm32);3185 3186    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,3187                                   res.carry_out, res.overflow))3188      return false;3189  }3190  return true;3191}3192 3193// This instruction adds a register value and an optionally-shifted register3194// value, and writes the result to the destination register. It can optionally3195// update the condition flags based on the result.3196bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode,3197                                          const ARMEncoding encoding) {3198#if 03199    // ARM pseudo code...3200    if ConditionPassed() then3201        EncodingSpecificOperations();3202        shifted = Shift(R[m], shift_t, shift_n, APSR.C);3203        (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');3204        if d == 15 then3205            ALUWritePC(result); // setflags is always FALSE here3206        else3207            R[d] = result;3208            if setflags then3209                APSR.N = result<31>;3210                APSR.Z = IsZeroBit(result);3211                APSR.C = carry;3212                APSR.V = overflow;3213#endif3214 3215  bool success = false;3216 3217  if (ConditionPassed(opcode)) {3218    uint32_t Rd, Rn, Rm;3219    ARM_ShifterType shift_t;3220    uint32_t shift_n; // the shift applied to the value read from Rm3221    bool setflags;3222    switch (encoding) {3223    case eEncodingT1:3224      Rd = Bits32(opcode, 2, 0);3225      Rn = Bits32(opcode, 5, 3);3226      Rm = Bits32(opcode, 8, 6);3227      setflags = !InITBlock();3228      shift_t = SRType_LSL;3229      shift_n = 0;3230      break;3231    case eEncodingT2:3232      Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);3233      Rm = Bits32(opcode, 6, 3);3234      setflags = false;3235      shift_t = SRType_LSL;3236      shift_n = 0;3237      if (Rn == 15 && Rm == 15)3238        return false;3239      if (Rd == 15 && InITBlock() && !LastInITBlock())3240        return false;3241      break;3242    case eEncodingA1:3243      Rd = Bits32(opcode, 15, 12);3244      Rn = Bits32(opcode, 19, 16);3245      Rm = Bits32(opcode, 3, 0);3246      setflags = BitIsSet(opcode, 20);3247      shift_n = DecodeImmShiftARM(opcode, shift_t);3248      break;3249    default:3250      return false;3251    }3252 3253    // Read the first operand.3254    uint32_t val1 = ReadCoreReg(Rn, &success);3255    if (!success)3256      return false;3257 3258    // Read the second operand.3259    uint32_t val2 = ReadCoreReg(Rm, &success);3260    if (!success)3261      return false;3262 3263    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);3264    if (!success)3265      return false;3266    AddWithCarryResult res = AddWithCarry(val1, shifted, 0);3267 3268    EmulateInstruction::Context context;3269    context.type = eContextArithmetic;3270    std::optional<RegisterInfo> op1_reg =3271        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn);3272    std::optional<RegisterInfo> op2_reg =3273        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm);3274    context.SetRegisterRegisterOperands(*op1_reg, *op2_reg);3275 3276    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,3277                                   res.carry_out, res.overflow))3278      return false;3279  }3280  return true;3281}3282 3283// Compare Negative (immediate) adds a register value and an immediate value.3284// It updates the condition flags based on the result, and discards the result.3285bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,3286                                          const ARMEncoding encoding) {3287#if 03288    // ARM pseudo code...3289    if ConditionPassed() then3290        EncodingSpecificOperations();3291        (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');3292        APSR.N = result<31>;3293        APSR.Z = IsZeroBit(result);3294        APSR.C = carry;3295        APSR.V = overflow;3296#endif3297 3298  bool success = false;3299 3300  uint32_t Rn;    // the first operand3301  uint32_t imm32; // the immediate value to be compared with3302  switch (encoding) {3303  case eEncodingT1:3304    Rn = Bits32(opcode, 19, 16);3305    imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)3306    if (Rn == 15)3307      return false;3308    break;3309  case eEncodingA1:3310    Rn = Bits32(opcode, 19, 16);3311    imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)3312    break;3313  default:3314    return false;3315  }3316  // Read the register value from the operand register Rn.3317  uint32_t reg_val = ReadCoreReg(Rn, &success);3318  if (!success)3319    return false;3320 3321  AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);3322 3323  EmulateInstruction::Context context;3324  context.type = EmulateInstruction::eContextImmediate;3325  context.SetNoArgs();3326  return WriteFlags(context, res.result, res.carry_out, res.overflow);3327}3328 3329// Compare Negative (register) adds a register value and an optionally-shifted3330// register value. It updates the condition flags based on the result, and3331// discards the result.3332bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,3333                                          const ARMEncoding encoding) {3334#if 03335    // ARM pseudo code...3336    if ConditionPassed() then3337        EncodingSpecificOperations();3338        shifted = Shift(R[m], shift_t, shift_n, APSR.C);3339        (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');3340        APSR.N = result<31>;3341        APSR.Z = IsZeroBit(result);3342        APSR.C = carry;3343        APSR.V = overflow;3344#endif3345 3346  bool success = false;3347 3348  uint32_t Rn; // the first operand3349  uint32_t Rm; // the second operand3350  ARM_ShifterType shift_t;3351  uint32_t shift_n; // the shift applied to the value read from Rm3352  switch (encoding) {3353  case eEncodingT1:3354    Rn = Bits32(opcode, 2, 0);3355    Rm = Bits32(opcode, 5, 3);3356    shift_t = SRType_LSL;3357    shift_n = 0;3358    break;3359  case eEncodingT2:3360    Rn = Bits32(opcode, 19, 16);3361    Rm = Bits32(opcode, 3, 0);3362    shift_n = DecodeImmShiftThumb(opcode, shift_t);3363    // if n == 15 || BadReg(m) then UNPREDICTABLE;3364    if (Rn == 15 || BadReg(Rm))3365      return false;3366    break;3367  case eEncodingA1:3368    Rn = Bits32(opcode, 19, 16);3369    Rm = Bits32(opcode, 3, 0);3370    shift_n = DecodeImmShiftARM(opcode, shift_t);3371    break;3372  default:3373    return false;3374  }3375  // Read the register value from register Rn.3376  uint32_t val1 = ReadCoreReg(Rn, &success);3377  if (!success)3378    return false;3379 3380  // Read the register value from register Rm.3381  uint32_t val2 = ReadCoreReg(Rm, &success);3382  if (!success)3383    return false;3384 3385  uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);3386  if (!success)3387    return false;3388  AddWithCarryResult res = AddWithCarry(val1, shifted, 0);3389 3390  EmulateInstruction::Context context;3391  context.type = EmulateInstruction::eContextImmediate;3392  context.SetNoArgs();3393  return WriteFlags(context, res.result, res.carry_out, res.overflow);3394}3395 3396// Compare (immediate) subtracts an immediate value from a register value. It3397// updates the condition flags based on the result, and discards the result.3398bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,3399                                          const ARMEncoding encoding) {3400#if 03401    // ARM pseudo code...3402    if ConditionPassed() then3403        EncodingSpecificOperations();3404        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');3405        APSR.N = result<31>;3406        APSR.Z = IsZeroBit(result);3407        APSR.C = carry;3408        APSR.V = overflow;3409#endif3410 3411  bool success = false;3412 3413  uint32_t Rn;    // the first operand3414  uint32_t imm32; // the immediate value to be compared with3415  switch (encoding) {3416  case eEncodingT1:3417    Rn = Bits32(opcode, 10, 8);3418    imm32 = Bits32(opcode, 7, 0);3419    break;3420  case eEncodingT2:3421    Rn = Bits32(opcode, 19, 16);3422    imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)3423    if (Rn == 15)3424      return false;3425    break;3426  case eEncodingA1:3427    Rn = Bits32(opcode, 19, 16);3428    imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)3429    break;3430  default:3431    return false;3432  }3433  // Read the register value from the operand register Rn.3434  uint32_t reg_val = ReadCoreReg(Rn, &success);3435  if (!success)3436    return false;3437 3438  AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);3439 3440  EmulateInstruction::Context context;3441  context.type = EmulateInstruction::eContextImmediate;3442  context.SetNoArgs();3443  return WriteFlags(context, res.result, res.carry_out, res.overflow);3444}3445 3446// Compare (register) subtracts an optionally-shifted register value from a3447// register value. It updates the condition flags based on the result, and3448// discards the result.3449bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,3450                                          const ARMEncoding encoding) {3451#if 03452    // ARM pseudo code...3453    if ConditionPassed() then3454        EncodingSpecificOperations();3455        shifted = Shift(R[m], shift_t, shift_n, APSR.C);3456        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');3457        APSR.N = result<31>;3458        APSR.Z = IsZeroBit(result);3459        APSR.C = carry;3460        APSR.V = overflow;3461#endif3462 3463  bool success = false;3464 3465  uint32_t Rn; // the first operand3466  uint32_t Rm; // the second operand3467  ARM_ShifterType shift_t;3468  uint32_t shift_n; // the shift applied to the value read from Rm3469  switch (encoding) {3470  case eEncodingT1:3471    Rn = Bits32(opcode, 2, 0);3472    Rm = Bits32(opcode, 5, 3);3473    shift_t = SRType_LSL;3474    shift_n = 0;3475    break;3476  case eEncodingT2:3477    Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);3478    Rm = Bits32(opcode, 6, 3);3479    shift_t = SRType_LSL;3480    shift_n = 0;3481    if (Rn < 8 && Rm < 8)3482      return false;3483    if (Rn == 15 || Rm == 15)3484      return false;3485    break;3486  case eEncodingT3:3487    Rn = Bits32(opcode, 19, 16);3488    Rm = Bits32(opcode, 3, 0);3489    shift_n = DecodeImmShiftThumb(opcode, shift_t);3490    if (Rn == 15 || BadReg(Rm))3491      return false;3492    break;3493  case eEncodingA1:3494    Rn = Bits32(opcode, 19, 16);3495    Rm = Bits32(opcode, 3, 0);3496    shift_n = DecodeImmShiftARM(opcode, shift_t);3497    break;3498  default:3499    return false;3500  }3501  // Read the register value from register Rn.3502  uint32_t val1 = ReadCoreReg(Rn, &success);3503  if (!success)3504    return false;3505 3506  // Read the register value from register Rm.3507  uint32_t val2 = ReadCoreReg(Rm, &success);3508  if (!success)3509    return false;3510 3511  uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);3512  if (!success)3513    return false;3514  AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);3515 3516  EmulateInstruction::Context context;3517  context.type = EmulateInstruction::eContextImmediate;3518  context.SetNoArgs();3519  return WriteFlags(context, res.result, res.carry_out, res.overflow);3520}3521 3522// Arithmetic Shift Right (immediate) shifts a register value right by an3523// immediate number of bits, shifting in copies of its sign bit, and writes the3524// result to the destination register.  It can optionally update the condition3525// flags based on the result.3526bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode,3527                                          const ARMEncoding encoding) {3528#if 03529    // ARM pseudo code...3530    if ConditionPassed() then3531        EncodingSpecificOperations();3532        (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);3533        if d == 15 then         // Can only occur for ARM encoding3534            ALUWritePC(result); // setflags is always FALSE here3535        else3536            R[d] = result;3537            if setflags then3538                APSR.N = result<31>;3539                APSR.Z = IsZeroBit(result);3540                APSR.C = carry;3541                // APSR.V unchanged3542#endif3543 3544  return EmulateShiftImm(opcode, encoding, SRType_ASR);3545}3546 3547// Arithmetic Shift Right (register) shifts a register value right by a3548// variable number of bits, shifting in copies of its sign bit, and writes the3549// result to the destination register. The variable number of bits is read from3550// the bottom byte of a register. It can optionally update the condition flags3551// based on the result.3552bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode,3553                                          const ARMEncoding encoding) {3554#if 03555    // ARM pseudo code...3556    if ConditionPassed() then3557        EncodingSpecificOperations();3558        shift_n = UInt(R[m]<7:0>);3559        (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);3560        R[d] = result;3561        if setflags then3562            APSR.N = result<31>;3563            APSR.Z = IsZeroBit(result);3564            APSR.C = carry;3565            // APSR.V unchanged3566#endif3567 3568  return EmulateShiftReg(opcode, encoding, SRType_ASR);3569}3570 3571// Logical Shift Left (immediate) shifts a register value left by an immediate3572// number of bits, shifting in zeros, and writes the result to the destination3573// register.  It can optionally update the condition flags based on the result.3574bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode,3575                                          const ARMEncoding encoding) {3576#if 03577    // ARM pseudo code...3578    if ConditionPassed() then3579        EncodingSpecificOperations();3580        (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);3581        if d == 15 then         // Can only occur for ARM encoding3582            ALUWritePC(result); // setflags is always FALSE here3583        else3584            R[d] = result;3585            if setflags then3586                APSR.N = result<31>;3587                APSR.Z = IsZeroBit(result);3588                APSR.C = carry;3589                // APSR.V unchanged3590#endif3591 3592  return EmulateShiftImm(opcode, encoding, SRType_LSL);3593}3594 3595// Logical Shift Left (register) shifts a register value left by a variable3596// number of bits, shifting in zeros, and writes the result to the destination3597// register.  The variable number of bits is read from the bottom byte of a3598// register. It can optionally update the condition flags based on the result.3599bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode,3600                                          const ARMEncoding encoding) {3601#if 03602    // ARM pseudo code...3603    if ConditionPassed() then3604        EncodingSpecificOperations();3605        shift_n = UInt(R[m]<7:0>);3606        (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);3607        R[d] = result;3608        if setflags then3609            APSR.N = result<31>;3610            APSR.Z = IsZeroBit(result);3611            APSR.C = carry;3612            // APSR.V unchanged3613#endif3614 3615  return EmulateShiftReg(opcode, encoding, SRType_LSL);3616}3617 3618// Logical Shift Right (immediate) shifts a register value right by an3619// immediate number of bits, shifting in zeros, and writes the result to the3620// destination register.  It can optionally update the condition flags based on3621// the result.3622bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode,3623                                          const ARMEncoding encoding) {3624#if 03625    // ARM pseudo code...3626    if ConditionPassed() then3627        EncodingSpecificOperations();3628        (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);3629        if d == 15 then         // Can only occur for ARM encoding3630            ALUWritePC(result); // setflags is always FALSE here3631        else3632            R[d] = result;3633            if setflags then3634                APSR.N = result<31>;3635                APSR.Z = IsZeroBit(result);3636                APSR.C = carry;3637                // APSR.V unchanged3638#endif3639 3640  return EmulateShiftImm(opcode, encoding, SRType_LSR);3641}3642 3643// Logical Shift Right (register) shifts a register value right by a variable3644// number of bits, shifting in zeros, and writes the result to the destination3645// register.  The variable number of bits is read from the bottom byte of a3646// register. It can optionally update the condition flags based on the result.3647bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode,3648                                          const ARMEncoding encoding) {3649#if 03650    // ARM pseudo code...3651    if ConditionPassed() then3652        EncodingSpecificOperations();3653        shift_n = UInt(R[m]<7:0>);3654        (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);3655        R[d] = result;3656        if setflags then3657            APSR.N = result<31>;3658            APSR.Z = IsZeroBit(result);3659            APSR.C = carry;3660            // APSR.V unchanged3661#endif3662 3663  return EmulateShiftReg(opcode, encoding, SRType_LSR);3664}3665 3666// Rotate Right (immediate) provides the value of the contents of a register3667// rotated by a constant value. The bits that are rotated off the right end are3668// inserted into the vacated bit positions on the left. It can optionally3669// update the condition flags based on the result.3670bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode,3671                                          const ARMEncoding encoding) {3672#if 03673    // ARM pseudo code...3674    if ConditionPassed() then3675        EncodingSpecificOperations();3676        (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);3677        if d == 15 then         // Can only occur for ARM encoding3678            ALUWritePC(result); // setflags is always FALSE here3679        else3680            R[d] = result;3681            if setflags then3682                APSR.N = result<31>;3683                APSR.Z = IsZeroBit(result);3684                APSR.C = carry;3685                // APSR.V unchanged3686#endif3687 3688  return EmulateShiftImm(opcode, encoding, SRType_ROR);3689}3690 3691// Rotate Right (register) provides the value of the contents of a register3692// rotated by a variable number of bits. The bits that are rotated off the3693// right end are inserted into the vacated bit positions on the left. The3694// variable number of bits is read from the bottom byte of a register. It can3695// optionally update the condition flags based on the result.3696bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode,3697                                          const ARMEncoding encoding) {3698#if 03699    // ARM pseudo code...3700    if ConditionPassed() then3701        EncodingSpecificOperations();3702        shift_n = UInt(R[m]<7:0>);3703        (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);3704        R[d] = result;3705        if setflags then3706            APSR.N = result<31>;3707            APSR.Z = IsZeroBit(result);3708            APSR.C = carry;3709            // APSR.V unchanged3710#endif3711 3712  return EmulateShiftReg(opcode, encoding, SRType_ROR);3713}3714 3715// Rotate Right with Extend provides the value of the contents of a register3716// shifted right by one place, with the carry flag shifted into bit [31].3717//3718// RRX can optionally update the condition flags based on the result.3719// In that case, bit [0] is shifted into the carry flag.3720bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode,3721                                       const ARMEncoding encoding) {3722#if 03723    // ARM pseudo code...3724    if ConditionPassed() then3725        EncodingSpecificOperations();3726        (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);3727        if d == 15 then         // Can only occur for ARM encoding3728            ALUWritePC(result); // setflags is always FALSE here3729        else3730            R[d] = result;3731            if setflags then3732                APSR.N = result<31>;3733                APSR.Z = IsZeroBit(result);3734                APSR.C = carry;3735                // APSR.V unchanged3736#endif3737 3738  return EmulateShiftImm(opcode, encoding, SRType_RRX);3739}3740 3741bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode,3742                                            const ARMEncoding encoding,3743                                            ARM_ShifterType shift_type) {3744  //    assert(shift_type == SRType_ASR3745  //           || shift_type == SRType_LSL3746  //           || shift_type == SRType_LSR3747  //           || shift_type == SRType_ROR3748  //           || shift_type == SRType_RRX);3749 3750  bool success = false;3751 3752  if (ConditionPassed(opcode)) {3753    uint32_t Rd;    // the destination register3754    uint32_t Rm;    // the first operand register3755    uint32_t imm5;  // encoding for the shift amount3756    uint32_t carry; // the carry bit after the shift operation3757    bool setflags;3758 3759    // Special case handling!3760    // A8.6.139 ROR (immediate) -- Encoding T13761    ARMEncoding use_encoding = encoding;3762    if (shift_type == SRType_ROR && use_encoding == eEncodingT1) {3763      // Morph the T1 encoding from the ARM Architecture Manual into T23764      // encoding to have the same decoding of bit fields as the other Thumb23765      // shift operations.3766      use_encoding = eEncodingT2;3767    }3768 3769    switch (use_encoding) {3770    case eEncodingT1:3771      Rd = Bits32(opcode, 2, 0);3772      Rm = Bits32(opcode, 5, 3);3773      setflags = !InITBlock();3774      imm5 = Bits32(opcode, 10, 6);3775      break;3776    case eEncodingT2:3777      // A8.6.141 RRX3778      // There's no imm form of RRX instructions.3779      if (shift_type == SRType_RRX)3780        return false;3781 3782      Rd = Bits32(opcode, 11, 8);3783      Rm = Bits32(opcode, 3, 0);3784      setflags = BitIsSet(opcode, 20);3785      imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);3786      if (BadReg(Rd) || BadReg(Rm))3787        return false;3788      break;3789    case eEncodingA1:3790      Rd = Bits32(opcode, 15, 12);3791      Rm = Bits32(opcode, 3, 0);3792      setflags = BitIsSet(opcode, 20);3793      imm5 = Bits32(opcode, 11, 7);3794      break;3795    default:3796      return false;3797    }3798 3799    // A8.6.139 ROR (immediate)3800    if (shift_type == SRType_ROR && imm5 == 0)3801      shift_type = SRType_RRX;3802 3803    // Get the first operand.3804    uint32_t value = ReadCoreReg(Rm, &success);3805    if (!success)3806      return false;3807 3808    // Decode the shift amount if not RRX.3809    uint32_t amt =3810        (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));3811 3812    uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);3813    if (!success)3814      return false;3815 3816    // The context specifies that an immediate is to be moved into Rd.3817    EmulateInstruction::Context context;3818    context.type = EmulateInstruction::eContextImmediate;3819    context.SetNoArgs();3820 3821    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))3822      return false;3823  }3824  return true;3825}3826 3827bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode,3828                                            const ARMEncoding encoding,3829                                            ARM_ShifterType shift_type) {3830  // assert(shift_type == SRType_ASR3831  //        || shift_type == SRType_LSL3832  //        || shift_type == SRType_LSR3833  //        || shift_type == SRType_ROR);3834 3835  bool success = false;3836 3837  if (ConditionPassed(opcode)) {3838    uint32_t Rd; // the destination register3839    uint32_t Rn; // the first operand register3840    uint32_t3841        Rm; // the register whose bottom byte contains the amount to shift by3842    uint32_t carry; // the carry bit after the shift operation3843    bool setflags;3844    switch (encoding) {3845    case eEncodingT1:3846      Rd = Bits32(opcode, 2, 0);3847      Rn = Rd;3848      Rm = Bits32(opcode, 5, 3);3849      setflags = !InITBlock();3850      break;3851    case eEncodingT2:3852      Rd = Bits32(opcode, 11, 8);3853      Rn = Bits32(opcode, 19, 16);3854      Rm = Bits32(opcode, 3, 0);3855      setflags = BitIsSet(opcode, 20);3856      if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))3857        return false;3858      break;3859    case eEncodingA1:3860      Rd = Bits32(opcode, 15, 12);3861      Rn = Bits32(opcode, 3, 0);3862      Rm = Bits32(opcode, 11, 8);3863      setflags = BitIsSet(opcode, 20);3864      if (Rd == 15 || Rn == 15 || Rm == 15)3865        return false;3866      break;3867    default:3868      return false;3869    }3870 3871    // Get the first operand.3872    uint32_t value = ReadCoreReg(Rn, &success);3873    if (!success)3874      return false;3875    // Get the Rm register content.3876    uint32_t val = ReadCoreReg(Rm, &success);3877    if (!success)3878      return false;3879 3880    // Get the shift amount.3881    uint32_t amt = Bits32(val, 7, 0);3882 3883    uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);3884    if (!success)3885      return false;3886 3887    // The context specifies that an immediate is to be moved into Rd.3888    EmulateInstruction::Context context;3889    context.type = EmulateInstruction::eContextImmediate;3890    context.SetNoArgs();3891 3892    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))3893      return false;3894  }3895  return true;3896}3897 3898// LDM loads multiple registers from consecutive memory locations, using an3899// address from a base register.  Optionally the address just above the highest3900// of those locations can be written back to the base register.3901bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode,3902                                       const ARMEncoding encoding) {3903#if 03904    // ARM pseudo code...3905    if ConditionPassed()3906        EncodingSpecificOperations(); NullCheckIfThumbEE (n);3907        address = R[n];3908                  3909        for i = 0 to 143910            if registers<i> == '1' then3911                R[i] = MemA[address, 4]; address = address + 4;3912        if registers<15> == '1' then3913            LoadWritePC (MemA[address, 4]);3914                  3915        if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);3916        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A13917 3918#endif3919 3920  bool success = false;3921  if (ConditionPassed(opcode)) {3922    uint32_t n;3923    uint32_t registers = 0;3924    bool wback;3925    const uint32_t addr_byte_size = GetAddressByteSize();3926    switch (encoding) {3927    case eEncodingT1:3928      // n = UInt(Rn); registers = '00000000':register_list; wback =3929      // (registers<n> == '0');3930      n = Bits32(opcode, 10, 8);3931      registers = Bits32(opcode, 7, 0);3932      registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.3933      wback = BitIsClear(registers, n);3934      // if BitCount(registers) < 1 then UNPREDICTABLE;3935      if (BitCount(registers) < 1)3936        return false;3937      break;3938    case eEncodingT2:3939      // if W == '1' && Rn == '1101' then SEE POP;3940      // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');3941      n = Bits32(opcode, 19, 16);3942      registers = Bits32(opcode, 15, 0);3943      registers = registers & 0xdfff; // Make sure bit 13 is zero.3944      wback = BitIsSet(opcode, 21);3945 3946      // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then3947      // UNPREDICTABLE;3948      if ((n == 15) || (BitCount(registers) < 2) ||3949          (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))3950        return false;3951 3952      // if registers<15> == '1' && InITBlock() && !LastInITBlock() then3953      // UNPREDICTABLE;3954      if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())3955        return false;3956 3957      // if wback && registers<n> == '1' then UNPREDICTABLE;3958      if (wback && BitIsSet(registers, n))3959        return false;3960      break;3961 3962    case eEncodingA1:3963      n = Bits32(opcode, 19, 16);3964      registers = Bits32(opcode, 15, 0);3965      wback = BitIsSet(opcode, 21);3966      if ((n == 15) || (BitCount(registers) < 1))3967        return false;3968      break;3969    default:3970      return false;3971    }3972 3973    int32_t offset = 0;3974    const addr_t base_address =3975        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);3976    if (!success)3977      return false;3978 3979    EmulateInstruction::Context context;3980    context.type = EmulateInstruction::eContextRegisterPlusOffset;3981    std::optional<RegisterInfo> dwarf_reg =3982        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);3983    context.SetRegisterPlusOffset(*dwarf_reg, offset);3984 3985    for (int i = 0; i < 14; ++i) {3986      if (BitIsSet(registers, i)) {3987        context.type = EmulateInstruction::eContextRegisterPlusOffset;3988        context.SetRegisterPlusOffset(*dwarf_reg, offset);3989        if (wback && (n == 13)) // Pop Instruction3990        {3991          context.type = EmulateInstruction::eContextPopRegisterOffStack;3992          context.SetAddress(base_address + offset);3993        }3994 3995        // R[i] = MemA [address, 4]; address = address + 4;3996        uint32_t data = MemARead(context, base_address + offset, addr_byte_size,3997                                 0, &success);3998        if (!success)3999          return false;4000 4001        if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,4002                                   data))4003          return false;4004 4005        offset += addr_byte_size;4006      }4007    }4008 4009    if (BitIsSet(registers, 15)) {4010      // LoadWritePC (MemA [address, 4]);4011      context.type = EmulateInstruction::eContextRegisterPlusOffset;4012      context.SetRegisterPlusOffset(*dwarf_reg, offset);4013      uint32_t data =4014          MemARead(context, base_address + offset, addr_byte_size, 0, &success);4015      if (!success)4016        return false;4017      // In ARMv5T and above, this is an interworking branch.4018      if (!LoadWritePC(context, data))4019        return false;4020    }4021 4022    if (wback && BitIsClear(registers, n)) {4023      // R[n] = R[n] + 4 * BitCount (registers)4024      int32_t offset = addr_byte_size * BitCount(registers);4025      context.type = EmulateInstruction::eContextAdjustBaseRegister;4026      context.SetRegisterPlusOffset(*dwarf_reg, offset);4027 4028      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4029                                 base_address + offset))4030        return false;4031    }4032    if (wback && BitIsSet(registers, n))4033      // R[n] bits(32) UNKNOWN;4034      return WriteBits32Unknown(n);4035  }4036  return true;4037}4038 4039// LDMDA loads multiple registers from consecutive memory locations using an4040// address from a base register.4041// The consecutive memory locations end at this address and the address just4042// below the lowest of those locations can optionally be written back to the4043// base register.4044bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode,4045                                         const ARMEncoding encoding) {4046#if 04047    // ARM pseudo code...4048    if ConditionPassed() then 4049        EncodingSpecificOperations(); 4050        address = R[n] - 4*BitCount(registers) + 4;4051                  4052        for i = 0 to 14 4053            if registers<i> == '1' then4054                  R[i] = MemA[address,4]; address = address + 4; 4055                  4056        if registers<15> == '1' then4057            LoadWritePC(MemA[address,4]);4058                  4059        if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 4060        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;4061#endif4062 4063  bool success = false;4064 4065  if (ConditionPassed(opcode)) {4066    uint32_t n;4067    uint32_t registers = 0;4068    bool wback;4069    const uint32_t addr_byte_size = GetAddressByteSize();4070 4071    // EncodingSpecificOperations();4072    switch (encoding) {4073    case eEncodingA1:4074      // n = UInt(Rn); registers = register_list; wback = (W == '1');4075      n = Bits32(opcode, 19, 16);4076      registers = Bits32(opcode, 15, 0);4077      wback = BitIsSet(opcode, 21);4078 4079      // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4080      if ((n == 15) || (BitCount(registers) < 1))4081        return false;4082 4083      break;4084 4085    default:4086      return false;4087    }4088    // address = R[n] - 4*BitCount(registers) + 4;4089 4090    int32_t offset = 0;4091    addr_t Rn = ReadCoreReg(n, &success);4092 4093    if (!success)4094      return false;4095 4096    addr_t address =4097        Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size;4098 4099    EmulateInstruction::Context context;4100    context.type = EmulateInstruction::eContextRegisterPlusOffset;4101    std::optional<RegisterInfo> dwarf_reg =4102        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);4103    context.SetRegisterPlusOffset(*dwarf_reg, offset);4104 4105    // for i = 0 to 144106    for (int i = 0; i < 14; ++i) {4107      // if registers<i> == '1' then4108      if (BitIsSet(registers, i)) {4109        // R[i] = MemA[address,4]; address = address + 4;4110        context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));4111        uint32_t data =4112            MemARead(context, address + offset, addr_byte_size, 0, &success);4113        if (!success)4114          return false;4115        if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,4116                                   data))4117          return false;4118        offset += addr_byte_size;4119      }4120    }4121 4122    // if registers<15> == '1' then4123    //     LoadWritePC(MemA[address,4]);4124    if (BitIsSet(registers, 15)) {4125      context.SetRegisterPlusOffset(*dwarf_reg, offset);4126      uint32_t data =4127          MemARead(context, address + offset, addr_byte_size, 0, &success);4128      if (!success)4129        return false;4130      // In ARMv5T and above, this is an interworking branch.4131      if (!LoadWritePC(context, data))4132        return false;4133    }4134 4135    // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);4136    if (wback && BitIsClear(registers, n)) {4137 4138      offset = (addr_byte_size * BitCount(registers)) * -1;4139      context.type = EmulateInstruction::eContextAdjustBaseRegister;4140      context.SetImmediateSigned(offset);4141      addr_t addr = Rn + offset;4142      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4143                                 addr))4144        return false;4145    }4146 4147    // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;4148    if (wback && BitIsSet(registers, n))4149      return WriteBits32Unknown(n);4150  }4151  return true;4152}4153 4154// LDMDB loads multiple registers from consecutive memory locations using an4155// address from a base register.  The4156// consecutive memory locations end just below this address, and the address of4157// the lowest of those locations can be optionally written back to the base4158// register.4159bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode,4160                                         const ARMEncoding encoding) {4161#if 04162    // ARM pseudo code...4163    if ConditionPassed() then 4164        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4165        address = R[n] - 4*BitCount(registers);4166                  4167        for i = 0 to 14 4168            if registers<i> == '1' then4169                  R[i] = MemA[address,4]; address = address + 4; 4170        if registers<15> == '1' then4171                  LoadWritePC(MemA[address,4]);4172                  4173        if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 4174        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A14175#endif4176 4177  bool success = false;4178 4179  if (ConditionPassed(opcode)) {4180    uint32_t n;4181    uint32_t registers = 0;4182    bool wback;4183    const uint32_t addr_byte_size = GetAddressByteSize();4184    switch (encoding) {4185    case eEncodingT1:4186      // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');4187      n = Bits32(opcode, 19, 16);4188      registers = Bits32(opcode, 15, 0);4189      registers = registers & 0xdfff; // Make sure bit 13 is a zero.4190      wback = BitIsSet(opcode, 21);4191 4192      // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then4193      // UNPREDICTABLE;4194      if ((n == 15) || (BitCount(registers) < 2) ||4195          (BitIsSet(opcode, 14) && BitIsSet(opcode, 15)))4196        return false;4197 4198      // if registers<15> == '1' && InITBlock() && !LastInITBlock() then4199      // UNPREDICTABLE;4200      if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())4201        return false;4202 4203      // if wback && registers<n> == '1' then UNPREDICTABLE;4204      if (wback && BitIsSet(registers, n))4205        return false;4206 4207      break;4208 4209    case eEncodingA1:4210      // n = UInt(Rn); registers = register_list; wback = (W == '1');4211      n = Bits32(opcode, 19, 16);4212      registers = Bits32(opcode, 15, 0);4213      wback = BitIsSet(opcode, 21);4214 4215      // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4216      if ((n == 15) || (BitCount(registers) < 1))4217        return false;4218 4219      break;4220 4221    default:4222      return false;4223    }4224 4225    // address = R[n] - 4*BitCount(registers);4226 4227    int32_t offset = 0;4228    addr_t Rn =4229        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);4230 4231    if (!success)4232      return false;4233 4234    addr_t address = Rn - (addr_byte_size * BitCount(registers));4235    EmulateInstruction::Context context;4236    context.type = EmulateInstruction::eContextRegisterPlusOffset;4237    std::optional<RegisterInfo> dwarf_reg =4238        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);4239    context.SetRegisterPlusOffset(*dwarf_reg, Rn - address);4240 4241    for (int i = 0; i < 14; ++i) {4242      if (BitIsSet(registers, i)) {4243        // R[i] = MemA[address,4]; address = address + 4;4244        context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset));4245        uint32_t data =4246            MemARead(context, address + offset, addr_byte_size, 0, &success);4247        if (!success)4248          return false;4249 4250        if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,4251                                   data))4252          return false;4253 4254        offset += addr_byte_size;4255      }4256    }4257 4258    // if registers<15> == '1' then4259    //     LoadWritePC(MemA[address,4]);4260    if (BitIsSet(registers, 15)) {4261      context.SetRegisterPlusOffset(*dwarf_reg, offset);4262      uint32_t data =4263          MemARead(context, address + offset, addr_byte_size, 0, &success);4264      if (!success)4265        return false;4266      // In ARMv5T and above, this is an interworking branch.4267      if (!LoadWritePC(context, data))4268        return false;4269    }4270 4271    // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);4272    if (wback && BitIsClear(registers, n)) {4273 4274      offset = (addr_byte_size * BitCount(registers)) * -1;4275      context.type = EmulateInstruction::eContextAdjustBaseRegister;4276      context.SetImmediateSigned(offset);4277      addr_t addr = Rn + offset;4278      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4279                                 addr))4280        return false;4281    }4282 4283    // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only4284    // possible for encoding A14285    if (wback && BitIsSet(registers, n))4286      return WriteBits32Unknown(n);4287  }4288  return true;4289}4290 4291// LDMIB loads multiple registers from consecutive memory locations using an4292// address from a base register.  The4293// consecutive memory locations start just above this address, and thea ddress4294// of the last of those locations can optinoally be written back to the base4295// register.4296bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode,4297                                         const ARMEncoding encoding) {4298#if 04299    if ConditionPassed() then4300        EncodingSpecificOperations(); 4301        address = R[n] + 4;4302                  4303        for i = 0 to 14 4304            if registers<i> == '1' then4305                  R[i] = MemA[address,4]; address = address + 4; 4306        if registers<15> == '1' then4307            LoadWritePC(MemA[address,4]);4308                  4309        if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 4310        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;4311#endif4312 4313  bool success = false;4314 4315  if (ConditionPassed(opcode)) {4316    uint32_t n;4317    uint32_t registers = 0;4318    bool wback;4319    const uint32_t addr_byte_size = GetAddressByteSize();4320    switch (encoding) {4321    case eEncodingA1:4322      // n = UInt(Rn); registers = register_list; wback = (W == '1');4323      n = Bits32(opcode, 19, 16);4324      registers = Bits32(opcode, 15, 0);4325      wback = BitIsSet(opcode, 21);4326 4327      // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4328      if ((n == 15) || (BitCount(registers) < 1))4329        return false;4330 4331      break;4332    default:4333      return false;4334    }4335    // address = R[n] + 4;4336 4337    int32_t offset = 0;4338    addr_t Rn =4339        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);4340 4341    if (!success)4342      return false;4343 4344    addr_t address = Rn + addr_byte_size;4345 4346    EmulateInstruction::Context context;4347    context.type = EmulateInstruction::eContextRegisterPlusOffset;4348    std::optional<RegisterInfo> dwarf_reg =4349        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);4350    context.SetRegisterPlusOffset(*dwarf_reg, offset);4351 4352    for (int i = 0; i < 14; ++i) {4353      if (BitIsSet(registers, i)) {4354        // R[i] = MemA[address,4]; address = address + 4;4355 4356        context.SetRegisterPlusOffset(*dwarf_reg, offset + addr_byte_size);4357        uint32_t data =4358            MemARead(context, address + offset, addr_byte_size, 0, &success);4359        if (!success)4360          return false;4361 4362        if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i,4363                                   data))4364          return false;4365 4366        offset += addr_byte_size;4367      }4368    }4369 4370    // if registers<15> == '1' then4371    //     LoadWritePC(MemA[address,4]);4372    if (BitIsSet(registers, 15)) {4373      context.SetRegisterPlusOffset(*dwarf_reg, offset);4374      uint32_t data =4375          MemARead(context, address + offset, addr_byte_size, 0, &success);4376      if (!success)4377        return false;4378      // In ARMv5T and above, this is an interworking branch.4379      if (!LoadWritePC(context, data))4380        return false;4381    }4382 4383    // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);4384    if (wback && BitIsClear(registers, n)) {4385 4386      offset = addr_byte_size * BitCount(registers);4387      context.type = EmulateInstruction::eContextAdjustBaseRegister;4388      context.SetImmediateSigned(offset);4389      addr_t addr = Rn + offset;4390      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4391                                 addr))4392        return false;4393    }4394 4395    // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only4396    // possible for encoding A14397    if (wback && BitIsSet(registers, n))4398      return WriteBits32Unknown(n);4399  }4400  return true;4401}4402 4403// Load Register (immediate) calculates an address from a base register value4404// and an immediate offset, loads a word from memory, and writes to a register.4405// LDR (immediate, Thumb)4406bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode,4407                                              const ARMEncoding encoding) {4408#if 04409    // ARM pseudo code...4410    if (ConditionPassed())4411    {4412        EncodingSpecificOperations(); NullCheckIfThumbEE(15);4413        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);4414        address = if index then offset_addr else R[n];4415        data = MemU[address,4];4416        if wback then R[n] = offset_addr;4417        if t == 15 then4418            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;4419        elsif UnalignedSupport() || address<1:0> = '00' then4420            R[t] = data;4421        else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv74422    }4423#endif4424 4425  bool success = false;4426 4427  if (ConditionPassed(opcode)) {4428    uint32_t Rt;        // the destination register4429    uint32_t Rn;        // the base register4430    uint32_t imm32;     // the immediate offset used to form the address4431    addr_t offset_addr; // the offset address4432    addr_t address;     // the calculated address4433    uint32_t data;      // the literal data value from memory load4434    bool add, index, wback;4435    switch (encoding) {4436    case eEncodingT1:4437      Rt = Bits32(opcode, 2, 0);4438      Rn = Bits32(opcode, 5, 3);4439      imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);4440      // index = TRUE; add = TRUE; wback = FALSE4441      add = true;4442      index = true;4443      wback = false;4444 4445      break;4446 4447    case eEncodingT2:4448      // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);4449      Rt = Bits32(opcode, 10, 8);4450      Rn = 13;4451      imm32 = Bits32(opcode, 7, 0) << 2;4452 4453      // index = TRUE; add = TRUE; wback = FALSE;4454      index = true;4455      add = true;4456      wback = false;4457 4458      break;4459 4460    case eEncodingT3:4461      // if Rn == '1111' then SEE LDR (literal);4462      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);4463      Rt = Bits32(opcode, 15, 12);4464      Rn = Bits32(opcode, 19, 16);4465      imm32 = Bits32(opcode, 11, 0);4466 4467      // index = TRUE; add = TRUE; wback = FALSE;4468      index = true;4469      add = true;4470      wback = false;4471 4472      // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;4473      if ((Rt == 15) && InITBlock() && !LastInITBlock())4474        return false;4475 4476      break;4477 4478    case eEncodingT4:4479      // if Rn == '1111' then SEE LDR (literal);4480      // if P == '1' && U == '1' && W == '0' then SEE LDRT;4481      // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 ==4482      // '00000100' then SEE POP;4483      // if P == '0' && W == '0' then UNDEFINED;4484      if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))4485        return false;4486 4487      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);4488      Rt = Bits32(opcode, 15, 12);4489      Rn = Bits32(opcode, 19, 16);4490      imm32 = Bits32(opcode, 7, 0);4491 4492      // index = (P == '1'); add = (U == '1'); wback = (W == '1');4493      index = BitIsSet(opcode, 10);4494      add = BitIsSet(opcode, 9);4495      wback = BitIsSet(opcode, 8);4496 4497      // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock())4498      // then UNPREDICTABLE;4499      if ((wback && (Rn == Rt)) ||4500          ((Rt == 15) && InITBlock() && !LastInITBlock()))4501        return false;4502 4503      break;4504 4505    default:4506      return false;4507    }4508    uint32_t base = ReadCoreReg(Rn, &success);4509    if (!success)4510      return false;4511    if (add)4512      offset_addr = base + imm32;4513    else4514      offset_addr = base - imm32;4515 4516    address = (index ? offset_addr : base);4517 4518    std::optional<RegisterInfo> base_reg =4519        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn);4520    if (wback) {4521      EmulateInstruction::Context ctx;4522      if (Rn == 13) {4523        ctx.type = eContextAdjustStackPointer;4524        ctx.SetImmediateSigned((int32_t)(offset_addr - base));4525      } else if (Rn == GetFramePointerRegisterNumber()) {4526        ctx.type = eContextSetFramePointer;4527        ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));4528      } else {4529        ctx.type = EmulateInstruction::eContextAdjustBaseRegister;4530        ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));4531      }4532 4533      if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn,4534                                 offset_addr))4535        return false;4536    }4537 4538    // Prepare to write to the Rt register.4539    EmulateInstruction::Context context;4540    context.type = EmulateInstruction::eContextRegisterLoad;4541    context.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base));4542 4543    // Read memory from the address.4544    data = MemURead(context, address, 4, 0, &success);4545    if (!success)4546      return false;4547 4548    if (Rt == 15) {4549      if (Bits32(address, 1, 0) == 0) {4550        if (!LoadWritePC(context, data))4551          return false;4552      } else4553        return false;4554    } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) {4555      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt,4556                                 data))4557        return false;4558    } else4559      WriteBits32Unknown(Rt);4560  }4561  return true;4562}4563 4564// STM (Store Multiple Increment After) stores multiple registers to consecutive4565// memory locations using an address4566// from a base register.  The consecutive memory locations start at this4567// address, and the address just above the last of those locations can4568// optionally be written back to the base register.4569bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode,4570                                       const ARMEncoding encoding) {4571#if 04572    if ConditionPassed() then 4573        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4574        address = R[n];4575                  4576        for i = 0 to 14 4577            if registers<i> == '1' then4578                if i == n && wback && i != LowestSetBit(registers) then 4579                    MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A14580                else 4581                    MemA[address,4] = R[i];4582                address = address + 4;4583                  4584        if registers<15> == '1' then // Only possible for encoding A1 4585            MemA[address,4] = PCStoreValue();4586        if wback then R[n] = R[n] + 4*BitCount(registers);4587#endif4588 4589  bool success = false;4590 4591  if (ConditionPassed(opcode)) {4592    uint32_t n;4593    uint32_t registers = 0;4594    bool wback;4595    const uint32_t addr_byte_size = GetAddressByteSize();4596 4597    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);4598    switch (encoding) {4599    case eEncodingT1:4600      // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;4601      n = Bits32(opcode, 10, 8);4602      registers = Bits32(opcode, 7, 0);4603      registers = registers & 0x00ff; // Make sure the top 8 bits are zeros.4604      wback = true;4605 4606      // if BitCount(registers) < 1 then UNPREDICTABLE;4607      if (BitCount(registers) < 1)4608        return false;4609 4610      break;4611 4612    case eEncodingT2:4613      // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');4614      n = Bits32(opcode, 19, 16);4615      registers = Bits32(opcode, 15, 0);4616      registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.4617      wback = BitIsSet(opcode, 21);4618 4619      // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;4620      if ((n == 15) || (BitCount(registers) < 2))4621        return false;4622 4623      // if wback && registers<n> == '1' then UNPREDICTABLE;4624      if (wback && BitIsSet(registers, n))4625        return false;4626 4627      break;4628 4629    case eEncodingA1:4630      // n = UInt(Rn); registers = register_list; wback = (W == '1');4631      n = Bits32(opcode, 19, 16);4632      registers = Bits32(opcode, 15, 0);4633      wback = BitIsSet(opcode, 21);4634 4635      // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4636      if ((n == 15) || (BitCount(registers) < 1))4637        return false;4638 4639      break;4640 4641    default:4642      return false;4643    }4644 4645    // address = R[n];4646    int32_t offset = 0;4647    const addr_t address =4648        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);4649    if (!success)4650      return false;4651 4652    EmulateInstruction::Context context;4653    context.type = EmulateInstruction::eContextRegisterStore;4654    std::optional<RegisterInfo> base_reg =4655        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);4656 4657    // for i = 0 to 144658    uint32_t lowest_set_bit = 14;4659    for (uint32_t i = 0; i < 14; ++i) {4660      // if registers<i> == '1' then4661      if (BitIsSet(registers, i)) {4662        if (i < lowest_set_bit)4663          lowest_set_bit = i;4664        // if i == n && wback && i != LowestSetBit(registers) then4665        if ((i == n) && wback && (i != lowest_set_bit))4666          // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings4667          // T1 and A14668          WriteBits32UnknownToMemory(address + offset);4669        else {4670          // MemA[address,4] = R[i];4671          uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,4672                                               0, &success);4673          if (!success)4674            return false;4675 4676          std::optional<RegisterInfo> data_reg =4677              GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);4678          context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);4679          if (!MemAWrite(context, address + offset, data, addr_byte_size))4680            return false;4681        }4682 4683        // address = address + 4;4684        offset += addr_byte_size;4685      }4686    }4687 4688    // if registers<15> == '1' then // Only possible for encoding A14689    //     MemA[address,4] = PCStoreValue();4690    if (BitIsSet(registers, 15)) {4691      std::optional<RegisterInfo> pc_reg =4692          GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);4693      context.SetRegisterPlusOffset(*pc_reg, 8);4694      const uint32_t pc = ReadCoreReg(PC_REG, &success);4695      if (!success)4696        return false;4697 4698      if (!MemAWrite(context, address + offset, pc, addr_byte_size))4699        return false;4700    }4701 4702    // if wback then R[n] = R[n] + 4*BitCount(registers);4703    if (wback) {4704      offset = addr_byte_size * BitCount(registers);4705      context.type = EmulateInstruction::eContextAdjustBaseRegister;4706      context.SetImmediateSigned(offset);4707      addr_t data = address + offset;4708      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4709                                 data))4710        return false;4711    }4712  }4713  return true;4714}4715 4716// STMDA (Store Multiple Decrement After) stores multiple registers to4717// consecutive memory locations using an address from a base register.  The4718// consecutive memory locations end at this address, and the address just below4719// the lowest of those locations can optionally be written back to the base4720// register.4721bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode,4722                                         const ARMEncoding encoding) {4723#if 04724    if ConditionPassed() then 4725        EncodingSpecificOperations();                   4726        address = R[n] - 4*BitCount(registers) + 4;4727                  4728        for i = 0 to 14 4729            if registers<i> == '1' then4730                if i == n && wback && i != LowestSetBit(registers) then 4731                    MemA[address,4] = bits(32) UNKNOWN;4732                else 4733                    MemA[address,4] = R[i];4734                address = address + 4;4735                  4736        if registers<15> == '1' then 4737            MemA[address,4] = PCStoreValue();4738                  4739        if wback then R[n] = R[n] - 4*BitCount(registers);4740#endif4741 4742  bool success = false;4743 4744  if (ConditionPassed(opcode)) {4745    uint32_t n;4746    uint32_t registers = 0;4747    bool wback;4748    const uint32_t addr_byte_size = GetAddressByteSize();4749 4750    // EncodingSpecificOperations();4751    switch (encoding) {4752    case eEncodingA1:4753      // n = UInt(Rn); registers = register_list; wback = (W == '1');4754      n = Bits32(opcode, 19, 16);4755      registers = Bits32(opcode, 15, 0);4756      wback = BitIsSet(opcode, 21);4757 4758      // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4759      if ((n == 15) || (BitCount(registers) < 1))4760        return false;4761      break;4762    default:4763      return false;4764    }4765 4766    // address = R[n] - 4*BitCount(registers) + 4;4767    int32_t offset = 0;4768    addr_t Rn = ReadCoreReg(n, &success);4769    if (!success)4770      return false;4771 4772    addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4;4773 4774    EmulateInstruction::Context context;4775    context.type = EmulateInstruction::eContextRegisterStore;4776    std::optional<RegisterInfo> base_reg =4777        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);4778 4779    // for i = 0 to 144780    uint32_t lowest_bit_set = 14;4781    for (uint32_t i = 0; i < 14; ++i) {4782      // if registers<i> == '1' then4783      if (BitIsSet(registers, i)) {4784        if (i < lowest_bit_set)4785          lowest_bit_set = i;4786        // if i == n && wback && i != LowestSetBit(registers) then4787        if ((i == n) && wback && (i != lowest_bit_set))4788          // MemA[address,4] = bits(32) UNKNOWN;4789          WriteBits32UnknownToMemory(address + offset);4790        else {4791          // MemA[address,4] = R[i];4792          uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,4793                                               0, &success);4794          if (!success)4795            return false;4796 4797          std::optional<RegisterInfo> data_reg =4798              GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);4799          context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,4800                                                  Rn - (address + offset));4801          if (!MemAWrite(context, address + offset, data, addr_byte_size))4802            return false;4803        }4804 4805        // address = address + 4;4806        offset += addr_byte_size;4807      }4808    }4809 4810    // if registers<15> == '1' then4811    //    MemA[address,4] = PCStoreValue();4812    if (BitIsSet(registers, 15)) {4813      std::optional<RegisterInfo> pc_reg =4814          GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);4815      context.SetRegisterPlusOffset(*pc_reg, 8);4816      const uint32_t pc = ReadCoreReg(PC_REG, &success);4817      if (!success)4818        return false;4819 4820      if (!MemAWrite(context, address + offset, pc, addr_byte_size))4821        return false;4822    }4823 4824    // if wback then R[n] = R[n] - 4*BitCount(registers);4825    if (wback) {4826      offset = (addr_byte_size * BitCount(registers)) * -1;4827      context.type = EmulateInstruction::eContextAdjustBaseRegister;4828      context.SetImmediateSigned(offset);4829      addr_t data = Rn + offset;4830      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4831                                 data))4832        return false;4833    }4834  }4835  return true;4836}4837 4838// STMDB (Store Multiple Decrement Before) stores multiple registers to4839// consecutive memory locations using an address from a base register.  The4840// consecutive memory locations end just below this address, and the address of4841// the first of those locations can optionally be written back to the base4842// register.4843bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode,4844                                         const ARMEncoding encoding) {4845#if 04846    if ConditionPassed() then 4847        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4848        address = R[n] - 4*BitCount(registers);4849                  4850        for i = 0 to 14 4851            if registers<i> == '1' then4852                if i == n && wback && i != LowestSetBit(registers) then 4853                    MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A14854                else 4855                    MemA[address,4] = R[i];4856                address = address + 4;4857                  4858        if registers<15> == '1' then // Only possible for encoding A1 4859            MemA[address,4] = PCStoreValue();4860                  4861        if wback then R[n] = R[n] - 4*BitCount(registers);4862#endif4863 4864  bool success = false;4865 4866  if (ConditionPassed(opcode)) {4867    uint32_t n;4868    uint32_t registers = 0;4869    bool wback;4870    const uint32_t addr_byte_size = GetAddressByteSize();4871 4872    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);4873    switch (encoding) {4874    case eEncodingT1:4875      // if W == '1' && Rn == '1101' then SEE PUSH;4876      if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) {4877        // See PUSH4878      }4879      // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');4880      n = Bits32(opcode, 19, 16);4881      registers = Bits32(opcode, 15, 0);4882      registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.4883      wback = BitIsSet(opcode, 21);4884      // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;4885      if ((n == 15) || BitCount(registers) < 2)4886        return false;4887      // if wback && registers<n> == '1' then UNPREDICTABLE;4888      if (wback && BitIsSet(registers, n))4889        return false;4890      break;4891 4892    case eEncodingA1:4893      // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE4894      // PUSH;4895      if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) &&4896          BitCount(Bits32(opcode, 15, 0)) >= 2) {4897        // See Push4898      }4899      // n = UInt(Rn); registers = register_list; wback = (W == '1');4900      n = Bits32(opcode, 19, 16);4901      registers = Bits32(opcode, 15, 0);4902      wback = BitIsSet(opcode, 21);4903      // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;4904      if ((n == 15) || BitCount(registers) < 1)4905        return false;4906      break;4907 4908    default:4909      return false;4910    }4911 4912    // address = R[n] - 4*BitCount(registers);4913 4914    int32_t offset = 0;4915    addr_t Rn =4916        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);4917    if (!success)4918      return false;4919 4920    addr_t address = Rn - (addr_byte_size * BitCount(registers));4921 4922    EmulateInstruction::Context context;4923    context.type = EmulateInstruction::eContextRegisterStore;4924    std::optional<RegisterInfo> base_reg =4925        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);4926 4927    // for i = 0 to 144928    uint32_t lowest_set_bit = 14;4929    for (uint32_t i = 0; i < 14; ++i) {4930      // if registers<i> == '1' then4931      if (BitIsSet(registers, i)) {4932        if (i < lowest_set_bit)4933          lowest_set_bit = i;4934        // if i == n && wback && i != LowestSetBit(registers) then4935        if ((i == n) && wback && (i != lowest_set_bit))4936          // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding4937          // A14938          WriteBits32UnknownToMemory(address + offset);4939        else {4940          // MemA[address,4] = R[i];4941          uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,4942                                               0, &success);4943          if (!success)4944            return false;4945 4946          std::optional<RegisterInfo> data_reg =4947              GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);4948          context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,4949                                                  Rn - (address + offset));4950          if (!MemAWrite(context, address + offset, data, addr_byte_size))4951            return false;4952        }4953 4954        // address = address + 4;4955        offset += addr_byte_size;4956      }4957    }4958 4959    // if registers<15> == '1' then // Only possible for encoding A14960    //     MemA[address,4] = PCStoreValue();4961    if (BitIsSet(registers, 15)) {4962      std::optional<RegisterInfo> pc_reg =4963          GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);4964      context.SetRegisterPlusOffset(*pc_reg, 8);4965      const uint32_t pc = ReadCoreReg(PC_REG, &success);4966      if (!success)4967        return false;4968 4969      if (!MemAWrite(context, address + offset, pc, addr_byte_size))4970        return false;4971    }4972 4973    // if wback then R[n] = R[n] - 4*BitCount(registers);4974    if (wback) {4975      offset = (addr_byte_size * BitCount(registers)) * -1;4976      context.type = EmulateInstruction::eContextAdjustBaseRegister;4977      context.SetImmediateSigned(offset);4978      addr_t data = Rn + offset;4979      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,4980                                 data))4981        return false;4982    }4983  }4984  return true;4985}4986 4987// STMIB (Store Multiple Increment Before) stores multiple registers to4988// consecutive memory locations using an address from a base register.  The4989// consecutive memory locations start just above this address, and the address4990// of the last of those locations can optionally be written back to the base4991// register.4992bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode,4993                                         const ARMEncoding encoding) {4994#if 04995    if ConditionPassed() then 4996        EncodingSpecificOperations(); 4997        address = R[n] + 4;4998                  4999        for i = 0 to 14 5000            if registers<i> == '1' then5001                if i == n && wback && i != LowestSetBit(registers) then5002                    MemA[address,4] = bits(32) UNKNOWN;5003                else 5004                    MemA[address,4] = R[i];5005                address = address + 4;5006                  5007        if registers<15> == '1' then 5008            MemA[address,4] = PCStoreValue();5009                  5010        if wback then R[n] = R[n] + 4*BitCount(registers);5011#endif5012 5013  bool success = false;5014 5015  if (ConditionPassed(opcode)) {5016    uint32_t n;5017    uint32_t registers = 0;5018    bool wback;5019    const uint32_t addr_byte_size = GetAddressByteSize();5020 5021    // EncodingSpecificOperations();5022    switch (encoding) {5023    case eEncodingA1:5024      // n = UInt(Rn); registers = register_list; wback = (W == '1');5025      n = Bits32(opcode, 19, 16);5026      registers = Bits32(opcode, 15, 0);5027      wback = BitIsSet(opcode, 21);5028 5029      // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;5030      if ((n == 15) && (BitCount(registers) < 1))5031        return false;5032      break;5033    default:5034      return false;5035    }5036    // address = R[n] + 4;5037 5038    int32_t offset = 0;5039    addr_t Rn = ReadCoreReg(n, &success);5040    if (!success)5041      return false;5042 5043    addr_t address = Rn + addr_byte_size;5044 5045    EmulateInstruction::Context context;5046    context.type = EmulateInstruction::eContextRegisterStore;5047    std::optional<RegisterInfo> base_reg =5048        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);5049 5050    uint32_t lowest_set_bit = 14;5051    // for i = 0 to 145052    for (uint32_t i = 0; i < 14; ++i) {5053      // if registers<i> == '1' then5054      if (BitIsSet(registers, i)) {5055        if (i < lowest_set_bit)5056          lowest_set_bit = i;5057        // if i == n && wback && i != LowestSetBit(registers) then5058        if ((i == n) && wback && (i != lowest_set_bit))5059          // MemA[address,4] = bits(32) UNKNOWN;5060          WriteBits32UnknownToMemory(address + offset);5061        // else5062        else {5063          // MemA[address,4] = R[i];5064          uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i,5065                                               0, &success);5066          if (!success)5067            return false;5068 5069          std::optional<RegisterInfo> data_reg =5070              GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i);5071          context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,5072                                                  offset + addr_byte_size);5073          if (!MemAWrite(context, address + offset, data, addr_byte_size))5074            return false;5075        }5076 5077        // address = address + 4;5078        offset += addr_byte_size;5079      }5080    }5081 5082    // if registers<15> == '1' then5083    // MemA[address,4] = PCStoreValue();5084    if (BitIsSet(registers, 15)) {5085      std::optional<RegisterInfo> pc_reg =5086          GetRegisterInfo(eRegisterKindDWARF, dwarf_pc);5087      context.SetRegisterPlusOffset(*pc_reg, 8);5088      const uint32_t pc = ReadCoreReg(PC_REG, &success);5089      if (!success)5090        return false;5091 5092      if (!MemAWrite(context, address + offset, pc, addr_byte_size))5093        return false;5094    }5095 5096    // if wback then R[n] = R[n] + 4*BitCount(registers);5097    if (wback) {5098      offset = addr_byte_size * BitCount(registers);5099      context.type = EmulateInstruction::eContextAdjustBaseRegister;5100      context.SetImmediateSigned(offset);5101      addr_t data = Rn + offset;5102      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,5103                                 data))5104        return false;5105    }5106  }5107  return true;5108}5109 5110// STR (store immediate) calculates an address from a base register value and an5111// immediate offset, and stores a word5112// from a register to memory.  It can use offset, post-indexed, or pre-indexed5113// addressing.5114bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode,5115                                            const ARMEncoding encoding) {5116#if 05117    if ConditionPassed() then 5118        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5119        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5120        address = if index then offset_addr else R[n]; 5121        if UnalignedSupport() || address<1:0> == '00' then5122            MemU[address,4] = R[t]; 5123        else // Can only occur before ARMv75124            MemU[address,4] = bits(32) UNKNOWN; 5125        if wback then R[n] = offset_addr;5126#endif5127 5128  bool success = false;5129 5130  if (ConditionPassed(opcode)) {5131    const uint32_t addr_byte_size = GetAddressByteSize();5132 5133    uint32_t t;5134    uint32_t n;5135    uint32_t imm32;5136    bool index;5137    bool add;5138    bool wback;5139    // EncodingSpecificOperations (); NullCheckIfThumbEE(n);5140    switch (encoding) {5141    case eEncodingT1:5142      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);5143      t = Bits32(opcode, 2, 0);5144      n = Bits32(opcode, 5, 3);5145      imm32 = Bits32(opcode, 10, 6) << 2;5146 5147      // index = TRUE; add = TRUE; wback = FALSE;5148      index = true;5149      add = false;5150      wback = false;5151      break;5152 5153    case eEncodingT2:5154      // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);5155      t = Bits32(opcode, 10, 8);5156      n = 13;5157      imm32 = Bits32(opcode, 7, 0) << 2;5158 5159      // index = TRUE; add = TRUE; wback = FALSE;5160      index = true;5161      add = true;5162      wback = false;5163      break;5164 5165    case eEncodingT3:5166      // if Rn == '1111' then UNDEFINED;5167      if (Bits32(opcode, 19, 16) == 15)5168        return false;5169 5170      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);5171      t = Bits32(opcode, 15, 12);5172      n = Bits32(opcode, 19, 16);5173      imm32 = Bits32(opcode, 11, 0);5174 5175      // index = TRUE; add = TRUE; wback = FALSE;5176      index = true;5177      add = true;5178      wback = false;5179 5180      // if t == 15 then UNPREDICTABLE;5181      if (t == 15)5182        return false;5183      break;5184 5185    case eEncodingT4:5186      // if P == '1' && U == '1' && W == '0' then SEE STRT;5187      // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 ==5188      // '00000100' then SEE PUSH;5189      // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;5190      if ((Bits32(opcode, 19, 16) == 15) ||5191          (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)))5192        return false;5193 5194      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);5195      t = Bits32(opcode, 15, 12);5196      n = Bits32(opcode, 19, 16);5197      imm32 = Bits32(opcode, 7, 0);5198 5199      // index = (P == '1'); add = (U == '1'); wback = (W == '1');5200      index = BitIsSet(opcode, 10);5201      add = BitIsSet(opcode, 9);5202      wback = BitIsSet(opcode, 8);5203 5204      // if t == 15 || (wback && n == t) then UNPREDICTABLE;5205      if ((t == 15) || (wback && (n == t)))5206        return false;5207      break;5208 5209    default:5210      return false;5211    }5212 5213    addr_t offset_addr;5214    addr_t address;5215 5216    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);5217    uint32_t base_address = ReadCoreReg(n, &success);5218    if (!success)5219      return false;5220 5221    if (add)5222      offset_addr = base_address + imm32;5223    else5224      offset_addr = base_address - imm32;5225 5226    // address = if index then offset_addr else R[n];5227    if (index)5228      address = offset_addr;5229    else5230      address = base_address;5231 5232    EmulateInstruction::Context context;5233    if (n == 13)5234      context.type = eContextPushRegisterOnStack;5235    else5236      context.type = eContextRegisterStore;5237 5238    std::optional<RegisterInfo> base_reg =5239        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);5240 5241    // if UnalignedSupport() || address<1:0> == '00' then5242    if (UnalignedSupport() ||5243        (BitIsClear(address, 1) && BitIsClear(address, 0))) {5244      // MemU[address,4] = R[t];5245      uint32_t data =5246          ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);5247      if (!success)5248        return false;5249 5250      std::optional<RegisterInfo> data_reg =5251          GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);5252      int32_t offset = address - base_address;5253      context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset);5254      if (!MemUWrite(context, address, data, addr_byte_size))5255        return false;5256    } else {5257      // MemU[address,4] = bits(32) UNKNOWN;5258      WriteBits32UnknownToMemory(address);5259    }5260 5261    // if wback then R[n] = offset_addr;5262    if (wback) {5263      if (n == 13)5264        context.type = eContextAdjustStackPointer;5265      else5266        context.type = eContextAdjustBaseRegister;5267      context.SetAddress(offset_addr);5268 5269      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,5270                                 offset_addr))5271        return false;5272    }5273  }5274  return true;5275}5276 5277// STR (Store Register) calculates an address from a base register value and an5278// offset register value, stores a5279// word from a register to memory.   The offset register value can optionally5280// be shifted.5281bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode,5282                                               const ARMEncoding encoding) {5283#if 05284    if ConditionPassed() then 5285        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5286        offset = Shift(R[m], shift_t, shift_n, APSR.C); 5287        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5288        address = if index then offset_addr else R[n]; 5289        if t == 15 then // Only possible for encoding A15290            data = PCStoreValue(); 5291        else5292            data = R[t]; 5293        if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then5294            MemU[address,4] = data; 5295        else // Can only occur before ARMv75296            MemU[address,4] = bits(32) UNKNOWN; 5297        if wback then R[n] = offset_addr;5298#endif5299 5300  bool success = false;5301 5302  if (ConditionPassed(opcode)) {5303    const uint32_t addr_byte_size = GetAddressByteSize();5304 5305    uint32_t t;5306    uint32_t n;5307    uint32_t m;5308    ARM_ShifterType shift_t;5309    uint32_t shift_n;5310    bool index;5311    bool add;5312    bool wback;5313 5314    // EncodingSpecificOperations (); NullCheckIfThumbEE(n);5315    switch (encoding) {5316    case eEncodingT1:5317      // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation5318      // in ThumbEE";5319      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5320      t = Bits32(opcode, 2, 0);5321      n = Bits32(opcode, 5, 3);5322      m = Bits32(opcode, 8, 6);5323 5324      // index = TRUE; add = TRUE; wback = FALSE;5325      index = true;5326      add = true;5327      wback = false;5328 5329      // (shift_t, shift_n) = (SRType_LSL, 0);5330      shift_t = SRType_LSL;5331      shift_n = 0;5332      break;5333 5334    case eEncodingT2:5335      // if Rn == '1111' then UNDEFINED;5336      if (Bits32(opcode, 19, 16) == 15)5337        return false;5338 5339      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5340      t = Bits32(opcode, 15, 12);5341      n = Bits32(opcode, 19, 16);5342      m = Bits32(opcode, 3, 0);5343 5344      // index = TRUE; add = TRUE; wback = FALSE;5345      index = true;5346      add = true;5347      wback = false;5348 5349      // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));5350      shift_t = SRType_LSL;5351      shift_n = Bits32(opcode, 5, 4);5352 5353      // if t == 15 || BadReg(m) then UNPREDICTABLE;5354      if ((t == 15) || (BadReg(m)))5355        return false;5356      break;5357 5358    case eEncodingA1: {5359      // if P == '0' && W == '1' then SEE STRT;5360      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5361      t = Bits32(opcode, 15, 12);5362      n = Bits32(opcode, 19, 16);5363      m = Bits32(opcode, 3, 0);5364 5365      // index = (P == '1');     add = (U == '1');       wback = (P == '0') ||5366      // (W == '1');5367      index = BitIsSet(opcode, 24);5368      add = BitIsSet(opcode, 23);5369      wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));5370 5371      // (shift_t, shift_n) = DecodeImmShift(type, imm5);5372      uint32_t typ = Bits32(opcode, 6, 5);5373      uint32_t imm5 = Bits32(opcode, 11, 7);5374      shift_n = DecodeImmShift(typ, imm5, shift_t);5375 5376      // if m == 15 then UNPREDICTABLE;5377      if (m == 15)5378        return false;5379 5380      // if wback && (n == 15 || n == t) then UNPREDICTABLE;5381      if (wback && ((n == 15) || (n == t)))5382        return false;5383 5384      break;5385    }5386    default:5387      return false;5388    }5389 5390    addr_t offset_addr;5391    addr_t address;5392    int32_t offset = 0;5393 5394    addr_t base_address =5395        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);5396    if (!success)5397      return false;5398 5399    uint32_t Rm_data =5400        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);5401    if (!success)5402      return false;5403 5404    // offset = Shift(R[m], shift_t, shift_n, APSR.C);5405    offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success);5406    if (!success)5407      return false;5408 5409    // offset_addr = if add then (R[n] + offset) else (R[n] - offset);5410    if (add)5411      offset_addr = base_address + offset;5412    else5413      offset_addr = base_address - offset;5414 5415    // address = if index then offset_addr else R[n];5416    if (index)5417      address = offset_addr;5418    else5419      address = base_address;5420 5421    uint32_t data;5422    // if t == 15 then // Only possible for encoding A15423    if (t == 15)5424      // data = PCStoreValue();5425      data = ReadCoreReg(PC_REG, &success);5426    else5427      // data = R[t];5428      data =5429          ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);5430 5431    if (!success)5432      return false;5433 5434    EmulateInstruction::Context context;5435    context.type = eContextRegisterStore;5436 5437    // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() ==5438    // InstrSet_ARM then5439    if (UnalignedSupport() ||5440        (BitIsClear(address, 1) && BitIsClear(address, 0)) ||5441        CurrentInstrSet() == eModeARM) {5442      // MemU[address,4] = data;5443 5444      std::optional<RegisterInfo> base_reg =5445          GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);5446      std::optional<RegisterInfo> data_reg =5447          GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);5448 5449      context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,5450                                              address - base_address);5451      if (!MemUWrite(context, address, data, addr_byte_size))5452        return false;5453 5454    } else5455      // MemU[address,4] = bits(32) UNKNOWN;5456      WriteBits32UnknownToMemory(address);5457 5458    // if wback then R[n] = offset_addr;5459    if (wback) {5460      context.type = eContextRegisterLoad;5461      context.SetAddress(offset_addr);5462      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,5463                                 offset_addr))5464        return false;5465    }5466  }5467  return true;5468}5469 5470bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode,5471                                             const ARMEncoding encoding) {5472#if 05473    if ConditionPassed() then 5474        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5475        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5476        address = if index then offset_addr else R[n]; 5477        MemU[address,1] = R[t]<7:0>; 5478        if wback then R[n] = offset_addr;5479#endif5480 5481  bool success = false;5482 5483  if (ConditionPassed(opcode)) {5484    uint32_t t;5485    uint32_t n;5486    uint32_t imm32;5487    bool index;5488    bool add;5489    bool wback;5490    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);5491    switch (encoding) {5492    case eEncodingT1:5493      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);5494      t = Bits32(opcode, 2, 0);5495      n = Bits32(opcode, 5, 3);5496      imm32 = Bits32(opcode, 10, 6);5497 5498      // index = TRUE; add = TRUE; wback = FALSE;5499      index = true;5500      add = true;5501      wback = false;5502      break;5503 5504    case eEncodingT2:5505      // if Rn == '1111' then UNDEFINED;5506      if (Bits32(opcode, 19, 16) == 15)5507        return false;5508 5509      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);5510      t = Bits32(opcode, 15, 12);5511      n = Bits32(opcode, 19, 16);5512      imm32 = Bits32(opcode, 11, 0);5513 5514      // index = TRUE; add = TRUE; wback = FALSE;5515      index = true;5516      add = true;5517      wback = false;5518 5519      // if BadReg(t) then UNPREDICTABLE;5520      if (BadReg(t))5521        return false;5522      break;5523 5524    case eEncodingT3:5525      // if P == '1' && U == '1' && W == '0' then SEE STRBT;5526      // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;5527      if (Bits32(opcode, 19, 16) == 15)5528        return false;5529 5530      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);5531      t = Bits32(opcode, 15, 12);5532      n = Bits32(opcode, 19, 16);5533      imm32 = Bits32(opcode, 7, 0);5534 5535      // index = (P == '1'); add = (U == '1'); wback = (W == '1');5536      index = BitIsSet(opcode, 10);5537      add = BitIsSet(opcode, 9);5538      wback = BitIsSet(opcode, 8);5539 5540      // if BadReg(t) || (wback && n == t) then UNPREDICTABLE5541      if ((BadReg(t)) || (wback && (n == t)))5542        return false;5543      break;5544 5545    default:5546      return false;5547    }5548 5549    addr_t offset_addr;5550    addr_t address;5551    addr_t base_address =5552        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);5553    if (!success)5554      return false;5555 5556    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);5557    if (add)5558      offset_addr = base_address + imm32;5559    else5560      offset_addr = base_address - imm32;5561 5562    // address = if index then offset_addr else R[n];5563    if (index)5564      address = offset_addr;5565    else5566      address = base_address;5567 5568    // MemU[address,1] = R[t]<7:0>5569    std::optional<RegisterInfo> base_reg =5570        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);5571    std::optional<RegisterInfo> data_reg =5572        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);5573 5574    EmulateInstruction::Context context;5575    context.type = eContextRegisterStore;5576    context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,5577                                            address - base_address);5578 5579    uint32_t data =5580        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);5581    if (!success)5582      return false;5583 5584    data = Bits32(data, 7, 0);5585 5586    if (!MemUWrite(context, address, data, 1))5587      return false;5588 5589    // if wback then R[n] = offset_addr;5590    if (wback) {5591      context.type = eContextRegisterLoad;5592      context.SetAddress(offset_addr);5593      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,5594                                 offset_addr))5595        return false;5596    }5597  }5598 5599  return true;5600}5601 5602// STRH (register) calculates an address from a base register value and an5603// offset register value, and stores a5604// halfword from a register to memory.  The offset register value can be5605// shifted left by 0, 1, 2, or 3 bits.5606bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode,5607                                                const ARMEncoding encoding) {5608#if 05609    if ConditionPassed() then 5610        EncodingSpecificOperations(); NullCheckIfThumbEE(n);5611        offset = Shift(R[m], shift_t, shift_n, APSR.C); 5612        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5613        address = if index then offset_addr else R[n]; 5614        if UnalignedSupport() || address<0> == '0' then5615            MemU[address,2] = R[t]<15:0>; 5616        else // Can only occur before ARMv75617            MemU[address,2] = bits(16) UNKNOWN; 5618        if wback then R[n] = offset_addr;5619#endif5620 5621  bool success = false;5622 5623  if (ConditionPassed(opcode)) {5624    uint32_t t;5625    uint32_t n;5626    uint32_t m;5627    bool index;5628    bool add;5629    bool wback;5630    ARM_ShifterType shift_t;5631    uint32_t shift_n;5632 5633    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);5634    switch (encoding) {5635    case eEncodingT1:5636      // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation5637      // in ThumbEE";5638      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5639      t = Bits32(opcode, 2, 0);5640      n = Bits32(opcode, 5, 3);5641      m = Bits32(opcode, 8, 6);5642 5643      // index = TRUE; add = TRUE; wback = FALSE;5644      index = true;5645      add = true;5646      wback = false;5647 5648      // (shift_t, shift_n) = (SRType_LSL, 0);5649      shift_t = SRType_LSL;5650      shift_n = 0;5651 5652      break;5653 5654    case eEncodingT2:5655      // if Rn == '1111' then UNDEFINED;5656      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5657      t = Bits32(opcode, 15, 12);5658      n = Bits32(opcode, 19, 16);5659      m = Bits32(opcode, 3, 0);5660      if (n == 15)5661        return false;5662 5663      // index = TRUE; add = TRUE; wback = FALSE;5664      index = true;5665      add = true;5666      wback = false;5667 5668      // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));5669      shift_t = SRType_LSL;5670      shift_n = Bits32(opcode, 5, 4);5671 5672      // if BadReg(t) || BadReg(m) then UNPREDICTABLE;5673      if (BadReg(t) || BadReg(m))5674        return false;5675 5676      break;5677 5678    case eEncodingA1:5679      // if P == '0' && W == '1' then SEE STRHT;5680      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);5681      t = Bits32(opcode, 15, 12);5682      n = Bits32(opcode, 19, 16);5683      m = Bits32(opcode, 3, 0);5684 5685      // index = (P == '1');     add = (U == '1');       wback = (P == '0') ||5686      // (W == '1');5687      index = BitIsSet(opcode, 24);5688      add = BitIsSet(opcode, 23);5689      wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));5690 5691      // (shift_t, shift_n) = (SRType_LSL, 0);5692      shift_t = SRType_LSL;5693      shift_n = 0;5694 5695      // if t == 15 || m == 15 then UNPREDICTABLE;5696      if ((t == 15) || (m == 15))5697        return false;5698 5699      // if wback && (n == 15 || n == t) then UNPREDICTABLE;5700      if (wback && ((n == 15) || (n == t)))5701        return false;5702 5703      break;5704 5705    default:5706      return false;5707    }5708 5709    uint32_t Rm = ReadCoreReg(m, &success);5710    if (!success)5711      return false;5712 5713    uint32_t Rn = ReadCoreReg(n, &success);5714    if (!success)5715      return false;5716 5717    // offset = Shift(R[m], shift_t, shift_n, APSR.C);5718    uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);5719    if (!success)5720      return false;5721 5722    // offset_addr = if add then (R[n] + offset) else (R[n] - offset);5723    addr_t offset_addr;5724    if (add)5725      offset_addr = Rn + offset;5726    else5727      offset_addr = Rn - offset;5728 5729    // address = if index then offset_addr else R[n];5730    addr_t address;5731    if (index)5732      address = offset_addr;5733    else5734      address = Rn;5735 5736    EmulateInstruction::Context context;5737    context.type = eContextRegisterStore;5738 5739    // if UnalignedSupport() || address<0> == '0' then5740    if (UnalignedSupport() || BitIsClear(address, 0)) {5741      // MemU[address,2] = R[t]<15:0>;5742      uint32_t Rt = ReadCoreReg(t, &success);5743      if (!success)5744        return false;5745 5746      EmulateInstruction::Context context;5747      context.type = eContextRegisterStore;5748      std::optional<RegisterInfo> base_reg =5749          GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);5750      std::optional<RegisterInfo> offset_reg =5751          GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);5752      std::optional<RegisterInfo> data_reg =5753          GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);5754      context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,5755                                                      *data_reg);5756 5757      if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2))5758        return false;5759    } else // Can only occur before ARMv75760    {5761      // MemU[address,2] = bits(16) UNKNOWN;5762    }5763 5764    // if wback then R[n] = offset_addr;5765    if (wback) {5766      context.type = eContextAdjustBaseRegister;5767      context.SetAddress(offset_addr);5768      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,5769                                 offset_addr))5770        return false;5771    }5772  }5773 5774  return true;5775}5776 5777// Add with Carry (immediate) adds an immediate value and the carry flag value5778// to a register value, and writes the result to the destination register.  It5779// can optionally update the condition flags based on the result.5780bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode,5781                                          const ARMEncoding encoding) {5782#if 05783    // ARM pseudo code...5784    if ConditionPassed() then5785        EncodingSpecificOperations();5786        (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);5787        if d == 15 then         // Can only occur for ARM encoding5788            ALUWritePC(result); // setflags is always FALSE here5789        else5790            R[d] = result;5791            if setflags then5792                APSR.N = result<31>;5793                APSR.Z = IsZeroBit(result);5794                APSR.C = carry;5795                APSR.V = overflow;5796#endif5797 5798  bool success = false;5799 5800  if (ConditionPassed(opcode)) {5801    uint32_t Rd, Rn;5802    uint32_t5803        imm32; // the immediate value to be added to the value obtained from Rn5804    bool setflags;5805    switch (encoding) {5806    case eEncodingT1:5807      Rd = Bits32(opcode, 11, 8);5808      Rn = Bits32(opcode, 19, 16);5809      setflags = BitIsSet(opcode, 20);5810      imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)5811      if (BadReg(Rd) || BadReg(Rn))5812        return false;5813      break;5814    case eEncodingA1:5815      Rd = Bits32(opcode, 15, 12);5816      Rn = Bits32(opcode, 19, 16);5817      setflags = BitIsSet(opcode, 20);5818      imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)5819 5820      if (Rd == 15 && setflags)5821        return EmulateSUBSPcLrEtc(opcode, encoding);5822      break;5823    default:5824      return false;5825    }5826 5827    // Read the first operand.5828    int32_t val1 = ReadCoreReg(Rn, &success);5829    if (!success)5830      return false;5831 5832    AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);5833 5834    EmulateInstruction::Context context;5835    context.type = EmulateInstruction::eContextImmediate;5836    context.SetNoArgs();5837 5838    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,5839                                   res.carry_out, res.overflow))5840      return false;5841  }5842  return true;5843}5844 5845// Add with Carry (register) adds a register value, the carry flag value, and5846// an optionally-shifted register value, and writes the result to the5847// destination register.  It can optionally update the condition flags based on5848// the result.5849bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode,5850                                          const ARMEncoding encoding) {5851#if 05852    // ARM pseudo code...5853    if ConditionPassed() then5854        EncodingSpecificOperations();5855        shifted = Shift(R[m], shift_t, shift_n, APSR.C);5856        (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);5857        if d == 15 then         // Can only occur for ARM encoding5858            ALUWritePC(result); // setflags is always FALSE here5859        else5860            R[d] = result;5861            if setflags then5862                APSR.N = result<31>;5863                APSR.Z = IsZeroBit(result);5864                APSR.C = carry;5865                APSR.V = overflow;5866#endif5867 5868  bool success = false;5869 5870  if (ConditionPassed(opcode)) {5871    uint32_t Rd, Rn, Rm;5872    ARM_ShifterType shift_t;5873    uint32_t shift_n; // the shift applied to the value read from Rm5874    bool setflags;5875    switch (encoding) {5876    case eEncodingT1:5877      Rd = Rn = Bits32(opcode, 2, 0);5878      Rm = Bits32(opcode, 5, 3);5879      setflags = !InITBlock();5880      shift_t = SRType_LSL;5881      shift_n = 0;5882      break;5883    case eEncodingT2:5884      Rd = Bits32(opcode, 11, 8);5885      Rn = Bits32(opcode, 19, 16);5886      Rm = Bits32(opcode, 3, 0);5887      setflags = BitIsSet(opcode, 20);5888      shift_n = DecodeImmShiftThumb(opcode, shift_t);5889      if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))5890        return false;5891      break;5892    case eEncodingA1:5893      Rd = Bits32(opcode, 15, 12);5894      Rn = Bits32(opcode, 19, 16);5895      Rm = Bits32(opcode, 3, 0);5896      setflags = BitIsSet(opcode, 20);5897      shift_n = DecodeImmShiftARM(opcode, shift_t);5898 5899      if (Rd == 15 && setflags)5900        return EmulateSUBSPcLrEtc(opcode, encoding);5901      break;5902    default:5903      return false;5904    }5905 5906    // Read the first operand.5907    int32_t val1 = ReadCoreReg(Rn, &success);5908    if (!success)5909      return false;5910 5911    // Read the second operand.5912    int32_t val2 = ReadCoreReg(Rm, &success);5913    if (!success)5914      return false;5915 5916    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);5917    if (!success)5918      return false;5919    AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);5920 5921    EmulateInstruction::Context context;5922    context.type = EmulateInstruction::eContextImmediate;5923    context.SetNoArgs();5924 5925    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,5926                                   res.carry_out, res.overflow))5927      return false;5928  }5929  return true;5930}5931 5932// This instruction adds an immediate value to the PC value to form a PC-5933// relative address, and writes the result to the destination register.5934bool EmulateInstructionARM::EmulateADR(const uint32_t opcode,5935                                       const ARMEncoding encoding) {5936#if 05937    // ARM pseudo code...5938    if ConditionPassed() then5939        EncodingSpecificOperations();5940        result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);5941        if d == 15 then         // Can only occur for ARM encodings5942            ALUWritePC(result);5943        else5944            R[d] = result;5945#endif5946 5947  bool success = false;5948 5949  if (ConditionPassed(opcode)) {5950    uint32_t Rd;5951    uint32_t imm32; // the immediate value to be added/subtracted to/from the PC5952    bool add;5953    switch (encoding) {5954    case eEncodingT1:5955      Rd = Bits32(opcode, 10, 8);5956      imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)5957      add = true;5958      break;5959    case eEncodingT2:5960    case eEncodingT3:5961      Rd = Bits32(opcode, 11, 8);5962      imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)5963      add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB5964      if (BadReg(Rd))5965        return false;5966      break;5967    case eEncodingA1:5968    case eEncodingA2:5969      Rd = Bits32(opcode, 15, 12);5970      imm32 = ARMExpandImm(opcode);          // imm32 = ARMExpandImm(imm12)5971      add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB5972      break;5973    default:5974      return false;5975    }5976 5977    // Read the PC value.5978    uint32_t pc = ReadCoreReg(PC_REG, &success);5979    if (!success)5980      return false;5981 5982    uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);5983 5984    EmulateInstruction::Context context;5985    context.type = EmulateInstruction::eContextImmediate;5986    context.SetNoArgs();5987 5988    if (!WriteCoreReg(context, result, Rd))5989      return false;5990  }5991  return true;5992}5993 5994// This instruction performs a bitwise AND of a register value and an immediate5995// value, and writes the result to the destination register.  It can optionally5996// update the condition flags based on the result.5997bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode,5998                                          const ARMEncoding encoding) {5999#if 06000    // ARM pseudo code...6001    if ConditionPassed() then6002        EncodingSpecificOperations();6003        result = R[n] AND imm32;6004        if d == 15 then         // Can only occur for ARM encoding6005            ALUWritePC(result); // setflags is always FALSE here6006        else6007            R[d] = result;6008            if setflags then6009                APSR.N = result<31>;6010                APSR.Z = IsZeroBit(result);6011                APSR.C = carry;6012                // APSR.V unchanged6013#endif6014 6015  bool success = false;6016 6017  if (ConditionPassed(opcode)) {6018    uint32_t Rd, Rn;6019    uint32_t6020        imm32; // the immediate value to be ANDed to the value obtained from Rn6021    bool setflags;6022    uint32_t carry; // the carry bit after ARM/Thumb Expand operation6023    switch (encoding) {6024    case eEncodingT1:6025      Rd = Bits32(opcode, 11, 8);6026      Rn = Bits32(opcode, 19, 16);6027      setflags = BitIsSet(opcode, 20);6028      imm32 = ThumbExpandImm_C(6029          opcode, APSR_C,6030          carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)6031      // if Rd == '1111' && S == '1' then SEE TST (immediate);6032      if (Rd == 15 && setflags)6033        return EmulateTSTImm(opcode, eEncodingT1);6034      if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))6035        return false;6036      break;6037    case eEncodingA1:6038      Rd = Bits32(opcode, 15, 12);6039      Rn = Bits32(opcode, 19, 16);6040      setflags = BitIsSet(opcode, 20);6041      imm32 =6042          ARMExpandImm_C(opcode, APSR_C,6043                         carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)6044 6045      if (Rd == 15 && setflags)6046        return EmulateSUBSPcLrEtc(opcode, encoding);6047      break;6048    default:6049      return false;6050    }6051 6052    // Read the first operand.6053    uint32_t val1 = ReadCoreReg(Rn, &success);6054    if (!success)6055      return false;6056 6057    uint32_t result = val1 & imm32;6058 6059    EmulateInstruction::Context context;6060    context.type = EmulateInstruction::eContextImmediate;6061    context.SetNoArgs();6062 6063    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))6064      return false;6065  }6066  return true;6067}6068 6069// This instruction performs a bitwise AND of a register value and an6070// optionally-shifted register value, and writes the result to the destination6071// register.  It can optionally update the condition flags based on the result.6072bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode,6073                                          const ARMEncoding encoding) {6074#if 06075    // ARM pseudo code...6076    if ConditionPassed() then6077        EncodingSpecificOperations();6078        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);6079        result = R[n] AND shifted;6080        if d == 15 then         // Can only occur for ARM encoding6081            ALUWritePC(result); // setflags is always FALSE here6082        else6083            R[d] = result;6084            if setflags then6085                APSR.N = result<31>;6086                APSR.Z = IsZeroBit(result);6087                APSR.C = carry;6088                // APSR.V unchanged6089#endif6090 6091  bool success = false;6092 6093  if (ConditionPassed(opcode)) {6094    uint32_t Rd, Rn, Rm;6095    ARM_ShifterType shift_t;6096    uint32_t shift_n; // the shift applied to the value read from Rm6097    bool setflags;6098    uint32_t carry;6099    switch (encoding) {6100    case eEncodingT1:6101      Rd = Rn = Bits32(opcode, 2, 0);6102      Rm = Bits32(opcode, 5, 3);6103      setflags = !InITBlock();6104      shift_t = SRType_LSL;6105      shift_n = 0;6106      break;6107    case eEncodingT2:6108      Rd = Bits32(opcode, 11, 8);6109      Rn = Bits32(opcode, 19, 16);6110      Rm = Bits32(opcode, 3, 0);6111      setflags = BitIsSet(opcode, 20);6112      shift_n = DecodeImmShiftThumb(opcode, shift_t);6113      // if Rd == '1111' && S == '1' then SEE TST (register);6114      if (Rd == 15 && setflags)6115        return EmulateTSTReg(opcode, eEncodingT2);6116      if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))6117        return false;6118      break;6119    case eEncodingA1:6120      Rd = Bits32(opcode, 15, 12);6121      Rn = Bits32(opcode, 19, 16);6122      Rm = Bits32(opcode, 3, 0);6123      setflags = BitIsSet(opcode, 20);6124      shift_n = DecodeImmShiftARM(opcode, shift_t);6125 6126      if (Rd == 15 && setflags)6127        return EmulateSUBSPcLrEtc(opcode, encoding);6128      break;6129    default:6130      return false;6131    }6132 6133    // Read the first operand.6134    uint32_t val1 = ReadCoreReg(Rn, &success);6135    if (!success)6136      return false;6137 6138    // Read the second operand.6139    uint32_t val2 = ReadCoreReg(Rm, &success);6140    if (!success)6141      return false;6142 6143    uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);6144    if (!success)6145      return false;6146    uint32_t result = val1 & shifted;6147 6148    EmulateInstruction::Context context;6149    context.type = EmulateInstruction::eContextImmediate;6150    context.SetNoArgs();6151 6152    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))6153      return false;6154  }6155  return true;6156}6157 6158// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and6159// the complement of an immediate value, and writes the result to the6160// destination register.  It can optionally update the condition flags based on6161// the result.6162bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode,6163                                          const ARMEncoding encoding) {6164#if 06165    // ARM pseudo code...6166    if ConditionPassed() then6167        EncodingSpecificOperations();6168        result = R[n] AND NOT(imm32);6169        if d == 15 then         // Can only occur for ARM encoding6170            ALUWritePC(result); // setflags is always FALSE here6171        else6172            R[d] = result;6173            if setflags then6174                APSR.N = result<31>;6175                APSR.Z = IsZeroBit(result);6176                APSR.C = carry;6177                // APSR.V unchanged6178#endif6179 6180  bool success = false;6181 6182  if (ConditionPassed(opcode)) {6183    uint32_t Rd, Rn;6184    uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to6185                    // the value obtained from Rn6186    bool setflags;6187    uint32_t carry; // the carry bit after ARM/Thumb Expand operation6188    switch (encoding) {6189    case eEncodingT1:6190      Rd = Bits32(opcode, 11, 8);6191      Rn = Bits32(opcode, 19, 16);6192      setflags = BitIsSet(opcode, 20);6193      imm32 = ThumbExpandImm_C(6194          opcode, APSR_C,6195          carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)6196      if (BadReg(Rd) || BadReg(Rn))6197        return false;6198      break;6199    case eEncodingA1:6200      Rd = Bits32(opcode, 15, 12);6201      Rn = Bits32(opcode, 19, 16);6202      setflags = BitIsSet(opcode, 20);6203      imm32 =6204          ARMExpandImm_C(opcode, APSR_C,6205                         carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)6206 6207      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related6208      // instructions;6209      if (Rd == 15 && setflags)6210        return EmulateSUBSPcLrEtc(opcode, encoding);6211      break;6212    default:6213      return false;6214    }6215 6216    // Read the first operand.6217    uint32_t val1 = ReadCoreReg(Rn, &success);6218    if (!success)6219      return false;6220 6221    uint32_t result = val1 & ~imm32;6222 6223    EmulateInstruction::Context context;6224    context.type = EmulateInstruction::eContextImmediate;6225    context.SetNoArgs();6226 6227    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))6228      return false;6229  }6230  return true;6231}6232 6233// Bitwise Bit Clear (register) performs a bitwise AND of a register value and6234// the complement of an optionally-shifted register value, and writes the6235// result to the destination register. It can optionally update the condition6236// flags based on the result.6237bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode,6238                                          const ARMEncoding encoding) {6239#if 06240    // ARM pseudo code...6241    if ConditionPassed() then6242        EncodingSpecificOperations();6243        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);6244        result = R[n] AND NOT(shifted);6245        if d == 15 then         // Can only occur for ARM encoding6246            ALUWritePC(result); // setflags is always FALSE here6247        else6248            R[d] = result;6249            if setflags then6250                APSR.N = result<31>;6251                APSR.Z = IsZeroBit(result);6252                APSR.C = carry;6253                // APSR.V unchanged6254#endif6255 6256  bool success = false;6257 6258  if (ConditionPassed(opcode)) {6259    uint32_t Rd, Rn, Rm;6260    ARM_ShifterType shift_t;6261    uint32_t shift_n; // the shift applied to the value read from Rm6262    bool setflags;6263    uint32_t carry;6264    switch (encoding) {6265    case eEncodingT1:6266      Rd = Rn = Bits32(opcode, 2, 0);6267      Rm = Bits32(opcode, 5, 3);6268      setflags = !InITBlock();6269      shift_t = SRType_LSL;6270      shift_n = 0;6271      break;6272    case eEncodingT2:6273      Rd = Bits32(opcode, 11, 8);6274      Rn = Bits32(opcode, 19, 16);6275      Rm = Bits32(opcode, 3, 0);6276      setflags = BitIsSet(opcode, 20);6277      shift_n = DecodeImmShiftThumb(opcode, shift_t);6278      if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))6279        return false;6280      break;6281    case eEncodingA1:6282      Rd = Bits32(opcode, 15, 12);6283      Rn = Bits32(opcode, 19, 16);6284      Rm = Bits32(opcode, 3, 0);6285      setflags = BitIsSet(opcode, 20);6286      shift_n = DecodeImmShiftARM(opcode, shift_t);6287 6288      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related6289      // instructions;6290      if (Rd == 15 && setflags)6291        return EmulateSUBSPcLrEtc(opcode, encoding);6292      break;6293    default:6294      return false;6295    }6296 6297    // Read the first operand.6298    uint32_t val1 = ReadCoreReg(Rn, &success);6299    if (!success)6300      return false;6301 6302    // Read the second operand.6303    uint32_t val2 = ReadCoreReg(Rm, &success);6304    if (!success)6305      return false;6306 6307    uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);6308    if (!success)6309      return false;6310    uint32_t result = val1 & ~shifted;6311 6312    EmulateInstruction::Context context;6313    context.type = EmulateInstruction::eContextImmediate;6314    context.SetNoArgs();6315 6316    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))6317      return false;6318  }6319  return true;6320}6321 6322// LDR (immediate, ARM) calculates an address from a base register value and an6323// immediate offset, loads a word6324// from memory, and writes it to a register.  It can use offset, post-indexed,6325// or pre-indexed addressing.6326bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode,6327                                                   const ARMEncoding encoding) {6328#if 06329    if ConditionPassed() then 6330        EncodingSpecificOperations(); 6331        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6332        address = if index then offset_addr else R[n]; 6333        data = MemU[address,4]; 6334        if wback then R[n] = offset_addr; 6335        if t == 15 then6336            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6337        elsif UnalignedSupport() || address<1:0> = '00' then6338            R[t] = data; 6339        else // Can only apply before ARMv76340            R[t] = ROR(data, 8*UInt(address<1:0>));6341#endif6342 6343  bool success = false;6344 6345  if (ConditionPassed(opcode)) {6346    const uint32_t addr_byte_size = GetAddressByteSize();6347 6348    uint32_t t;6349    uint32_t n;6350    uint32_t imm32;6351    bool index;6352    bool add;6353    bool wback;6354 6355    switch (encoding) {6356    case eEncodingA1:6357      // if Rn == '1111' then SEE LDR (literal);6358      // if P == '0' && W == '1' then SEE LDRT;6359      // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 ==6360      // '000000000100' then SEE POP;6361      // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);6362      t = Bits32(opcode, 15, 12);6363      n = Bits32(opcode, 19, 16);6364      imm32 = Bits32(opcode, 11, 0);6365 6366      // index = (P == '1');     add = (U == '1');       wback = (P == '0') ||6367      // (W == '1');6368      index = BitIsSet(opcode, 24);6369      add = BitIsSet(opcode, 23);6370      wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));6371 6372      // if wback && n == t then UNPREDICTABLE;6373      if (wback && (n == t))6374        return false;6375 6376      break;6377 6378    default:6379      return false;6380    }6381 6382    addr_t address;6383    addr_t offset_addr;6384    addr_t base_address = ReadCoreReg(n, &success);6385    if (!success)6386      return false;6387 6388    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);6389    if (add)6390      offset_addr = base_address + imm32;6391    else6392      offset_addr = base_address - imm32;6393 6394    // address = if index then offset_addr else R[n];6395    if (index)6396      address = offset_addr;6397    else6398      address = base_address;6399 6400    // data = MemU[address,4];6401 6402    std::optional<RegisterInfo> base_reg =6403        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);6404    EmulateInstruction::Context context;6405    context.type = eContextRegisterLoad;6406    context.SetRegisterPlusOffset(*base_reg, address - base_address);6407 6408    uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);6409    if (!success)6410      return false;6411 6412    // if wback then R[n] = offset_addr;6413    if (wback) {6414      context.type = eContextAdjustBaseRegister;6415      context.SetAddress(offset_addr);6416      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,6417                                 offset_addr))6418        return false;6419    }6420 6421    // if t == 15 then6422    if (t == 15) {6423      // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;6424      if (BitIsClear(address, 1) && BitIsClear(address, 0)) {6425        // LoadWritePC (data);6426        context.type = eContextRegisterLoad;6427        context.SetRegisterPlusOffset(*base_reg, address - base_address);6428        LoadWritePC(context, data);6429      } else6430        return false;6431    }6432    // elsif UnalignedSupport() || address<1:0> = '00' then6433    else if (UnalignedSupport() ||6434             (BitIsClear(address, 1) && BitIsClear(address, 0))) {6435      // R[t] = data;6436      context.type = eContextRegisterLoad;6437      context.SetRegisterPlusOffset(*base_reg, address - base_address);6438      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,6439                                 data))6440        return false;6441    }6442    // else // Can only apply before ARMv76443    else {6444      // R[t] = ROR(data, 8*UInt(address<1:0>));6445      data = ROR(data, Bits32(address, 1, 0), &success);6446      if (!success)6447        return false;6448      context.type = eContextRegisterLoad;6449      context.SetImmediate(data);6450      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,6451                                 data))6452        return false;6453    }6454  }6455  return true;6456}6457 6458// LDR (register) calculates an address from a base register value and an offset6459// register value, loads a word6460// from memory, and writes it to a register.  The offset register value can6461// optionally be shifted.6462bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode,6463                                               const ARMEncoding encoding) {6464#if 06465    if ConditionPassed() then 6466        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6467        offset = Shift(R[m], shift_t, shift_n, APSR.C); 6468        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6469        address = if index then offset_addr else R[n]; 6470        data = MemU[address,4]; 6471        if wback then R[n] = offset_addr; 6472        if t == 15 then6473            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6474        elsif UnalignedSupport() || address<1:0> = '00' then6475            R[t] = data; 6476        else // Can only apply before ARMv76477            if CurrentInstrSet() == InstrSet_ARM then 6478                R[t] = ROR(data, 8*UInt(address<1:0>));6479            else 6480                R[t] = bits(32) UNKNOWN;6481#endif6482 6483  bool success = false;6484 6485  if (ConditionPassed(opcode)) {6486    const uint32_t addr_byte_size = GetAddressByteSize();6487 6488    uint32_t t;6489    uint32_t n;6490    uint32_t m;6491    bool index;6492    bool add;6493    bool wback;6494    ARM_ShifterType shift_t;6495    uint32_t shift_n;6496 6497    switch (encoding) {6498    case eEncodingT1:6499      // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation6500      // in ThumbEE";6501      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6502      t = Bits32(opcode, 2, 0);6503      n = Bits32(opcode, 5, 3);6504      m = Bits32(opcode, 8, 6);6505 6506      // index = TRUE; add = TRUE; wback = FALSE;6507      index = true;6508      add = true;6509      wback = false;6510 6511      // (shift_t, shift_n) = (SRType_LSL, 0);6512      shift_t = SRType_LSL;6513      shift_n = 0;6514 6515      break;6516 6517    case eEncodingT2:6518      // if Rn == '1111' then SEE LDR (literal);6519      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6520      t = Bits32(opcode, 15, 12);6521      n = Bits32(opcode, 19, 16);6522      m = Bits32(opcode, 3, 0);6523 6524      // index = TRUE; add = TRUE; wback = FALSE;6525      index = true;6526      add = true;6527      wback = false;6528 6529      // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));6530      shift_t = SRType_LSL;6531      shift_n = Bits32(opcode, 5, 4);6532 6533      // if BadReg(m) then UNPREDICTABLE;6534      if (BadReg(m))6535        return false;6536 6537      // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;6538      if ((t == 15) && InITBlock() && !LastInITBlock())6539        return false;6540 6541      break;6542 6543    case eEncodingA1: {6544      // if P == '0' && W == '1' then SEE LDRT;6545      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6546      t = Bits32(opcode, 15, 12);6547      n = Bits32(opcode, 19, 16);6548      m = Bits32(opcode, 3, 0);6549 6550      // index = (P == '1');     add = (U == '1');       wback = (P == '0') ||6551      // (W == '1');6552      index = BitIsSet(opcode, 24);6553      add = BitIsSet(opcode, 23);6554      wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));6555 6556      // (shift_t, shift_n) = DecodeImmShift(type, imm5);6557      uint32_t type = Bits32(opcode, 6, 5);6558      uint32_t imm5 = Bits32(opcode, 11, 7);6559      shift_n = DecodeImmShift(type, imm5, shift_t);6560 6561      // if m == 15 then UNPREDICTABLE;6562      if (m == 15)6563        return false;6564 6565      // if wback && (n == 15 || n == t) then UNPREDICTABLE;6566      if (wback && ((n == 15) || (n == t)))6567        return false;6568    } break;6569 6570    default:6571      return false;6572    }6573 6574    uint32_t Rm =6575        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);6576    if (!success)6577      return false;6578 6579    uint32_t Rn =6580        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);6581    if (!success)6582      return false;6583 6584    addr_t offset_addr;6585    addr_t address;6586 6587    // offset = Shift(R[m], shift_t, shift_n, APSR.C);   -- Note "The APSR is6588    // an application level alias for the CPSR".6589    addr_t offset =6590        Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success);6591    if (!success)6592      return false;6593 6594    // offset_addr = if add then (R[n] + offset) else (R[n] - offset);6595    if (add)6596      offset_addr = Rn + offset;6597    else6598      offset_addr = Rn - offset;6599 6600    // address = if index then offset_addr else R[n];6601    if (index)6602      address = offset_addr;6603    else6604      address = Rn;6605 6606    // data = MemU[address,4];6607    std::optional<RegisterInfo> base_reg =6608        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);6609    EmulateInstruction::Context context;6610    context.type = eContextRegisterLoad;6611    context.SetRegisterPlusOffset(*base_reg, address - Rn);6612 6613    uint64_t data = MemURead(context, address, addr_byte_size, 0, &success);6614    if (!success)6615      return false;6616 6617    // if wback then R[n] = offset_addr;6618    if (wback) {6619      context.type = eContextAdjustBaseRegister;6620      context.SetAddress(offset_addr);6621      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,6622                                 offset_addr))6623        return false;6624    }6625 6626    // if t == 15 then6627    if (t == 15) {6628      // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;6629      if (BitIsClear(address, 1) && BitIsClear(address, 0)) {6630        context.type = eContextRegisterLoad;6631        context.SetRegisterPlusOffset(*base_reg, address - Rn);6632        LoadWritePC(context, data);6633      } else6634        return false;6635    }6636    // elsif UnalignedSupport() || address<1:0> = '00' then6637    else if (UnalignedSupport() ||6638             (BitIsClear(address, 1) && BitIsClear(address, 0))) {6639      // R[t] = data;6640      context.type = eContextRegisterLoad;6641      context.SetRegisterPlusOffset(*base_reg, address - Rn);6642      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,6643                                 data))6644        return false;6645    } else // Can only apply before ARMv76646    {6647      // if CurrentInstrSet() == InstrSet_ARM then6648      if (CurrentInstrSet() == eModeARM) {6649        // R[t] = ROR(data, 8*UInt(address<1:0>));6650        data = ROR(data, Bits32(address, 1, 0), &success);6651        if (!success)6652          return false;6653        context.type = eContextRegisterLoad;6654        context.SetImmediate(data);6655        if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,6656                                   data))6657          return false;6658      } else {6659        // R[t] = bits(32) UNKNOWN;6660        WriteBits32Unknown(t);6661      }6662    }6663  }6664  return true;6665}6666 6667// LDRB (immediate, Thumb)6668bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode,6669                                                 const ARMEncoding encoding) {6670#if 06671    if ConditionPassed() then 6672        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6673        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6674        address = if index then offset_addr else R[n]; 6675        R[t] = ZeroExtend(MemU[address,1], 32); 6676        if wback then R[n] = offset_addr;6677#endif6678 6679  bool success = false;6680 6681  if (ConditionPassed(opcode)) {6682    uint32_t t;6683    uint32_t n;6684    uint32_t imm32;6685    bool index;6686    bool add;6687    bool wback;6688 6689    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);6690    switch (encoding) {6691    case eEncodingT1:6692      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);6693      t = Bits32(opcode, 2, 0);6694      n = Bits32(opcode, 5, 3);6695      imm32 = Bits32(opcode, 10, 6);6696 6697      // index = TRUE; add = TRUE; wback = FALSE;6698      index = true;6699      add = true;6700      wback = false;6701 6702      break;6703 6704    case eEncodingT2:6705      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);6706      t = Bits32(opcode, 15, 12);6707      n = Bits32(opcode, 19, 16);6708      imm32 = Bits32(opcode, 11, 0);6709 6710      // index = TRUE; add = TRUE; wback = FALSE;6711      index = true;6712      add = true;6713      wback = false;6714 6715      // if Rt == '1111' then SEE PLD;6716      if (t == 15)6717        return false; // PLD is not implemented yet6718 6719      // if Rn == '1111' then SEE LDRB (literal);6720      if (n == 15)6721        return EmulateLDRBLiteral(opcode, eEncodingT1);6722 6723      // if t == 13 then UNPREDICTABLE;6724      if (t == 13)6725        return false;6726 6727      break;6728 6729    case eEncodingT3:6730      // if P == '1' && U == '1' && W == '0' then SEE LDRBT;6731      // if P == '0' && W == '0' then UNDEFINED;6732      if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))6733        return false;6734 6735      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);6736      t = Bits32(opcode, 15, 12);6737      n = Bits32(opcode, 19, 16);6738      imm32 = Bits32(opcode, 7, 0);6739 6740      // index = (P == '1'); add = (U == '1'); wback = (W == '1');6741      index = BitIsSet(opcode, 10);6742      add = BitIsSet(opcode, 9);6743      wback = BitIsSet(opcode, 8);6744 6745      // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD;6746      if (t == 15)6747        return false; // PLD is not implemented yet6748 6749      // if Rn == '1111' then SEE LDRB (literal);6750      if (n == 15)6751        return EmulateLDRBLiteral(opcode, eEncodingT1);6752 6753      // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;6754      if (BadReg(t) || (wback && (n == t)))6755        return false;6756 6757      break;6758 6759    default:6760      return false;6761    }6762 6763    uint32_t Rn =6764        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);6765    if (!success)6766      return false;6767 6768    addr_t address;6769    addr_t offset_addr;6770 6771    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);6772    if (add)6773      offset_addr = Rn + imm32;6774    else6775      offset_addr = Rn - imm32;6776 6777    // address = if index then offset_addr else R[n];6778    if (index)6779      address = offset_addr;6780    else6781      address = Rn;6782 6783    // R[t] = ZeroExtend(MemU[address,1], 32);6784    std::optional<RegisterInfo> base_reg =6785        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);6786    std::optional<RegisterInfo> data_reg =6787        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);6788 6789    EmulateInstruction::Context context;6790    context.type = eContextRegisterLoad;6791    context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);6792 6793    uint64_t data = MemURead(context, address, 1, 0, &success);6794    if (!success)6795      return false;6796 6797    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))6798      return false;6799 6800    // if wback then R[n] = offset_addr;6801    if (wback) {6802      context.type = eContextAdjustBaseRegister;6803      context.SetAddress(offset_addr);6804      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,6805                                 offset_addr))6806        return false;6807    }6808  }6809  return true;6810}6811 6812// LDRB (literal) calculates an address from the PC value and an immediate6813// offset, loads a byte from memory,6814// zero-extends it to form a 32-bit word and writes it to a register.6815bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode,6816                                               const ARMEncoding encoding) {6817#if 06818    if ConditionPassed() then 6819        EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6820        base = Align(PC,4); 6821        address = if add then (base + imm32) else (base - imm32); 6822        R[t] = ZeroExtend(MemU[address,1], 32);6823#endif6824 6825  bool success = false;6826 6827  if (ConditionPassed(opcode)) {6828    uint32_t t;6829    uint32_t imm32;6830    bool add;6831    switch (encoding) {6832    case eEncodingT1:6833      // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');6834      t = Bits32(opcode, 15, 12);6835      imm32 = Bits32(opcode, 11, 0);6836      add = BitIsSet(opcode, 23);6837 6838      // if Rt == '1111' then SEE PLD;6839      if (t == 15)6840        return false; // PLD is not implemented yet6841 6842      // if t == 13 then UNPREDICTABLE;6843      if (t == 13)6844        return false;6845 6846      break;6847 6848    case eEncodingA1:6849      // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');6850      t = Bits32(opcode, 15, 12);6851      imm32 = Bits32(opcode, 11, 0);6852      add = BitIsSet(opcode, 23);6853 6854      // if t == 15 then UNPREDICTABLE;6855      if (t == 15)6856        return false;6857      break;6858 6859    default:6860      return false;6861    }6862 6863    // base = Align(PC,4);6864    uint32_t pc_val = ReadCoreReg(PC_REG, &success);6865    if (!success)6866      return false;6867 6868    uint32_t base = AlignPC(pc_val);6869 6870    addr_t address;6871    // address = if add then (base + imm32) else (base - imm32);6872    if (add)6873      address = base + imm32;6874    else6875      address = base - imm32;6876 6877    // R[t] = ZeroExtend(MemU[address,1], 32);6878    EmulateInstruction::Context context;6879    context.type = eContextRelativeBranchImmediate;6880    context.SetImmediate(address - base);6881 6882    uint64_t data = MemURead(context, address, 1, 0, &success);6883    if (!success)6884      return false;6885 6886    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))6887      return false;6888  }6889  return true;6890}6891 6892// LDRB (register) calculates an address from a base register value and an6893// offset rigister value, loads a byte from memory, zero-extends it to form a6894// 32-bit word, and writes it to a register. The offset register value can6895// optionally be shifted.6896bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode,6897                                                const ARMEncoding encoding) {6898#if 06899    if ConditionPassed() then 6900        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6901        offset = Shift(R[m], shift_t, shift_n, APSR.C); 6902        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6903        address = if index then offset_addr else R[n]; 6904        R[t] = ZeroExtend(MemU[address,1],32); 6905        if wback then R[n] = offset_addr;6906#endif6907 6908  bool success = false;6909 6910  if (ConditionPassed(opcode)) {6911    uint32_t t;6912    uint32_t n;6913    uint32_t m;6914    bool index;6915    bool add;6916    bool wback;6917    ARM_ShifterType shift_t;6918    uint32_t shift_n;6919 6920    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);6921    switch (encoding) {6922    case eEncodingT1:6923      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6924      t = Bits32(opcode, 2, 0);6925      n = Bits32(opcode, 5, 3);6926      m = Bits32(opcode, 8, 6);6927 6928      // index = TRUE; add = TRUE; wback = FALSE;6929      index = true;6930      add = true;6931      wback = false;6932 6933      // (shift_t, shift_n) = (SRType_LSL, 0);6934      shift_t = SRType_LSL;6935      shift_n = 0;6936      break;6937 6938    case eEncodingT2:6939      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6940      t = Bits32(opcode, 15, 12);6941      n = Bits32(opcode, 19, 16);6942      m = Bits32(opcode, 3, 0);6943 6944      // index = TRUE; add = TRUE; wback = FALSE;6945      index = true;6946      add = true;6947      wback = false;6948 6949      // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));6950      shift_t = SRType_LSL;6951      shift_n = Bits32(opcode, 5, 4);6952 6953      // if Rt == '1111' then SEE PLD;6954      if (t == 15)6955        return false; // PLD is not implemented yet6956 6957      // if Rn == '1111' then SEE LDRB (literal);6958      if (n == 15)6959        return EmulateLDRBLiteral(opcode, eEncodingT1);6960 6961      // if t == 13 || BadReg(m) then UNPREDICTABLE;6962      if ((t == 13) || BadReg(m))6963        return false;6964      break;6965 6966    case eEncodingA1: {6967      // if P == '0' && W == '1' then SEE LDRBT;6968      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);6969      t = Bits32(opcode, 15, 12);6970      n = Bits32(opcode, 19, 16);6971      m = Bits32(opcode, 3, 0);6972 6973      // index = (P == '1');     add = (U == '1');       wback = (P == '0') ||6974      // (W == '1');6975      index = BitIsSet(opcode, 24);6976      add = BitIsSet(opcode, 23);6977      wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));6978 6979      // (shift_t, shift_n) = DecodeImmShift(type, imm5);6980      uint32_t type = Bits32(opcode, 6, 5);6981      uint32_t imm5 = Bits32(opcode, 11, 7);6982      shift_n = DecodeImmShift(type, imm5, shift_t);6983 6984      // if t == 15 || m == 15 then UNPREDICTABLE;6985      if ((t == 15) || (m == 15))6986        return false;6987 6988      // if wback && (n == 15 || n == t) then UNPREDICTABLE;6989      if (wback && ((n == 15) || (n == t)))6990        return false;6991    } break;6992 6993    default:6994      return false;6995    }6996 6997    addr_t offset_addr;6998    addr_t address;6999 7000    // offset = Shift(R[m], shift_t, shift_n, APSR.C);7001    uint32_t Rm =7002        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);7003    if (!success)7004      return false;7005 7006    addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);7007    if (!success)7008      return false;7009 7010    // offset_addr = if add then (R[n] + offset) else (R[n] - offset);7011    uint32_t Rn =7012        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);7013    if (!success)7014      return false;7015 7016    if (add)7017      offset_addr = Rn + offset;7018    else7019      offset_addr = Rn - offset;7020 7021    // address = if index then offset_addr else R[n];7022    if (index)7023      address = offset_addr;7024    else7025      address = Rn;7026 7027    // R[t] = ZeroExtend(MemU[address,1],32);7028    std::optional<RegisterInfo> base_reg =7029        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);7030 7031    EmulateInstruction::Context context;7032    context.type = eContextRegisterLoad;7033    context.SetRegisterPlusOffset(*base_reg, address - Rn);7034 7035    uint64_t data = MemURead(context, address, 1, 0, &success);7036    if (!success)7037      return false;7038 7039    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))7040      return false;7041 7042    // if wback then R[n] = offset_addr;7043    if (wback) {7044      context.type = eContextAdjustBaseRegister;7045      context.SetAddress(offset_addr);7046      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,7047                                 offset_addr))7048        return false;7049    }7050  }7051  return true;7052}7053 7054// LDRH (immediate, Thumb) calculates an address from a base register value and7055// an immediate offset, loads a7056// halfword from memory, zero-extends it to form a 32-bit word, and writes it7057// to a register.  It can use offset, post-indexed, or pre-indexed addressing.7058bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode,7059                                                 const ARMEncoding encoding) {7060#if 07061    if ConditionPassed() then 7062        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7063        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7064        address = if index then offset_addr else R[n]; 7065        data = MemU[address,2]; 7066        if wback then R[n] = offset_addr; 7067        if UnalignedSupport() || address<0> = '0' then7068            R[t] = ZeroExtend(data, 32); 7069        else // Can only apply before ARMv77070            R[t] = bits(32) UNKNOWN;7071#endif7072 7073  bool success = false;7074 7075  if (ConditionPassed(opcode)) {7076    uint32_t t;7077    uint32_t n;7078    uint32_t imm32;7079    bool index;7080    bool add;7081    bool wback;7082 7083    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);7084    switch (encoding) {7085    case eEncodingT1:7086      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);7087      t = Bits32(opcode, 2, 0);7088      n = Bits32(opcode, 5, 3);7089      imm32 = Bits32(opcode, 10, 6) << 1;7090 7091      // index = TRUE; add = TRUE; wback = FALSE;7092      index = true;7093      add = true;7094      wback = false;7095 7096      break;7097 7098    case eEncodingT2:7099      // if Rt == '1111' then SEE "Unallocated memory hints";7100      // if Rn == '1111' then SEE LDRH (literal);7101      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);7102      t = Bits32(opcode, 15, 12);7103      n = Bits32(opcode, 19, 16);7104      imm32 = Bits32(opcode, 11, 0);7105 7106      // index = TRUE; add = TRUE; wback = FALSE;7107      index = true;7108      add = true;7109      wback = false;7110 7111      // if t == 13 then UNPREDICTABLE;7112      if (t == 13)7113        return false;7114      break;7115 7116    case eEncodingT3:7117      // if Rn == '1111' then SEE LDRH (literal);7118      // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE7119      // "Unallocated memory hints";7120      // if P == '1' && U == '1' && W == '0' then SEE LDRHT;7121      // if P == '0' && W == '0' then UNDEFINED;7122      if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))7123        return false;7124 7125      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);7126      t = Bits32(opcode, 15, 12);7127      n = Bits32(opcode, 19, 16);7128      imm32 = Bits32(opcode, 7, 0);7129 7130      // index = (P == '1'); add = (U == '1'); wback = (W == '1');7131      index = BitIsSet(opcode, 10);7132      add = BitIsSet(opcode, 9);7133      wback = BitIsSet(opcode, 8);7134 7135      // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;7136      if (BadReg(t) || (wback && (n == t)))7137        return false;7138      break;7139 7140    default:7141      return false;7142    }7143 7144    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);7145    uint32_t Rn =7146        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);7147    if (!success)7148      return false;7149 7150    addr_t offset_addr;7151    addr_t address;7152 7153    if (add)7154      offset_addr = Rn + imm32;7155    else7156      offset_addr = Rn - imm32;7157 7158    // address = if index then offset_addr else R[n];7159    if (index)7160      address = offset_addr;7161    else7162      address = Rn;7163 7164    // data = MemU[address,2];7165    std::optional<RegisterInfo> base_reg =7166        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);7167 7168    EmulateInstruction::Context context;7169    context.type = eContextRegisterLoad;7170    context.SetRegisterPlusOffset(*base_reg, address - Rn);7171 7172    uint64_t data = MemURead(context, address, 2, 0, &success);7173    if (!success)7174      return false;7175 7176    // if wback then R[n] = offset_addr;7177    if (wback) {7178      context.type = eContextAdjustBaseRegister;7179      context.SetAddress(offset_addr);7180      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,7181                                 offset_addr))7182        return false;7183    }7184 7185    // if UnalignedSupport() || address<0> = '0' then7186    if (UnalignedSupport() || BitIsClear(address, 0)) {7187      // R[t] = ZeroExtend(data, 32);7188      context.type = eContextRegisterLoad;7189      context.SetRegisterPlusOffset(*base_reg, address - Rn);7190      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7191                                 data))7192        return false;7193    } else // Can only apply before ARMv77194    {7195      // R[t] = bits(32) UNKNOWN;7196      WriteBits32Unknown(t);7197    }7198  }7199  return true;7200}7201 7202// LDRH (literal) calculates an address from the PC value and an immediate7203// offset, loads a halfword from memory,7204// zero-extends it to form a 32-bit word, and writes it to a register.7205bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode,7206                                               const ARMEncoding encoding) {7207#if 07208    if ConditionPassed() then 7209        EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7210        base = Align(PC,4); 7211        address = if add then (base + imm32) else (base - imm32); 7212        data = MemU[address,2]; 7213        if UnalignedSupport() || address<0> = '0' then7214            R[t] = ZeroExtend(data, 32); 7215        else // Can only apply before ARMv77216            R[t] = bits(32) UNKNOWN;7217#endif7218 7219  bool success = false;7220 7221  if (ConditionPassed(opcode)) {7222    uint32_t t;7223    uint32_t imm32;7224    bool add;7225 7226    // EncodingSpecificOperations(); NullCheckIfThumbEE(15);7227    switch (encoding) {7228    case eEncodingT1:7229      // if Rt == '1111' then SEE "Unallocated memory hints";7230      // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');7231      t = Bits32(opcode, 15, 12);7232      imm32 = Bits32(opcode, 11, 0);7233      add = BitIsSet(opcode, 23);7234 7235      // if t == 13 then UNPREDICTABLE;7236      if (t == 13)7237        return false;7238 7239      break;7240 7241    case eEncodingA1: {7242      uint32_t imm4H = Bits32(opcode, 11, 8);7243      uint32_t imm4L = Bits32(opcode, 3, 0);7244 7245      // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');7246      t = Bits32(opcode, 15, 12);7247      imm32 = (imm4H << 4) | imm4L;7248      add = BitIsSet(opcode, 23);7249 7250      // if t == 15 then UNPREDICTABLE;7251      if (t == 15)7252        return false;7253      break;7254    }7255 7256    default:7257      return false;7258    }7259 7260    // base = Align(PC,4);7261    uint64_t pc_value = ReadCoreReg(PC_REG, &success);7262    if (!success)7263      return false;7264 7265    addr_t base = AlignPC(pc_value);7266    addr_t address;7267 7268    // address = if add then (base + imm32) else (base - imm32);7269    if (add)7270      address = base + imm32;7271    else7272      address = base - imm32;7273 7274    // data = MemU[address,2];7275    std::optional<RegisterInfo> base_reg =7276        GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);7277 7278    EmulateInstruction::Context context;7279    context.type = eContextRegisterLoad;7280    context.SetRegisterPlusOffset(*base_reg, address - base);7281 7282    uint64_t data = MemURead(context, address, 2, 0, &success);7283    if (!success)7284      return false;7285 7286    // if UnalignedSupport() || address<0> = '0' then7287    if (UnalignedSupport() || BitIsClear(address, 0)) {7288      // R[t] = ZeroExtend(data, 32);7289      context.type = eContextRegisterLoad;7290      context.SetRegisterPlusOffset(*base_reg, address - base);7291      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7292                                 data))7293        return false;7294 7295    } else // Can only apply before ARMv77296    {7297      // R[t] = bits(32) UNKNOWN;7298      WriteBits32Unknown(t);7299    }7300  }7301  return true;7302}7303 7304// LDRH (literal) calculates an address from a base register value and an offset7305// register value, loads a halfword7306// from memory, zero-extends it to form a 32-bit word, and writes it to a7307// register.  The offset register value can be shifted left by 0, 1, 2, or 37308// bits.7309bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode,7310                                                const ARMEncoding encoding) {7311#if 07312    if ConditionPassed() then 7313        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7314        offset = Shift(R[m], shift_t, shift_n, APSR.C); 7315        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7316        address = if index then offset_addr else R[n]; 7317        data = MemU[address,2]; 7318        if wback then R[n] = offset_addr; 7319        if UnalignedSupport() || address<0> = '0' then7320            R[t] = ZeroExtend(data, 32); 7321        else // Can only apply before ARMv77322            R[t] = bits(32) UNKNOWN;7323#endif7324 7325  bool success = false;7326 7327  if (ConditionPassed(opcode)) {7328    uint32_t t;7329    uint32_t n;7330    uint32_t m;7331    bool index;7332    bool add;7333    bool wback;7334    ARM_ShifterType shift_t;7335    uint32_t shift_n;7336 7337    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);7338    switch (encoding) {7339    case eEncodingT1:7340      // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation7341      // in ThumbEE";7342      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7343      t = Bits32(opcode, 2, 0);7344      n = Bits32(opcode, 5, 3);7345      m = Bits32(opcode, 8, 6);7346 7347      // index = TRUE; add = TRUE; wback = FALSE;7348      index = true;7349      add = true;7350      wback = false;7351 7352      // (shift_t, shift_n) = (SRType_LSL, 0);7353      shift_t = SRType_LSL;7354      shift_n = 0;7355 7356      break;7357 7358    case eEncodingT2:7359      // if Rn == '1111' then SEE LDRH (literal);7360      // if Rt == '1111' then SEE "Unallocated memory hints";7361      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7362      t = Bits32(opcode, 15, 12);7363      n = Bits32(opcode, 19, 16);7364      m = Bits32(opcode, 3, 0);7365 7366      // index = TRUE; add = TRUE; wback = FALSE;7367      index = true;7368      add = true;7369      wback = false;7370 7371      // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));7372      shift_t = SRType_LSL;7373      shift_n = Bits32(opcode, 5, 4);7374 7375      // if t == 13 || BadReg(m) then UNPREDICTABLE;7376      if ((t == 13) || BadReg(m))7377        return false;7378      break;7379 7380    case eEncodingA1:7381      // if P == '0' && W == '1' then SEE LDRHT;7382      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7383      t = Bits32(opcode, 15, 12);7384      n = Bits32(opcode, 19, 16);7385      m = Bits32(opcode, 3, 0);7386 7387      // index = (P == '1');     add = (U == '1');       wback = (P == '0') ||7388      // (W == '1');7389      index = BitIsSet(opcode, 24);7390      add = BitIsSet(opcode, 23);7391      wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));7392 7393      // (shift_t, shift_n) = (SRType_LSL, 0);7394      shift_t = SRType_LSL;7395      shift_n = 0;7396 7397      // if t == 15 || m == 15 then UNPREDICTABLE;7398      if ((t == 15) || (m == 15))7399        return false;7400 7401      // if wback && (n == 15 || n == t) then UNPREDICTABLE;7402      if (wback && ((n == 15) || (n == t)))7403        return false;7404 7405      break;7406 7407    default:7408      return false;7409    }7410 7411    // offset = Shift(R[m], shift_t, shift_n, APSR.C);7412 7413    uint64_t Rm =7414        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);7415    if (!success)7416      return false;7417 7418    addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);7419    if (!success)7420      return false;7421 7422    addr_t offset_addr;7423    addr_t address;7424 7425    // offset_addr = if add then (R[n] + offset) else (R[n] - offset);7426    uint64_t Rn =7427        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);7428    if (!success)7429      return false;7430 7431    if (add)7432      offset_addr = Rn + offset;7433    else7434      offset_addr = Rn - offset;7435 7436    // address = if index then offset_addr else R[n];7437    if (index)7438      address = offset_addr;7439    else7440      address = Rn;7441 7442    // data = MemU[address,2];7443    std::optional<RegisterInfo> base_reg =7444        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);7445    std::optional<RegisterInfo> offset_reg =7446        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);7447 7448    EmulateInstruction::Context context;7449    context.type = eContextRegisterLoad;7450    context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);7451    uint64_t data = MemURead(context, address, 2, 0, &success);7452    if (!success)7453      return false;7454 7455    // if wback then R[n] = offset_addr;7456    if (wback) {7457      context.type = eContextAdjustBaseRegister;7458      context.SetAddress(offset_addr);7459      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,7460                                 offset_addr))7461        return false;7462    }7463 7464    // if UnalignedSupport() || address<0> = '0' then7465    if (UnalignedSupport() || BitIsClear(address, 0)) {7466      // R[t] = ZeroExtend(data, 32);7467      context.type = eContextRegisterLoad;7468      context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);7469      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7470                                 data))7471        return false;7472    } else // Can only apply before ARMv77473    {7474      // R[t] = bits(32) UNKNOWN;7475      WriteBits32Unknown(t);7476    }7477  }7478  return true;7479}7480 7481// LDRSB (immediate) calculates an address from a base register value and an7482// immediate offset, loads a byte from7483// memory, sign-extends it to form a 32-bit word, and writes it to a register.7484// It can use offset, post-indexed, or pre-indexed addressing.7485bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode,7486                                                  const ARMEncoding encoding) {7487#if 07488    if ConditionPassed() then 7489        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7490        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7491        address = if index then offset_addr else R[n]; 7492        R[t] = SignExtend(MemU[address,1], 32); 7493        if wback then R[n] = offset_addr;7494#endif7495 7496  bool success = false;7497 7498  if (ConditionPassed(opcode)) {7499    uint32_t t;7500    uint32_t n;7501    uint32_t imm32;7502    bool index;7503    bool add;7504    bool wback;7505 7506    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);7507    switch (encoding) {7508    case eEncodingT1:7509      // if Rt == '1111' then SEE PLI;7510      // if Rn == '1111' then SEE LDRSB (literal);7511      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);7512      t = Bits32(opcode, 15, 12);7513      n = Bits32(opcode, 19, 16);7514      imm32 = Bits32(opcode, 11, 0);7515 7516      // index = TRUE; add = TRUE; wback = FALSE;7517      index = true;7518      add = true;7519      wback = false;7520 7521      // if t == 13 then UNPREDICTABLE;7522      if (t == 13)7523        return false;7524 7525      break;7526 7527    case eEncodingT2:7528      // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI;7529      // if Rn == '1111' then SEE LDRSB (literal);7530      // if P == '1' && U == '1' && W == '0' then SEE LDRSBT;7531      // if P == '0' && W == '0' then UNDEFINED;7532      if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))7533        return false;7534 7535      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);7536      t = Bits32(opcode, 15, 12);7537      n = Bits32(opcode, 19, 16);7538      imm32 = Bits32(opcode, 7, 0);7539 7540      // index = (P == '1'); add = (U == '1'); wback = (W == '1');7541      index = BitIsSet(opcode, 10);7542      add = BitIsSet(opcode, 9);7543      wback = BitIsSet(opcode, 8);7544 7545      // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;7546      if (((t == 13) ||7547           ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) ||7548                          BitIsSet(opcode, 8)))) ||7549          (wback && (n == t)))7550        return false;7551 7552      break;7553 7554    case eEncodingA1: {7555      // if Rn == '1111' then SEE LDRSB (literal);7556      // if P == '0' && W == '1' then SEE LDRSBT;7557      // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);7558      t = Bits32(opcode, 15, 12);7559      n = Bits32(opcode, 19, 16);7560 7561      uint32_t imm4H = Bits32(opcode, 11, 8);7562      uint32_t imm4L = Bits32(opcode, 3, 0);7563      imm32 = (imm4H << 4) | imm4L;7564 7565      // index = (P == '1');     add = (U == '1');       wback = (P == '0') ||7566      // (W == '1');7567      index = BitIsSet(opcode, 24);7568      add = BitIsSet(opcode, 23);7569      wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21));7570 7571      // if t == 15 || (wback && n == t) then UNPREDICTABLE;7572      if ((t == 15) || (wback && (n == t)))7573        return false;7574 7575      break;7576    }7577 7578    default:7579      return false;7580    }7581 7582    uint64_t Rn = ReadCoreReg(n, &success);7583    if (!success)7584      return false;7585 7586    addr_t offset_addr;7587    addr_t address;7588 7589    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);7590    if (add)7591      offset_addr = Rn + imm32;7592    else7593      offset_addr = Rn - imm32;7594 7595    // address = if index then offset_addr else R[n];7596    if (index)7597      address = offset_addr;7598    else7599      address = Rn;7600 7601    // R[t] = SignExtend(MemU[address,1], 32);7602    std::optional<RegisterInfo> base_reg =7603        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);7604 7605    EmulateInstruction::Context context;7606    context.type = eContextRegisterLoad;7607    context.SetRegisterPlusOffset(*base_reg, address - Rn);7608 7609    uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);7610    if (!success)7611      return false;7612 7613    int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);7614    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7615                               (uint64_t)signed_data))7616      return false;7617 7618    // if wback then R[n] = offset_addr;7619    if (wback) {7620      context.type = eContextAdjustBaseRegister;7621      context.SetAddress(offset_addr);7622      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,7623                                 offset_addr))7624        return false;7625    }7626  }7627 7628  return true;7629}7630 7631// LDRSB (literal) calculates an address from the PC value and an immediate7632// offset, loads a byte from memory,7633// sign-extends it to form a 32-bit word, and writes tit to a register.7634bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode,7635                                                const ARMEncoding encoding) {7636#if 07637    if ConditionPassed() then 7638        EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7639        base = Align(PC,4); 7640        address = if add then (base + imm32) else (base - imm32); 7641        R[t] = SignExtend(MemU[address,1], 32);7642#endif7643 7644  bool success = false;7645 7646  if (ConditionPassed(opcode)) {7647    uint32_t t;7648    uint32_t imm32;7649    bool add;7650 7651    // EncodingSpecificOperations(); NullCheckIfThumbEE(15);7652    switch (encoding) {7653    case eEncodingT1:7654      // if Rt == '1111' then SEE PLI;7655      // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');7656      t = Bits32(opcode, 15, 12);7657      imm32 = Bits32(opcode, 11, 0);7658      add = BitIsSet(opcode, 23);7659 7660      // if t == 13 then UNPREDICTABLE;7661      if (t == 13)7662        return false;7663 7664      break;7665 7666    case eEncodingA1: {7667      // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');7668      t = Bits32(opcode, 15, 12);7669      uint32_t imm4H = Bits32(opcode, 11, 8);7670      uint32_t imm4L = Bits32(opcode, 3, 0);7671      imm32 = (imm4H << 4) | imm4L;7672      add = BitIsSet(opcode, 23);7673 7674      // if t == 15 then UNPREDICTABLE;7675      if (t == 15)7676        return false;7677 7678      break;7679    }7680 7681    default:7682      return false;7683    }7684 7685    // base = Align(PC,4);7686    uint64_t pc_value = ReadCoreReg(PC_REG, &success);7687    if (!success)7688      return false;7689    uint64_t base = AlignPC(pc_value);7690 7691    // address = if add then (base + imm32) else (base - imm32);7692    addr_t address;7693    if (add)7694      address = base + imm32;7695    else7696      address = base - imm32;7697 7698    // R[t] = SignExtend(MemU[address,1], 32);7699    std::optional<RegisterInfo> base_reg =7700        GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);7701 7702    EmulateInstruction::Context context;7703    context.type = eContextRegisterLoad;7704    context.SetRegisterPlusOffset(*base_reg, address - base);7705 7706    uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);7707    if (!success)7708      return false;7709 7710    int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);7711    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7712                               (uint64_t)signed_data))7713      return false;7714  }7715  return true;7716}7717 7718// LDRSB (register) calculates an address from a base register value and an7719// offset register value, loadsa byte from7720// memory, sign-extends it to form a 32-bit word, and writes it to a register.7721// The offset register value can be shifted left by 0, 1, 2, or 3 bits.7722bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode,7723                                                 const ARMEncoding encoding) {7724#if 07725    if ConditionPassed() then 7726        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7727        offset = Shift(R[m], shift_t, shift_n, APSR.C); 7728        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7729        address = if index then offset_addr else R[n]; 7730        R[t] = SignExtend(MemU[address,1], 32); 7731        if wback then R[n] = offset_addr;7732#endif7733 7734  bool success = false;7735 7736  if (ConditionPassed(opcode)) {7737    uint32_t t;7738    uint32_t n;7739    uint32_t m;7740    bool index;7741    bool add;7742    bool wback;7743    ARM_ShifterType shift_t;7744    uint32_t shift_n;7745 7746    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);7747    switch (encoding) {7748    case eEncodingT1:7749      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7750      t = Bits32(opcode, 2, 0);7751      n = Bits32(opcode, 5, 3);7752      m = Bits32(opcode, 8, 6);7753 7754      // index = TRUE; add = TRUE; wback = FALSE;7755      index = true;7756      add = true;7757      wback = false;7758 7759      // (shift_t, shift_n) = (SRType_LSL, 0);7760      shift_t = SRType_LSL;7761      shift_n = 0;7762 7763      break;7764 7765    case eEncodingT2:7766      // if Rt == '1111' then SEE PLI;7767      // if Rn == '1111' then SEE LDRSB (literal);7768      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7769      t = Bits32(opcode, 15, 12);7770      n = Bits32(opcode, 19, 16);7771      m = Bits32(opcode, 3, 0);7772 7773      // index = TRUE; add = TRUE; wback = FALSE;7774      index = true;7775      add = true;7776      wback = false;7777 7778      // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));7779      shift_t = SRType_LSL;7780      shift_n = Bits32(opcode, 5, 4);7781 7782      // if t == 13 || BadReg(m) then UNPREDICTABLE;7783      if ((t == 13) || BadReg(m))7784        return false;7785      break;7786 7787    case eEncodingA1:7788      // if P == '0' && W == '1' then SEE LDRSBT;7789      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);7790      t = Bits32(opcode, 15, 12);7791      n = Bits32(opcode, 19, 16);7792      m = Bits32(opcode, 3, 0);7793 7794      // index = (P == '1');     add = (U == '1');       wback = (P == '0') ||7795      // (W == '1');7796      index = BitIsSet(opcode, 24);7797      add = BitIsSet(opcode, 23);7798      wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);7799 7800      // (shift_t, shift_n) = (SRType_LSL, 0);7801      shift_t = SRType_LSL;7802      shift_n = 0;7803 7804      // if t == 15 || m == 15 then UNPREDICTABLE;7805      if ((t == 15) || (m == 15))7806        return false;7807 7808      // if wback && (n == 15 || n == t) then UNPREDICTABLE;7809      if (wback && ((n == 15) || (n == t)))7810        return false;7811      break;7812 7813    default:7814      return false;7815    }7816 7817    uint64_t Rm =7818        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);7819    if (!success)7820      return false;7821 7822    // offset = Shift(R[m], shift_t, shift_n, APSR.C);7823    addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);7824    if (!success)7825      return false;7826 7827    addr_t offset_addr;7828    addr_t address;7829 7830    // offset_addr = if add then (R[n] + offset) else (R[n] - offset);7831    uint64_t Rn =7832        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);7833    if (!success)7834      return false;7835 7836    if (add)7837      offset_addr = Rn + offset;7838    else7839      offset_addr = Rn - offset;7840 7841    // address = if index then offset_addr else R[n];7842    if (index)7843      address = offset_addr;7844    else7845      address = Rn;7846 7847    // R[t] = SignExtend(MemU[address,1], 32);7848    std::optional<RegisterInfo> base_reg =7849        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);7850    std::optional<RegisterInfo> offset_reg =7851        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);7852 7853    EmulateInstruction::Context context;7854    context.type = eContextRegisterLoad;7855    context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);7856 7857    uint64_t unsigned_data = MemURead(context, address, 1, 0, &success);7858    if (!success)7859      return false;7860 7861    int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);7862    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,7863                               (uint64_t)signed_data))7864      return false;7865 7866    // if wback then R[n] = offset_addr;7867    if (wback) {7868      context.type = eContextAdjustBaseRegister;7869      context.SetAddress(offset_addr);7870      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,7871                                 offset_addr))7872        return false;7873    }7874  }7875  return true;7876}7877 7878// LDRSH (immediate) calculates an address from a base register value and an7879// immediate offset, loads a halfword from7880// memory, sign-extends it to form a 32-bit word, and writes it to a register.7881// It can use offset, post-indexed, or pre-indexed addressing.7882bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode,7883                                                  const ARMEncoding encoding) {7884#if 07885    if ConditionPassed() then 7886        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7887        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7888        address = if index then offset_addr else R[n]; 7889        data = MemU[address,2]; 7890        if wback then R[n] = offset_addr; 7891        if UnalignedSupport() || address<0> = '0' then7892            R[t] = SignExtend(data, 32); 7893        else // Can only apply before ARMv77894            R[t] = bits(32) UNKNOWN;7895#endif7896 7897  bool success = false;7898 7899  if (ConditionPassed(opcode)) {7900    uint32_t t;7901    uint32_t n;7902    uint32_t imm32;7903    bool index;7904    bool add;7905    bool wback;7906 7907    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);7908    switch (encoding) {7909    case eEncodingT1:7910      // if Rn == '1111' then SEE LDRSH (literal);7911      // if Rt == '1111' then SEE "Unallocated memory hints";7912      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);7913      t = Bits32(opcode, 15, 12);7914      n = Bits32(opcode, 19, 16);7915      imm32 = Bits32(opcode, 11, 0);7916 7917      // index = TRUE; add = TRUE; wback = FALSE;7918      index = true;7919      add = true;7920      wback = false;7921 7922      // if t == 13 then UNPREDICTABLE;7923      if (t == 13)7924        return false;7925 7926      break;7927 7928    case eEncodingT2:7929      // if Rn == '1111' then SEE LDRSH (literal);7930      // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE7931      // "Unallocated memory hints";7932      // if P == '1' && U == '1' && W == '0' then SEE LDRSHT;7933      // if P == '0' && W == '0' then UNDEFINED;7934      if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))7935        return false;7936 7937      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);7938      t = Bits32(opcode, 15, 12);7939      n = Bits32(opcode, 19, 16);7940      imm32 = Bits32(opcode, 7, 0);7941 7942      // index = (P == '1'); add = (U == '1'); wback = (W == '1');7943      index = BitIsSet(opcode, 10);7944      add = BitIsSet(opcode, 9);7945      wback = BitIsSet(opcode, 8);7946 7947      // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;7948      if (BadReg(t) || (wback && (n == t)))7949        return false;7950 7951      break;7952 7953    case eEncodingA1: {7954      // if Rn == '1111' then SEE LDRSH (literal);7955      // if P == '0' && W == '1' then SEE LDRSHT;7956      // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);7957      t = Bits32(opcode, 15, 12);7958      n = Bits32(opcode, 19, 16);7959      uint32_t imm4H = Bits32(opcode, 11, 8);7960      uint32_t imm4L = Bits32(opcode, 3, 0);7961      imm32 = (imm4H << 4) | imm4L;7962 7963      // index = (P == '1');     add = (U == '1');       wback = (P == '0') ||7964      // (W == '1');7965      index = BitIsSet(opcode, 24);7966      add = BitIsSet(opcode, 23);7967      wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);7968 7969      // if t == 15 || (wback && n == t) then UNPREDICTABLE;7970      if ((t == 15) || (wback && (n == t)))7971        return false;7972 7973      break;7974    }7975 7976    default:7977      return false;7978    }7979 7980    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);7981    uint64_t Rn =7982        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);7983    if (!success)7984      return false;7985 7986    addr_t offset_addr;7987    if (add)7988      offset_addr = Rn + imm32;7989    else7990      offset_addr = Rn - imm32;7991 7992    // address = if index then offset_addr else R[n];7993    addr_t address;7994    if (index)7995      address = offset_addr;7996    else7997      address = Rn;7998 7999    // data = MemU[address,2];8000    std::optional<RegisterInfo> base_reg =8001        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);8002 8003    EmulateInstruction::Context context;8004    context.type = eContextRegisterLoad;8005    context.SetRegisterPlusOffset(*base_reg, address - Rn);8006 8007    uint64_t data = MemURead(context, address, 2, 0, &success);8008    if (!success)8009      return false;8010 8011    // if wback then R[n] = offset_addr;8012    if (wback) {8013      context.type = eContextAdjustBaseRegister;8014      context.SetAddress(offset_addr);8015      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,8016                                 offset_addr))8017        return false;8018    }8019 8020    // if UnalignedSupport() || address<0> = '0' then8021    if (UnalignedSupport() || BitIsClear(address, 0)) {8022      // R[t] = SignExtend(data, 32);8023      int64_t signed_data = llvm::SignExtend64<16>(data);8024      context.type = eContextRegisterLoad;8025      context.SetRegisterPlusOffset(*base_reg, address - Rn);8026      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,8027                                 (uint64_t)signed_data))8028        return false;8029    } else // Can only apply before ARMv78030    {8031      // R[t] = bits(32) UNKNOWN;8032      WriteBits32Unknown(t);8033    }8034  }8035  return true;8036}8037 8038// LDRSH (literal) calculates an address from the PC value and an immediate8039// offset, loads a halfword from memory,8040// sign-extends it to from a 32-bit word, and writes it to a register.8041bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode,8042                                                const ARMEncoding encoding) {8043#if 08044    if ConditionPassed() then 8045        EncodingSpecificOperations(); NullCheckIfThumbEE(15); 8046        base = Align(PC,4); 8047        address = if add then (base + imm32) else (base - imm32); 8048        data = MemU[address,2]; 8049        if UnalignedSupport() || address<0> = '0' then8050            R[t] = SignExtend(data, 32);8051        else // Can only apply before ARMv78052            R[t] = bits(32) UNKNOWN;8053#endif8054 8055  bool success = false;8056 8057  if (ConditionPassed(opcode)) {8058    uint32_t t;8059    uint32_t imm32;8060    bool add;8061 8062    // EncodingSpecificOperations(); NullCheckIfThumbEE(15);8063    switch (encoding) {8064    case eEncodingT1:8065      // if Rt == '1111' then SEE "Unallocated memory hints";8066      // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1');8067      t = Bits32(opcode, 15, 12);8068      imm32 = Bits32(opcode, 11, 0);8069      add = BitIsSet(opcode, 23);8070 8071      // if t == 13 then UNPREDICTABLE;8072      if (t == 13)8073        return false;8074 8075      break;8076 8077    case eEncodingA1: {8078      // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');8079      t = Bits32(opcode, 15, 12);8080      uint32_t imm4H = Bits32(opcode, 11, 8);8081      uint32_t imm4L = Bits32(opcode, 3, 0);8082      imm32 = (imm4H << 4) | imm4L;8083      add = BitIsSet(opcode, 23);8084 8085      // if t == 15 then UNPREDICTABLE;8086      if (t == 15)8087        return false;8088 8089      break;8090    }8091    default:8092      return false;8093    }8094 8095    // base = Align(PC,4);8096    uint64_t pc_value = ReadCoreReg(PC_REG, &success);8097    if (!success)8098      return false;8099 8100    uint64_t base = AlignPC(pc_value);8101 8102    addr_t address;8103    // address = if add then (base + imm32) else (base - imm32);8104    if (add)8105      address = base + imm32;8106    else8107      address = base - imm32;8108 8109    // data = MemU[address,2];8110    std::optional<RegisterInfo> base_reg =8111        GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);8112 8113    EmulateInstruction::Context context;8114    context.type = eContextRegisterLoad;8115    context.SetRegisterPlusOffset(*base_reg, imm32);8116 8117    uint64_t data = MemURead(context, address, 2, 0, &success);8118    if (!success)8119      return false;8120 8121    // if UnalignedSupport() || address<0> = '0' then8122    if (UnalignedSupport() || BitIsClear(address, 0)) {8123      // R[t] = SignExtend(data, 32);8124      int64_t signed_data = llvm::SignExtend64<16>(data);8125      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,8126                                 (uint64_t)signed_data))8127        return false;8128    } else // Can only apply before ARMv78129    {8130      // R[t] = bits(32) UNKNOWN;8131      WriteBits32Unknown(t);8132    }8133  }8134  return true;8135}8136 8137// LDRSH (register) calculates an address from a base register value and an8138// offset register value, loads a halfword8139// from memory, sign-extends it to form a 32-bit word, and writes it to a8140// register.  The offset register value can be shifted left by 0, 1, 2, or 38141// bits.8142bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode,8143                                                 const ARMEncoding encoding) {8144#if 08145    if ConditionPassed() then 8146        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 8147        offset = Shift(R[m], shift_t, shift_n, APSR.C); 8148        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 8149        address = if index then offset_addr else R[n]; 8150        data = MemU[address,2]; 8151        if wback then R[n] = offset_addr; 8152        if UnalignedSupport() || address<0> = '0' then8153            R[t] = SignExtend(data, 32); 8154        else // Can only apply before ARMv78155            R[t] = bits(32) UNKNOWN;8156#endif8157 8158  bool success = false;8159 8160  if (ConditionPassed(opcode)) {8161    uint32_t t;8162    uint32_t n;8163    uint32_t m;8164    bool index;8165    bool add;8166    bool wback;8167    ARM_ShifterType shift_t;8168    uint32_t shift_n;8169 8170    // EncodingSpecificOperations(); NullCheckIfThumbEE(n);8171    switch (encoding) {8172    case eEncodingT1:8173      // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation8174      // in ThumbEE";8175      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);8176      t = Bits32(opcode, 2, 0);8177      n = Bits32(opcode, 5, 3);8178      m = Bits32(opcode, 8, 6);8179 8180      // index = TRUE; add = TRUE; wback = FALSE;8181      index = true;8182      add = true;8183      wback = false;8184 8185      // (shift_t, shift_n) = (SRType_LSL, 0);8186      shift_t = SRType_LSL;8187      shift_n = 0;8188 8189      break;8190 8191    case eEncodingT2:8192      // if Rn == '1111' then SEE LDRSH (literal);8193      // if Rt == '1111' then SEE "Unallocated memory hints";8194      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);8195      t = Bits32(opcode, 15, 12);8196      n = Bits32(opcode, 19, 16);8197      m = Bits32(opcode, 3, 0);8198 8199      // index = TRUE; add = TRUE; wback = FALSE;8200      index = true;8201      add = true;8202      wback = false;8203 8204      // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));8205      shift_t = SRType_LSL;8206      shift_n = Bits32(opcode, 5, 4);8207 8208      // if t == 13 || BadReg(m) then UNPREDICTABLE;8209      if ((t == 13) || BadReg(m))8210        return false;8211 8212      break;8213 8214    case eEncodingA1:8215      // if P == '0' && W == '1' then SEE LDRSHT;8216      // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);8217      t = Bits32(opcode, 15, 12);8218      n = Bits32(opcode, 19, 16);8219      m = Bits32(opcode, 3, 0);8220 8221      // index = (P == '1');     add = (U == '1');       wback = (P == '0') ||8222      // (W == '1');8223      index = BitIsSet(opcode, 24);8224      add = BitIsSet(opcode, 23);8225      wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);8226 8227      // (shift_t, shift_n) = (SRType_LSL, 0);8228      shift_t = SRType_LSL;8229      shift_n = 0;8230 8231      // if t == 15 || m == 15 then UNPREDICTABLE;8232      if ((t == 15) || (m == 15))8233        return false;8234 8235      // if wback && (n == 15 || n == t) then UNPREDICTABLE;8236      if (wback && ((n == 15) || (n == t)))8237        return false;8238 8239      break;8240 8241    default:8242      return false;8243    }8244 8245    uint64_t Rm =8246        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);8247    if (!success)8248      return false;8249 8250    uint64_t Rn =8251        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);8252    if (!success)8253      return false;8254 8255    // offset = Shift(R[m], shift_t, shift_n, APSR.C);8256    addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success);8257    if (!success)8258      return false;8259 8260    addr_t offset_addr;8261    addr_t address;8262 8263    // offset_addr = if add then (R[n] + offset) else (R[n] - offset);8264    if (add)8265      offset_addr = Rn + offset;8266    else8267      offset_addr = Rn - offset;8268 8269    // address = if index then offset_addr else R[n];8270    if (index)8271      address = offset_addr;8272    else8273      address = Rn;8274 8275    // data = MemU[address,2];8276    std::optional<RegisterInfo> base_reg =8277        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);8278    std::optional<RegisterInfo> offset_reg =8279        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);8280 8281    EmulateInstruction::Context context;8282    context.type = eContextRegisterLoad;8283    context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);8284 8285    uint64_t data = MemURead(context, address, 2, 0, &success);8286    if (!success)8287      return false;8288 8289    // if wback then R[n] = offset_addr;8290    if (wback) {8291      context.type = eContextAdjustBaseRegister;8292      context.SetAddress(offset_addr);8293      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,8294                                 offset_addr))8295        return false;8296    }8297 8298    // if UnalignedSupport() || address<0> = '0' then8299    if (UnalignedSupport() || BitIsClear(address, 0)) {8300      // R[t] = SignExtend(data, 32);8301      context.type = eContextRegisterLoad;8302      context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg);8303 8304      int64_t signed_data = llvm::SignExtend64<16>(data);8305      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t,8306                                 (uint64_t)signed_data))8307        return false;8308    } else // Can only apply before ARMv78309    {8310      // R[t] = bits(32) UNKNOWN;8311      WriteBits32Unknown(t);8312    }8313  }8314  return true;8315}8316 8317// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and8318// writes the result to the destination8319// register.  You can specifiy a rotation by 0, 8, 16, or 24 bits before8320// extracting the 8-bit value.8321bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode,8322                                        const ARMEncoding encoding) {8323#if 08324    if ConditionPassed() then 8325        EncodingSpecificOperations();8326        rotated = ROR(R[m], rotation); 8327        R[d] = SignExtend(rotated<7:0>, 32);8328#endif8329 8330  bool success = false;8331 8332  if (ConditionPassed(opcode)) {8333    uint32_t d;8334    uint32_t m;8335    uint32_t rotation;8336 8337    // EncodingSpecificOperations();8338    switch (encoding) {8339    case eEncodingT1:8340      // d = UInt(Rd); m = UInt(Rm); rotation = 0;8341      d = Bits32(opcode, 2, 0);8342      m = Bits32(opcode, 5, 3);8343      rotation = 0;8344 8345      break;8346 8347    case eEncodingT2:8348      // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8349      d = Bits32(opcode, 11, 8);8350      m = Bits32(opcode, 3, 0);8351      rotation = Bits32(opcode, 5, 4) << 3;8352 8353      // if BadReg(d) || BadReg(m) then UNPREDICTABLE;8354      if (BadReg(d) || BadReg(m))8355        return false;8356 8357      break;8358 8359    case eEncodingA1:8360      // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8361      d = Bits32(opcode, 15, 12);8362      m = Bits32(opcode, 3, 0);8363      rotation = Bits32(opcode, 11, 10) << 3;8364 8365      // if d == 15 || m == 15 then UNPREDICTABLE;8366      if ((d == 15) || (m == 15))8367        return false;8368 8369      break;8370 8371    default:8372      return false;8373    }8374 8375    uint64_t Rm =8376        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);8377    if (!success)8378      return false;8379 8380    // rotated = ROR(R[m], rotation);8381    uint64_t rotated = ROR(Rm, rotation, &success);8382    if (!success)8383      return false;8384 8385    // R[d] = SignExtend(rotated<7:0>, 32);8386    int64_t data = llvm::SignExtend64<8>(rotated);8387 8388    std::optional<RegisterInfo> source_reg =8389        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);8390 8391    EmulateInstruction::Context context;8392    context.type = eContextRegisterLoad;8393    context.SetRegister(*source_reg);8394 8395    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,8396                               (uint64_t)data))8397      return false;8398  }8399  return true;8400}8401 8402// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and8403// writes the result to the destination8404// register.  You can specify a rotation by 0, 8, 16, or 24 bits before8405// extracting the 16-bit value.8406bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode,8407                                        const ARMEncoding encoding) {8408#if 08409    if ConditionPassed() then 8410        EncodingSpecificOperations(); 8411        rotated = ROR(R[m], rotation); 8412        R[d] = SignExtend(rotated<15:0>, 32);8413#endif8414 8415  bool success = false;8416 8417  if (ConditionPassed(opcode)) {8418    uint32_t d;8419    uint32_t m;8420    uint32_t rotation;8421 8422    // EncodingSpecificOperations();8423    switch (encoding) {8424    case eEncodingT1:8425      // d = UInt(Rd); m = UInt(Rm); rotation = 0;8426      d = Bits32(opcode, 2, 0);8427      m = Bits32(opcode, 5, 3);8428      rotation = 0;8429 8430      break;8431 8432    case eEncodingT2:8433      // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8434      d = Bits32(opcode, 11, 8);8435      m = Bits32(opcode, 3, 0);8436      rotation = Bits32(opcode, 5, 4) << 3;8437 8438      // if BadReg(d) || BadReg(m) then UNPREDICTABLE;8439      if (BadReg(d) || BadReg(m))8440        return false;8441 8442      break;8443 8444    case eEncodingA1:8445      // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8446      d = Bits32(opcode, 15, 12);8447      m = Bits32(opcode, 3, 0);8448      rotation = Bits32(opcode, 11, 10) << 3;8449 8450      // if d == 15 || m == 15 then UNPREDICTABLE;8451      if ((d == 15) || (m == 15))8452        return false;8453 8454      break;8455 8456    default:8457      return false;8458    }8459 8460    uint64_t Rm =8461        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);8462    if (!success)8463      return false;8464 8465    // rotated = ROR(R[m], rotation);8466    uint64_t rotated = ROR(Rm, rotation, &success);8467    if (!success)8468      return false;8469 8470    // R[d] = SignExtend(rotated<15:0>, 32);8471    std::optional<RegisterInfo> source_reg =8472        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);8473 8474    EmulateInstruction::Context context;8475    context.type = eContextRegisterLoad;8476    context.SetRegister(*source_reg);8477 8478    int64_t data = llvm::SignExtend64<16>(rotated);8479    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,8480                               (uint64_t)data))8481      return false;8482  }8483 8484  return true;8485}8486 8487// UXTB extracts an 8-bit value from a register, zero-extends it to 32 bits, and8488// writes the result to the destination8489// register.  You can specify a rotation by 0, 8, 16, or 24 bits before8490// extracting the 8-bit value.8491bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode,8492                                        const ARMEncoding encoding) {8493#if 08494    if ConditionPassed() then 8495        EncodingSpecificOperations(); 8496        rotated = ROR(R[m], rotation); 8497        R[d] = ZeroExtend(rotated<7:0>, 32);8498#endif8499 8500  bool success = false;8501 8502  if (ConditionPassed(opcode)) {8503    uint32_t d;8504    uint32_t m;8505    uint32_t rotation;8506 8507    // EncodingSpecificOperations();8508    switch (encoding) {8509    case eEncodingT1:8510      // d = UInt(Rd); m = UInt(Rm); rotation = 0;8511      d = Bits32(opcode, 2, 0);8512      m = Bits32(opcode, 5, 3);8513      rotation = 0;8514 8515      break;8516 8517    case eEncodingT2:8518      // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8519      d = Bits32(opcode, 11, 8);8520      m = Bits32(opcode, 3, 0);8521      rotation = Bits32(opcode, 5, 4) << 3;8522 8523      // if BadReg(d) || BadReg(m) then UNPREDICTABLE;8524      if (BadReg(d) || BadReg(m))8525        return false;8526 8527      break;8528 8529    case eEncodingA1:8530      // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8531      d = Bits32(opcode, 15, 12);8532      m = Bits32(opcode, 3, 0);8533      rotation = Bits32(opcode, 11, 10) << 3;8534 8535      // if d == 15 || m == 15 then UNPREDICTABLE;8536      if ((d == 15) || (m == 15))8537        return false;8538 8539      break;8540 8541    default:8542      return false;8543    }8544 8545    uint64_t Rm =8546        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);8547    if (!success)8548      return false;8549 8550    // rotated = ROR(R[m], rotation);8551    uint64_t rotated = ROR(Rm, rotation, &success);8552    if (!success)8553      return false;8554 8555    // R[d] = ZeroExtend(rotated<7:0>, 32);8556    std::optional<RegisterInfo> source_reg =8557        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);8558 8559    EmulateInstruction::Context context;8560    context.type = eContextRegisterLoad;8561    context.SetRegister(*source_reg);8562 8563    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,8564                               Bits32(rotated, 7, 0)))8565      return false;8566  }8567  return true;8568}8569 8570// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and8571// writes the result to the destination8572// register.  You can specify a rotation by 0, 8, 16, or 24 bits before8573// extracting the 16-bit value.8574bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode,8575                                        const ARMEncoding encoding) {8576#if 08577    if ConditionPassed() then 8578        EncodingSpecificOperations(); 8579        rotated = ROR(R[m], rotation); 8580        R[d] = ZeroExtend(rotated<15:0>, 32);8581#endif8582 8583  bool success = false;8584 8585  if (ConditionPassed(opcode)) {8586    uint32_t d;8587    uint32_t m;8588    uint32_t rotation;8589 8590    switch (encoding) {8591    case eEncodingT1:8592      // d = UInt(Rd); m = UInt(Rm); rotation = 0;8593      d = Bits32(opcode, 2, 0);8594      m = Bits32(opcode, 5, 3);8595      rotation = 0;8596 8597      break;8598 8599    case eEncodingT2:8600      // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8601      d = Bits32(opcode, 11, 8);8602      m = Bits32(opcode, 3, 0);8603      rotation = Bits32(opcode, 5, 4) << 3;8604 8605      // if BadReg(d) || BadReg(m) then UNPREDICTABLE;8606      if (BadReg(d) || BadReg(m))8607        return false;8608 8609      break;8610 8611    case eEncodingA1:8612      // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000');8613      d = Bits32(opcode, 15, 12);8614      m = Bits32(opcode, 3, 0);8615      rotation = Bits32(opcode, 11, 10) << 3;8616 8617      // if d == 15 || m == 15 then UNPREDICTABLE;8618      if ((d == 15) || (m == 15))8619        return false;8620 8621      break;8622 8623    default:8624      return false;8625    }8626 8627    uint64_t Rm =8628        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success);8629    if (!success)8630      return false;8631 8632    // rotated = ROR(R[m], rotation);8633    uint64_t rotated = ROR(Rm, rotation, &success);8634    if (!success)8635      return false;8636 8637    // R[d] = ZeroExtend(rotated<15:0>, 32);8638    std::optional<RegisterInfo> source_reg =8639        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);8640 8641    EmulateInstruction::Context context;8642    context.type = eContextRegisterLoad;8643    context.SetRegister(*source_reg);8644 8645    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,8646                               Bits32(rotated, 15, 0)))8647      return false;8648  }8649  return true;8650}8651 8652// RFE (Return From Exception) loads the PC and the CPSR from the word at the8653// specified address and the following8654// word respectively.8655bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode,8656                                       const ARMEncoding encoding) {8657#if 08658    if ConditionPassed() then 8659        EncodingSpecificOperations(); 8660        if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then8661            UNPREDICTABLE; 8662        else8663            address = if increment then R[n] else R[n]-8; 8664            if wordhigher then address = address+4; 8665            CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 8666            BranchWritePC(MemA[address,4]);8667            if wback then R[n] = if increment then R[n]+8 else R[n]-8;8668#endif8669 8670  bool success = false;8671 8672  if (ConditionPassed(opcode)) {8673    uint32_t n;8674    bool wback;8675    bool increment;8676    bool wordhigher;8677 8678    // EncodingSpecificOperations();8679    switch (encoding) {8680    case eEncodingT1:8681      // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher =8682      // FALSE;8683      n = Bits32(opcode, 19, 16);8684      wback = BitIsSet(opcode, 21);8685      increment = false;8686      wordhigher = false;8687 8688      // if n == 15 then UNPREDICTABLE;8689      if (n == 15)8690        return false;8691 8692      // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;8693      if (InITBlock() && !LastInITBlock())8694        return false;8695 8696      break;8697 8698    case eEncodingT2:8699      // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE;8700      n = Bits32(opcode, 19, 16);8701      wback = BitIsSet(opcode, 21);8702      increment = true;8703      wordhigher = false;8704 8705      // if n == 15 then UNPREDICTABLE;8706      if (n == 15)8707        return false;8708 8709      // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;8710      if (InITBlock() && !LastInITBlock())8711        return false;8712 8713      break;8714 8715    case eEncodingA1:8716      // n = UInt(Rn);8717      n = Bits32(opcode, 19, 16);8718 8719      // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U);8720      wback = BitIsSet(opcode, 21);8721      increment = BitIsSet(opcode, 23);8722      wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23));8723 8724      // if n == 15 then UNPREDICTABLE;8725      if (n == 15)8726        return false;8727 8728      break;8729 8730    default:8731      return false;8732    }8733 8734    // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE8735    // then8736    if (!CurrentModeIsPrivileged())8737      // UNPREDICTABLE;8738      return false;8739    else {8740      uint64_t Rn =8741          ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success);8742      if (!success)8743        return false;8744 8745      addr_t address;8746      // address = if increment then R[n] else R[n]-8;8747      if (increment)8748        address = Rn;8749      else8750        address = Rn - 8;8751 8752      // if wordhigher then address = address+4;8753      if (wordhigher)8754        address = address + 4;8755 8756      // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);8757      std::optional<RegisterInfo> base_reg =8758          GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);8759 8760      EmulateInstruction::Context context;8761      context.type = eContextReturnFromException;8762      context.SetRegisterPlusOffset(*base_reg, address - Rn);8763 8764      uint64_t data = MemARead(context, address + 4, 4, 0, &success);8765      if (!success)8766        return false;8767 8768      CPSRWriteByInstr(data, 15, true);8769 8770      // BranchWritePC(MemA[address,4]);8771      uint64_t data2 = MemARead(context, address, 4, 0, &success);8772      if (!success)8773        return false;8774 8775      BranchWritePC(context, data2);8776 8777      // if wback then R[n] = if increment then R[n]+8 else R[n]-8;8778      if (wback) {8779        context.type = eContextAdjustBaseRegister;8780        if (increment) {8781          context.SetOffset(8);8782          if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,8783                                     Rn + 8))8784            return false;8785        } else {8786          context.SetOffset(-8);8787          if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,8788                                     Rn - 8))8789            return false;8790        }8791      } // if wback8792    }8793  } // if ConditionPassed()8794  return true;8795}8796 8797// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a8798// register value and an immediate value, and writes the result to the8799// destination register.  It can optionally update the condition flags based on8800// the result.8801bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode,8802                                          const ARMEncoding encoding) {8803#if 08804    // ARM pseudo code...8805    if ConditionPassed() then8806        EncodingSpecificOperations();8807        result = R[n] EOR imm32;8808        if d == 15 then         // Can only occur for ARM encoding8809            ALUWritePC(result); // setflags is always FALSE here8810        else8811            R[d] = result;8812            if setflags then8813                APSR.N = result<31>;8814                APSR.Z = IsZeroBit(result);8815                APSR.C = carry;8816                // APSR.V unchanged8817#endif8818 8819  bool success = false;8820 8821  if (ConditionPassed(opcode)) {8822    uint32_t Rd, Rn;8823    uint32_t8824        imm32; // the immediate value to be ORed to the value obtained from Rn8825    bool setflags;8826    uint32_t carry; // the carry bit after ARM/Thumb Expand operation8827    switch (encoding) {8828    case eEncodingT1:8829      Rd = Bits32(opcode, 11, 8);8830      Rn = Bits32(opcode, 19, 16);8831      setflags = BitIsSet(opcode, 20);8832      imm32 = ThumbExpandImm_C(8833          opcode, APSR_C,8834          carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)8835      // if Rd == '1111' && S == '1' then SEE TEQ (immediate);8836      if (Rd == 15 && setflags)8837        return EmulateTEQImm(opcode, eEncodingT1);8838      if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))8839        return false;8840      break;8841    case eEncodingA1:8842      Rd = Bits32(opcode, 15, 12);8843      Rn = Bits32(opcode, 19, 16);8844      setflags = BitIsSet(opcode, 20);8845      imm32 =8846          ARMExpandImm_C(opcode, APSR_C,8847                         carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)8848 8849      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related8850      // instructions;8851      if (Rd == 15 && setflags)8852        return EmulateSUBSPcLrEtc(opcode, encoding);8853      break;8854    default:8855      return false;8856    }8857 8858    // Read the first operand.8859    uint32_t val1 = ReadCoreReg(Rn, &success);8860    if (!success)8861      return false;8862 8863    uint32_t result = val1 ^ imm32;8864 8865    EmulateInstruction::Context context;8866    context.type = EmulateInstruction::eContextImmediate;8867    context.SetNoArgs();8868 8869    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))8870      return false;8871  }8872  return true;8873}8874 8875// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a8876// register value and an optionally-shifted register value, and writes the8877// result to the destination register. It can optionally update the condition8878// flags based on the result.8879bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode,8880                                          const ARMEncoding encoding) {8881#if 08882    // ARM pseudo code...8883    if ConditionPassed() then8884        EncodingSpecificOperations();8885        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);8886        result = R[n] EOR shifted;8887        if d == 15 then         // Can only occur for ARM encoding8888            ALUWritePC(result); // setflags is always FALSE here8889        else8890            R[d] = result;8891            if setflags then8892                APSR.N = result<31>;8893                APSR.Z = IsZeroBit(result);8894                APSR.C = carry;8895                // APSR.V unchanged8896#endif8897 8898  bool success = false;8899 8900  if (ConditionPassed(opcode)) {8901    uint32_t Rd, Rn, Rm;8902    ARM_ShifterType shift_t;8903    uint32_t shift_n; // the shift applied to the value read from Rm8904    bool setflags;8905    uint32_t carry;8906    switch (encoding) {8907    case eEncodingT1:8908      Rd = Rn = Bits32(opcode, 2, 0);8909      Rm = Bits32(opcode, 5, 3);8910      setflags = !InITBlock();8911      shift_t = SRType_LSL;8912      shift_n = 0;8913      break;8914    case eEncodingT2:8915      Rd = Bits32(opcode, 11, 8);8916      Rn = Bits32(opcode, 19, 16);8917      Rm = Bits32(opcode, 3, 0);8918      setflags = BitIsSet(opcode, 20);8919      shift_n = DecodeImmShiftThumb(opcode, shift_t);8920      // if Rd == '1111' && S == '1' then SEE TEQ (register);8921      if (Rd == 15 && setflags)8922        return EmulateTEQReg(opcode, eEncodingT1);8923      if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))8924        return false;8925      break;8926    case eEncodingA1:8927      Rd = Bits32(opcode, 15, 12);8928      Rn = Bits32(opcode, 19, 16);8929      Rm = Bits32(opcode, 3, 0);8930      setflags = BitIsSet(opcode, 20);8931      shift_n = DecodeImmShiftARM(opcode, shift_t);8932 8933      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related8934      // instructions;8935      if (Rd == 15 && setflags)8936        return EmulateSUBSPcLrEtc(opcode, encoding);8937      break;8938    default:8939      return false;8940    }8941 8942    // Read the first operand.8943    uint32_t val1 = ReadCoreReg(Rn, &success);8944    if (!success)8945      return false;8946 8947    // Read the second operand.8948    uint32_t val2 = ReadCoreReg(Rm, &success);8949    if (!success)8950      return false;8951 8952    uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);8953    if (!success)8954      return false;8955    uint32_t result = val1 ^ shifted;8956 8957    EmulateInstruction::Context context;8958    context.type = EmulateInstruction::eContextImmediate;8959    context.SetNoArgs();8960 8961    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))8962      return false;8963  }8964  return true;8965}8966 8967// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value8968// and an immediate value, and writes the result to the destination register.8969// It can optionally update the condition flags based on the result.8970bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode,8971                                          const ARMEncoding encoding) {8972#if 08973    // ARM pseudo code...8974    if ConditionPassed() then8975        EncodingSpecificOperations();8976        result = R[n] OR imm32;8977        if d == 15 then         // Can only occur for ARM encoding8978            ALUWritePC(result); // setflags is always FALSE here8979        else8980            R[d] = result;8981            if setflags then8982                APSR.N = result<31>;8983                APSR.Z = IsZeroBit(result);8984                APSR.C = carry;8985                // APSR.V unchanged8986#endif8987 8988  bool success = false;8989 8990  if (ConditionPassed(opcode)) {8991    uint32_t Rd, Rn;8992    uint32_t8993        imm32; // the immediate value to be ORed to the value obtained from Rn8994    bool setflags;8995    uint32_t carry; // the carry bit after ARM/Thumb Expand operation8996    switch (encoding) {8997    case eEncodingT1:8998      Rd = Bits32(opcode, 11, 8);8999      Rn = Bits32(opcode, 19, 16);9000      setflags = BitIsSet(opcode, 20);9001      imm32 = ThumbExpandImm_C(9002          opcode, APSR_C,9003          carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)9004      // if Rn == '1111' then SEE MOV (immediate);9005      if (Rn == 15)9006        return EmulateMOVRdImm(opcode, eEncodingT2);9007      if (BadReg(Rd) || Rn == 13)9008        return false;9009      break;9010    case eEncodingA1:9011      Rd = Bits32(opcode, 15, 12);9012      Rn = Bits32(opcode, 19, 16);9013      setflags = BitIsSet(opcode, 20);9014      imm32 =9015          ARMExpandImm_C(opcode, APSR_C,9016                         carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)9017 9018      if (Rd == 15 && setflags)9019        return EmulateSUBSPcLrEtc(opcode, encoding);9020      break;9021    default:9022      return false;9023    }9024 9025    // Read the first operand.9026    uint32_t val1 = ReadCoreReg(Rn, &success);9027    if (!success)9028      return false;9029 9030    uint32_t result = val1 | imm32;9031 9032    EmulateInstruction::Context context;9033    context.type = EmulateInstruction::eContextImmediate;9034    context.SetNoArgs();9035 9036    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))9037      return false;9038  }9039  return true;9040}9041 9042// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value9043// and an optionally-shifted register value, and writes the result to the9044// destination register.  It can optionally update the condition flags based on9045// the result.9046bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode,9047                                          const ARMEncoding encoding) {9048#if 09049    // ARM pseudo code...9050    if ConditionPassed() then9051        EncodingSpecificOperations();9052        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);9053        result = R[n] OR shifted;9054        if d == 15 then         // Can only occur for ARM encoding9055            ALUWritePC(result); // setflags is always FALSE here9056        else9057            R[d] = result;9058            if setflags then9059                APSR.N = result<31>;9060                APSR.Z = IsZeroBit(result);9061                APSR.C = carry;9062                // APSR.V unchanged9063#endif9064 9065  bool success = false;9066 9067  if (ConditionPassed(opcode)) {9068    uint32_t Rd, Rn, Rm;9069    ARM_ShifterType shift_t;9070    uint32_t shift_n; // the shift applied to the value read from Rm9071    bool setflags;9072    uint32_t carry;9073    switch (encoding) {9074    case eEncodingT1:9075      Rd = Rn = Bits32(opcode, 2, 0);9076      Rm = Bits32(opcode, 5, 3);9077      setflags = !InITBlock();9078      shift_t = SRType_LSL;9079      shift_n = 0;9080      break;9081    case eEncodingT2:9082      Rd = Bits32(opcode, 11, 8);9083      Rn = Bits32(opcode, 19, 16);9084      Rm = Bits32(opcode, 3, 0);9085      setflags = BitIsSet(opcode, 20);9086      shift_n = DecodeImmShiftThumb(opcode, shift_t);9087      // if Rn == '1111' then SEE MOV (register);9088      if (Rn == 15)9089        return EmulateMOVRdRm(opcode, eEncodingT3);9090      if (BadReg(Rd) || Rn == 13 || BadReg(Rm))9091        return false;9092      break;9093    case eEncodingA1:9094      Rd = Bits32(opcode, 15, 12);9095      Rn = Bits32(opcode, 19, 16);9096      Rm = Bits32(opcode, 3, 0);9097      setflags = BitIsSet(opcode, 20);9098      shift_n = DecodeImmShiftARM(opcode, shift_t);9099 9100      if (Rd == 15 && setflags)9101        return EmulateSUBSPcLrEtc(opcode, encoding);9102      break;9103    default:9104      return false;9105    }9106 9107    // Read the first operand.9108    uint32_t val1 = ReadCoreReg(Rn, &success);9109    if (!success)9110      return false;9111 9112    // Read the second operand.9113    uint32_t val2 = ReadCoreReg(Rm, &success);9114    if (!success)9115      return false;9116 9117    uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);9118    if (!success)9119      return false;9120    uint32_t result = val1 | shifted;9121 9122    EmulateInstruction::Context context;9123    context.type = EmulateInstruction::eContextImmediate;9124    context.SetNoArgs();9125 9126    if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))9127      return false;9128  }9129  return true;9130}9131 9132// Reverse Subtract (immediate) subtracts a register value from an immediate9133// value, and writes the result to the destination register. It can optionally9134// update the condition flags based on the result.9135bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,9136                                          const ARMEncoding encoding) {9137#if 09138    // ARM pseudo code...9139    if ConditionPassed() then9140        EncodingSpecificOperations();9141        (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');9142        if d == 15 then         // Can only occur for ARM encoding9143            ALUWritePC(result); // setflags is always FALSE here9144        else9145            R[d] = result;9146            if setflags then9147                APSR.N = result<31>;9148                APSR.Z = IsZeroBit(result);9149                APSR.C = carry;9150                APSR.V = overflow;9151#endif9152 9153  bool success = false;9154 9155  uint32_t Rd; // the destination register9156  uint32_t Rn; // the first operand9157  bool setflags;9158  uint32_t9159      imm32; // the immediate value to be added to the value obtained from Rn9160  switch (encoding) {9161  case eEncodingT1:9162    Rd = Bits32(opcode, 2, 0);9163    Rn = Bits32(opcode, 5, 3);9164    setflags = !InITBlock();9165    imm32 = 0;9166    break;9167  case eEncodingT2:9168    Rd = Bits32(opcode, 11, 8);9169    Rn = Bits32(opcode, 19, 16);9170    setflags = BitIsSet(opcode, 20);9171    imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)9172    if (BadReg(Rd) || BadReg(Rn))9173      return false;9174    break;9175  case eEncodingA1:9176    Rd = Bits32(opcode, 15, 12);9177    Rn = Bits32(opcode, 19, 16);9178    setflags = BitIsSet(opcode, 20);9179    imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)9180 9181    // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9182    // instructions;9183    if (Rd == 15 && setflags)9184      return EmulateSUBSPcLrEtc(opcode, encoding);9185    break;9186  default:9187    return false;9188  }9189  // Read the register value from the operand register Rn.9190  uint32_t reg_val = ReadCoreReg(Rn, &success);9191  if (!success)9192    return false;9193 9194  AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);9195 9196  EmulateInstruction::Context context;9197  context.type = EmulateInstruction::eContextImmediate;9198  context.SetNoArgs();9199 9200  return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9201                                   res.carry_out, res.overflow);9202}9203 9204// Reverse Subtract (register) subtracts a register value from an optionally-9205// shifted register value, and writes the result to the destination register.9206// It can optionally update the condition flags based on the result.9207bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,9208                                          const ARMEncoding encoding) {9209#if 09210    // ARM pseudo code...9211    if ConditionPassed() then9212        EncodingSpecificOperations();9213        shifted = Shift(R[m], shift_t, shift_n, APSR.C);9214        (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');9215        if d == 15 then         // Can only occur for ARM encoding9216            ALUWritePC(result); // setflags is always FALSE here9217        else9218            R[d] = result;9219            if setflags then9220                APSR.N = result<31>;9221                APSR.Z = IsZeroBit(result);9222                APSR.C = carry;9223                APSR.V = overflow;9224#endif9225 9226  bool success = false;9227 9228  uint32_t Rd; // the destination register9229  uint32_t Rn; // the first operand9230  uint32_t Rm; // the second operand9231  bool setflags;9232  ARM_ShifterType shift_t;9233  uint32_t shift_n; // the shift applied to the value read from Rm9234  switch (encoding) {9235  case eEncodingT1:9236    Rd = Bits32(opcode, 11, 8);9237    Rn = Bits32(opcode, 19, 16);9238    Rm = Bits32(opcode, 3, 0);9239    setflags = BitIsSet(opcode, 20);9240    shift_n = DecodeImmShiftThumb(opcode, shift_t);9241    // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;9242    if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))9243      return false;9244    break;9245  case eEncodingA1:9246    Rd = Bits32(opcode, 15, 12);9247    Rn = Bits32(opcode, 19, 16);9248    Rm = Bits32(opcode, 3, 0);9249    setflags = BitIsSet(opcode, 20);9250    shift_n = DecodeImmShiftARM(opcode, shift_t);9251 9252    // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9253    // instructions;9254    if (Rd == 15 && setflags)9255      return EmulateSUBSPcLrEtc(opcode, encoding);9256    break;9257  default:9258    return false;9259  }9260  // Read the register value from register Rn.9261  uint32_t val1 = ReadCoreReg(Rn, &success);9262  if (!success)9263    return false;9264 9265  // Read the register value from register Rm.9266  uint32_t val2 = ReadCoreReg(Rm, &success);9267  if (!success)9268    return false;9269 9270  uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);9271  if (!success)9272    return false;9273  AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);9274 9275  EmulateInstruction::Context context;9276  context.type = EmulateInstruction::eContextImmediate;9277  context.SetNoArgs();9278  return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9279                                   res.carry_out, res.overflow);9280}9281 9282// Reverse Subtract with Carry (immediate) subtracts a register value and the9283// value of NOT (Carry flag) from an immediate value, and writes the result to9284// the destination register. It can optionally update the condition flags based9285// on the result.9286bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,9287                                          const ARMEncoding encoding) {9288#if 09289    // ARM pseudo code...9290    if ConditionPassed() then9291        EncodingSpecificOperations();9292        (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);9293        if d == 15 then9294            ALUWritePC(result); // setflags is always FALSE here9295        else9296            R[d] = result;9297            if setflags then9298                APSR.N = result<31>;9299                APSR.Z = IsZeroBit(result);9300                APSR.C = carry;9301                APSR.V = overflow;9302#endif9303 9304  bool success = false;9305 9306  uint32_t Rd; // the destination register9307  uint32_t Rn; // the first operand9308  bool setflags;9309  uint32_t9310      imm32; // the immediate value to be added to the value obtained from Rn9311  switch (encoding) {9312  case eEncodingA1:9313    Rd = Bits32(opcode, 15, 12);9314    Rn = Bits32(opcode, 19, 16);9315    setflags = BitIsSet(opcode, 20);9316    imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)9317 9318    // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9319    // instructions;9320    if (Rd == 15 && setflags)9321      return EmulateSUBSPcLrEtc(opcode, encoding);9322    break;9323  default:9324    return false;9325  }9326  // Read the register value from the operand register Rn.9327  uint32_t reg_val = ReadCoreReg(Rn, &success);9328  if (!success)9329    return false;9330 9331  AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);9332 9333  EmulateInstruction::Context context;9334  context.type = EmulateInstruction::eContextImmediate;9335  context.SetNoArgs();9336 9337  return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9338                                   res.carry_out, res.overflow);9339}9340 9341// Reverse Subtract with Carry (register) subtracts a register value and the9342// value of NOT (Carry flag) from an optionally-shifted register value, and9343// writes the result to the destination register. It can optionally update the9344// condition flags based on the result.9345bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,9346                                          const ARMEncoding encoding) {9347#if 09348    // ARM pseudo code...9349    if ConditionPassed() then9350        EncodingSpecificOperations();9351        shifted = Shift(R[m], shift_t, shift_n, APSR.C);9352        (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);9353        if d == 15 then9354            ALUWritePC(result); // setflags is always FALSE here9355        else9356            R[d] = result;9357            if setflags then9358                APSR.N = result<31>;9359                APSR.Z = IsZeroBit(result);9360                APSR.C = carry;9361                APSR.V = overflow;9362#endif9363 9364  bool success = false;9365 9366  uint32_t Rd; // the destination register9367  uint32_t Rn; // the first operand9368  uint32_t Rm; // the second operand9369  bool setflags;9370  ARM_ShifterType shift_t;9371  uint32_t shift_n; // the shift applied to the value read from Rm9372  switch (encoding) {9373  case eEncodingA1:9374    Rd = Bits32(opcode, 15, 12);9375    Rn = Bits32(opcode, 19, 16);9376    Rm = Bits32(opcode, 3, 0);9377    setflags = BitIsSet(opcode, 20);9378    shift_n = DecodeImmShiftARM(opcode, shift_t);9379 9380    // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9381    // instructions;9382    if (Rd == 15 && setflags)9383      return EmulateSUBSPcLrEtc(opcode, encoding);9384    break;9385  default:9386    return false;9387  }9388  // Read the register value from register Rn.9389  uint32_t val1 = ReadCoreReg(Rn, &success);9390  if (!success)9391    return false;9392 9393  // Read the register value from register Rm.9394  uint32_t val2 = ReadCoreReg(Rm, &success);9395  if (!success)9396    return false;9397 9398  uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);9399  if (!success)9400    return false;9401  AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);9402 9403  EmulateInstruction::Context context;9404  context.type = EmulateInstruction::eContextImmediate;9405  context.SetNoArgs();9406  return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9407                                   res.carry_out, res.overflow);9408}9409 9410// Subtract with Carry (immediate) subtracts an immediate value and the value9411// of9412// NOT (Carry flag) from a register value, and writes the result to the9413// destination register.9414// It can optionally update the condition flags based on the result.9415bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,9416                                          const ARMEncoding encoding) {9417#if 09418    // ARM pseudo code...9419    if ConditionPassed() then9420        EncodingSpecificOperations();9421        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);9422        if d == 15 then         // Can only occur for ARM encoding9423            ALUWritePC(result); // setflags is always FALSE here9424        else9425            R[d] = result;9426            if setflags then9427                APSR.N = result<31>;9428                APSR.Z = IsZeroBit(result);9429                APSR.C = carry;9430                APSR.V = overflow;9431#endif9432 9433  bool success = false;9434 9435  uint32_t Rd; // the destination register9436  uint32_t Rn; // the first operand9437  bool setflags;9438  uint32_t9439      imm32; // the immediate value to be added to the value obtained from Rn9440  switch (encoding) {9441  case eEncodingT1:9442    Rd = Bits32(opcode, 11, 8);9443    Rn = Bits32(opcode, 19, 16);9444    setflags = BitIsSet(opcode, 20);9445    imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)9446    if (BadReg(Rd) || BadReg(Rn))9447      return false;9448    break;9449  case eEncodingA1:9450    Rd = Bits32(opcode, 15, 12);9451    Rn = Bits32(opcode, 19, 16);9452    setflags = BitIsSet(opcode, 20);9453    imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)9454 9455    // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9456    // instructions;9457    if (Rd == 15 && setflags)9458      return EmulateSUBSPcLrEtc(opcode, encoding);9459    break;9460  default:9461    return false;9462  }9463  // Read the register value from the operand register Rn.9464  uint32_t reg_val = ReadCoreReg(Rn, &success);9465  if (!success)9466    return false;9467 9468  AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);9469 9470  EmulateInstruction::Context context;9471  context.type = EmulateInstruction::eContextImmediate;9472  context.SetNoArgs();9473 9474  return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9475                                   res.carry_out, res.overflow);9476}9477 9478// Subtract with Carry (register) subtracts an optionally-shifted register9479// value and the value of9480// NOT (Carry flag) from a register value, and writes the result to the9481// destination register.9482// It can optionally update the condition flags based on the result.9483bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,9484                                          const ARMEncoding encoding) {9485#if 09486    // ARM pseudo code...9487    if ConditionPassed() then9488        EncodingSpecificOperations();9489        shifted = Shift(R[m], shift_t, shift_n, APSR.C);9490        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);9491        if d == 15 then         // Can only occur for ARM encoding9492            ALUWritePC(result); // setflags is always FALSE here9493        else9494            R[d] = result;9495            if setflags then9496                APSR.N = result<31>;9497                APSR.Z = IsZeroBit(result);9498                APSR.C = carry;9499                APSR.V = overflow;9500#endif9501 9502  bool success = false;9503 9504  uint32_t Rd; // the destination register9505  uint32_t Rn; // the first operand9506  uint32_t Rm; // the second operand9507  bool setflags;9508  ARM_ShifterType shift_t;9509  uint32_t shift_n; // the shift applied to the value read from Rm9510  switch (encoding) {9511  case eEncodingT1:9512    Rd = Rn = Bits32(opcode, 2, 0);9513    Rm = Bits32(opcode, 5, 3);9514    setflags = !InITBlock();9515    shift_t = SRType_LSL;9516    shift_n = 0;9517    break;9518  case eEncodingT2:9519    Rd = Bits32(opcode, 11, 8);9520    Rn = Bits32(opcode, 19, 16);9521    Rm = Bits32(opcode, 3, 0);9522    setflags = BitIsSet(opcode, 20);9523    shift_n = DecodeImmShiftThumb(opcode, shift_t);9524    if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))9525      return false;9526    break;9527  case eEncodingA1:9528    Rd = Bits32(opcode, 15, 12);9529    Rn = Bits32(opcode, 19, 16);9530    Rm = Bits32(opcode, 3, 0);9531    setflags = BitIsSet(opcode, 20);9532    shift_n = DecodeImmShiftARM(opcode, shift_t);9533 9534    // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9535    // instructions;9536    if (Rd == 15 && setflags)9537      return EmulateSUBSPcLrEtc(opcode, encoding);9538    break;9539  default:9540    return false;9541  }9542  // Read the register value from register Rn.9543  uint32_t val1 = ReadCoreReg(Rn, &success);9544  if (!success)9545    return false;9546 9547  // Read the register value from register Rm.9548  uint32_t val2 = ReadCoreReg(Rm, &success);9549  if (!success)9550    return false;9551 9552  uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);9553  if (!success)9554    return false;9555  AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);9556 9557  EmulateInstruction::Context context;9558  context.type = EmulateInstruction::eContextImmediate;9559  context.SetNoArgs();9560  return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9561                                   res.carry_out, res.overflow);9562}9563 9564// This instruction subtracts an immediate value from a register value, and9565// writes the result to the destination register.  It can optionally update the9566// condition flags based on the result.9567bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,9568                                               const ARMEncoding encoding) {9569#if 09570    // ARM pseudo code...9571    if ConditionPassed() then9572        EncodingSpecificOperations();9573        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');9574        R[d] = result;9575        if setflags then9576            APSR.N = result<31>;9577            APSR.Z = IsZeroBit(result);9578            APSR.C = carry;9579            APSR.V = overflow;9580#endif9581 9582  bool success = false;9583 9584  uint32_t Rd; // the destination register9585  uint32_t Rn; // the first operand9586  bool setflags;9587  uint32_t imm32; // the immediate value to be subtracted from the value9588                  // obtained from Rn9589  switch (encoding) {9590  case eEncodingT1:9591    Rd = Bits32(opcode, 2, 0);9592    Rn = Bits32(opcode, 5, 3);9593    setflags = !InITBlock();9594    imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)9595    break;9596  case eEncodingT2:9597    Rd = Rn = Bits32(opcode, 10, 8);9598    setflags = !InITBlock();9599    imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)9600    break;9601  case eEncodingT3:9602    Rd = Bits32(opcode, 11, 8);9603    Rn = Bits32(opcode, 19, 16);9604    setflags = BitIsSet(opcode, 20);9605    imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)9606 9607    // if Rd == '1111' && S == '1' then SEE CMP (immediate);9608    if (Rd == 15 && setflags)9609      return EmulateCMPImm(opcode, eEncodingT2);9610 9611    // if Rn == '1101' then SEE SUB (SP minus immediate);9612    if (Rn == 13)9613      return EmulateSUBSPImm(opcode, eEncodingT2);9614 9615    // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;9616    if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)9617      return false;9618    break;9619  case eEncodingT4:9620    Rd = Bits32(opcode, 11, 8);9621    Rn = Bits32(opcode, 19, 16);9622    setflags = BitIsSet(opcode, 20);9623    imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)9624 9625    // if Rn == '1111' then SEE ADR;9626    if (Rn == 15)9627      return EmulateADR(opcode, eEncodingT2);9628 9629    // if Rn == '1101' then SEE SUB (SP minus immediate);9630    if (Rn == 13)9631      return EmulateSUBSPImm(opcode, eEncodingT3);9632 9633    if (BadReg(Rd))9634      return false;9635    break;9636  default:9637    return false;9638  }9639  // Read the register value from the operand register Rn.9640  uint32_t reg_val = ReadCoreReg(Rn, &success);9641  if (!success)9642    return false;9643 9644  AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);9645 9646  EmulateInstruction::Context context;9647  context.type = EmulateInstruction::eContextImmediate;9648  context.SetNoArgs();9649 9650  return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9651                                   res.carry_out, res.overflow);9652}9653 9654// This instruction subtracts an immediate value from a register value, and9655// writes the result to the destination register.  It can optionally update the9656// condition flags based on the result.9657bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode,9658                                             const ARMEncoding encoding) {9659#if 09660    // ARM pseudo code...9661    if ConditionPassed() then9662        EncodingSpecificOperations();9663        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');9664        if d == 15 then9665            ALUWritePC(result); // setflags is always FALSE here9666        else9667            R[d] = result;9668            if setflags then9669                APSR.N = result<31>;9670                APSR.Z = IsZeroBit(result);9671                APSR.C = carry;9672                APSR.V = overflow;9673#endif9674 9675  bool success = false;9676 9677  if (ConditionPassed(opcode)) {9678    uint32_t Rd; // the destination register9679    uint32_t Rn; // the first operand9680    bool setflags;9681    uint32_t imm32; // the immediate value to be subtracted from the value9682                    // obtained from Rn9683    switch (encoding) {9684    case eEncodingA1:9685      Rd = Bits32(opcode, 15, 12);9686      Rn = Bits32(opcode, 19, 16);9687      setflags = BitIsSet(opcode, 20);9688      imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)9689 9690      // if Rn == '1111' && S == '0' then SEE ADR;9691      if (Rn == 15 && !setflags)9692        return EmulateADR(opcode, eEncodingA2);9693 9694      // if Rn == '1101' then SEE SUB (SP minus immediate);9695      if (Rn == 13)9696        return EmulateSUBSPImm(opcode, eEncodingA1);9697 9698      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related9699      // instructions;9700      if (Rd == 15 && setflags)9701        return EmulateSUBSPcLrEtc(opcode, encoding);9702      break;9703    default:9704      return false;9705    }9706    // Read the register value from the operand register Rn.9707    uint32_t reg_val = ReadCoreReg(Rn, &success);9708    if (!success)9709      return false;9710 9711    AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);9712 9713    EmulateInstruction::Context context;9714    if (Rd == 13)9715      context.type = EmulateInstruction::eContextAdjustStackPointer;9716    else9717      context.type = EmulateInstruction::eContextRegisterPlusOffset;9718 9719    std::optional<RegisterInfo> dwarf_reg =9720        GetRegisterInfo(eRegisterKindDWARF, Rn);9721    int64_t imm32_signed = imm32;9722    context.SetRegisterPlusOffset(*dwarf_reg, -imm32_signed);9723 9724    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,9725                                   res.carry_out, res.overflow))9726      return false;9727  }9728  return true;9729}9730 9731// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a9732// register value and an immediate value.  It updates the condition flags based9733// on the result, and discards the result.9734bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode,9735                                          const ARMEncoding encoding) {9736#if 09737    // ARM pseudo code...9738    if ConditionPassed() then9739        EncodingSpecificOperations();9740        result = R[n] EOR imm32;9741        APSR.N = result<31>;9742        APSR.Z = IsZeroBit(result);9743        APSR.C = carry;9744        // APSR.V unchanged9745#endif9746 9747  bool success = false;9748 9749  if (ConditionPassed(opcode)) {9750    uint32_t Rn;9751    uint32_t9752        imm32; // the immediate value to be ANDed to the value obtained from Rn9753    uint32_t carry; // the carry bit after ARM/Thumb Expand operation9754    switch (encoding) {9755    case eEncodingT1:9756      Rn = Bits32(opcode, 19, 16);9757      imm32 = ThumbExpandImm_C(9758          opcode, APSR_C,9759          carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)9760      if (BadReg(Rn))9761        return false;9762      break;9763    case eEncodingA1:9764      Rn = Bits32(opcode, 19, 16);9765      imm32 =9766          ARMExpandImm_C(opcode, APSR_C,9767                         carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)9768      break;9769    default:9770      return false;9771    }9772 9773    // Read the first operand.9774    uint32_t val1 = ReadCoreReg(Rn, &success);9775    if (!success)9776      return false;9777 9778    uint32_t result = val1 ^ imm32;9779 9780    EmulateInstruction::Context context;9781    context.type = EmulateInstruction::eContextImmediate;9782    context.SetNoArgs();9783 9784    if (!WriteFlags(context, result, carry))9785      return false;9786  }9787  return true;9788}9789 9790// Test Equivalence (register) performs a bitwise exclusive OR operation on a9791// register value and an optionally-shifted register value.  It updates the9792// condition flags based on the result, and discards the result.9793bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode,9794                                          const ARMEncoding encoding) {9795#if 09796    // ARM pseudo code...9797    if ConditionPassed() then9798        EncodingSpecificOperations();9799        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);9800        result = R[n] EOR shifted;9801        APSR.N = result<31>;9802        APSR.Z = IsZeroBit(result);9803        APSR.C = carry;9804        // APSR.V unchanged9805#endif9806 9807  bool success = false;9808 9809  if (ConditionPassed(opcode)) {9810    uint32_t Rn, Rm;9811    ARM_ShifterType shift_t;9812    uint32_t shift_n; // the shift applied to the value read from Rm9813    uint32_t carry;9814    switch (encoding) {9815    case eEncodingT1:9816      Rn = Bits32(opcode, 19, 16);9817      Rm = Bits32(opcode, 3, 0);9818      shift_n = DecodeImmShiftThumb(opcode, shift_t);9819      if (BadReg(Rn) || BadReg(Rm))9820        return false;9821      break;9822    case eEncodingA1:9823      Rn = Bits32(opcode, 19, 16);9824      Rm = Bits32(opcode, 3, 0);9825      shift_n = DecodeImmShiftARM(opcode, shift_t);9826      break;9827    default:9828      return false;9829    }9830 9831    // Read the first operand.9832    uint32_t val1 = ReadCoreReg(Rn, &success);9833    if (!success)9834      return false;9835 9836    // Read the second operand.9837    uint32_t val2 = ReadCoreReg(Rm, &success);9838    if (!success)9839      return false;9840 9841    uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);9842    if (!success)9843      return false;9844    uint32_t result = val1 ^ shifted;9845 9846    EmulateInstruction::Context context;9847    context.type = EmulateInstruction::eContextImmediate;9848    context.SetNoArgs();9849 9850    if (!WriteFlags(context, result, carry))9851      return false;9852  }9853  return true;9854}9855 9856// Test (immediate) performs a bitwise AND operation on a register value and an9857// immediate value. It updates the condition flags based on the result, and9858// discards the result.9859bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode,9860                                          const ARMEncoding encoding) {9861#if 09862    // ARM pseudo code...9863    if ConditionPassed() then9864        EncodingSpecificOperations();9865        result = R[n] AND imm32;9866        APSR.N = result<31>;9867        APSR.Z = IsZeroBit(result);9868        APSR.C = carry;9869        // APSR.V unchanged9870#endif9871 9872  bool success = false;9873 9874  if (ConditionPassed(opcode)) {9875    uint32_t Rn;9876    uint32_t9877        imm32; // the immediate value to be ANDed to the value obtained from Rn9878    uint32_t carry; // the carry bit after ARM/Thumb Expand operation9879    switch (encoding) {9880    case eEncodingT1:9881      Rn = Bits32(opcode, 19, 16);9882      imm32 = ThumbExpandImm_C(9883          opcode, APSR_C,9884          carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)9885      if (BadReg(Rn))9886        return false;9887      break;9888    case eEncodingA1:9889      Rn = Bits32(opcode, 19, 16);9890      imm32 =9891          ARMExpandImm_C(opcode, APSR_C,9892                         carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)9893      break;9894    default:9895      return false;9896    }9897 9898    // Read the first operand.9899    uint32_t val1 = ReadCoreReg(Rn, &success);9900    if (!success)9901      return false;9902 9903    uint32_t result = val1 & imm32;9904 9905    EmulateInstruction::Context context;9906    context.type = EmulateInstruction::eContextImmediate;9907    context.SetNoArgs();9908 9909    if (!WriteFlags(context, result, carry))9910      return false;9911  }9912  return true;9913}9914 9915// Test (register) performs a bitwise AND operation on a register value and an9916// optionally-shifted register value. It updates the condition flags based on9917// the result, and discards the result.9918bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode,9919                                          const ARMEncoding encoding) {9920#if 09921    // ARM pseudo code...9922    if ConditionPassed() then9923        EncodingSpecificOperations();9924        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);9925        result = R[n] AND shifted;9926        APSR.N = result<31>;9927        APSR.Z = IsZeroBit(result);9928        APSR.C = carry;9929        // APSR.V unchanged9930#endif9931 9932  bool success = false;9933 9934  if (ConditionPassed(opcode)) {9935    uint32_t Rn, Rm;9936    ARM_ShifterType shift_t;9937    uint32_t shift_n; // the shift applied to the value read from Rm9938    uint32_t carry;9939    switch (encoding) {9940    case eEncodingT1:9941      Rn = Bits32(opcode, 2, 0);9942      Rm = Bits32(opcode, 5, 3);9943      shift_t = SRType_LSL;9944      shift_n = 0;9945      break;9946    case eEncodingT2:9947      Rn = Bits32(opcode, 19, 16);9948      Rm = Bits32(opcode, 3, 0);9949      shift_n = DecodeImmShiftThumb(opcode, shift_t);9950      if (BadReg(Rn) || BadReg(Rm))9951        return false;9952      break;9953    case eEncodingA1:9954      Rn = Bits32(opcode, 19, 16);9955      Rm = Bits32(opcode, 3, 0);9956      shift_n = DecodeImmShiftARM(opcode, shift_t);9957      break;9958    default:9959      return false;9960    }9961 9962    // Read the first operand.9963    uint32_t val1 = ReadCoreReg(Rn, &success);9964    if (!success)9965      return false;9966 9967    // Read the second operand.9968    uint32_t val2 = ReadCoreReg(Rm, &success);9969    if (!success)9970      return false;9971 9972    uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);9973    if (!success)9974      return false;9975    uint32_t result = val1 & shifted;9976 9977    EmulateInstruction::Context context;9978    context.type = EmulateInstruction::eContextImmediate;9979    context.SetNoArgs();9980 9981    if (!WriteFlags(context, result, carry))9982      return false;9983  }9984  return true;9985}9986 9987// A8.6.216 SUB (SP minus register)9988bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode,9989                                            const ARMEncoding encoding) {9990#if 09991    if ConditionPassed() then9992        EncodingSpecificOperations();9993        shifted = Shift(R[m], shift_t, shift_n, APSR.C);9994        (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');9995        if d == 15 then // Can only occur for ARM encoding9996            ALUWritePC(result); // setflags is always FALSE here9997        else9998            R[d] = result;9999            if setflags then10000                APSR.N = result<31>;10001                APSR.Z = IsZeroBit(result);10002                APSR.C = carry;10003                APSR.V = overflow;10004#endif10005 10006  bool success = false;10007 10008  if (ConditionPassed(opcode)) {10009    uint32_t d;10010    uint32_t m;10011    bool setflags;10012    ARM_ShifterType shift_t;10013    uint32_t shift_n;10014 10015    switch (encoding) {10016    case eEncodingT1:10017      // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');10018      d = Bits32(opcode, 11, 8);10019      m = Bits32(opcode, 3, 0);10020      setflags = BitIsSet(opcode, 20);10021 10022      // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);10023      shift_n = DecodeImmShiftThumb(opcode, shift_t);10024 10025      // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then10026      // UNPREDICTABLE;10027      if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))10028        return false;10029 10030      // if d == 15 || BadReg(m) then UNPREDICTABLE;10031      if ((d == 15) || BadReg(m))10032        return false;10033      break;10034 10035    case eEncodingA1:10036      // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1');10037      d = Bits32(opcode, 15, 12);10038      m = Bits32(opcode, 3, 0);10039      setflags = BitIsSet(opcode, 20);10040 10041      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related10042      // instructions;10043      if (d == 15 && setflags)10044        EmulateSUBSPcLrEtc(opcode, encoding);10045 10046      // (shift_t, shift_n) = DecodeImmShift(type, imm5);10047      shift_n = DecodeImmShiftARM(opcode, shift_t);10048      break;10049 10050    default:10051      return false;10052    }10053 10054    // shifted = Shift(R[m], shift_t, shift_n, APSR.C);10055    uint32_t Rm = ReadCoreReg(m, &success);10056    if (!success)10057      return false;10058 10059    uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);10060    if (!success)10061      return false;10062 10063    // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1');10064    uint32_t sp_val = ReadCoreReg(SP_REG, &success);10065    if (!success)10066      return false;10067 10068    AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1);10069 10070    EmulateInstruction::Context context;10071    context.type = eContextArithmetic;10072    std::optional<RegisterInfo> sp_reg =10073        GetRegisterInfo(eRegisterKindDWARF, dwarf_sp);10074    std::optional<RegisterInfo> dwarf_reg =10075        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);10076    context.SetRegisterRegisterOperands(*sp_reg, *dwarf_reg);10077 10078    if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,10079                                   res.carry_out, res.overflow))10080      return false;10081  }10082  return true;10083}10084 10085// A8.6.7 ADD (register-shifted register)10086bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode,10087                                               const ARMEncoding encoding) {10088#if 010089    if ConditionPassed() then10090        EncodingSpecificOperations();10091        shift_n = UInt(R[s]<7:0>);10092        shifted = Shift(R[m], shift_t, shift_n, APSR.C);10093        (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');10094        R[d] = result;10095        if setflags then10096            APSR.N = result<31>;10097            APSR.Z = IsZeroBit(result);10098            APSR.C = carry;10099            APSR.V = overflow;10100#endif10101 10102  bool success = false;10103 10104  if (ConditionPassed(opcode)) {10105    uint32_t d;10106    uint32_t n;10107    uint32_t m;10108    uint32_t s;10109    bool setflags;10110    ARM_ShifterType shift_t;10111 10112    switch (encoding) {10113    case eEncodingA1:10114      // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);10115      d = Bits32(opcode, 15, 12);10116      n = Bits32(opcode, 19, 16);10117      m = Bits32(opcode, 3, 0);10118      s = Bits32(opcode, 11, 8);10119 10120      // setflags = (S == '1'); shift_t = DecodeRegShift(type);10121      setflags = BitIsSet(opcode, 20);10122      shift_t = DecodeRegShift(Bits32(opcode, 6, 5));10123 10124      // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;10125      if ((d == 15) || (n == 15) || (m == 15) || (s == 15))10126        return false;10127      break;10128 10129    default:10130      return false;10131    }10132 10133    // shift_n = UInt(R[s]<7:0>);10134    uint32_t Rs = ReadCoreReg(s, &success);10135    if (!success)10136      return false;10137 10138    uint32_t shift_n = Bits32(Rs, 7, 0);10139 10140    // shifted = Shift(R[m], shift_t, shift_n, APSR.C);10141    uint32_t Rm = ReadCoreReg(m, &success);10142    if (!success)10143      return false;10144 10145    uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);10146    if (!success)10147      return false;10148 10149    // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');10150    uint32_t Rn = ReadCoreReg(n, &success);10151    if (!success)10152      return false;10153 10154    AddWithCarryResult res = AddWithCarry(Rn, shifted, 0);10155 10156    // R[d] = result;10157    EmulateInstruction::Context context;10158    context.type = eContextArithmetic;10159    std::optional<RegisterInfo> reg_n =10160        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10161    std::optional<RegisterInfo> reg_m =10162        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);10163 10164    context.SetRegisterRegisterOperands(*reg_n, *reg_m);10165 10166    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,10167                               res.result))10168      return false;10169 10170    // if setflags then10171    // APSR.N = result<31>;10172    // APSR.Z = IsZeroBit(result);10173    // APSR.C = carry;10174    // APSR.V = overflow;10175    if (setflags)10176      return WriteFlags(context, res.result, res.carry_out, res.overflow);10177  }10178  return true;10179}10180 10181// A8.6.213 SUB (register)10182bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode,10183                                          const ARMEncoding encoding) {10184#if 010185    if ConditionPassed() then10186        EncodingSpecificOperations();10187        shifted = Shift(R[m], shift_t, shift_n, APSR.C);10188        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');10189        if d == 15 then // Can only occur for ARM encoding10190            ALUWritePC(result); // setflags is always FALSE here10191        else10192            R[d] = result;10193            if setflags then10194                APSR.N = result<31>;10195                APSR.Z = IsZeroBit(result);10196                APSR.C = carry;10197                APSR.V = overflow;10198#endif10199 10200  bool success = false;10201 10202  if (ConditionPassed(opcode)) {10203    uint32_t d;10204    uint32_t n;10205    uint32_t m;10206    bool setflags;10207    ARM_ShifterType shift_t;10208    uint32_t shift_n;10209 10210    switch (encoding) {10211    case eEncodingT1:10212      // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();10213      d = Bits32(opcode, 2, 0);10214      n = Bits32(opcode, 5, 3);10215      m = Bits32(opcode, 8, 6);10216      setflags = !InITBlock();10217 10218      // (shift_t, shift_n) = (SRType_LSL, 0);10219      shift_t = SRType_LSL;10220      shift_n = 0;10221 10222      break;10223 10224    case eEncodingT2:10225      // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1");10226      d = Bits32(opcode, 11, 8);10227      n = Bits32(opcode, 19, 16);10228      m = Bits32(opcode, 3, 0);10229      setflags = BitIsSet(opcode, 20);10230 10231      // if Rd == "1111" && S == "1" then SEE CMP (register);10232      if (d == 15 && setflags == 1)10233        return EmulateCMPImm(opcode, eEncodingT3);10234 10235      // if Rn == "1101" then SEE SUB (SP minus register);10236      if (n == 13)10237        return EmulateSUBSPReg(opcode, eEncodingT1);10238 10239      // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);10240      shift_n = DecodeImmShiftThumb(opcode, shift_t);10241 10242      // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then10243      // UNPREDICTABLE;10244      if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) ||10245          BadReg(m))10246        return false;10247 10248      break;10249 10250    case eEncodingA1:10251      // if Rn == '1101' then SEE SUB (SP minus register);10252      // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1');10253      d = Bits32(opcode, 15, 12);10254      n = Bits32(opcode, 19, 16);10255      m = Bits32(opcode, 3, 0);10256      setflags = BitIsSet(opcode, 20);10257 10258      // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related10259      // instructions;10260      if ((d == 15) && setflags)10261        EmulateSUBSPcLrEtc(opcode, encoding);10262 10263      // (shift_t, shift_n) = DecodeImmShift(type, imm5);10264      shift_n = DecodeImmShiftARM(opcode, shift_t);10265 10266      break;10267 10268    default:10269      return false;10270    }10271 10272    // shifted = Shift(R[m], shift_t, shift_n, APSR.C);10273    uint32_t Rm = ReadCoreReg(m, &success);10274    if (!success)10275      return false;10276 10277    uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success);10278    if (!success)10279      return false;10280 10281    // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');10282    uint32_t Rn = ReadCoreReg(n, &success);10283    if (!success)10284      return false;10285 10286    AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1);10287 10288    // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result);10289    // // setflags is always FALSE here else10290    // R[d] = result;10291    // if setflags then10292    // APSR.N = result<31>;10293    // APSR.Z = IsZeroBit(result);10294    // APSR.C = carry;10295    // APSR.V = overflow;10296 10297    EmulateInstruction::Context context;10298    context.type = eContextArithmetic;10299    std::optional<RegisterInfo> reg_n =10300        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10301    std::optional<RegisterInfo> reg_m =10302        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);10303    context.SetRegisterRegisterOperands(*reg_n, *reg_m);10304 10305    if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags,10306                                   res.carry_out, res.overflow))10307      return false;10308  }10309  return true;10310}10311 10312// A8.6.202 STREX10313// Store Register Exclusive calculates an address from a base register value10314// and an immediate offset, and stores a word from a register to memory if the10315// executing processor has exclusive access to the memory addressed.10316bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode,10317                                         const ARMEncoding encoding) {10318#if 010319    if ConditionPassed() then10320        EncodingSpecificOperations(); NullCheckIfThumbEE(n);10321        address = R[n] + imm32;10322        if ExclusiveMonitorsPass(address,4) then10323            MemA[address,4] = R[t];10324            R[d] = 0;10325        else10326            R[d] = 1;10327#endif10328 10329  bool success = false;10330 10331  if (ConditionPassed(opcode)) {10332    uint32_t d;10333    uint32_t t;10334    uint32_t n;10335    uint32_t imm32;10336    const uint32_t addr_byte_size = GetAddressByteSize();10337 10338    switch (encoding) {10339    case eEncodingT1:10340      // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 =10341      // ZeroExtend(imm8:'00',10342      // 32);10343      d = Bits32(opcode, 11, 8);10344      t = Bits32(opcode, 15, 12);10345      n = Bits32(opcode, 19, 16);10346      imm32 = Bits32(opcode, 7, 0) << 2;10347 10348      // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;10349      if (BadReg(d) || BadReg(t) || (n == 15))10350        return false;10351 10352      // if d == n || d == t then UNPREDICTABLE;10353      if ((d == n) || (d == t))10354        return false;10355 10356      break;10357 10358    case eEncodingA1:10359      // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero10360      // offset10361      d = Bits32(opcode, 15, 12);10362      t = Bits32(opcode, 3, 0);10363      n = Bits32(opcode, 19, 16);10364      imm32 = 0;10365 10366      // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;10367      if ((d == 15) || (t == 15) || (n == 15))10368        return false;10369 10370      // if d == n || d == t then UNPREDICTABLE;10371      if ((d == n) || (d == t))10372        return false;10373 10374      break;10375 10376    default:10377      return false;10378    }10379 10380    // address = R[n] + imm32;10381    uint32_t Rn = ReadCoreReg(n, &success);10382    if (!success)10383      return false;10384 10385    addr_t address = Rn + imm32;10386 10387    std::optional<RegisterInfo> base_reg =10388        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10389    std::optional<RegisterInfo> data_reg =10390        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);10391    EmulateInstruction::Context context;10392    context.type = eContextRegisterStore;10393    context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, imm32);10394 10395    // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass10396    // (address, addr_byte_size)) -- For now, for the sake of emulation, we10397    // will say this10398    //                                                         always return10399    //                                                         true.10400    if (true) {10401      // MemA[address,4] = R[t];10402      uint32_t Rt =10403          ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success);10404      if (!success)10405        return false;10406 10407      if (!MemAWrite(context, address, Rt, addr_byte_size))10408        return false;10409 10410      // R[d] = 0;10411      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0))10412        return false;10413    }10414#if 0  // unreachable because if true10415        else10416        {10417            // R[d] = 1;10418            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))10419                return false;10420        }10421#endif // unreachable because if true10422  }10423  return true;10424}10425 10426// A8.6.197 STRB (immediate, ARM)10427bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode,10428                                              const ARMEncoding encoding) {10429#if 010430    if ConditionPassed() then10431        EncodingSpecificOperations();10432        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10433        address = if index then offset_addr else R[n];10434        MemU[address,1] = R[t]<7:0>;10435        if wback then R[n] = offset_addr;10436#endif10437 10438  bool success = false;10439 10440  if (ConditionPassed(opcode)) {10441    uint32_t t;10442    uint32_t n;10443    uint32_t imm32;10444    bool index;10445    bool add;10446    bool wback;10447 10448    switch (encoding) {10449    case eEncodingA1:10450      // if P == '0' && W == '1' then SEE STRBT;10451      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);10452      t = Bits32(opcode, 15, 12);10453      n = Bits32(opcode, 19, 16);10454      imm32 = Bits32(opcode, 11, 0);10455 10456      // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');10457      index = BitIsSet(opcode, 24);10458      add = BitIsSet(opcode, 23);10459      wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);10460 10461      // if t == 15 then UNPREDICTABLE;10462      if (t == 15)10463        return false;10464 10465      // if wback && (n == 15 || n == t) then UNPREDICTABLE;10466      if (wback && ((n == 15) || (n == t)))10467        return false;10468 10469      break;10470 10471    default:10472      return false;10473    }10474 10475    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10476    uint32_t Rn = ReadCoreReg(n, &success);10477    if (!success)10478      return false;10479 10480    addr_t offset_addr;10481    if (add)10482      offset_addr = Rn + imm32;10483    else10484      offset_addr = Rn - imm32;10485 10486    // address = if index then offset_addr else R[n];10487    addr_t address;10488    if (index)10489      address = offset_addr;10490    else10491      address = Rn;10492 10493    // MemU[address,1] = R[t]<7:0>;10494    uint32_t Rt = ReadCoreReg(t, &success);10495    if (!success)10496      return false;10497 10498    std::optional<RegisterInfo> base_reg =10499        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10500    std::optional<RegisterInfo> data_reg =10501        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);10502    EmulateInstruction::Context context;10503    context.type = eContextRegisterStore;10504    context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);10505 10506    if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1))10507      return false;10508 10509    // if wback then R[n] = offset_addr;10510    if (wback) {10511      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,10512                                 offset_addr))10513        return false;10514    }10515  }10516  return true;10517}10518 10519// A8.6.194 STR (immediate, ARM)10520bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode,10521                                             const ARMEncoding encoding) {10522#if 010523    if ConditionPassed() then10524        EncodingSpecificOperations();10525        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10526        address = if index then offset_addr else R[n];10527        MemU[address,4] = if t == 15 then PCStoreValue() else R[t];10528        if wback then R[n] = offset_addr;10529#endif10530 10531  bool success = false;10532 10533  if (ConditionPassed(opcode)) {10534    uint32_t t;10535    uint32_t n;10536    uint32_t imm32;10537    bool index;10538    bool add;10539    bool wback;10540 10541    const uint32_t addr_byte_size = GetAddressByteSize();10542 10543    switch (encoding) {10544    case eEncodingA1:10545      // if P == '0' && W == '1' then SEE STRT;10546      // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 ==10547      // '000000000100' then SEE PUSH;10548      // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);10549      t = Bits32(opcode, 15, 12);10550      n = Bits32(opcode, 19, 16);10551      imm32 = Bits32(opcode, 11, 0);10552 10553      // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');10554      index = BitIsSet(opcode, 24);10555      add = BitIsSet(opcode, 23);10556      wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);10557 10558      // if wback && (n == 15 || n == t) then UNPREDICTABLE;10559      if (wback && ((n == 15) || (n == t)))10560        return false;10561 10562      break;10563 10564    default:10565      return false;10566    }10567 10568    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10569    uint32_t Rn = ReadCoreReg(n, &success);10570    if (!success)10571      return false;10572 10573    addr_t offset_addr;10574    if (add)10575      offset_addr = Rn + imm32;10576    else10577      offset_addr = Rn - imm32;10578 10579    // address = if index then offset_addr else R[n];10580    addr_t address;10581    if (index)10582      address = offset_addr;10583    else10584      address = Rn;10585 10586    std::optional<RegisterInfo> base_reg =10587        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10588    std::optional<RegisterInfo> data_reg =10589        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);10590    EmulateInstruction::Context context;10591    context.type = eContextRegisterStore;10592    context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);10593 10594    // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];10595    uint32_t Rt = ReadCoreReg(t, &success);10596    if (!success)10597      return false;10598 10599    if (t == 15) {10600      uint32_t pc_value = ReadCoreReg(PC_REG, &success);10601      if (!success)10602        return false;10603 10604      if (!MemUWrite(context, address, pc_value, addr_byte_size))10605        return false;10606    } else {10607      if (!MemUWrite(context, address, Rt, addr_byte_size))10608        return false;10609    }10610 10611    // if wback then R[n] = offset_addr;10612    if (wback) {10613      context.type = eContextAdjustBaseRegister;10614      context.SetImmediate(offset_addr);10615 10616      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,10617                                 offset_addr))10618        return false;10619    }10620  }10621  return true;10622}10623 10624// A8.6.66 LDRD (immediate)10625// Load Register Dual (immediate) calculates an address from a base register10626// value and an immediate offset, loads two words from memory, and writes them10627// to two registers.  It can use offset, post-indexed, or pre-indexed10628// addressing.10629bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode,10630                                                 const ARMEncoding encoding) {10631#if 010632    if ConditionPassed() then10633        EncodingSpecificOperations(); NullCheckIfThumbEE(n);10634        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10635        address = if index then offset_addr else R[n];10636        R[t] = MemA[address,4];10637        R[t2] = MemA[address+4,4];10638        if wback then R[n] = offset_addr;10639#endif10640 10641  bool success = false;10642 10643  if (ConditionPassed(opcode)) {10644    uint32_t t;10645    uint32_t t2;10646    uint32_t n;10647    uint32_t imm32;10648    bool index;10649    bool add;10650    bool wback;10651 10652    switch (encoding) {10653    case eEncodingT1:10654      // if P == '0' && W == '0' then SEE 'Related encodings';10655      // if Rn == '1111' then SEE LDRD (literal);10656      // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =10657      // ZeroExtend(imm8:'00', 32);10658      t = Bits32(opcode, 15, 12);10659      t2 = Bits32(opcode, 11, 8);10660      n = Bits32(opcode, 19, 16);10661      imm32 = Bits32(opcode, 7, 0) << 2;10662 10663      // index = (P == '1'); add = (U == '1'); wback = (W == '1');10664      index = BitIsSet(opcode, 24);10665      add = BitIsSet(opcode, 23);10666      wback = BitIsSet(opcode, 21);10667 10668      // if wback && (n == t || n == t2) then UNPREDICTABLE;10669      if (wback && ((n == t) || (n == t2)))10670        return false;10671 10672      // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;10673      if (BadReg(t) || BadReg(t2) || (t == t2))10674        return false;10675 10676      break;10677 10678    case eEncodingA1:10679      // if Rn == '1111' then SEE LDRD (literal);10680      // if Rt<0> == '1' then UNPREDICTABLE;10681      // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,10682      // 32);10683      t = Bits32(opcode, 15, 12);10684      if (BitIsSet(t, 0))10685        return false;10686      t2 = t + 1;10687      n = Bits32(opcode, 19, 16);10688      imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);10689 10690      // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');10691      index = BitIsSet(opcode, 24);10692      add = BitIsSet(opcode, 23);10693      wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);10694 10695      // if P == '0' && W == '1' then UNPREDICTABLE;10696      if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))10697        return false;10698 10699      // if wback && (n == t || n == t2) then UNPREDICTABLE;10700      if (wback && ((n == t) || (n == t2)))10701        return false;10702 10703      // if t2 == 15 then UNPREDICTABLE;10704      if (t2 == 15)10705        return false;10706 10707      break;10708 10709    default:10710      return false;10711    }10712 10713    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10714    uint32_t Rn = ReadCoreReg(n, &success);10715    if (!success)10716      return false;10717 10718    addr_t offset_addr;10719    if (add)10720      offset_addr = Rn + imm32;10721    else10722      offset_addr = Rn - imm32;10723 10724    // address = if index then offset_addr else R[n];10725    addr_t address;10726    if (index)10727      address = offset_addr;10728    else10729      address = Rn;10730 10731    // R[t] = MemA[address,4];10732 10733    EmulateInstruction::Context context;10734    if (n == 13)10735      context.type = eContextPopRegisterOffStack;10736    else10737      context.type = eContextRegisterLoad;10738    context.SetAddress(address);10739 10740    const uint32_t addr_byte_size = GetAddressByteSize();10741    uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);10742    if (!success)10743      return false;10744 10745    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))10746      return false;10747 10748    // R[t2] = MemA[address+4,4];10749    context.SetAddress(address + 4);10750    data = MemARead(context, address + 4, addr_byte_size, 0, &success);10751    if (!success)10752      return false;10753 10754    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,10755                               data))10756      return false;10757 10758    // if wback then R[n] = offset_addr;10759    if (wback) {10760      context.type = eContextAdjustBaseRegister;10761      context.SetAddress(offset_addr);10762 10763      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,10764                                 offset_addr))10765        return false;10766    }10767  }10768  return true;10769}10770 10771// A8.6.68 LDRD (register)10772// Load Register Dual (register) calculates an address from a base register10773// value and a register offset, loads two words from memory, and writes them to10774// two registers.  It can use offset, post-indexed or pre-indexed addressing.10775bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode,10776                                                const ARMEncoding encoding) {10777#if 010778    if ConditionPassed() then10779        EncodingSpecificOperations();10780        offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);10781        address = if index then offset_addr else R[n];10782        R[t] = MemA[address,4];10783        R[t2] = MemA[address+4,4];10784        if wback then R[n] = offset_addr;10785#endif10786 10787  bool success = false;10788 10789  if (ConditionPassed(opcode)) {10790    uint32_t t;10791    uint32_t t2;10792    uint32_t n;10793    uint32_t m;10794    bool index;10795    bool add;10796    bool wback;10797 10798    switch (encoding) {10799    case eEncodingA1:10800      // if Rt<0> == '1' then UNPREDICTABLE;10801      // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);10802      t = Bits32(opcode, 15, 12);10803      if (BitIsSet(t, 0))10804        return false;10805      t2 = t + 1;10806      n = Bits32(opcode, 19, 16);10807      m = Bits32(opcode, 3, 0);10808 10809      // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');10810      index = BitIsSet(opcode, 24);10811      add = BitIsSet(opcode, 23);10812      wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);10813 10814      // if P == '0' && W == '1' then UNPREDICTABLE;10815      if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))10816        return false;10817 10818      // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;10819      if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))10820        return false;10821 10822      // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;10823      if (wback && ((n == 15) || (n == t) || (n == t2)))10824        return false;10825 10826      // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;10827      if ((ArchVersion() < 6) && wback && (m == n))10828        return false;10829      break;10830 10831    default:10832      return false;10833    }10834 10835    uint32_t Rn = ReadCoreReg(n, &success);10836    if (!success)10837      return false;10838 10839    uint32_t Rm = ReadCoreReg(m, &success);10840    if (!success)10841      return false;10842 10843    // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);10844    addr_t offset_addr;10845    if (add)10846      offset_addr = Rn + Rm;10847    else10848      offset_addr = Rn - Rm;10849 10850    // address = if index then offset_addr else R[n];10851    addr_t address;10852    if (index)10853      address = offset_addr;10854    else10855      address = Rn;10856 10857    EmulateInstruction::Context context;10858    if (n == 13)10859      context.type = eContextPopRegisterOffStack;10860    else10861      context.type = eContextRegisterLoad;10862    context.SetAddress(address);10863 10864    // R[t] = MemA[address,4];10865    const uint32_t addr_byte_size = GetAddressByteSize();10866    uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);10867    if (!success)10868      return false;10869 10870    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data))10871      return false;10872 10873    // R[t2] = MemA[address+4,4];10874 10875    data = MemARead(context, address + 4, addr_byte_size, 0, &success);10876    if (!success)10877      return false;10878 10879    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2,10880                               data))10881      return false;10882 10883    // if wback then R[n] = offset_addr;10884    if (wback) {10885      context.type = eContextAdjustBaseRegister;10886      context.SetAddress(offset_addr);10887 10888      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,10889                                 offset_addr))10890        return false;10891    }10892  }10893  return true;10894}10895 10896// A8.6.200 STRD (immediate)10897// Store Register Dual (immediate) calculates an address from a base register10898// value and an immediate offset, and stores two words from two registers to10899// memory.  It can use offset, post-indexed, or pre-indexed addressing.10900bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode,10901                                           const ARMEncoding encoding) {10902#if 010903    if ConditionPassed() then10904        EncodingSpecificOperations(); NullCheckIfThumbEE(n);10905        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10906        address = if index then offset_addr else R[n];10907        MemA[address,4] = R[t];10908        MemA[address+4,4] = R[t2];10909        if wback then R[n] = offset_addr;10910#endif10911 10912  bool success = false;10913 10914  if (ConditionPassed(opcode)) {10915    uint32_t t;10916    uint32_t t2;10917    uint32_t n;10918    uint32_t imm32;10919    bool index;10920    bool add;10921    bool wback;10922 10923    switch (encoding) {10924    case eEncodingT1:10925      // if P == '0' && W == '0' then SEE 'Related encodings';10926      // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 =10927      // ZeroExtend(imm8:'00', 32);10928      t = Bits32(opcode, 15, 12);10929      t2 = Bits32(opcode, 11, 8);10930      n = Bits32(opcode, 19, 16);10931      imm32 = Bits32(opcode, 7, 0) << 2;10932 10933      // index = (P == '1'); add = (U == '1'); wback = (W == '1');10934      index = BitIsSet(opcode, 24);10935      add = BitIsSet(opcode, 23);10936      wback = BitIsSet(opcode, 21);10937 10938      // if wback && (n == t || n == t2) then UNPREDICTABLE;10939      if (wback && ((n == t) || (n == t2)))10940        return false;10941 10942      // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;10943      if ((n == 15) || BadReg(t) || BadReg(t2))10944        return false;10945 10946      break;10947 10948    case eEncodingA1:10949      // if Rt<0> == '1' then UNPREDICTABLE;10950      // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L,10951      // 32);10952      t = Bits32(opcode, 15, 12);10953      if (BitIsSet(t, 0))10954        return false;10955 10956      t2 = t + 1;10957      n = Bits32(opcode, 19, 16);10958      imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0);10959 10960      // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');10961      index = BitIsSet(opcode, 24);10962      add = BitIsSet(opcode, 23);10963      wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);10964 10965      // if P == '0' && W == '1' then UNPREDICTABLE;10966      if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))10967        return false;10968 10969      // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;10970      if (wback && ((n == 15) || (n == t) || (n == t2)))10971        return false;10972 10973      // if t2 == 15 then UNPREDICTABLE;10974      if (t2 == 15)10975        return false;10976 10977      break;10978 10979    default:10980      return false;10981    }10982 10983    std::optional<RegisterInfo> base_reg =10984        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);10985 10986    uint32_t Rn = ReadCoreReg(n, &success);10987    if (!success)10988      return false;10989 10990    // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);10991    addr_t offset_addr;10992    if (add)10993      offset_addr = Rn + imm32;10994    else10995      offset_addr = Rn - imm32;10996 10997    // address = if index then offset_addr else R[n];10998    addr_t address;10999    if (index)11000      address = offset_addr;11001    else11002      address = Rn;11003 11004    // MemA[address,4] = R[t];11005    std::optional<RegisterInfo> data_reg =11006        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);11007 11008    uint32_t data = ReadCoreReg(t, &success);11009    if (!success)11010      return false;11011 11012    EmulateInstruction::Context context;11013    if (n == 13)11014      context.type = eContextPushRegisterOnStack;11015    else11016      context.type = eContextRegisterStore;11017    context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);11018 11019    const uint32_t addr_byte_size = GetAddressByteSize();11020 11021    if (!MemAWrite(context, address, data, addr_byte_size))11022      return false;11023 11024    // MemA[address+4,4] = R[t2];11025    data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2);11026    context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11027                                            (address + 4) - Rn);11028 11029    data = ReadCoreReg(t2, &success);11030    if (!success)11031      return false;11032 11033    if (!MemAWrite(context, address + 4, data, addr_byte_size))11034      return false;11035 11036    // if wback then R[n] = offset_addr;11037    if (wback) {11038      if (n == 13)11039        context.type = eContextAdjustStackPointer;11040      else11041        context.type = eContextAdjustBaseRegister;11042      context.SetAddress(offset_addr);11043 11044      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,11045                                 offset_addr))11046        return false;11047    }11048  }11049  return true;11050}11051 11052// A8.6.201 STRD (register)11053bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode,11054                                           const ARMEncoding encoding) {11055#if 011056    if ConditionPassed() then11057        EncodingSpecificOperations();11058        offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);11059        address = if index then offset_addr else R[n];11060        MemA[address,4] = R[t];11061        MemA[address+4,4] = R[t2];11062        if wback then R[n] = offset_addr;11063#endif11064 11065  bool success = false;11066 11067  if (ConditionPassed(opcode)) {11068    uint32_t t;11069    uint32_t t2;11070    uint32_t n;11071    uint32_t m;11072    bool index;11073    bool add;11074    bool wback;11075 11076    switch (encoding) {11077    case eEncodingA1:11078      // if Rt<0> == '1' then UNPREDICTABLE;11079      // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);11080      t = Bits32(opcode, 15, 12);11081      if (BitIsSet(t, 0))11082        return false;11083 11084      t2 = t + 1;11085      n = Bits32(opcode, 19, 16);11086      m = Bits32(opcode, 3, 0);11087 11088      // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1');11089      index = BitIsSet(opcode, 24);11090      add = BitIsSet(opcode, 23);11091      wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21);11092 11093      // if P == '0' && W == '1' then UNPREDICTABLE;11094      if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21))11095        return false;11096 11097      // if t2 == 15 || m == 15 then UNPREDICTABLE;11098      if ((t2 == 15) || (m == 15))11099        return false;11100 11101      // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;11102      if (wback && ((n == 15) || (n == t) || (n == t2)))11103        return false;11104 11105      // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;11106      if ((ArchVersion() < 6) && wback && (m == n))11107        return false;11108 11109      break;11110 11111    default:11112      return false;11113    }11114 11115    uint32_t Rn = ReadCoreReg(n, &success);11116    if (!success)11117      return false;11118 11119    uint32_t Rm = ReadCoreReg(m, &success);11120    if (!success)11121      return false;11122 11123    // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);11124    addr_t offset_addr;11125    if (add)11126      offset_addr = Rn + Rm;11127    else11128      offset_addr = Rn - Rm;11129 11130    // address = if index then offset_addr else R[n];11131    addr_t address;11132    if (index)11133      address = offset_addr;11134    else11135      address = Rn;11136    // MemA[address,4] = R[t];11137    uint32_t Rt = ReadCoreReg(t, &success);11138    if (!success)11139      return false;11140 11141    EmulateInstruction::Context context;11142    if (t == 13)11143      context.type = eContextPushRegisterOnStack;11144    else11145      context.type = eContextRegisterStore;11146 11147    std::optional<RegisterInfo> base_reg =11148        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);11149    std::optional<RegisterInfo> offset_reg =11150        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m);11151    std::optional<RegisterInfo> data_reg =11152        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t);11153    context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,11154                                                    *data_reg);11155 11156    const uint32_t addr_byte_size = GetAddressByteSize();11157 11158    if (!MemAWrite(context, address, Rt, addr_byte_size))11159      return false;11160 11161    // MemA[address+4,4] = R[t2];11162    uint32_t Rt2 = ReadCoreReg(t2, &success);11163    if (!success)11164      return false;11165 11166    data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2);11167 11168    context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg,11169                                                    *data_reg);11170 11171    if (!MemAWrite(context, address + 4, Rt2, addr_byte_size))11172      return false;11173 11174    // if wback then R[n] = offset_addr;11175    if (wback) {11176      context.type = eContextAdjustBaseRegister;11177      context.SetAddress(offset_addr);11178 11179      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,11180                                 offset_addr))11181        return false;11182    }11183  }11184  return true;11185}11186 11187// A8.6.319 VLDM11188// Vector Load Multiple loads multiple extension registers from consecutive11189// memory locations using an address from an ARM core register.11190bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode,11191                                        const ARMEncoding encoding) {11192#if 011193    if ConditionPassed() then11194        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);11195        address = if add then R[n] else R[n]-imm32;11196        if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;11197        for r = 0 to regs-111198            if single_regs then11199                S[d+r] = MemA[address,4]; address = address+4;11200            else11201                word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;11202                // Combine the word-aligned words in the correct order for11203                // current endianness.11204                D[d+r] = if BigEndian() then word1:word2 else word2:word1;11205#endif11206 11207  bool success = false;11208 11209  if (ConditionPassed(opcode)) {11210    bool single_regs;11211    bool add;11212    bool wback;11213    uint32_t d;11214    uint32_t n;11215    uint32_t imm32;11216    uint32_t regs;11217 11218    switch (encoding) {11219    case eEncodingT1:11220    case eEncodingA1:11221      // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';11222      // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;11223      // if P == '1' && W == '0' then SEE VLDR;11224      // if P == U && W == '1' then UNDEFINED;11225      if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))11226        return false;11227 11228      // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with11229      // !), 101 (DB with !)11230      // single_regs = FALSE; add = (U == '1'); wback = (W == '1');11231      single_regs = false;11232      add = BitIsSet(opcode, 23);11233      wback = BitIsSet(opcode, 21);11234 11235      // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);11236      d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);11237      n = Bits32(opcode, 19, 16);11238      imm32 = Bits32(opcode, 7, 0) << 2;11239 11240      // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'.11241      regs = Bits32(opcode, 7, 0) / 2;11242 11243      // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then11244      // UNPREDICTABLE;11245      if (n == 15 && (wback || CurrentInstrSet() != eModeARM))11246        return false;11247 11248      // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;11249      if ((regs == 0) || (regs > 16) || ((d + regs) > 32))11250        return false;11251 11252      break;11253 11254    case eEncodingT2:11255    case eEncodingA2:11256      // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';11257      // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP;11258      // if P == '1' && W == '0' then SEE VLDR;11259      // if P == U && W == '1' then UNDEFINED;11260      if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))11261        return false;11262 11263      // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with11264      // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W11265      // == '1'); d =11266      // UInt(Vd:D); n = UInt(Rn);11267      single_regs = true;11268      add = BitIsSet(opcode, 23);11269      wback = BitIsSet(opcode, 21);11270      d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);11271      n = Bits32(opcode, 19, 16);11272 11273      // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);11274      imm32 = Bits32(opcode, 7, 0) << 2;11275      regs = Bits32(opcode, 7, 0);11276 11277      // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then11278      // UNPREDICTABLE;11279      if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))11280        return false;11281 11282      // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;11283      if ((regs == 0) || ((d + regs) > 32))11284        return false;11285      break;11286 11287    default:11288      return false;11289    }11290 11291    uint32_t Rn = ReadCoreReg(n, &success);11292    if (!success)11293      return false;11294 11295    // address = if add then R[n] else R[n]-imm32;11296    addr_t address;11297    if (add)11298      address = Rn;11299    else11300      address = Rn - imm32;11301 11302    // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;11303    EmulateInstruction::Context context;11304 11305    if (wback) {11306      uint32_t value;11307      if (add)11308        value = Rn + imm32;11309      else11310        value = Rn - imm32;11311 11312      context.type = eContextAdjustBaseRegister;11313      context.SetImmediateSigned(value - Rn);11314      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,11315                                 value))11316        return false;11317    }11318 11319    const uint32_t addr_byte_size = GetAddressByteSize();11320    uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;11321 11322    context.type = eContextRegisterLoad;11323 11324    std::optional<RegisterInfo> base_reg =11325        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);11326 11327    // for r = 0 to regs-111328    for (uint32_t r = 0; r < regs; ++r) {11329      if (single_regs) {11330        // S[d+r] = MemA[address,4]; address = address+4;11331        context.SetRegisterPlusOffset(*base_reg, address - Rn);11332 11333        uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);11334        if (!success)11335          return false;11336 11337        if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,11338                                   start_reg + d + r, data))11339          return false;11340 11341        address = address + 4;11342      } else {11343        // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address =11344        // address+8;11345        context.SetRegisterPlusOffset(*base_reg, address - Rn);11346        uint32_t word1 =11347            MemARead(context, address, addr_byte_size, 0, &success);11348        if (!success)11349          return false;11350 11351        context.SetRegisterPlusOffset(*base_reg, (address + 4) - Rn);11352        uint32_t word2 =11353            MemARead(context, address + 4, addr_byte_size, 0, &success);11354        if (!success)11355          return false;11356 11357        address = address + 8;11358        // // Combine the word-aligned words in the correct order for current11359        // endianness.11360        // D[d+r] = if BigEndian() then word1:word2 else word2:word1;11361        uint64_t data;11362        if (GetByteOrder() == eByteOrderBig) {11363          data = word1;11364          data = (data << 32) | word2;11365        } else {11366          data = word2;11367          data = (data << 32) | word1;11368        }11369 11370        if (!WriteRegisterUnsigned(context, eRegisterKindDWARF,11371                                   start_reg + d + r, data))11372          return false;11373      }11374    }11375  }11376  return true;11377}11378 11379// A8.6.399 VSTM11380// Vector Store Multiple stores multiple extension registers to consecutive11381// memory locations using an address from an11382// ARM core register.11383bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode,11384                                        const ARMEncoding encoding) {11385#if 011386    if ConditionPassed() then11387        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);11388        address = if add then R[n] else R[n]-imm32;11389        if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;11390        for r = 0 to regs-111391            if single_regs then11392                MemA[address,4] = S[d+r]; address = address+4;11393            else11394                // Store as two word-aligned words in the correct order for11395                // current endianness.11396                MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;11397                MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;11398                address = address+8;11399#endif11400 11401  bool success = false;11402 11403  if (ConditionPassed(opcode)) {11404    bool single_regs;11405    bool add;11406    bool wback;11407    uint32_t d;11408    uint32_t n;11409    uint32_t imm32;11410    uint32_t regs;11411 11412    switch (encoding) {11413    case eEncodingT1:11414    case eEncodingA1:11415      // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';11416      // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;11417      // if P == '1' && W == '0' then SEE VSTR;11418      // if P == U && W == '1' then UNDEFINED;11419      if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))11420        return false;11421 11422      // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with11423      // !), 101 (DB with !)11424      // single_regs = FALSE; add = (U == '1'); wback = (W == '1');11425      single_regs = false;11426      add = BitIsSet(opcode, 23);11427      wback = BitIsSet(opcode, 21);11428 11429      // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32);11430      d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);11431      n = Bits32(opcode, 19, 16);11432      imm32 = Bits32(opcode, 7, 0) << 2;11433 11434      // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'.11435      regs = Bits32(opcode, 7, 0) / 2;11436 11437      // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then11438      // UNPREDICTABLE;11439      if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))11440        return false;11441 11442      // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;11443      if ((regs == 0) || (regs > 16) || ((d + regs) > 32))11444        return false;11445 11446      break;11447 11448    case eEncodingT2:11449    case eEncodingA2:11450      // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings';11451      // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH;11452      // if P == '1' && W == '0' then SEE VSTR;11453      // if P == U && W == '1' then UNDEFINED;11454      if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21))11455        return false;11456 11457      // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with11458      // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W11459      // == '1'); d =11460      // UInt(Vd:D); n = UInt(Rn);11461      single_regs = true;11462      add = BitIsSet(opcode, 23);11463      wback = BitIsSet(opcode, 21);11464      d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);11465      n = Bits32(opcode, 19, 16);11466 11467      // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8);11468      imm32 = Bits32(opcode, 7, 0) << 2;11469      regs = Bits32(opcode, 7, 0);11470 11471      // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then11472      // UNPREDICTABLE;11473      if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))11474        return false;11475 11476      // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;11477      if ((regs == 0) || ((d + regs) > 32))11478        return false;11479 11480      break;11481 11482    default:11483      return false;11484    }11485 11486    std::optional<RegisterInfo> base_reg =11487        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);11488 11489    uint32_t Rn = ReadCoreReg(n, &success);11490    if (!success)11491      return false;11492 11493    // address = if add then R[n] else R[n]-imm32;11494    addr_t address;11495    if (add)11496      address = Rn;11497    else11498      address = Rn - imm32;11499 11500    EmulateInstruction::Context context;11501    // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;11502    if (wback) {11503      uint32_t value;11504      if (add)11505        value = Rn + imm32;11506      else11507        value = Rn - imm32;11508 11509      context.type = eContextAdjustBaseRegister;11510      context.SetRegisterPlusOffset(*base_reg, value - Rn);11511 11512      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,11513                                 value))11514        return false;11515    }11516 11517    const uint32_t addr_byte_size = GetAddressByteSize();11518    uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;11519 11520    context.type = eContextRegisterStore;11521    // for r = 0 to regs-111522    for (uint32_t r = 0; r < regs; ++r) {11523 11524      if (single_regs) {11525        // MemA[address,4] = S[d+r]; address = address+4;11526        uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF,11527                                             start_reg + d + r, 0, &success);11528        if (!success)11529          return false;11530 11531        std::optional<RegisterInfo> data_reg =11532            GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r);11533        context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11534                                                address - Rn);11535        if (!MemAWrite(context, address, data, addr_byte_size))11536          return false;11537 11538        address = address + 4;11539      } else {11540        // // Store as two word-aligned words in the correct order for current11541        // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else11542        // D[d+r]<31:0>;11543        // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else11544        // D[d+r]<63:32>;11545        uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF,11546                                             start_reg + d + r, 0, &success);11547        if (!success)11548          return false;11549 11550        std::optional<RegisterInfo> data_reg =11551            GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r);11552 11553        if (GetByteOrder() == eByteOrderBig) {11554          context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11555                                                  address - Rn);11556          if (!MemAWrite(context, address, Bits64(data, 63, 32),11557                         addr_byte_size))11558            return false;11559 11560          context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11561                                                  (address + 4) - Rn);11562          if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),11563                         addr_byte_size))11564            return false;11565        } else {11566          context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11567                                                  address - Rn);11568          if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))11569            return false;11570 11571          context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11572                                                  (address + 4) - Rn);11573          if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),11574                         addr_byte_size))11575            return false;11576        }11577        // address = address+8;11578        address = address + 8;11579      }11580    }11581  }11582  return true;11583}11584 11585// A8.6.32011586// This instruction loads a single extension register from memory, using an11587// address from an ARM core register, with an optional offset.11588bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode,11589                                        ARMEncoding encoding) {11590#if 011591    if ConditionPassed() then11592        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);11593        base = if n == 15 then Align(PC,4) else R[n];11594        address = if add then (base + imm32) else (base - imm32);11595        if single_reg then11596            S[d] = MemA[address,4];11597        else11598            word1 = MemA[address,4]; word2 = MemA[address+4,4];11599            // Combine the word-aligned words in the correct order for current11600            // endianness.11601            D[d] = if BigEndian() then word1:word2 else word2:word1;11602#endif11603 11604  bool success = false;11605 11606  if (ConditionPassed(opcode)) {11607    bool single_reg;11608    bool add;11609    uint32_t imm32;11610    uint32_t d;11611    uint32_t n;11612 11613    switch (encoding) {11614    case eEncodingT1:11615    case eEncodingA1:11616      // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',11617      // 32);11618      single_reg = false;11619      add = BitIsSet(opcode, 23);11620      imm32 = Bits32(opcode, 7, 0) << 2;11621 11622      // d = UInt(D:Vd); n = UInt(Rn);11623      d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);11624      n = Bits32(opcode, 19, 16);11625 11626      break;11627 11628    case eEncodingT2:11629    case eEncodingA2:11630      // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);11631      single_reg = true;11632      add = BitIsSet(opcode, 23);11633      imm32 = Bits32(opcode, 7, 0) << 2;11634 11635      // d = UInt(Vd:D); n = UInt(Rn);11636      d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);11637      n = Bits32(opcode, 19, 16);11638 11639      break;11640 11641    default:11642      return false;11643    }11644    std::optional<RegisterInfo> base_reg =11645        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);11646 11647    uint32_t Rn = ReadCoreReg(n, &success);11648    if (!success)11649      return false;11650 11651    // base = if n == 15 then Align(PC,4) else R[n];11652    uint32_t base;11653    if (n == 15)11654      base = AlignPC(Rn);11655    else11656      base = Rn;11657 11658    // address = if add then (base + imm32) else (base - imm32);11659    addr_t address;11660    if (add)11661      address = base + imm32;11662    else11663      address = base - imm32;11664 11665    const uint32_t addr_byte_size = GetAddressByteSize();11666    uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;11667 11668    EmulateInstruction::Context context;11669    context.type = eContextRegisterLoad;11670    context.SetRegisterPlusOffset(*base_reg, address - base);11671 11672    if (single_reg) {11673      // S[d] = MemA[address,4];11674      uint32_t data = MemARead(context, address, addr_byte_size, 0, &success);11675      if (!success)11676        return false;11677 11678      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,11679                                 data))11680        return false;11681    } else {11682      // word1 = MemA[address,4]; word2 = MemA[address+4,4];11683      uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success);11684      if (!success)11685        return false;11686 11687      context.SetRegisterPlusOffset(*base_reg, (address + 4) - base);11688      uint32_t word2 =11689          MemARead(context, address + 4, addr_byte_size, 0, &success);11690      if (!success)11691        return false;11692      // // Combine the word-aligned words in the correct order for current11693      // endianness.11694      // D[d] = if BigEndian() then word1:word2 else word2:word1;11695      uint64_t data64;11696      if (GetByteOrder() == eByteOrderBig) {11697        data64 = word1;11698        data64 = (data64 << 32) | word2;11699      } else {11700        data64 = word2;11701        data64 = (data64 << 32) | word1;11702      }11703 11704      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d,11705                                 data64))11706        return false;11707    }11708  }11709  return true;11710}11711 11712// A8.6.400 VSTR11713// This instruction stores a signle extension register to memory, using an11714// address from an ARM core register, with an optional offset.11715bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode,11716                                        ARMEncoding encoding) {11717#if 011718    if ConditionPassed() then11719        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);11720        address = if add then (R[n] + imm32) else (R[n] - imm32);11721        if single_reg then11722            MemA[address,4] = S[d];11723        else11724            // Store as two word-aligned words in the correct order for current11725            // endianness.11726            MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;11727            MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;11728#endif11729 11730  bool success = false;11731 11732  if (ConditionPassed(opcode)) {11733    bool single_reg;11734    bool add;11735    uint32_t imm32;11736    uint32_t d;11737    uint32_t n;11738 11739    switch (encoding) {11740    case eEncodingT1:11741    case eEncodingA1:11742      // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00',11743      // 32);11744      single_reg = false;11745      add = BitIsSet(opcode, 23);11746      imm32 = Bits32(opcode, 7, 0) << 2;11747 11748      // d = UInt(D:Vd); n = UInt(Rn);11749      d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);11750      n = Bits32(opcode, 19, 16);11751 11752      // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;11753      if ((n == 15) && (CurrentInstrSet() != eModeARM))11754        return false;11755 11756      break;11757 11758    case eEncodingT2:11759    case eEncodingA2:11760      // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32);11761      single_reg = true;11762      add = BitIsSet(opcode, 23);11763      imm32 = Bits32(opcode, 7, 0) << 2;11764 11765      // d = UInt(Vd:D); n = UInt(Rn);11766      d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22);11767      n = Bits32(opcode, 19, 16);11768 11769      // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;11770      if ((n == 15) && (CurrentInstrSet() != eModeARM))11771        return false;11772 11773      break;11774 11775    default:11776      return false;11777    }11778 11779    uint32_t Rn = ReadCoreReg(n, &success);11780    if (!success)11781      return false;11782 11783    // address = if add then (R[n] + imm32) else (R[n] - imm32);11784    addr_t address;11785    if (add)11786      address = Rn + imm32;11787    else11788      address = Rn - imm32;11789 11790    const uint32_t addr_byte_size = GetAddressByteSize();11791    uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;11792 11793    std::optional<RegisterInfo> base_reg =11794        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);11795    std::optional<RegisterInfo> data_reg =11796        GetRegisterInfo(eRegisterKindDWARF, start_reg + d);11797    EmulateInstruction::Context context;11798    context.type = eContextRegisterStore;11799    context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);11800 11801    if (single_reg) {11802      // MemA[address,4] = S[d];11803      uint32_t data =11804          ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);11805      if (!success)11806        return false;11807 11808      if (!MemAWrite(context, address, data, addr_byte_size))11809        return false;11810    } else {11811      // // Store as two word-aligned words in the correct order for current11812      // endianness.11813      // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;11814      // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;11815      uint64_t data =11816          ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success);11817      if (!success)11818        return false;11819 11820      if (GetByteOrder() == eByteOrderBig) {11821        if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size))11822          return false;11823 11824        context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11825                                                (address + 4) - Rn);11826        if (!MemAWrite(context, address + 4, Bits64(data, 31, 0),11827                       addr_byte_size))11828          return false;11829      } else {11830        if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size))11831          return false;11832 11833        context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,11834                                                (address + 4) - Rn);11835        if (!MemAWrite(context, address + 4, Bits64(data, 63, 32),11836                       addr_byte_size))11837          return false;11838      }11839    }11840  }11841  return true;11842}11843 11844// A8.6.307 VLDI1 (multiple single elements) This instruction loads elements11845// from memory into one, two, three or four registers, without de-interleaving.11846// Every element of each register is loaded.11847bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode,11848                                                ARMEncoding encoding) {11849#if 011850    if ConditionPassed() then11851        EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);11852        address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();11853        if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);11854        for r = 0 to regs-111855            for e = 0 to elements-111856                Elem[D[d+r],e,esize] = MemU[address,ebytes];11857                address = address + ebytes;11858#endif11859 11860  bool success = false;11861 11862  if (ConditionPassed(opcode)) {11863    uint32_t regs;11864    uint32_t alignment;11865    uint32_t ebytes;11866    uint32_t esize;11867    uint32_t elements;11868    uint32_t d;11869    uint32_t n;11870    uint32_t m;11871    bool wback;11872    bool register_index;11873 11874    switch (encoding) {11875    case eEncodingT1:11876    case eEncodingA1: {11877      // case type of11878      // when '0111'11879      // regs = 1; if align<1> == '1' then UNDEFINED;11880      // when '1010'11881      // regs = 2; if align == '11' then UNDEFINED;11882      // when '0110'11883      // regs = 3; if align<1> == '1' then UNDEFINED;11884      // when '0010'11885      // regs = 4;11886      // otherwise11887      // SEE 'Related encodings';11888      uint32_t type = Bits32(opcode, 11, 8);11889      uint32_t align = Bits32(opcode, 5, 4);11890      if (type == 7) // '0111'11891      {11892        regs = 1;11893        if (BitIsSet(align, 1))11894          return false;11895      } else if (type == 10) // '1010'11896      {11897        regs = 2;11898        if (align == 3)11899          return false;11900 11901      } else if (type == 6) // '0110'11902      {11903        regs = 3;11904        if (BitIsSet(align, 1))11905          return false;11906      } else if (type == 2) // '0010'11907      {11908        regs = 4;11909      } else11910        return false;11911 11912      // alignment = if align == '00' then 1 else 4 << UInt(align);11913      if (align == 0)11914        alignment = 1;11915      else11916        alignment = 4 << align;11917 11918      // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;11919      ebytes = 1 << Bits32(opcode, 7, 6);11920      esize = 8 * ebytes;11921      elements = 8 / ebytes;11922 11923      // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);11924      d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);11925      n = Bits32(opcode, 19, 15);11926      m = Bits32(opcode, 3, 0);11927 11928      // wback = (m != 15); register_index = (m != 15 && m != 13);11929      wback = (m != 15);11930      register_index = ((m != 15) && (m != 13));11931 11932      // if d+regs > 32 then UNPREDICTABLE;11933      if ((d + regs) > 32)11934        return false;11935    } break;11936 11937    default:11938      return false;11939    }11940 11941    std::optional<RegisterInfo> base_reg =11942        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);11943 11944    uint32_t Rn = ReadCoreReg(n, &success);11945    if (!success)11946      return false;11947 11948    // address = R[n]; if (address MOD alignment) != 0 then11949    // GenerateAlignmentException();11950    addr_t address = Rn;11951    if ((address % alignment) != 0)11952      return false;11953 11954    EmulateInstruction::Context context;11955    // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);11956    if (wback) {11957      uint32_t Rm = ReadCoreReg(m, &success);11958      if (!success)11959        return false;11960 11961      uint32_t offset;11962      if (register_index)11963        offset = Rm;11964      else11965        offset = 8 * regs;11966 11967      uint32_t value = Rn + offset;11968      context.type = eContextAdjustBaseRegister;11969      context.SetRegisterPlusOffset(*base_reg, offset);11970 11971      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,11972                                 value))11973        return false;11974    }11975 11976    // for r = 0 to regs-111977    for (uint32_t r = 0; r < regs; ++r) {11978      // for e = 0 to elements-111979      uint64_t assembled_data = 0;11980      for (uint32_t e = 0; e < elements; ++e) {11981        // Elem[D[d+r],e,esize] = MemU[address,ebytes];11982        context.type = eContextRegisterLoad;11983        context.SetRegisterPlusOffset(*base_reg, address - Rn);11984        uint64_t data = MemURead(context, address, ebytes, 0, &success);11985        if (!success)11986          return false;11987 11988        assembled_data =11989            (data << (e * esize)) |11990            assembled_data; // New data goes to the left of existing data11991 11992        // address = address + ebytes;11993        address = address + ebytes;11994      }11995      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,11996                                 assembled_data))11997        return false;11998    }11999  }12000  return true;12001}12002 12003// A8.6.308 VLD1 (single element to one lane)12004//12005bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode,12006                                              const ARMEncoding encoding) {12007#if 012008    if ConditionPassed() then12009        EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);12010        address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();12011        if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12012        Elem[D[d],index,esize] = MemU[address,ebytes];12013#endif12014 12015  bool success = false;12016 12017  if (ConditionPassed(opcode)) {12018    uint32_t ebytes;12019    uint32_t esize;12020    uint32_t index;12021    uint32_t alignment;12022    uint32_t d;12023    uint32_t n;12024    uint32_t m;12025    bool wback;12026    bool register_index;12027 12028    switch (encoding) {12029    case eEncodingT1:12030    case eEncodingA1: {12031      uint32_t size = Bits32(opcode, 11, 10);12032      uint32_t index_align = Bits32(opcode, 7, 4);12033      // if size == '11' then SEE VLD1 (single element to all lanes);12034      if (size == 3)12035        return EmulateVLD1SingleAll(opcode, encoding);12036      // case size of12037      if (size == 0) // when '00'12038      {12039        // if index_align<0> != '0' then UNDEFINED;12040        if (BitIsClear(index_align, 0))12041          return false;12042 12043        // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;12044        ebytes = 1;12045        esize = 8;12046        index = Bits32(index_align, 3, 1);12047        alignment = 1;12048      } else if (size == 1) // when '01'12049      {12050        // if index_align<1> != '0' then UNDEFINED;12051        if (BitIsClear(index_align, 1))12052          return false;12053 12054        // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);12055        ebytes = 2;12056        esize = 16;12057        index = Bits32(index_align, 3, 2);12058 12059        // alignment = if index_align<0> == '0' then 1 else 2;12060        if (BitIsClear(index_align, 0))12061          alignment = 1;12062        else12063          alignment = 2;12064      } else if (size == 2) // when '10'12065      {12066        // if index_align<2> != '0' then UNDEFINED;12067        if (BitIsClear(index_align, 2))12068          return false;12069 12070        // if index_align<1:0> != '00' && index_align<1:0> != '11' then12071        // UNDEFINED;12072        if ((Bits32(index_align, 1, 0) != 0) &&12073            (Bits32(index_align, 1, 0) != 3))12074          return false;12075 12076        // ebytes = 4; esize = 32; index = UInt(index_align<3>);12077        ebytes = 4;12078        esize = 32;12079        index = Bit32(index_align, 3);12080 12081        // alignment = if index_align<1:0> == '00' then 1 else 4;12082        if (Bits32(index_align, 1, 0) == 0)12083          alignment = 1;12084        else12085          alignment = 4;12086      } else {12087        return false;12088      }12089      // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);12090      d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);12091      n = Bits32(opcode, 19, 16);12092      m = Bits32(opcode, 3, 0);12093 12094      // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 1512095      // then UNPREDICTABLE;12096      wback = (m != 15);12097      register_index = ((m != 15) && (m != 13));12098 12099      if (n == 15)12100        return false;12101 12102    } break;12103 12104    default:12105      return false;12106    }12107 12108    uint32_t Rn = ReadCoreReg(n, &success);12109    if (!success)12110      return false;12111 12112    // address = R[n]; if (address MOD alignment) != 0 then12113    // GenerateAlignmentException();12114    addr_t address = Rn;12115    if ((address % alignment) != 0)12116      return false;12117 12118    EmulateInstruction::Context context;12119    // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12120    if (wback) {12121      uint32_t Rm = ReadCoreReg(m, &success);12122      if (!success)12123        return false;12124 12125      uint32_t offset;12126      if (register_index)12127        offset = Rm;12128      else12129        offset = ebytes;12130 12131      uint32_t value = Rn + offset;12132 12133      context.type = eContextAdjustBaseRegister;12134      std::optional<RegisterInfo> base_reg =12135          GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);12136      context.SetRegisterPlusOffset(*base_reg, offset);12137 12138      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,12139                                 value))12140        return false;12141    }12142 12143    // Elem[D[d],index,esize] = MemU[address,ebytes];12144    uint32_t element = MemURead(context, address, esize, 0, &success);12145    if (!success)12146      return false;12147 12148    element = element << (index * esize);12149 12150    uint64_t reg_data =12151        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);12152    if (!success)12153      return false;12154 12155    uint64_t all_ones = -1;12156    uint64_t mask = all_ones12157                    << ((index + 1) * esize); // mask is all 1's to left of12158                                              // where 'element' goes, & all 0's12159    // at element & to the right of element.12160    if (index > 0)12161      mask = mask | Bits64(all_ones, (index * esize) - 1,12162                           0); // add 1's to the right of where 'element' goes.12163    // now mask should be 0's where element goes & 1's everywhere else.12164 12165    uint64_t masked_reg =12166        reg_data & mask; // Take original reg value & zero out 'element' bits12167    reg_data =12168        masked_reg & element; // Put 'element' into those bits in reg_data.12169 12170    context.type = eContextRegisterLoad;12171    if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d,12172                               reg_data))12173      return false;12174  }12175  return true;12176}12177 12178// A8.6.391 VST1 (multiple single elements) Vector Store (multiple single12179// elements) stores elements to memory from one, two, three, or four registers,12180// without interleaving.  Every element of each register is stored.12181bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode,12182                                                ARMEncoding encoding) {12183#if 012184    if ConditionPassed() then12185        EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);12186        address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();12187        if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);12188        for r = 0 to regs-112189            for e = 0 to elements-112190                MemU[address,ebytes] = Elem[D[d+r],e,esize];12191                address = address + ebytes;12192#endif12193 12194  bool success = false;12195 12196  if (ConditionPassed(opcode)) {12197    uint32_t regs;12198    uint32_t alignment;12199    uint32_t ebytes;12200    uint32_t esize;12201    uint32_t elements;12202    uint32_t d;12203    uint32_t n;12204    uint32_t m;12205    bool wback;12206    bool register_index;12207 12208    switch (encoding) {12209    case eEncodingT1:12210    case eEncodingA1: {12211      uint32_t type = Bits32(opcode, 11, 8);12212      uint32_t align = Bits32(opcode, 5, 4);12213 12214      // case type of12215      if (type == 7) // when '0111'12216      {12217        // regs = 1; if align<1> == '1' then UNDEFINED;12218        regs = 1;12219        if (BitIsSet(align, 1))12220          return false;12221      } else if (type == 10) // when '1010'12222      {12223        // regs = 2; if align == '11' then UNDEFINED;12224        regs = 2;12225        if (align == 3)12226          return false;12227      } else if (type == 6) // when '0110'12228      {12229        // regs = 3; if align<1> == '1' then UNDEFINED;12230        regs = 3;12231        if (BitIsSet(align, 1))12232          return false;12233      } else if (type == 2) // when '0010'12234        // regs = 4;12235        regs = 4;12236      else // otherwise12237        // SEE 'Related encodings';12238        return false;12239 12240      // alignment = if align == '00' then 1 else 4 << UInt(align);12241      if (align == 0)12242        alignment = 1;12243      else12244        alignment = 4 << align;12245 12246      // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;12247      ebytes = 1 << Bits32(opcode, 7, 6);12248      esize = 8 * ebytes;12249      elements = 8 / ebytes;12250 12251      // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);12252      d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);12253      n = Bits32(opcode, 19, 16);12254      m = Bits32(opcode, 3, 0);12255 12256      // wback = (m != 15); register_index = (m != 15 && m != 13);12257      wback = (m != 15);12258      register_index = ((m != 15) && (m != 13));12259 12260      // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;12261      if ((d + regs) > 32)12262        return false;12263 12264      if (n == 15)12265        return false;12266 12267    } break;12268 12269    default:12270      return false;12271    }12272 12273    std::optional<RegisterInfo> base_reg =12274        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);12275 12276    uint32_t Rn = ReadCoreReg(n, &success);12277    if (!success)12278      return false;12279 12280    // address = R[n]; if (address MOD alignment) != 0 then12281    // GenerateAlignmentException();12282    addr_t address = Rn;12283    if ((address % alignment) != 0)12284      return false;12285 12286    EmulateInstruction::Context context;12287    // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);12288    if (wback) {12289      uint32_t Rm = ReadCoreReg(m, &success);12290      if (!success)12291        return false;12292 12293      uint32_t offset;12294      if (register_index)12295        offset = Rm;12296      else12297        offset = 8 * regs;12298 12299      context.type = eContextAdjustBaseRegister;12300      context.SetRegisterPlusOffset(*base_reg, offset);12301 12302      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,12303                                 Rn + offset))12304        return false;12305    }12306 12307    context.type = eContextRegisterStore;12308    // for r = 0 to regs-112309    for (uint32_t r = 0; r < regs; ++r) {12310      std::optional<RegisterInfo> data_reg =12311          GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r);12312      uint64_t register_data = ReadRegisterUnsigned(12313          eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);12314      if (!success)12315        return false;12316 12317      // for e = 0 to elements-112318      for (uint32_t e = 0; e < elements; ++e) {12319        // MemU[address,ebytes] = Elem[D[d+r],e,esize];12320        uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize);12321 12322        context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg,12323                                                address - Rn);12324        if (!MemUWrite(context, address, word, ebytes))12325          return false;12326 12327        // address = address + ebytes;12328        address = address + ebytes;12329      }12330    }12331  }12332  return true;12333}12334 12335// A8.6.392 VST1 (single element from one lane) This instruction stores one12336// element to memory from one element of a register.12337bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode,12338                                              ARMEncoding encoding) {12339#if 012340    if ConditionPassed() then12341        EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);12342        address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();12343        if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12344        MemU[address,ebytes] = Elem[D[d],index,esize];12345#endif12346 12347  bool success = false;12348 12349  if (ConditionPassed(opcode)) {12350    uint32_t ebytes;12351    uint32_t esize;12352    uint32_t index;12353    uint32_t alignment;12354    uint32_t d;12355    uint32_t n;12356    uint32_t m;12357    bool wback;12358    bool register_index;12359 12360    switch (encoding) {12361    case eEncodingT1:12362    case eEncodingA1: {12363      uint32_t size = Bits32(opcode, 11, 10);12364      uint32_t index_align = Bits32(opcode, 7, 4);12365 12366      // if size == '11' then UNDEFINED;12367      if (size == 3)12368        return false;12369 12370      // case size of12371      if (size == 0) // when '00'12372      {12373        // if index_align<0> != '0' then UNDEFINED;12374        if (BitIsClear(index_align, 0))12375          return false;12376        // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;12377        ebytes = 1;12378        esize = 8;12379        index = Bits32(index_align, 3, 1);12380        alignment = 1;12381      } else if (size == 1) // when '01'12382      {12383        // if index_align<1> != '0' then UNDEFINED;12384        if (BitIsClear(index_align, 1))12385          return false;12386 12387        // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);12388        ebytes = 2;12389        esize = 16;12390        index = Bits32(index_align, 3, 2);12391 12392        // alignment = if index_align<0> == '0' then 1 else 2;12393        if (BitIsClear(index_align, 0))12394          alignment = 1;12395        else12396          alignment = 2;12397      } else if (size == 2) // when '10'12398      {12399        // if index_align<2> != '0' then UNDEFINED;12400        if (BitIsClear(index_align, 2))12401          return false;12402 12403        // if index_align<1:0> != '00' && index_align<1:0> != '11' then12404        // UNDEFINED;12405        if ((Bits32(index_align, 1, 0) != 0) &&12406            (Bits32(index_align, 1, 0) != 3))12407          return false;12408 12409        // ebytes = 4; esize = 32; index = UInt(index_align<3>);12410        ebytes = 4;12411        esize = 32;12412        index = Bit32(index_align, 3);12413 12414        // alignment = if index_align<1:0> == '00' then 1 else 4;12415        if (Bits32(index_align, 1, 0) == 0)12416          alignment = 1;12417        else12418          alignment = 4;12419      } else {12420        return false;12421      }12422      // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);12423      d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);12424      n = Bits32(opcode, 19, 16);12425      m = Bits32(opcode, 3, 0);12426 12427      // wback = (m != 15); register_index = (m != 15 && m != 13);  if n == 1512428      // then UNPREDICTABLE;12429      wback = (m != 15);12430      register_index = ((m != 15) && (m != 13));12431 12432      if (n == 15)12433        return false;12434    } break;12435 12436    default:12437      return false;12438    }12439 12440    std::optional<RegisterInfo> base_reg =12441        GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);12442 12443    uint32_t Rn = ReadCoreReg(n, &success);12444    if (!success)12445      return false;12446 12447    // address = R[n]; if (address MOD alignment) != 0 then12448    // GenerateAlignmentException();12449    addr_t address = Rn;12450    if ((address % alignment) != 0)12451      return false;12452 12453    EmulateInstruction::Context context;12454    // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12455    if (wback) {12456      uint32_t Rm = ReadCoreReg(m, &success);12457      if (!success)12458        return false;12459 12460      uint32_t offset;12461      if (register_index)12462        offset = Rm;12463      else12464        offset = ebytes;12465 12466      context.type = eContextAdjustBaseRegister;12467      context.SetRegisterPlusOffset(*base_reg, offset);12468 12469      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,12470                                 Rn + offset))12471        return false;12472    }12473 12474    // MemU[address,ebytes] = Elem[D[d],index,esize];12475    uint64_t register_data =12476        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success);12477    if (!success)12478      return false;12479 12480    uint64_t word =12481        Bits64(register_data, ((index + 1) * esize) - 1, index * esize);12482 12483    std::optional<RegisterInfo> data_reg =12484        GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d);12485    context.type = eContextRegisterStore;12486    context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn);12487 12488    if (!MemUWrite(context, address, word, ebytes))12489      return false;12490  }12491  return true;12492}12493 12494// A8.6.309 VLD1 (single element to all lanes) This instruction loads one12495// element from memory into every element of one or two vectors.12496bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode,12497                                                 const ARMEncoding encoding) {12498#if 012499    if ConditionPassed() then12500        EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);12501        address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();12502        if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12503        replicated_element = Replicate(MemU[address,ebytes], elements);12504        for r = 0 to regs-112505            D[d+r] = replicated_element;12506#endif12507 12508  bool success = false;12509 12510  if (ConditionPassed(opcode)) {12511    uint32_t ebytes;12512    uint32_t elements;12513    uint32_t regs;12514    uint32_t alignment;12515    uint32_t d;12516    uint32_t n;12517    uint32_t m;12518    bool wback;12519    bool register_index;12520 12521    switch (encoding) {12522    case eEncodingT1:12523    case eEncodingA1: {12524      // if size == '11' || (size == '00' && a == '1') then UNDEFINED;12525      uint32_t size = Bits32(opcode, 7, 6);12526      if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4)))12527        return false;12528 12529      // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0'12530      // then 1 else 2;12531      ebytes = 1 << size;12532      elements = 8 / ebytes;12533      if (BitIsClear(opcode, 5))12534        regs = 1;12535      else12536        regs = 2;12537 12538      // alignment = if a == '0' then 1 else ebytes;12539      if (BitIsClear(opcode, 4))12540        alignment = 1;12541      else12542        alignment = ebytes;12543 12544      // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);12545      d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12);12546      n = Bits32(opcode, 19, 16);12547      m = Bits32(opcode, 3, 0);12548 12549      // wback = (m != 15); register_index = (m != 15 && m != 13);12550      wback = (m != 15);12551      register_index = ((m != 15) && (m != 13));12552 12553      // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;12554      if ((d + regs) > 32)12555        return false;12556 12557      if (n == 15)12558        return false;12559    } break;12560 12561    default:12562      return false;12563    }12564 12565    uint32_t Rn = ReadCoreReg(n, &success);12566    if (!success)12567      return false;12568 12569    // address = R[n]; if (address MOD alignment) != 0 then12570    // GenerateAlignmentException();12571    addr_t address = Rn;12572    if ((address % alignment) != 0)12573      return false;12574 12575    EmulateInstruction::Context context;12576    // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);12577    if (wback) {12578      uint32_t Rm = ReadCoreReg(m, &success);12579      if (!success)12580        return false;12581 12582      uint32_t offset;12583      if (register_index)12584        offset = Rm;12585      else12586        offset = ebytes;12587 12588      context.type = eContextAdjustBaseRegister;12589      std::optional<RegisterInfo> base_reg =12590          GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n);12591      context.SetRegisterPlusOffset(*base_reg, offset);12592 12593      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n,12594                                 Rn + offset))12595        return false;12596    }12597 12598    // replicated_element = Replicate(MemU[address,ebytes], elements);12599 12600    context.type = eContextRegisterLoad;12601    uint64_t word = MemURead(context, address, ebytes, 0, &success);12602    if (!success)12603      return false;12604 12605    uint64_t replicated_element = 0;12606    uint32_t esize = ebytes * 8;12607    for (uint32_t e = 0; e < elements; ++e)12608      replicated_element =12609          (replicated_element << esize) | Bits64(word, esize - 1, 0);12610 12611    // for r = 0 to regs-112612    for (uint32_t r = 0; r < regs; ++r) {12613      // D[d+r] = replicated_element;12614      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r,12615                                 replicated_element))12616        return false;12617    }12618  }12619  return true;12620}12621 12622// B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const?12623// instruction provides an exception return without the use of the stack.  It12624// subtracts the immediate constant from the LR, branches to the resulting12625// address, and also copies the SPSR to the CPSR.12626bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode,12627                                               const ARMEncoding encoding) {12628#if 012629    if ConditionPassed() then12630        EncodingSpecificOperations();12631        if CurrentInstrSet() == InstrSet_ThumbEE then12632            UNPREDICTABLE;12633        operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;12634        case opcode of12635            when '0000' result = R[n] AND operand2; // AND12636            when '0001' result = R[n] EOR operand2; // EOR12637            when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB12638            when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB12639            when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD12640            when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC12641            when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC12642            when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC12643            when '1100' result = R[n] OR operand2; // ORR12644            when '1101' result = operand2; // MOV12645            when '1110' result = R[n] AND NOT(operand2); // BIC12646            when '1111' result = NOT(operand2); // MVN12647        CPSRWriteByInstr(SPSR[], '1111', TRUE);12648        BranchWritePC(result);12649#endif12650 12651  bool success = false;12652 12653  if (ConditionPassed(opcode)) {12654    uint32_t n;12655    uint32_t m;12656    uint32_t imm32;12657    bool register_form;12658    ARM_ShifterType shift_t;12659    uint32_t shift_n;12660    uint32_t code;12661 12662    switch (encoding) {12663    case eEncodingT1:12664      // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14;12665      // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010';12666      // // = SUB12667      n = 14;12668      imm32 = Bits32(opcode, 7, 0);12669      register_form = false;12670      code = 2;12671 12672      // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;12673      if (InITBlock() && !LastInITBlock())12674        return false;12675 12676      break;12677 12678    case eEncodingA1:12679      // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;12680      n = Bits32(opcode, 19, 16);12681      imm32 = ARMExpandImm(opcode);12682      register_form = false;12683      code = Bits32(opcode, 24, 21);12684 12685      break;12686 12687    case eEncodingA2:12688      // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;12689      n = Bits32(opcode, 19, 16);12690      m = Bits32(opcode, 3, 0);12691      register_form = true;12692 12693      // (shift_t, shift_n) = DecodeImmShift(type, imm5);12694      shift_n = DecodeImmShiftARM(opcode, shift_t);12695 12696      break;12697 12698    default:12699      return false;12700    }12701 12702    // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C)12703    // else imm32;12704    uint32_t operand2;12705    if (register_form) {12706      uint32_t Rm = ReadCoreReg(m, &success);12707      if (!success)12708        return false;12709 12710      operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success);12711      if (!success)12712        return false;12713    } else {12714      operand2 = imm32;12715    }12716 12717    uint32_t Rn = ReadCoreReg(n, &success);12718    if (!success)12719      return false;12720 12721    AddWithCarryResult result;12722 12723    // case opcode of12724    switch (code) {12725    case 0: // when '0000'12726      // result = R[n] AND operand2; // AND12727      result.result = Rn & operand2;12728      break;12729 12730    case 1: // when '0001'12731      // result = R[n] EOR operand2; // EOR12732      result.result = Rn ^ operand2;12733      break;12734 12735    case 2: // when '0010'12736      // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB12737      result = AddWithCarry(Rn, ~(operand2), 1);12738      break;12739 12740    case 3: // when '0011'12741      // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB12742      result = AddWithCarry(~(Rn), operand2, 1);12743      break;12744 12745    case 4: // when '0100'12746      // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD12747      result = AddWithCarry(Rn, operand2, 0);12748      break;12749 12750    case 5: // when '0101'12751      // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC12752      result = AddWithCarry(Rn, operand2, APSR_C);12753      break;12754 12755    case 6: // when '0110'12756      // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC12757      result = AddWithCarry(Rn, ~(operand2), APSR_C);12758      break;12759 12760    case 7: // when '0111'12761      // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC12762      result = AddWithCarry(~(Rn), operand2, APSR_C);12763      break;12764 12765    case 10: // when '1100'12766      // result = R[n] OR operand2; // ORR12767      result.result = Rn | operand2;12768      break;12769 12770    case 11: // when '1101'12771      // result = operand2; // MOV12772      result.result = operand2;12773      break;12774 12775    case 12: // when '1110'12776      // result = R[n] AND NOT(operand2); // BIC12777      result.result = Rn & ~(operand2);12778      break;12779 12780    case 15: // when '1111'12781      // result = NOT(operand2); // MVN12782      result.result = ~(operand2);12783      break;12784 12785    default:12786      return false;12787    }12788    // CPSRWriteByInstr(SPSR[], '1111', TRUE);12789 12790    // For now, in emulation mode, we don't have access to the SPSR, so we will12791    // use the CPSR instead, and hope for the best.12792    uint32_t spsr =12793        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);12794    if (!success)12795      return false;12796 12797    CPSRWriteByInstr(spsr, 15, true);12798 12799    // BranchWritePC(result);12800    EmulateInstruction::Context context;12801    context.type = eContextAdjustPC;12802    context.SetImmediate(result.result);12803 12804    BranchWritePC(context, result.result);12805  }12806  return true;12807}12808 12809EmulateInstructionARM::ARMOpcode *12810EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode,12811                                                  uint32_t arm_isa) {12812  static ARMOpcode g_arm_opcodes[] = {12813      // Prologue instructions12814 12815      // push register(s)12816      {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12817       &EmulateInstructionARM::EmulatePUSH, "push <registers>"},12818      {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,12819       &EmulateInstructionARM::EmulatePUSH, "push <register>"},12820 12821      // set r7 to point to a stack offset12822      {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32,12823       &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"},12824      {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32,12825       &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},12826      // copy the stack pointer to ip12827      {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32,12828       &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"},12829      {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,12830       &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"},12831      {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32,12832       &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},12833 12834      // adjust the stack pointer12835      {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32,12836       &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},12837      {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12838       &EmulateInstructionARM::EmulateSUBSPReg,12839       "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},12840 12841      // push one register12842      // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;12843      {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12844       &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"},12845 12846      // vector push consecutive extension register(s)12847      {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,12848       &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},12849      {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,12850       &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},12851 12852      // Epilogue instructions12853 12854      {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12855       &EmulateInstructionARM::EmulatePOP, "pop <registers>"},12856      {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32,12857       &EmulateInstructionARM::EmulatePOP, "pop <register>"},12858      {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32,12859       &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},12860      {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,12861       &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},12862 12863      // Supervisor Call (previously Software Interrupt)12864      {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32,12865       &EmulateInstructionARM::EmulateSVC, "svc #imm24"},12866 12867      // Branch instructions12868      // To resolve ambiguity, "blx <label>" should come before "b #imm24" and12869      // "bl <label>".12870      {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32,12871       &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},12872      {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32,12873       &EmulateInstructionARM::EmulateB, "b #imm24"},12874      {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32,12875       &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},12876      {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32,12877       &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},12878      // for example, "bx lr"12879      {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32,12880       &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},12881      // bxj12882      {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32,12883       &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},12884 12885      // Data-processing instructions12886      // adc (immediate)12887      {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12888       &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},12889      // adc (register)12890      {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12891       &EmulateInstructionARM::EmulateADCReg,12892       "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12893      // add (immediate)12894      {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32,12895       &EmulateInstructionARM::EmulateADDImmARM,12896       "add{s}<c> <Rd>, <Rn>, #const"},12897      // add (register)12898      {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32,12899       &EmulateInstructionARM::EmulateADDReg,12900       "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12901      // add (register-shifted register)12902      {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32,12903       &EmulateInstructionARM::EmulateADDRegShift,12904       "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},12905      // adr12906      {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12907       &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},12908      {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32,12909       &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},12910      // and (immediate)12911      {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32,12912       &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},12913      // and (register)12914      {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32,12915       &EmulateInstructionARM::EmulateANDReg,12916       "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12917      // bic (immediate)12918      {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12919       &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},12920      // bic (register)12921      {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12922       &EmulateInstructionARM::EmulateBICReg,12923       "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12924      // eor (immediate)12925      {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32,12926       &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},12927      // eor (register)12928      {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32,12929       &EmulateInstructionARM::EmulateEORReg,12930       "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12931      // orr (immediate)12932      {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32,12933       &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},12934      // orr (register)12935      {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32,12936       &EmulateInstructionARM::EmulateORRReg,12937       "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12938      // rsb (immediate)12939      {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32,12940       &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},12941      // rsb (register)12942      {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32,12943       &EmulateInstructionARM::EmulateRSBReg,12944       "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12945      // rsc (immediate)12946      {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12947       &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},12948      // rsc (register)12949      {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12950       &EmulateInstructionARM::EmulateRSCReg,12951       "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12952      // sbc (immediate)12953      {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12954       &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},12955      // sbc (register)12956      {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12957       &EmulateInstructionARM::EmulateSBCReg,12958       "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},12959      // sub (immediate, ARM)12960      {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32,12961       &EmulateInstructionARM::EmulateSUBImmARM,12962       "sub{s}<c> <Rd>, <Rn>, #<const>"},12963      // sub (sp minus immediate)12964      {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32,12965       &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},12966      // sub (register)12967      {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32,12968       &EmulateInstructionARM::EmulateSUBReg,12969       "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},12970      // teq (immediate)12971      {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32,12972       &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},12973      // teq (register)12974      {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32,12975       &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},12976      // tst (immediate)12977      {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32,12978       &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},12979      // tst (register)12980      {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32,12981       &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},12982 12983      // mov (immediate)12984      {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12985       &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},12986      {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32,12987       &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"},12988      // mov (register)12989      {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12990       &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},12991      // mvn (immediate)12992      {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12993       &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},12994      // mvn (register)12995      {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32,12996       &EmulateInstructionARM::EmulateMVNReg,12997       "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},12998      // cmn (immediate)12999      {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32,13000       &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},13001      // cmn (register)13002      {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32,13003       &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},13004      // cmp (immediate)13005      {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32,13006       &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},13007      // cmp (register)13008      {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32,13009       &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},13010      // asr (immediate)13011      {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32,13012       &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},13013      // asr (register)13014      {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,13015       &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},13016      // lsl (immediate)13017      {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32,13018       &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},13019      // lsl (register)13020      {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32,13021       &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},13022      // lsr (immediate)13023      {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32,13024       &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},13025      // lsr (register)13026      {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32,13027       &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},13028      // rrx is a special case encoding of ror (immediate)13029      {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,13030       &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},13031      // ror (immediate)13032      {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32,13033       &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},13034      // ror (register)13035      {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32,13036       &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},13037      // mul13038      {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32,13039       &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"},13040 13041      // subs pc, lr and related instructions13042      {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32,13043       &EmulateInstructionARM::EmulateSUBSPcLrEtc,13044       "<opc>S<c> PC,#<const> | <Rn>,#<const>"},13045      {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32,13046       &EmulateInstructionARM::EmulateSUBSPcLrEtc,13047       "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"},13048 13049      // Load instructions13050      {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32,13051       &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},13052      {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32,13053       &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"},13054      {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32,13055       &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},13056      {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32,13057       &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"},13058      {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32,13059       &EmulateInstructionARM::EmulateLDRImmediateARM,13060       "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"},13061      {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32,13062       &EmulateInstructionARM::EmulateLDRRegister,13063       "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"},13064      {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32,13065       &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},13066      {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32,13067       &EmulateInstructionARM::EmulateLDRBRegister,13068       "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"},13069      {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32,13070       &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},13071      {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,13072       &EmulateInstructionARM::EmulateLDRHRegister,13073       "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},13074      {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,13075       &EmulateInstructionARM::EmulateLDRSBImmediate,13076       "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"},13077      {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32,13078       &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"},13079      {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32,13080       &EmulateInstructionARM::EmulateLDRSBRegister,13081       "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},13082      {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,13083       &EmulateInstructionARM::EmulateLDRSHImmediate,13084       "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},13085      {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32,13086       &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},13087      {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32,13088       &EmulateInstructionARM::EmulateLDRSHRegister,13089       "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"},13090      {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,13091       &EmulateInstructionARM::EmulateLDRDImmediate,13092       "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},13093      {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,13094       &EmulateInstructionARM::EmulateLDRDRegister,13095       "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},13096      {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,13097       &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},13098      {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,13099       &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},13100      {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,13101       &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},13102      {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,13103       &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},13104      {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,13105       &EmulateInstructionARM::EmulateVLD1Multiple,13106       "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13107      {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,13108       &EmulateInstructionARM::EmulateVLD1Single,13109       "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13110      {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,13111       &EmulateInstructionARM::EmulateVLD1SingleAll,13112       "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13113 13114      // Store instructions13115      {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32,13116       &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},13117      {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32,13118       &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"},13119      {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32,13120       &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},13121      {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32,13122       &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"},13123      {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32,13124       &EmulateInstructionARM::EmulateSTRRegister,13125       "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"},13126      {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32,13127       &EmulateInstructionARM::EmulateSTRHRegister,13128       "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"},13129      {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13130       &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},13131      {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32,13132       &EmulateInstructionARM::EmulateSTRBImmARM,13133       "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},13134      {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32,13135       &EmulateInstructionARM::EmulateSTRImmARM,13136       "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},13137      {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,13138       &EmulateInstructionARM::EmulateSTRDImm,13139       "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},13140      {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32,13141       &EmulateInstructionARM::EmulateSTRDReg,13142       "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},13143      {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,13144       &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},13145      {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,13146       &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},13147      {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32,13148       &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},13149      {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32,13150       &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},13151      {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,13152       &EmulateInstructionARM::EmulateVST1Multiple,13153       "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13154      {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32,13155       &EmulateInstructionARM::EmulateVST1Single,13156       "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13157 13158      // Other instructions13159      {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13160       &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"},13161      {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13162       &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"},13163      {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13164       &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"},13165      {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13166       &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"},13167      {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32,13168       &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"}13169 13170  };13171  static const size_t k_num_arm_opcodes = std::size(g_arm_opcodes);13172 13173  for (size_t i = 0; i < k_num_arm_opcodes; ++i) {13174    if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&13175        (g_arm_opcodes[i].variants & arm_isa) != 0)13176      return &g_arm_opcodes[i];13177  }13178  return nullptr;13179}13180 13181EmulateInstructionARM::ARMOpcode *13182EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode,13183                                                    uint32_t arm_isa) {13184 13185  static ARMOpcode g_thumb_opcodes[] = {13186      // Prologue instructions13187 13188      // push register(s)13189      {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16,13190       &EmulateInstructionARM::EmulatePUSH, "push <registers>"},13191      {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13192       &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"},13193      {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13194       &EmulateInstructionARM::EmulatePUSH, "push.w <register>"},13195 13196      // set r7 to point to a stack offset13197      {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16,13198       &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"},13199      // copy the stack pointer to r713200      {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16,13201       &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"},13202      // move from high register to low register (comes after "mov r7, sp" to13203      // resolve ambiguity)13204      {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16,13205       &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"},13206 13207      // PC-relative load into register (see also EmulateADDSPRm)13208      {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16,13209       &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},13210 13211      // adjust the stack pointer13212      {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16,13213       &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},13214      {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16,13215       &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},13216      {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13217       &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},13218      {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13219       &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},13220      {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13221       &EmulateInstructionARM::EmulateSUBSPReg,13222       "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"},13223 13224      // vector push consecutive extension register(s)13225      {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13226       &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},13227      {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13228       &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},13229 13230      // Epilogue instructions13231 13232      {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13233       &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},13234      {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16,13235       &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},13236      {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16,13237       &EmulateInstructionARM::EmulatePOP, "pop <registers>"},13238      {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13239       &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"},13240      {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13241       &EmulateInstructionARM::EmulatePOP, "pop.w <register>"},13242      {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13243       &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},13244      {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13245       &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},13246 13247      // Supervisor Call (previously Software Interrupt)13248      {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16,13249       &EmulateInstructionARM::EmulateSVC, "svc #imm8"},13250 13251      // If Then makes up to four following instructions conditional.13252      // The next 5 opcode _must_ come before the if then instruction13253      {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,13254       &EmulateInstructionARM::EmulateNop, "nop"},13255      {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,13256       &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},13257      {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,13258       &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},13259      {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,13260       &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},13261      {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16,13262       &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},13263      {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,13264       &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},13265 13266      // Branch instructions13267      // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".13268      {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16,13269       &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},13270      {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16,13271       &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},13272      {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13273       &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},13274      {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,13275       &EmulateInstructionARM::EmulateB,13276       "b<c>.w #imm8 (outside or last in IT)"},13277      // J1 == J2 == 113278      {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32,13279       &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},13280      // J1 == J2 == 113281      {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32,13282       &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},13283      {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16,13284       &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},13285      // for example, "bx lr"13286      {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32,13287       &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},13288      // bxj13289      {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32,13290       &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},13291      // compare and branch13292      {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,13293       &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},13294      // table branch byte13295      {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13296       &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},13297      // table branch halfword13298      {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13299       &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},13300 13301      // Data-processing instructions13302      // adc (immediate)13303      {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13304       &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},13305      // adc (register)13306      {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16,13307       &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},13308      {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13309       &EmulateInstructionARM::EmulateADCReg,13310       "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13311      // add (register)13312      {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16,13313       &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},13314      // Make sure "add sp, <Rm>" comes before this instruction, so there's no13315      // ambiguity decoding the two.13316      {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16,13317       &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},13318      // adr13319      {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16,13320       &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},13321      {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13322       &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},13323      {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13324       &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},13325      // and (immediate)13326      {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13327       &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},13328      // and (register)13329      {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16,13330       &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},13331      {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13332       &EmulateInstructionARM::EmulateANDReg,13333       "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13334      // bic (immediate)13335      {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13336       &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},13337      // bic (register)13338      {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16,13339       &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},13340      {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13341       &EmulateInstructionARM::EmulateBICReg,13342       "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13343      // eor (immediate)13344      {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13345       &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},13346      // eor (register)13347      {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16,13348       &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},13349      {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13350       &EmulateInstructionARM::EmulateEORReg,13351       "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13352      // orr (immediate)13353      {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13354       &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},13355      // orr (register)13356      {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16,13357       &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},13358      {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13359       &EmulateInstructionARM::EmulateORRReg,13360       "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13361      // rsb (immediate)13362      {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16,13363       &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},13364      {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13365       &EmulateInstructionARM::EmulateRSBImm,13366       "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},13367      // rsb (register)13368      {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13369       &EmulateInstructionARM::EmulateRSBReg,13370       "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13371      // sbc (immediate)13372      {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13373       &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},13374      // sbc (register)13375      {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16,13376       &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},13377      {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13378       &EmulateInstructionARM::EmulateSBCReg,13379       "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},13380      // add (immediate, Thumb)13381      {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13382       &EmulateInstructionARM::EmulateADDImmThumb,13383       "adds|add<c> <Rd>,<Rn>,#<imm3>"},13384      {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,13385       &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"},13386      {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13387       &EmulateInstructionARM::EmulateADDImmThumb,13388       "add{s}<c>.w <Rd>,<Rn>,#<const>"},13389      {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,13390       &EmulateInstructionARM::EmulateADDImmThumb,13391       "addw<c> <Rd>,<Rn>,#<imm12>"},13392      // sub (immediate, Thumb)13393      {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16,13394       &EmulateInstructionARM::EmulateSUBImmThumb,13395       "subs|sub<c> <Rd>, <Rn> #imm3"},13396      {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16,13397       &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},13398      {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13399       &EmulateInstructionARM::EmulateSUBImmThumb,13400       "sub{s}<c>.w <Rd>, <Rn>, #<const>"},13401      {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,13402       &EmulateInstructionARM::EmulateSUBImmThumb,13403       "subw<c> <Rd>, <Rn>, #imm12"},13404      // sub (sp minus immediate)13405      {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13406       &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},13407      {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13408       &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},13409      // sub (register)13410      {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13411       &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},13412      {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13413       &EmulateInstructionARM::EmulateSUBReg,13414       "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},13415      // teq (immediate)13416      {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13417       &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},13418      // teq (register)13419      {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13420       &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},13421      // tst (immediate)13422      {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13423       &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},13424      // tst (register)13425      {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16,13426       &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},13427      {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13428       &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},13429 13430      // move from high register to high register13431      {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16,13432       &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},13433      // move from low register to low register13434      {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16,13435       &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},13436      // mov{s}<c>.w <Rd>, <Rm>13437      {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13438       &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},13439      // move immediate13440      {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16,13441       &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},13442      {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13443       &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},13444      {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13445       &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},13446      // mvn (immediate)13447      {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13448       &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},13449      // mvn (register)13450      {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16,13451       &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},13452      {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13453       &EmulateInstructionARM::EmulateMVNReg,13454       "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},13455      // cmn (immediate)13456      {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13457       &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},13458      // cmn (register)13459      {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16,13460       &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},13461      {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13462       &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},13463      // cmp (immediate)13464      {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16,13465       &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},13466      {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13467       &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},13468      // cmp (register) (Rn and Rm both from r0-r7)13469      {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16,13470       &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},13471      // cmp (register) (Rn and Rm not both from r0-r7)13472      {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16,13473       &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},13474      {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16,13475       &EmulateInstructionARM::EmulateCMPReg,13476       "cmp<c>.w <Rn>, <Rm> {, <shift>}"},13477      // asr (immediate)13478      {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16,13479       &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},13480      {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13481       &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},13482      // asr (register)13483      {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16,13484       &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},13485      {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13486       &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},13487      // lsl (immediate)13488      {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16,13489       &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},13490      {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13491       &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},13492      // lsl (register)13493      {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16,13494       &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},13495      {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13496       &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},13497      // lsr (immediate)13498      {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16,13499       &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},13500      {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13501       &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},13502      // lsr (register)13503      {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16,13504       &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},13505      {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13506       &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},13507      // rrx is a special case encoding of ror (immediate)13508      {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13509       &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},13510      // ror (immediate)13511      {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13512       &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},13513      // ror (register)13514      {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16,13515       &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},13516      {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13517       &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},13518      // mul13519      {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13520       &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"},13521      // mul13522      {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13523       &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"},13524 13525      // subs pc, lr and related instructions13526      {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13527       &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"},13528 13529      // RFE instructions  *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE13530      // LDM.. Instructions in this table;13531      // otherwise the wrong instructions will be selected.13532 13533      {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13534       &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"},13535      {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13536       &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"},13537 13538      // Load instructions13539      {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13540       &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"},13541      {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13542       &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"},13543      {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13544       &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"},13545      {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13546       &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},13547      {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,13548       &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},13549      {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13550       &EmulateInstructionARM::EmulateLDRRtRnImm,13551       "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},13552      {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,13553       &EmulateInstructionARM::EmulateLDRRtRnImm,13554       "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},13555      // Thumb2 PC-relative load into register13556      {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13557       &EmulateInstructionARM::EmulateLDRRtPCRelative,13558       "ldr<c>.w <Rt>, [PC, +/-#imm}]"},13559      {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13560       &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"},13561      {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13562       &EmulateInstructionARM::EmulateLDRRegister,13563       "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"},13564      {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13565       &EmulateInstructionARM::EmulateLDRBImmediate,13566       "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"},13567      {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13568       &EmulateInstructionARM::EmulateLDRBImmediate,13569       "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"},13570      {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13571       &EmulateInstructionARM::EmulateLDRBImmediate,13572       "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"},13573      {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13574       &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"},13575      {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16,13576       &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"},13577      {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13578       &EmulateInstructionARM::EmulateLDRBRegister,13579       "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},13580      {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13581       &EmulateInstructionARM::EmulateLDRHImmediate,13582       "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"},13583      {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13584       &EmulateInstructionARM::EmulateLDRHImmediate,13585       "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"},13586      {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13587       &EmulateInstructionARM::EmulateLDRHImmediate,13588       "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"},13589      {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13590       &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"},13591      {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13592       &EmulateInstructionARM::EmulateLDRHRegister,13593       "ldrh<c> <Rt>, [<Rn>,<Rm>]"},13594      {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13595       &EmulateInstructionARM::EmulateLDRHRegister,13596       "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},13597      {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13598       &EmulateInstructionARM::EmulateLDRSBImmediate,13599       "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"},13600      {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13601       &EmulateInstructionARM::EmulateLDRSBImmediate,13602       "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"},13603      {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13604       &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"},13605      {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13606       &EmulateInstructionARM::EmulateLDRSBRegister,13607       "ldrsb<c> <Rt>,[<Rn>,<Rm>]"},13608      {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13609       &EmulateInstructionARM::EmulateLDRSBRegister,13610       "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"},13611      {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13612       &EmulateInstructionARM::EmulateLDRSHImmediate,13613       "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"},13614      {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13615       &EmulateInstructionARM::EmulateLDRSHImmediate,13616       "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"},13617      {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13618       &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"},13619      {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13620       &EmulateInstructionARM::EmulateLDRSHRegister,13621       "ldrsh<c> <Rt>,[<Rn>,<Rm>]"},13622      {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13623       &EmulateInstructionARM::EmulateLDRSHRegister,13624       "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},13625      {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13626       &EmulateInstructionARM::EmulateLDRDImmediate,13627       "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},13628      {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,13629       &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},13630      {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,13631       &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},13632      {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,13633       &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},13634      {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,13635       &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},13636      {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,13637       &EmulateInstructionARM::EmulateVLD1Multiple,13638       "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},13639      {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,13640       &EmulateInstructionARM::EmulateVLD1Single,13641       "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},13642      {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,13643       &EmulateInstructionARM::EmulateVLD1SingleAll,13644       "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13645 13646      // Store instructions13647      {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13648       &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"},13649      {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13650       &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"},13651      {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13652       &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"},13653      {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13654       &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"},13655      {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16,13656       &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"},13657      {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13658       &EmulateInstructionARM::EmulateSTRThumb,13659       "str<c>.w <Rt>, [<Rn>,#<imm12>]"},13660      {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32,13661       &EmulateInstructionARM::EmulateSTRThumb,13662       "str<c> <Rt>, [<Rn>,#+/-<imm8>]"},13663      {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13664       &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"},13665      {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13666       &EmulateInstructionARM::EmulateSTRRegister,13667       "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"},13668      {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13669       &EmulateInstructionARM::EmulateSTRBThumb,13670       "strb<c> <Rt>, [<Rn>, #<imm5>]"},13671      {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13672       &EmulateInstructionARM::EmulateSTRBThumb,13673       "strb<c>.w <Rt>, [<Rn>, #<imm12>]"},13674      {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32,13675       &EmulateInstructionARM::EmulateSTRBThumb,13676       "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"},13677      {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16,13678       &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"},13679      {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13680       &EmulateInstructionARM::EmulateSTRHRegister,13681       "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"},13682      {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13683       &EmulateInstructionARM::EmulateSTREX,13684       "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"},13685      {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32,13686       &EmulateInstructionARM::EmulateSTRDImm,13687       "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},13688      {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,13689       &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},13690      {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,13691       &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},13692      {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32,13693       &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},13694      {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32,13695       &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},13696      {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,13697       &EmulateInstructionARM::EmulateVST1Multiple,13698       "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13699      {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32,13700       &EmulateInstructionARM::EmulateVST1Single,13701       "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},13702 13703      // Other instructions13704      {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,13705       &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"},13706      {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32,13707       &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"},13708      {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,13709       &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"},13710      {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13711       &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"},13712      {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,13713       &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"},13714      {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13715       &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"},13716      {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16,13717       &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"},13718      {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32,13719       &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"},13720  };13721 13722  const size_t k_num_thumb_opcodes = std::size(g_thumb_opcodes);13723  for (size_t i = 0; i < k_num_thumb_opcodes; ++i) {13724    if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&13725        (g_thumb_opcodes[i].variants & arm_isa) != 0)13726      return &g_thumb_opcodes[i];13727  }13728  return nullptr;13729}13730 13731bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) {13732  m_arch = arch;13733  m_arm_isa = 0;13734  llvm::StringRef arch_cstr = arch.GetArchitectureName();13735  if (arch_cstr.equals_insensitive("armv4t"))13736    m_arm_isa = ARMv4T;13737  else if (arch_cstr.equals_insensitive("armv5tej"))13738    m_arm_isa = ARMv5TEJ;13739  else if (arch_cstr.equals_insensitive("armv5te"))13740    m_arm_isa = ARMv5TE;13741  else if (arch_cstr.equals_insensitive("armv5t"))13742    m_arm_isa = ARMv5T;13743  else if (arch_cstr.equals_insensitive("armv6k"))13744    m_arm_isa = ARMv6K;13745  else if (arch_cstr.equals_insensitive("armv6t2"))13746    m_arm_isa = ARMv6T2;13747  else if (arch_cstr.equals_insensitive("armv7s"))13748    m_arm_isa = ARMv7S;13749  else if (arch_cstr.equals_insensitive("arm"))13750    m_arm_isa = ARMvAll;13751  else if (arch_cstr.equals_insensitive("thumb"))13752    m_arm_isa = ARMvAll;13753  else if (arch_cstr.starts_with_insensitive("armv4"))13754    m_arm_isa = ARMv4;13755  else if (arch_cstr.starts_with_insensitive("armv6"))13756    m_arm_isa = ARMv6;13757  else if (arch_cstr.starts_with_insensitive("armv7"))13758    m_arm_isa = ARMv7;13759  else if (arch_cstr.starts_with_insensitive("armv8"))13760    m_arm_isa = ARMv8;13761  return m_arm_isa != 0;13762}13763 13764bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode,13765                                           const Address &inst_addr,13766                                           Target *target) {13767  if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) {13768    if (m_arch.GetTriple().getArch() == llvm::Triple::thumb ||13769        m_arch.IsAlwaysThumbInstructions())13770      m_opcode_mode = eModeThumb;13771    else {13772      AddressClass addr_class = inst_addr.GetAddressClass();13773 13774      if ((addr_class == AddressClass::eCode) ||13775          (addr_class == AddressClass::eUnknown))13776        m_opcode_mode = eModeARM;13777      else if (addr_class == AddressClass::eCodeAlternateISA)13778        m_opcode_mode = eModeThumb;13779      else13780        return false;13781    }13782    if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions())13783      m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;13784    else13785      m_opcode_cpsr = CPSR_MODE_USR;13786    return true;13787  }13788  return false;13789}13790 13791bool EmulateInstructionARM::ReadInstruction() {13792  bool success = false;13793  m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric,13794                                       LLDB_REGNUM_GENERIC_FLAGS, 0, &success);13795  if (success) {13796    addr_t pc =13797        ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,13798                             LLDB_INVALID_ADDRESS, &success);13799    if (success) {13800      Context read_inst_context;13801      read_inst_context.type = eContextReadOpcode;13802      read_inst_context.SetNoArgs();13803 13804      if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) {13805        m_opcode_mode = eModeThumb;13806        uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);13807 13808        if (success) {13809          if ((thumb_opcode & 0xe000) != 0xe000 ||13810              ((thumb_opcode & 0x1800u) == 0)) {13811            m_opcode.SetOpcode16(thumb_opcode, GetByteOrder());13812          } else {13813            m_opcode.SetOpcode32(13814                (thumb_opcode << 16) |13815                    MemARead(read_inst_context, pc + 2, 2, 0, &success),13816                GetByteOrder());13817          }13818        }13819      } else {13820        m_opcode_mode = eModeARM;13821        m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success),13822                             GetByteOrder());13823      }13824 13825      if (!m_ignore_conditions) {13826        // If we are not ignoreing the conditions then init the it session from13827        // the current value of cpsr.13828        uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) |13829                      Bits32(m_opcode_cpsr, 26, 25);13830        if (it != 0)13831          m_it_session.InitIT(it);13832      }13833    }13834  }13835  if (!success) {13836    m_opcode_mode = eModeInvalid;13837    m_addr = LLDB_INVALID_ADDRESS;13838  }13839  return success;13840}13841 13842uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; }13843 13844bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) {13845  // If we are ignoring conditions, then always return true. this allows us to13846  // iterate over disassembly code and still emulate an instruction even if we13847  // don't have all the right bits set in the CPSR register...13848  if (m_ignore_conditions)13849    return true;13850 13851  const uint32_t cond = CurrentCond(opcode);13852  if (cond == UINT32_MAX)13853    return false;13854 13855  bool result = false;13856  switch (UnsignedBits(cond, 3, 1)) {13857  case 0:13858    if (m_opcode_cpsr == 0)13859      result = true;13860    else13861      result = (m_opcode_cpsr & MASK_CPSR_Z) != 0;13862    break;13863  case 1:13864    if (m_opcode_cpsr == 0)13865      result = true;13866    else13867      result = (m_opcode_cpsr & MASK_CPSR_C) != 0;13868    break;13869  case 2:13870    if (m_opcode_cpsr == 0)13871      result = true;13872    else13873      result = (m_opcode_cpsr & MASK_CPSR_N) != 0;13874    break;13875  case 3:13876    if (m_opcode_cpsr == 0)13877      result = true;13878    else13879      result = (m_opcode_cpsr & MASK_CPSR_V) != 0;13880    break;13881  case 4:13882    if (m_opcode_cpsr == 0)13883      result = true;13884    else13885      result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) &&13886               ((m_opcode_cpsr & MASK_CPSR_Z) == 0);13887    break;13888  case 5:13889    if (m_opcode_cpsr == 0)13890      result = true;13891    else {13892      bool n = (m_opcode_cpsr & MASK_CPSR_N);13893      bool v = (m_opcode_cpsr & MASK_CPSR_V);13894      result = n == v;13895    }13896    break;13897  case 6:13898    if (m_opcode_cpsr == 0)13899      result = true;13900    else {13901      bool n = (m_opcode_cpsr & MASK_CPSR_N);13902      bool v = (m_opcode_cpsr & MASK_CPSR_V);13903      result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);13904    }13905    break;13906  case 7:13907    // Always execute (cond == 0b1110, or the special 0b1111 which gives13908    // opcodes different meanings, but always means execution happens.13909    return true;13910  }13911 13912  if (cond & 1)13913    result = !result;13914  return result;13915}13916 13917uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) {13918  switch (m_opcode_mode) {13919  case eModeInvalid:13920    break;13921 13922  case eModeARM:13923    return UnsignedBits(opcode, 31, 28);13924 13925  case eModeThumb:13926    // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit13927    // 'cond' field of the encoding.13928    {13929      const uint32_t byte_size = m_opcode.GetByteSize();13930      if (byte_size == 2) {13931        if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f)13932          return Bits32(opcode, 11, 8);13933      } else if (byte_size == 4) {13934        if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 &&13935            Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) {13936          return Bits32(opcode, 25, 22);13937        }13938      } else13939        // We have an invalid thumb instruction, let's bail out.13940        break;13941 13942      return m_it_session.GetCond();13943    }13944  }13945  return UINT32_MAX; // Return invalid value13946}13947 13948bool EmulateInstructionARM::InITBlock() {13949  return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();13950}13951 13952bool EmulateInstructionARM::LastInITBlock() {13953  return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();13954}13955 13956bool EmulateInstructionARM::BadMode(uint32_t mode) {13957 13958  switch (mode) {13959  case 16:13960    return false; // '10000'13961  case 17:13962    return false; // '10001'13963  case 18:13964    return false; // '10010'13965  case 19:13966    return false; // '10011'13967  case 22:13968    return false; // '10110'13969  case 23:13970    return false; // '10111'13971  case 27:13972    return false; // '11011'13973  case 31:13974    return false; // '11111'13975  default:13976    return true;13977  }13978  return true;13979}13980 13981bool EmulateInstructionARM::CurrentModeIsPrivileged() {13982  uint32_t mode = Bits32(m_opcode_cpsr, 4, 0);13983 13984  if (BadMode(mode))13985    return false;13986 13987  if (mode == 16)13988    return false;13989 13990  return true;13991}13992 13993void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask,13994                                             bool affect_execstate) {13995  bool privileged = CurrentModeIsPrivileged();13996 13997  uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20;13998 13999  if (BitIsSet(bytemask, 3)) {14000    tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27);14001    if (affect_execstate)14002      tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24);14003  }14004 14005  if (BitIsSet(bytemask, 2)) {14006    tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16);14007  }14008 14009  if (BitIsSet(bytemask, 1)) {14010    if (affect_execstate)14011      tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10);14012    tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9);14013    if (privileged)14014      tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8);14015  }14016 14017  if (BitIsSet(bytemask, 0)) {14018    if (privileged)14019      tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6);14020    if (affect_execstate)14021      tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5);14022    if (privileged)14023      tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0);14024  }14025 14026  m_opcode_cpsr = tmp_cpsr;14027}14028 14029bool EmulateInstructionARM::BranchWritePC(const Context &context,14030                                          uint32_t addr) {14031  addr_t target;14032 14033  // Check the current instruction set.14034  if (CurrentInstrSet() == eModeARM)14035    target = addr & 0xfffffffc;14036  else14037    target = addr & 0xfffffffe;14038 14039  return WriteRegisterUnsigned(context, eRegisterKindGeneric,14040                               LLDB_REGNUM_GENERIC_PC, target);14041}14042 14043// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by14044// inspecting addr.14045bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {14046  addr_t target;14047  // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,14048  // we want to record it and issue a WriteRegister callback so the clients can14049  // track the mode changes accordingly.14050  bool cpsr_changed = false;14051 14052  if (BitIsSet(addr, 0)) {14053    if (CurrentInstrSet() != eModeThumb) {14054      SelectInstrSet(eModeThumb);14055      cpsr_changed = true;14056    }14057    target = addr & 0xfffffffe;14058    context.SetISA(eModeThumb);14059  } else if (BitIsClear(addr, 1)) {14060    if (CurrentInstrSet() != eModeARM) {14061      SelectInstrSet(eModeARM);14062      cpsr_changed = true;14063    }14064    target = addr & 0xfffffffc;14065    context.SetISA(eModeARM);14066  } else14067    return false; // address<1:0> == '10' => UNPREDICTABLE14068 14069  if (cpsr_changed) {14070    if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,14071                               LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))14072      return false;14073  }14074  return WriteRegisterUnsigned(context, eRegisterKindGeneric,14075                               LLDB_REGNUM_GENERIC_PC, target);14076}14077 14078// Dispatches to either BXWritePC or BranchWritePC based on architecture14079// versions.14080bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) {14081  if (ArchVersion() >= ARMv5T)14082    return BXWritePC(context, addr);14083  else14084    return BranchWritePC((const Context)context, addr);14085}14086 14087// Dispatches to either BXWritePC or BranchWritePC based on architecture14088// versions and current instruction set.14089bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) {14090  if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)14091    return BXWritePC(context, addr);14092  else14093    return BranchWritePC((const Context)context, addr);14094}14095 14096EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() {14097  return m_opcode_mode;14098}14099 14100// Set the 'T' bit of our CPSR.  The m_opcode_mode gets updated when the next14101// ReadInstruction() is performed.  This function has a side effect of updating14102// the m_new_inst_cpsr member variable if necessary.14103bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) {14104  m_new_inst_cpsr = m_opcode_cpsr;14105  switch (arm_or_thumb) {14106  default:14107    return false;14108  case eModeARM:14109    // Clear the T bit.14110    m_new_inst_cpsr &= ~MASK_CPSR_T;14111    break;14112  case eModeThumb:14113    // Set the T bit.14114    m_new_inst_cpsr |= MASK_CPSR_T;14115    break;14116  }14117  return true;14118}14119 14120// This function returns TRUE if the processor currently provides support for14121// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,14122// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.14123bool EmulateInstructionARM::UnalignedSupport() {14124  return (ArchVersion() >= ARMv7);14125}14126 14127// The main addition and subtraction instructions can produce status14128// information about both unsigned carry and signed overflow conditions.  This14129// status information can be used to synthesize multi-word additions and14130// subtractions.14131EmulateInstructionARM::AddWithCarryResult14132EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) {14133  uint32_t result;14134  uint8_t carry_out;14135  uint8_t overflow;14136 14137  uint64_t unsigned_sum = x + y + carry_in;14138  int64_t signed_sum = 0;14139  int32_t signed_sum32;14140  if (llvm::AddOverflow((int32_t)x, (int32_t)y, signed_sum32))14141    signed_sum++;14142  signed_sum += signed_sum32;14143 14144  signed_sum += (int32_t)carry_in;14145 14146  result = UnsignedBits(unsigned_sum, 31, 0);14147  //    carry_out = (result == unsigned_sum ? 0 : 1);14148  overflow = ((int32_t)result == signed_sum ? 0 : 1);14149 14150  if (carry_in)14151    carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0;14152  else14153    carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0;14154 14155  AddWithCarryResult res = {result, carry_out, overflow};14156  return res;14157}14158 14159uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) {14160  lldb::RegisterKind reg_kind;14161  uint32_t reg_num;14162  switch (num) {14163  case SP_REG:14164    reg_kind = eRegisterKindGeneric;14165    reg_num = LLDB_REGNUM_GENERIC_SP;14166    break;14167  case LR_REG:14168    reg_kind = eRegisterKindGeneric;14169    reg_num = LLDB_REGNUM_GENERIC_RA;14170    break;14171  case PC_REG:14172    reg_kind = eRegisterKindGeneric;14173    reg_num = LLDB_REGNUM_GENERIC_PC;14174    break;14175  default:14176    if (num < SP_REG) {14177      reg_kind = eRegisterKindDWARF;14178      reg_num = dwarf_r0 + num;14179    } else {14180      // assert(0 && "Invalid register number");14181      *success = false;14182      return UINT32_MAX;14183    }14184    break;14185  }14186 14187  // Read our register.14188  uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success);14189 14190  // When executing an ARM instruction , PC reads as the address of the current14191  // instruction plus 8. When executing a Thumb instruction , PC reads as the14192  // address of the current instruction plus 4.14193  if (num == 15) {14194    if (CurrentInstrSet() == eModeARM)14195      val += 8;14196    else14197      val += 4;14198  }14199 14200  return val;14201}14202 14203// Write the result to the ARM core register Rd, and optionally update the14204// condition flags based on the result.14205//14206// This helper method tries to encapsulate the following pseudocode from the14207// ARM Architecture Reference Manual:14208//14209// if d == 15 then         // Can only occur for encoding A114210//     ALUWritePC(result); // setflags is always FALSE here14211// else14212//     R[d] = result;14213//     if setflags then14214//         APSR.N = result<31>;14215//         APSR.Z = IsZeroBit(result);14216//         APSR.C = carry;14217//         // APSR.V unchanged14218//14219// In the above case, the API client does not pass in the overflow arg, which14220// defaults to ~0u.14221bool EmulateInstructionARM::WriteCoreRegOptionalFlags(14222    Context &context, const uint32_t result, const uint32_t Rd, bool setflags,14223    const uint32_t carry, const uint32_t overflow) {14224  if (Rd == 15) {14225    if (!ALUWritePC(context, result))14226      return false;14227  } else {14228    lldb::RegisterKind reg_kind;14229    uint32_t reg_num;14230    switch (Rd) {14231    case SP_REG:14232      reg_kind = eRegisterKindGeneric;14233      reg_num = LLDB_REGNUM_GENERIC_SP;14234      break;14235    case LR_REG:14236      reg_kind = eRegisterKindGeneric;14237      reg_num = LLDB_REGNUM_GENERIC_RA;14238      break;14239    default:14240      reg_kind = eRegisterKindDWARF;14241      reg_num = dwarf_r0 + Rd;14242    }14243    if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result))14244      return false;14245    if (setflags)14246      return WriteFlags(context, result, carry, overflow);14247  }14248  return true;14249}14250 14251// This helper method tries to encapsulate the following pseudocode from the14252// ARM Architecture Reference Manual:14253//14254// APSR.N = result<31>;14255// APSR.Z = IsZeroBit(result);14256// APSR.C = carry;14257// APSR.V = overflow14258//14259// Default arguments can be specified for carry and overflow parameters, which14260// means not to update the respective flags.14261bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result,14262                                       const uint32_t carry,14263                                       const uint32_t overflow) {14264  m_new_inst_cpsr = m_opcode_cpsr;14265  SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));14266  SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);14267  if (carry != ~0u)14268    SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);14269  if (overflow != ~0u)14270    SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);14271  if (m_new_inst_cpsr != m_opcode_cpsr) {14272    if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,14273                               LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))14274      return false;14275  }14276  return true;14277}14278 14279bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {14280  ARMOpcode *opcode_data = nullptr;14281 14282  if (m_opcode_mode == eModeThumb)14283    opcode_data =14284        GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);14285  else if (m_opcode_mode == eModeARM)14286    opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa);14287 14288  const bool auto_advance_pc =14289      evaluate_options & eEmulateInstructionOptionAutoAdvancePC;14290  m_ignore_conditions =14291      evaluate_options & eEmulateInstructionOptionIgnoreConditions;14292 14293  bool success = false;14294  if (m_opcode_cpsr == 0 || !m_ignore_conditions) {14295    m_opcode_cpsr =14296        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);14297  }14298 14299  // Only return false if we are unable to read the CPSR if we care about14300  // conditions14301  if (!success && !m_ignore_conditions)14302    return false;14303 14304  uint32_t orig_pc_value = 0;14305  if (auto_advance_pc) {14306    orig_pc_value =14307        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);14308    if (!success)14309      return false;14310  }14311 14312  // Call the Emulate... function if we managed to decode the opcode.14313  if (opcode_data) {14314    success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(),14315                                             opcode_data->encoding);14316    if (!success)14317      return false;14318  }14319 14320  // Advance the ITSTATE bits to their values for the next instruction if we14321  // haven't just executed an IT instruction what initialized it.14322  if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() &&14323      (opcode_data == nullptr ||14324       opcode_data->callback != &EmulateInstructionARM::EmulateIT))14325    m_it_session.ITAdvance();14326 14327  if (auto_advance_pc) {14328    uint32_t after_pc_value =14329        ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success);14330    if (!success)14331      return false;14332 14333    if (after_pc_value == orig_pc_value) {14334      after_pc_value += m_opcode.GetByteSize();14335 14336      EmulateInstruction::Context context;14337      context.type = eContextAdvancePC;14338      context.SetNoArgs();14339      if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc,14340                                 after_pc_value))14341        return false;14342    }14343  }14344  return true;14345}14346 14347EmulateInstruction::InstructionCondition14348EmulateInstructionARM::GetInstructionCondition() {14349  const uint32_t cond = CurrentCond(m_opcode.GetOpcode32());14350  if (cond == 0xe || cond == 0xf || cond == UINT32_MAX)14351    return EmulateInstruction::UnconditionalCondition;14352  return cond;14353}14354 14355bool EmulateInstructionARM::TestEmulation(Stream &out_stream, ArchSpec &arch,14356                                          OptionValueDictionary *test_data) {14357  if (!test_data) {14358    out_stream.Printf("TestEmulation: Missing test data.\n");14359    return false;14360  }14361 14362  static constexpr llvm::StringLiteral opcode_key("opcode");14363  static constexpr llvm::StringLiteral before_key("before_state");14364  static constexpr llvm::StringLiteral after_key("after_state");14365 14366  OptionValueSP value_sp = test_data->GetValueForKey(opcode_key);14367 14368  uint32_t test_opcode;14369  if ((value_sp.get() == nullptr) ||14370      (value_sp->GetType() != OptionValue::eTypeUInt64)) {14371    out_stream.Printf("TestEmulation: Error reading opcode from test file.\n");14372    return false;14373  }14374  test_opcode = value_sp->GetValueAs<uint64_t>().value_or(0);14375 14376  if (arch.GetTriple().getArch() == llvm::Triple::thumb ||14377      arch.IsAlwaysThumbInstructions()) {14378    m_opcode_mode = eModeThumb;14379    if (test_opcode < 0x10000)14380      m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder());14381    else14382      m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());14383  } else if (arch.GetTriple().getArch() == llvm::Triple::arm) {14384    m_opcode_mode = eModeARM;14385    m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder());14386  } else {14387    out_stream.Printf("TestEmulation:  Invalid arch.\n");14388    return false;14389  }14390 14391  EmulationStateARM before_state;14392  EmulationStateARM after_state;14393 14394  value_sp = test_data->GetValueForKey(before_key);14395  if ((value_sp.get() == nullptr) ||14396      (value_sp->GetType() != OptionValue::eTypeDictionary)) {14397    out_stream.Printf("TestEmulation:  Failed to find 'before' state.\n");14398    return false;14399  }14400 14401  OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary();14402  if (!before_state.LoadStateFromDictionary(state_dictionary)) {14403    out_stream.Printf("TestEmulation:  Failed loading 'before' state.\n");14404    return false;14405  }14406 14407  value_sp = test_data->GetValueForKey(after_key);14408  if ((value_sp.get() == nullptr) ||14409      (value_sp->GetType() != OptionValue::eTypeDictionary)) {14410    out_stream.Printf("TestEmulation:  Failed to find 'after' state.\n");14411    return false;14412  }14413 14414  state_dictionary = value_sp->GetAsDictionary();14415  if (!after_state.LoadStateFromDictionary(state_dictionary)) {14416    out_stream.Printf("TestEmulation: Failed loading 'after' state.\n");14417    return false;14418  }14419 14420  SetBaton((void *)&before_state);14421  SetCallbacks(&EmulationStateARM::ReadPseudoMemory,14422               &EmulationStateARM::WritePseudoMemory,14423               &EmulationStateARM::ReadPseudoRegister,14424               &EmulationStateARM::WritePseudoRegister);14425 14426  bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC);14427  if (!success) {14428    out_stream.Printf("TestEmulation:  EvaluateInstruction() failed.\n");14429    return false;14430  }14431 14432  success = before_state.CompareState(after_state, out_stream);14433  if (!success)14434    out_stream.Printf("TestEmulation:  State after emulation does not match "14435                      "'after' state.\n");14436 14437  return success;14438}14439//14440//14441// const char *14442// EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)14443//{14444//    if (reg_kind == eRegisterKindGeneric)14445//    {14446//        switch (reg_num)14447//        {14448//        case LLDB_REGNUM_GENERIC_PC:    return "pc";14449//        case LLDB_REGNUM_GENERIC_SP:    return "sp";14450//        case LLDB_REGNUM_GENERIC_FP:    return "fp";14451//        case LLDB_REGNUM_GENERIC_RA:    return "lr";14452//        case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";14453//        default: return NULL;14454//        }14455//    }14456//    else if (reg_kind == eRegisterKindDWARF)14457//    {14458//        return GetARMDWARFRegisterName (reg_num);14459//    }14460//    return NULL;14461//}14462//14463bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) {14464  unwind_plan.Clear();14465  unwind_plan.SetRegisterKind(eRegisterKindDWARF);14466 14467  UnwindPlan::Row row;14468 14469  // Our previous Call Frame Address is the stack pointer14470  row.GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0);14471 14472  unwind_plan.AppendRow(std::move(row));14473  unwind_plan.SetSourceName("EmulateInstructionARM");14474  unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);14475  unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);14476  unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);14477  unwind_plan.SetReturnAddressRegister(dwarf_lr);14478  return true;14479}14480 14481llvm::Expected<unsigned>14482ARMSingleStepBreakpointLocationsPredictor::GetBreakpointSize(14483    lldb::addr_t bp_addr) {14484  auto flags = m_emulator_up->ReadRegisterUnsigned(14485      eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_ADDRESS,14486      nullptr);14487  if (flags == LLDB_INVALID_ADDRESS)14488    return llvm::createStringError(llvm::inconvertibleErrorCode(),14489                                   "Reading flags failed!");14490 14491  return (flags & 0x20) ? /* Thumb mode */ 2 : /* Arm mode */ 4;14492}14493