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(®_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