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-exception 6 // 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 30 using namespace lldb; 31 using namespace lldb_private; 32 33 LLDB_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 implementation 43 // 44 45 static 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-7 235 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 accumulator 261 // 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 - 15 288 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 - 7 424 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/Neon 450 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.50 604 // Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition. 605 static 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. 615 bool 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 IT 621 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. 634 void 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. 646 bool ITSession::InITBlock() { return ITCounter != 0; } 647 648 // Return true if we're the last instruction inside an IT Block. 649 bool ITSession::LastInITBlock() { return ITCounter == 1; } 650 651 // Get condition bits for the current thumb instruction. 652 uint32_t ITSession::GetCond() { 653 if (InITBlock()) 654 return Bits32(ITState, 7, 4); 655 else 656 return COND_AL; 657 } 658 659 // ARM constants used during decoding 660 #define REG_RD 0 661 #define LDM_REGLIST 1 662 #define SP_REG 13 663 #define LR_REG 14 664 #define PC_REG 15 665 #define PC_REGLIST_BIT 0x8000 666 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 0 695 #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 implementation 706 // 707 708 void EmulateInstructionARM::Initialize() { 709 PluginManager::RegisterPlugin(GetPluginNameStatic(), 710 GetPluginDescriptionStatic(), CreateInstance); 711 } 712 713 void EmulateInstructionARM::Terminate() { 714 PluginManager::UnregisterPlugin(CreateInstance); 715 } 716 717 llvm::StringRef EmulateInstructionARM::GetPluginDescriptionStatic() { 718 return "Emulate instructions for the ARM architecture."; 719 } 720 721 EmulateInstruction * 722 EmulateInstructionARM::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 744 bool 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 for 754 // many ARM instructions. 755 bool 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 ARM 767 // instructions. 768 bool 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 786 std::optional<RegisterInfo> 787 EmulateInstructionARM::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 821 uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const { 822 if (m_arch.GetTriple().isAndroid()) 823 return LLDB_INVALID_REGNUM; // Don't use frame pointer on android 824 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 // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: 834 is_apple = true; 835 break; 836 default: 837 break; 838 } 839 840 /* On Apple iOS et al, the frame pointer register is always r7. 841 * Typically on other ARM systems, thumb code uses r7; arm code uses r11. 842 * Windows on ARM, which is in thumb mode, uses r11 though. 843 */ 844 845 uint32_t fp_regnum = 11; 846 847 if (is_apple) 848 fp_regnum = 7; 849 850 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows()) 851 fp_regnum = 7; 852 853 return fp_regnum; 854 } 855 856 uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const { 857 bool is_apple = false; 858 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) 859 is_apple = true; 860 switch (m_arch.GetTriple().getOS()) { 861 case llvm::Triple::Darwin: 862 case llvm::Triple::MacOSX: 863 case llvm::Triple::IOS: 864 is_apple = true; 865 break; 866 default: 867 break; 868 } 869 870 /* On Apple iOS et al, the frame pointer register is always r7. 871 * Typically on other ARM systems, thumb code uses r7; arm code uses r11. 872 * Windows on ARM, which is in thumb mode, uses r11 though. 873 */ 874 875 uint32_t fp_regnum = dwarf_r11; 876 877 if (is_apple) 878 fp_regnum = dwarf_r7; 879 880 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows()) 881 fp_regnum = dwarf_r7; 882 883 return fp_regnum; 884 } 885 886 // Push Multiple Registers stores multiple registers to the stack, storing to 887 // consecutive memory locations ending just below the address in SP, and 888 // updates 889 // SP to point to the start of the stored data. 890 bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode, 891 const ARMEncoding encoding) { 892 #if 0 893 // ARM pseudo code... 894 if (ConditionPassed()) 895 { 896 EncodingSpecificOperations(); 897 NullCheckIfThumbEE(13); 898 address = SP - 4*BitCount(registers); 899 900 for (i = 0 to 14) 901 { 902 if (registers<i> == '1') 903 { 904 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1 905 MemA[address,4] = bits(32) UNKNOWN; 906 else 907 MemA[address,4] = R[i]; 908 address = address + 4; 909 } 910 } 911 912 if (registers<15> == '1') // Only possible for encoding A1 or A2 913 MemA[address,4] = PCStoreValue(); 914 915 SP = SP - 4*BitCount(registers); 916 } 917 #endif 918 919 bool success = false; 920 if (ConditionPassed(opcode)) { 921 const uint32_t addr_byte_size = GetAddressByteSize(); 922 const addr_t sp = ReadCoreReg(SP_REG, &success); 923 if (!success) 924 return false; 925 uint32_t registers = 0; 926 uint32_t Rt; // the source register 927 switch (encoding) { 928 case eEncodingT1: 929 registers = Bits32(opcode, 7, 0); 930 // The M bit represents LR. 931 if (Bit32(opcode, 8)) 932 registers |= (1u << 14); 933 // if BitCount(registers) < 1 then UNPREDICTABLE; 934 if (BitCount(registers) < 1) 935 return false; 936 break; 937 case eEncodingT2: 938 // Ignore bits 15 & 13. 939 registers = Bits32(opcode, 15, 0) & ~0xa000; 940 // if BitCount(registers) < 2 then UNPREDICTABLE; 941 if (BitCount(registers) < 2) 942 return false; 943 break; 944 case eEncodingT3: 945 Rt = Bits32(opcode, 15, 12); 946 // if BadReg(t) then UNPREDICTABLE; 947 if (BadReg(Rt)) 948 return false; 949 registers = (1u << Rt); 950 break; 951 case eEncodingA1: 952 registers = Bits32(opcode, 15, 0); 953 // Instead of return false, let's handle the following case as well, 954 // which amounts to pushing one reg onto the full descending stacks. 955 // if BitCount(register_list) < 2 then SEE STMDB / STMFD; 956 break; 957 case eEncodingA2: 958 Rt = Bits32(opcode, 15, 12); 959 // if t == 13 then UNPREDICTABLE; 960 if (Rt == dwarf_sp) 961 return false; 962 registers = (1u << Rt); 963 break; 964 default: 965 return false; 966 } 967 addr_t sp_offset = addr_byte_size * BitCount(registers); 968 addr_t addr = sp - sp_offset; 969 uint32_t i; 970 971 EmulateInstruction::Context context; 972 context.type = EmulateInstruction::eContextPushRegisterOnStack; 973 std::optional<RegisterInfo> sp_reg = 974 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 975 for (i = 0; i < 15; ++i) { 976 if (BitIsSet(registers, i)) { 977 std::optional<RegisterInfo> reg_info = 978 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); 979 context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp); 980 uint32_t reg_value = ReadCoreReg(i, &success); 981 if (!success) 982 return false; 983 if (!MemAWrite(context, addr, reg_value, addr_byte_size)) 984 return false; 985 addr += addr_byte_size; 986 } 987 } 988 989 if (BitIsSet(registers, 15)) { 990 std::optional<RegisterInfo> reg_info = 991 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 992 context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp); 993 const uint32_t pc = ReadCoreReg(PC_REG, &success); 994 if (!success) 995 return false; 996 if (!MemAWrite(context, addr, pc, addr_byte_size)) 997 return false; 998 } 999 1000 context.type = EmulateInstruction::eContextAdjustStackPointer; 1001 context.SetImmediateSigned(-sp_offset); 1002 1003 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 1004 LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 1005 return false; 1006 } 1007 return true; 1008 } 1009 1010 // Pop Multiple Registers loads multiple registers from the stack, loading from 1011 // consecutive memory locations staring at the address in SP, and updates 1012 // SP to point just above the loaded data. 1013 bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode, 1014 const ARMEncoding encoding) { 1015 #if 0 1016 // ARM pseudo code... 1017 if (ConditionPassed()) 1018 { 1019 EncodingSpecificOperations(); NullCheckIfThumbEE(13); 1020 address = SP; 1021 for i = 0 to 14 1022 if registers<i> == '1' then 1023 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4; 1024 if registers<15> == '1' then 1025 if UnalignedAllowed then 1026 LoadWritePC(MemU[address,4]); 1027 else 1028 LoadWritePC(MemA[address,4]); 1029 if registers<13> == '0' then SP = SP + 4*BitCount(registers); 1030 if registers<13> == '1' then SP = bits(32) UNKNOWN; 1031 } 1032 #endif 1033 1034 bool success = false; 1035 1036 if (ConditionPassed(opcode)) { 1037 const uint32_t addr_byte_size = GetAddressByteSize(); 1038 const addr_t sp = ReadCoreReg(SP_REG, &success); 1039 if (!success) 1040 return false; 1041 uint32_t registers = 0; 1042 uint32_t Rt; // the destination register 1043 switch (encoding) { 1044 case eEncodingT1: 1045 registers = Bits32(opcode, 7, 0); 1046 // The P bit represents PC. 1047 if (Bit32(opcode, 8)) 1048 registers |= (1u << 15); 1049 // if BitCount(registers) < 1 then UNPREDICTABLE; 1050 if (BitCount(registers) < 1) 1051 return false; 1052 break; 1053 case eEncodingT2: 1054 // Ignore bit 13. 1055 registers = Bits32(opcode, 15, 0) & ~0x2000; 1056 // if BitCount(registers) < 2 || (P == '1' && M == '1') then 1057 // UNPREDICTABLE; 1058 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14))) 1059 return false; 1060 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then 1061 // UNPREDICTABLE; 1062 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 1063 return false; 1064 break; 1065 case eEncodingT3: 1066 Rt = Bits32(opcode, 15, 12); 1067 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then 1068 // UNPREDICTABLE; 1069 if (Rt == 13) 1070 return false; 1071 if (Rt == 15 && InITBlock() && !LastInITBlock()) 1072 return false; 1073 registers = (1u << Rt); 1074 break; 1075 case eEncodingA1: 1076 registers = Bits32(opcode, 15, 0); 1077 // Instead of return false, let's handle the following case as well, 1078 // which amounts to popping one reg from the full descending stacks. 1079 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; 1080 1081 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE; 1082 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7) 1083 return false; 1084 break; 1085 case eEncodingA2: 1086 Rt = Bits32(opcode, 15, 12); 1087 // if t == 13 then UNPREDICTABLE; 1088 if (Rt == dwarf_sp) 1089 return false; 1090 registers = (1u << Rt); 1091 break; 1092 default: 1093 return false; 1094 } 1095 addr_t sp_offset = addr_byte_size * BitCount(registers); 1096 addr_t addr = sp; 1097 uint32_t i, data; 1098 1099 EmulateInstruction::Context context; 1100 context.type = EmulateInstruction::eContextPopRegisterOffStack; 1101 1102 std::optional<RegisterInfo> sp_reg = 1103 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 1104 1105 for (i = 0; i < 15; ++i) { 1106 if (BitIsSet(registers, i)) { 1107 context.SetAddress(addr); 1108 data = MemARead(context, addr, 4, 0, &success); 1109 if (!success) 1110 return false; 1111 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, 1112 data)) 1113 return false; 1114 addr += addr_byte_size; 1115 } 1116 } 1117 1118 if (BitIsSet(registers, 15)) { 1119 context.SetRegisterPlusOffset(*sp_reg, addr - sp); 1120 data = MemARead(context, addr, 4, 0, &success); 1121 if (!success) 1122 return false; 1123 // In ARMv5T and above, this is an interworking branch. 1124 if (!LoadWritePC(context, data)) 1125 return false; 1126 // addr += addr_byte_size; 1127 } 1128 1129 context.type = EmulateInstruction::eContextAdjustStackPointer; 1130 context.SetImmediateSigned(sp_offset); 1131 1132 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 1133 LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 1134 return false; 1135 } 1136 return true; 1137 } 1138 1139 // Set r7 or ip to point to saved value residing within the stack. 1140 // ADD (SP plus immediate) 1141 bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode, 1142 const ARMEncoding encoding) { 1143 #if 0 1144 // ARM pseudo code... 1145 if (ConditionPassed()) 1146 { 1147 EncodingSpecificOperations(); 1148 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 1149 if d == 15 then 1150 ALUWritePC(result); // setflags is always FALSE here 1151 else 1152 R[d] = result; 1153 if setflags then 1154 APSR.N = result<31>; 1155 APSR.Z = IsZeroBit(result); 1156 APSR.C = carry; 1157 APSR.V = overflow; 1158 } 1159 #endif 1160 1161 bool success = false; 1162 1163 if (ConditionPassed(opcode)) { 1164 const addr_t sp = ReadCoreReg(SP_REG, &success); 1165 if (!success) 1166 return false; 1167 uint32_t Rd; // the destination register 1168 uint32_t imm32; 1169 switch (encoding) { 1170 case eEncodingT1: 1171 Rd = 7; 1172 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32) 1173 break; 1174 case eEncodingA1: 1175 Rd = Bits32(opcode, 15, 12); 1176 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1177 break; 1178 default: 1179 return false; 1180 } 1181 addr_t sp_offset = imm32; 1182 addr_t addr = sp + sp_offset; // a pointer to the stack area 1183 1184 EmulateInstruction::Context context; 1185 if (Rd == GetFramePointerRegisterNumber()) 1186 context.type = eContextSetFramePointer; 1187 else 1188 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1189 std::optional<RegisterInfo> sp_reg = 1190 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 1191 context.SetRegisterPlusOffset(*sp_reg, sp_offset); 1192 1193 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, 1194 addr)) 1195 return false; 1196 } 1197 return true; 1198 } 1199 1200 // Set r7 or ip to the current stack pointer. 1201 // MOV (register) 1202 bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode, 1203 const ARMEncoding encoding) { 1204 #if 0 1205 // ARM pseudo code... 1206 if (ConditionPassed()) 1207 { 1208 EncodingSpecificOperations(); 1209 result = R[m]; 1210 if d == 15 then 1211 ALUWritePC(result); // setflags is always FALSE here 1212 else 1213 R[d] = result; 1214 if setflags then 1215 APSR.N = result<31>; 1216 APSR.Z = IsZeroBit(result); 1217 // APSR.C unchanged 1218 // APSR.V unchanged 1219 } 1220 #endif 1221 1222 bool success = false; 1223 1224 if (ConditionPassed(opcode)) { 1225 const addr_t sp = ReadCoreReg(SP_REG, &success); 1226 if (!success) 1227 return false; 1228 uint32_t Rd; // the destination register 1229 switch (encoding) { 1230 case eEncodingT1: 1231 Rd = 7; 1232 break; 1233 case eEncodingA1: 1234 Rd = 12; 1235 break; 1236 default: 1237 return false; 1238 } 1239 1240 EmulateInstruction::Context context; 1241 if (Rd == GetFramePointerRegisterNumber()) 1242 context.type = EmulateInstruction::eContextSetFramePointer; 1243 else 1244 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1245 std::optional<RegisterInfo> sp_reg = 1246 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 1247 context.SetRegisterPlusOffset(*sp_reg, 0); 1248 1249 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) 1250 return false; 1251 } 1252 return true; 1253 } 1254 1255 // Move from high register (r8-r15) to low register (r0-r7). 1256 // MOV (register) 1257 bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode, 1258 const ARMEncoding encoding) { 1259 return EmulateMOVRdRm(opcode, encoding); 1260 } 1261 1262 // Move from register to register. 1263 // MOV (register) 1264 bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode, 1265 const ARMEncoding encoding) { 1266 #if 0 1267 // ARM pseudo code... 1268 if (ConditionPassed()) 1269 { 1270 EncodingSpecificOperations(); 1271 result = R[m]; 1272 if d == 15 then 1273 ALUWritePC(result); // setflags is always FALSE here 1274 else 1275 R[d] = result; 1276 if setflags then 1277 APSR.N = result<31>; 1278 APSR.Z = IsZeroBit(result); 1279 // APSR.C unchanged 1280 // APSR.V unchanged 1281 } 1282 #endif 1283 1284 bool success = false; 1285 1286 if (ConditionPassed(opcode)) { 1287 uint32_t Rm; // the source register 1288 uint32_t Rd; // the destination register 1289 bool setflags; 1290 switch (encoding) { 1291 case eEncodingT1: 1292 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 1293 Rm = Bits32(opcode, 6, 3); 1294 setflags = false; 1295 if (Rd == 15 && InITBlock() && !LastInITBlock()) 1296 return false; 1297 break; 1298 case eEncodingT2: 1299 Rd = Bits32(opcode, 2, 0); 1300 Rm = Bits32(opcode, 5, 3); 1301 setflags = true; 1302 if (InITBlock()) 1303 return false; 1304 break; 1305 case eEncodingT3: 1306 Rd = Bits32(opcode, 11, 8); 1307 Rm = Bits32(opcode, 3, 0); 1308 setflags = BitIsSet(opcode, 20); 1309 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 1310 if (setflags && (BadReg(Rd) || BadReg(Rm))) 1311 return false; 1312 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then 1313 // UNPREDICTABLE; 1314 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13))) 1315 return false; 1316 break; 1317 case eEncodingA1: 1318 Rd = Bits32(opcode, 15, 12); 1319 Rm = Bits32(opcode, 3, 0); 1320 setflags = BitIsSet(opcode, 20); 1321 1322 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 1323 // instructions; 1324 if (Rd == 15 && setflags) 1325 return EmulateSUBSPcLrEtc(opcode, encoding); 1326 break; 1327 default: 1328 return false; 1329 } 1330 uint32_t result = ReadCoreReg(Rm, &success); 1331 if (!success) 1332 return false; 1333 1334 // The context specifies that Rm is to be moved into Rd. 1335 EmulateInstruction::Context context; 1336 if (Rd == 13) 1337 context.type = EmulateInstruction::eContextAdjustStackPointer; 1338 else if (Rd == GetFramePointerRegisterNumber() && Rm == 13) 1339 context.type = EmulateInstruction::eContextSetFramePointer; 1340 else 1341 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1342 std::optional<RegisterInfo> dwarf_reg = 1343 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 1344 context.SetRegisterPlusOffset(*dwarf_reg, 0); 1345 1346 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags)) 1347 return false; 1348 } 1349 return true; 1350 } 1351 1352 // Move (immediate) writes an immediate value to the destination register. It 1353 // can optionally update the condition flags based on the value. 1354 // MOV (immediate) 1355 bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode, 1356 const ARMEncoding encoding) { 1357 #if 0 1358 // ARM pseudo code... 1359 if (ConditionPassed()) 1360 { 1361 EncodingSpecificOperations(); 1362 result = imm32; 1363 if d == 15 then // Can only occur for ARM encoding 1364 ALUWritePC(result); // setflags is always FALSE here 1365 else 1366 R[d] = result; 1367 if setflags then 1368 APSR.N = result<31>; 1369 APSR.Z = IsZeroBit(result); 1370 APSR.C = carry; 1371 // APSR.V unchanged 1372 } 1373 #endif 1374 1375 if (ConditionPassed(opcode)) { 1376 uint32_t Rd; // the destination register 1377 uint32_t imm32; // the immediate value to be written to Rd 1378 uint32_t carry = 1379 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C. 1380 // for setflags == false, this value is a don't care initialized to 1381 // 0 to silence the static analyzer 1382 bool setflags; 1383 switch (encoding) { 1384 case eEncodingT1: 1385 Rd = Bits32(opcode, 10, 8); 1386 setflags = !InITBlock(); 1387 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 1388 carry = APSR_C; 1389 1390 break; 1391 1392 case eEncodingT2: 1393 Rd = Bits32(opcode, 11, 8); 1394 setflags = BitIsSet(opcode, 20); 1395 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 1396 if (BadReg(Rd)) 1397 return false; 1398 1399 break; 1400 1401 case eEncodingT3: { 1402 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 1403 // 32); 1404 Rd = Bits32(opcode, 11, 8); 1405 setflags = false; 1406 uint32_t imm4 = Bits32(opcode, 19, 16); 1407 uint32_t imm3 = Bits32(opcode, 14, 12); 1408 uint32_t i = Bit32(opcode, 26); 1409 uint32_t imm8 = Bits32(opcode, 7, 0); 1410 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; 1411 1412 // if BadReg(d) then UNPREDICTABLE; 1413 if (BadReg(Rd)) 1414 return false; 1415 } break; 1416 1417 case eEncodingA1: 1418 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) = 1419 // ARMExpandImm_C(imm12, APSR.C); 1420 Rd = Bits32(opcode, 15, 12); 1421 setflags = BitIsSet(opcode, 20); 1422 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); 1423 1424 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 1425 // instructions; 1426 if ((Rd == 15) && setflags) 1427 return EmulateSUBSPcLrEtc(opcode, encoding); 1428 1429 break; 1430 1431 case eEncodingA2: { 1432 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32); 1433 Rd = Bits32(opcode, 15, 12); 1434 setflags = false; 1435 uint32_t imm4 = Bits32(opcode, 19, 16); 1436 uint32_t imm12 = Bits32(opcode, 11, 0); 1437 imm32 = (imm4 << 12) | imm12; 1438 1439 // if d == 15 then UNPREDICTABLE; 1440 if (Rd == 15) 1441 return false; 1442 } break; 1443 1444 default: 1445 return false; 1446 } 1447 uint32_t result = imm32; 1448 1449 // The context specifies that an immediate is to be moved into Rd. 1450 EmulateInstruction::Context context; 1451 context.type = EmulateInstruction::eContextImmediate; 1452 context.SetNoArgs(); 1453 1454 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1455 return false; 1456 } 1457 return true; 1458 } 1459 1460 // MUL multiplies two register values. The least significant 32 bits of the 1461 // result are written to the destination 1462 // register. These 32 bits do not depend on whether the source register values 1463 // are considered to be signed values or unsigned values. 1464 // 1465 // Optionally, it can update the condition flags based on the result. In the 1466 // Thumb instruction set, this option is limited to only a few forms of the 1467 // instruction. 1468 bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode, 1469 const ARMEncoding encoding) { 1470 #if 0 1471 if ConditionPassed() then 1472 EncodingSpecificOperations(); 1473 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 1474 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 1475 result = operand1 * operand2; 1476 R[d] = result<31:0>; 1477 if setflags then 1478 APSR.N = result<31>; 1479 APSR.Z = IsZeroBit(result); 1480 if ArchVersion() == 4 then 1481 APSR.C = bit UNKNOWN; 1482 // else APSR.C unchanged 1483 // APSR.V always unchanged 1484 #endif 1485 1486 if (ConditionPassed(opcode)) { 1487 uint32_t d; 1488 uint32_t n; 1489 uint32_t m; 1490 bool setflags; 1491 1492 // EncodingSpecificOperations(); 1493 switch (encoding) { 1494 case eEncodingT1: 1495 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock(); 1496 d = Bits32(opcode, 2, 0); 1497 n = Bits32(opcode, 5, 3); 1498 m = Bits32(opcode, 2, 0); 1499 setflags = !InITBlock(); 1500 1501 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 1502 if ((ArchVersion() < ARMv6) && (d == n)) 1503 return false; 1504 1505 break; 1506 1507 case eEncodingT2: 1508 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE; 1509 d = Bits32(opcode, 11, 8); 1510 n = Bits32(opcode, 19, 16); 1511 m = Bits32(opcode, 3, 0); 1512 setflags = false; 1513 1514 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE; 1515 if (BadReg(d) || BadReg(n) || BadReg(m)) 1516 return false; 1517 1518 break; 1519 1520 case eEncodingA1: 1521 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); 1522 d = Bits32(opcode, 19, 16); 1523 n = Bits32(opcode, 3, 0); 1524 m = Bits32(opcode, 11, 8); 1525 setflags = BitIsSet(opcode, 20); 1526 1527 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; 1528 if ((d == 15) || (n == 15) || (m == 15)) 1529 return false; 1530 1531 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 1532 if ((ArchVersion() < ARMv6) && (d == n)) 1533 return false; 1534 1535 break; 1536 1537 default: 1538 return false; 1539 } 1540 1541 bool success = false; 1542 1543 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final 1544 // results 1545 uint64_t operand1 = 1546 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 1547 if (!success) 1548 return false; 1549 1550 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final 1551 // results 1552 uint64_t operand2 = 1553 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 1554 if (!success) 1555 return false; 1556 1557 // result = operand1 * operand2; 1558 uint64_t result = operand1 * operand2; 1559 1560 // R[d] = result<31:0>; 1561 std::optional<RegisterInfo> op1_reg = 1562 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 1563 std::optional<RegisterInfo> op2_reg = 1564 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 1565 1566 EmulateInstruction::Context context; 1567 context.type = eContextArithmetic; 1568 context.SetRegisterRegisterOperands(*op1_reg, *op2_reg); 1569 1570 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 1571 (0x0000ffff & result))) 1572 return false; 1573 1574 // if setflags then 1575 if (setflags) { 1576 // APSR.N = result<31>; 1577 // APSR.Z = IsZeroBit(result); 1578 m_new_inst_cpsr = m_opcode_cpsr; 1579 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31)); 1580 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 1581 if (m_new_inst_cpsr != m_opcode_cpsr) { 1582 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 1583 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 1584 return false; 1585 } 1586 1587 // if ArchVersion() == 4 then 1588 // APSR.C = bit UNKNOWN; 1589 } 1590 } 1591 return true; 1592 } 1593 1594 // Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to 1595 // the destination register. It can optionally update the condition flags based 1596 // on the value. 1597 bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode, 1598 const ARMEncoding encoding) { 1599 #if 0 1600 // ARM pseudo code... 1601 if (ConditionPassed()) 1602 { 1603 EncodingSpecificOperations(); 1604 result = NOT(imm32); 1605 if d == 15 then // Can only occur for ARM encoding 1606 ALUWritePC(result); // setflags is always FALSE here 1607 else 1608 R[d] = result; 1609 if setflags then 1610 APSR.N = result<31>; 1611 APSR.Z = IsZeroBit(result); 1612 APSR.C = carry; 1613 // APSR.V unchanged 1614 } 1615 #endif 1616 1617 if (ConditionPassed(opcode)) { 1618 uint32_t Rd; // the destination register 1619 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C 1620 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C 1621 bool setflags; 1622 switch (encoding) { 1623 case eEncodingT1: 1624 Rd = Bits32(opcode, 11, 8); 1625 setflags = BitIsSet(opcode, 20); 1626 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 1627 break; 1628 case eEncodingA1: 1629 Rd = Bits32(opcode, 15, 12); 1630 setflags = BitIsSet(opcode, 20); 1631 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); 1632 1633 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 1634 // instructions; 1635 if (Rd == 15 && setflags) 1636 return EmulateSUBSPcLrEtc(opcode, encoding); 1637 break; 1638 default: 1639 return false; 1640 } 1641 uint32_t result = ~imm32; 1642 1643 // The context specifies that an immediate is to be moved into Rd. 1644 EmulateInstruction::Context context; 1645 context.type = EmulateInstruction::eContextImmediate; 1646 context.SetNoArgs(); 1647 1648 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1649 return false; 1650 } 1651 return true; 1652 } 1653 1654 // Bitwise NOT (register) writes the bitwise inverse of a register value to the 1655 // destination register. It can optionally update the condition flags based on 1656 // the result. 1657 bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode, 1658 const ARMEncoding encoding) { 1659 #if 0 1660 // ARM pseudo code... 1661 if (ConditionPassed()) 1662 { 1663 EncodingSpecificOperations(); 1664 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 1665 result = NOT(shifted); 1666 if d == 15 then // Can only occur for ARM encoding 1667 ALUWritePC(result); // setflags is always FALSE here 1668 else 1669 R[d] = result; 1670 if setflags then 1671 APSR.N = result<31>; 1672 APSR.Z = IsZeroBit(result); 1673 APSR.C = carry; 1674 // APSR.V unchanged 1675 } 1676 #endif 1677 1678 if (ConditionPassed(opcode)) { 1679 uint32_t Rm; // the source register 1680 uint32_t Rd; // the destination register 1681 ARM_ShifterType shift_t; 1682 uint32_t shift_n; // the shift applied to the value read from Rm 1683 bool setflags; 1684 uint32_t carry; // the carry bit after the shift operation 1685 switch (encoding) { 1686 case eEncodingT1: 1687 Rd = Bits32(opcode, 2, 0); 1688 Rm = Bits32(opcode, 5, 3); 1689 setflags = !InITBlock(); 1690 shift_t = SRType_LSL; 1691 shift_n = 0; 1692 if (InITBlock()) 1693 return false; 1694 break; 1695 case eEncodingT2: 1696 Rd = Bits32(opcode, 11, 8); 1697 Rm = Bits32(opcode, 3, 0); 1698 setflags = BitIsSet(opcode, 20); 1699 shift_n = DecodeImmShiftThumb(opcode, shift_t); 1700 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 1701 if (BadReg(Rd) || BadReg(Rm)) 1702 return false; 1703 break; 1704 case eEncodingA1: 1705 Rd = Bits32(opcode, 15, 12); 1706 Rm = Bits32(opcode, 3, 0); 1707 setflags = BitIsSet(opcode, 20); 1708 shift_n = DecodeImmShiftARM(opcode, shift_t); 1709 break; 1710 default: 1711 return false; 1712 } 1713 bool success = false; 1714 uint32_t value = ReadCoreReg(Rm, &success); 1715 if (!success) 1716 return false; 1717 1718 uint32_t shifted = 1719 Shift_C(value, shift_t, shift_n, APSR_C, carry, &success); 1720 if (!success) 1721 return false; 1722 uint32_t result = ~shifted; 1723 1724 // The context specifies that an immediate is to be moved into Rd. 1725 EmulateInstruction::Context context; 1726 context.type = EmulateInstruction::eContextImmediate; 1727 context.SetNoArgs(); 1728 1729 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1730 return false; 1731 } 1732 return true; 1733 } 1734 1735 // PC relative immediate load into register, possibly followed by ADD (SP plus 1736 // register). 1737 // LDR (literal) 1738 bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode, 1739 const ARMEncoding encoding) { 1740 #if 0 1741 // ARM pseudo code... 1742 if (ConditionPassed()) 1743 { 1744 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 1745 base = Align(PC,4); 1746 address = if add then (base + imm32) else (base - imm32); 1747 data = MemU[address,4]; 1748 if t == 15 then 1749 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 1750 elsif UnalignedSupport() || address<1:0> = '00' then 1751 R[t] = data; 1752 else // Can only apply before ARMv7 1753 if CurrentInstrSet() == InstrSet_ARM then 1754 R[t] = ROR(data, 8*UInt(address<1:0>)); 1755 else 1756 R[t] = bits(32) UNKNOWN; 1757 } 1758 #endif 1759 1760 if (ConditionPassed(opcode)) { 1761 bool success = false; 1762 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1763 if (!success) 1764 return false; 1765 1766 // PC relative immediate load context 1767 EmulateInstruction::Context context; 1768 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1769 std::optional<RegisterInfo> pc_reg = 1770 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 1771 context.SetRegisterPlusOffset(*pc_reg, 0); 1772 1773 uint32_t Rt; // the destination register 1774 uint32_t imm32; // immediate offset from the PC 1775 bool add; // +imm32 or -imm32? 1776 addr_t base; // the base address 1777 addr_t address; // the PC relative address 1778 uint32_t data; // the literal data value from the PC relative load 1779 switch (encoding) { 1780 case eEncodingT1: 1781 Rt = Bits32(opcode, 10, 8); 1782 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32); 1783 add = true; 1784 break; 1785 case eEncodingT2: 1786 Rt = Bits32(opcode, 15, 12); 1787 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32); 1788 add = BitIsSet(opcode, 23); 1789 if (Rt == 15 && InITBlock() && !LastInITBlock()) 1790 return false; 1791 break; 1792 default: 1793 return false; 1794 } 1795 1796 base = Align(pc, 4); 1797 if (add) 1798 address = base + imm32; 1799 else 1800 address = base - imm32; 1801 1802 context.SetRegisterPlusOffset(*pc_reg, address - base); 1803 data = MemURead(context, address, 4, 0, &success); 1804 if (!success) 1805 return false; 1806 1807 if (Rt == 15) { 1808 if (Bits32(address, 1, 0) == 0) { 1809 // In ARMv5T and above, this is an interworking branch. 1810 if (!LoadWritePC(context, data)) 1811 return false; 1812 } else 1813 return false; 1814 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) { 1815 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt, 1816 data)) 1817 return false; 1818 } else // We don't handle ARM for now. 1819 return false; 1820 } 1821 return true; 1822 } 1823 1824 // An add operation to adjust the SP. 1825 // ADD (SP plus immediate) 1826 bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode, 1827 const ARMEncoding encoding) { 1828 #if 0 1829 // ARM pseudo code... 1830 if (ConditionPassed()) 1831 { 1832 EncodingSpecificOperations(); 1833 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 1834 if d == 15 then // Can only occur for ARM encoding 1835 ALUWritePC(result); // setflags is always FALSE here 1836 else 1837 R[d] = result; 1838 if setflags then 1839 APSR.N = result<31>; 1840 APSR.Z = IsZeroBit(result); 1841 APSR.C = carry; 1842 APSR.V = overflow; 1843 } 1844 #endif 1845 1846 bool success = false; 1847 1848 if (ConditionPassed(opcode)) { 1849 const addr_t sp = ReadCoreReg(SP_REG, &success); 1850 if (!success) 1851 return false; 1852 uint32_t imm32; // the immediate operand 1853 uint32_t d; 1854 bool setflags; 1855 switch (encoding) { 1856 case eEncodingT1: 1857 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32); 1858 d = Bits32(opcode, 10, 8); 1859 imm32 = (Bits32(opcode, 7, 0) << 2); 1860 setflags = false; 1861 break; 1862 1863 case eEncodingT2: 1864 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32); 1865 d = 13; 1866 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1867 setflags = false; 1868 break; 1869 1870 case eEncodingT3: 1871 // d = UInt(Rd); setflags = (S == "1"); imm32 = 1872 // ThumbExpandImm(i:imm3:imm8); 1873 d = Bits32(opcode, 11, 8); 1874 imm32 = ThumbExpandImm(opcode); 1875 setflags = Bit32(opcode, 20); 1876 1877 // if Rd == "1111" && S == "1" then SEE CMN (immediate); 1878 if (d == 15 && setflags == 1) 1879 return false; // CMN (immediate) not yet supported 1880 1881 // if d == 15 && S == "0" then UNPREDICTABLE; 1882 if (d == 15 && setflags == 0) 1883 return false; 1884 break; 1885 1886 case eEncodingT4: { 1887 // if Rn == '1111' then SEE ADR; 1888 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); 1889 d = Bits32(opcode, 11, 8); 1890 setflags = false; 1891 uint32_t i = Bit32(opcode, 26); 1892 uint32_t imm3 = Bits32(opcode, 14, 12); 1893 uint32_t imm8 = Bits32(opcode, 7, 0); 1894 imm32 = (i << 11) | (imm3 << 8) | imm8; 1895 1896 // if d == 15 then UNPREDICTABLE; 1897 if (d == 15) 1898 return false; 1899 } break; 1900 1901 default: 1902 return false; 1903 } 1904 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 1905 AddWithCarryResult res = AddWithCarry(sp, imm32, 0); 1906 1907 EmulateInstruction::Context context; 1908 if (d == 13) 1909 context.type = EmulateInstruction::eContextAdjustStackPointer; 1910 else 1911 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1912 1913 std::optional<RegisterInfo> sp_reg = 1914 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 1915 context.SetRegisterPlusOffset(*sp_reg, res.result - sp); 1916 1917 if (d == 15) { 1918 if (!ALUWritePC(context, res.result)) 1919 return false; 1920 } else { 1921 // R[d] = result; 1922 // if setflags then 1923 // APSR.N = result<31>; 1924 // APSR.Z = IsZeroBit(result); 1925 // APSR.C = carry; 1926 // APSR.V = overflow; 1927 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags, 1928 res.carry_out, res.overflow)) 1929 return false; 1930 } 1931 } 1932 return true; 1933 } 1934 1935 // An add operation to adjust the SP. 1936 // ADD (SP plus register) 1937 bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode, 1938 const ARMEncoding encoding) { 1939 #if 0 1940 // ARM pseudo code... 1941 if (ConditionPassed()) 1942 { 1943 EncodingSpecificOperations(); 1944 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 1945 (result, carry, overflow) = AddWithCarry(SP, shifted, '0'); 1946 if d == 15 then 1947 ALUWritePC(result); // setflags is always FALSE here 1948 else 1949 R[d] = result; 1950 if setflags then 1951 APSR.N = result<31>; 1952 APSR.Z = IsZeroBit(result); 1953 APSR.C = carry; 1954 APSR.V = overflow; 1955 } 1956 #endif 1957 1958 bool success = false; 1959 1960 if (ConditionPassed(opcode)) { 1961 const addr_t sp = ReadCoreReg(SP_REG, &success); 1962 if (!success) 1963 return false; 1964 uint32_t Rm; // the second operand 1965 switch (encoding) { 1966 case eEncodingT2: 1967 Rm = Bits32(opcode, 6, 3); 1968 break; 1969 default: 1970 return false; 1971 } 1972 int32_t reg_value = ReadCoreReg(Rm, &success); 1973 if (!success) 1974 return false; 1975 1976 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value 1977 1978 EmulateInstruction::Context context; 1979 context.type = eContextArithmetic; 1980 std::optional<RegisterInfo> sp_reg = 1981 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 1982 std::optional<RegisterInfo> other_reg = 1983 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 1984 context.SetRegisterRegisterOperands(*sp_reg, *other_reg); 1985 1986 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 1987 LLDB_REGNUM_GENERIC_SP, addr)) 1988 return false; 1989 } 1990 return true; 1991 } 1992 1993 // Branch with Link and Exchange Instruction Sets (immediate) calls a 1994 // subroutine at a PC-relative address, and changes instruction set from ARM to 1995 // Thumb, or from Thumb to ARM. 1996 // BLX (immediate) 1997 bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode, 1998 const ARMEncoding encoding) { 1999 #if 0 2000 // ARM pseudo code... 2001 if (ConditionPassed()) 2002 { 2003 EncodingSpecificOperations(); 2004 if CurrentInstrSet() == InstrSet_ARM then 2005 LR = PC - 4; 2006 else 2007 LR = PC<31:1> : '1'; 2008 if targetInstrSet == InstrSet_ARM then 2009 targetAddress = Align(PC,4) + imm32; 2010 else 2011 targetAddress = PC + imm32; 2012 SelectInstrSet(targetInstrSet); 2013 BranchWritePC(targetAddress); 2014 } 2015 #endif 2016 2017 bool success = true; 2018 2019 if (ConditionPassed(opcode)) { 2020 EmulateInstruction::Context context; 2021 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2022 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2023 if (!success) 2024 return false; 2025 addr_t lr; // next instruction address 2026 addr_t target; // target address 2027 int32_t imm32; // PC-relative offset 2028 switch (encoding) { 2029 case eEncodingT1: { 2030 lr = pc | 1u; // return address 2031 uint32_t S = Bit32(opcode, 26); 2032 uint32_t imm10 = Bits32(opcode, 25, 16); 2033 uint32_t J1 = Bit32(opcode, 13); 2034 uint32_t J2 = Bit32(opcode, 11); 2035 uint32_t imm11 = Bits32(opcode, 10, 0); 2036 uint32_t I1 = !(J1 ^ S); 2037 uint32_t I2 = !(J2 ^ S); 2038 uint32_t imm25 = 2039 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2040 imm32 = llvm::SignExtend32<25>(imm25); 2041 target = pc + imm32; 2042 SelectInstrSet(eModeThumb); 2043 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2044 if (InITBlock() && !LastInITBlock()) 2045 return false; 2046 break; 2047 } 2048 case eEncodingT2: { 2049 lr = pc | 1u; // return address 2050 uint32_t S = Bit32(opcode, 26); 2051 uint32_t imm10H = Bits32(opcode, 25, 16); 2052 uint32_t J1 = Bit32(opcode, 13); 2053 uint32_t J2 = Bit32(opcode, 11); 2054 uint32_t imm10L = Bits32(opcode, 10, 1); 2055 uint32_t I1 = !(J1 ^ S); 2056 uint32_t I2 = !(J2 ^ S); 2057 uint32_t imm25 = 2058 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2); 2059 imm32 = llvm::SignExtend32<25>(imm25); 2060 target = Align(pc, 4) + imm32; 2061 SelectInstrSet(eModeARM); 2062 context.SetISAAndImmediateSigned(eModeARM, 4 + imm32); 2063 if (InITBlock() && !LastInITBlock()) 2064 return false; 2065 break; 2066 } 2067 case eEncodingA1: 2068 lr = pc - 4; // return address 2069 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 2070 target = Align(pc, 4) + imm32; 2071 SelectInstrSet(eModeARM); 2072 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32); 2073 break; 2074 case eEncodingA2: 2075 lr = pc - 4; // return address 2076 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | 2077 Bits32(opcode, 24, 24) << 1); 2078 target = pc + imm32; 2079 SelectInstrSet(eModeThumb); 2080 context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32); 2081 break; 2082 default: 2083 return false; 2084 } 2085 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2086 LLDB_REGNUM_GENERIC_RA, lr)) 2087 return false; 2088 if (!BranchWritePC(context, target)) 2089 return false; 2090 if (m_opcode_cpsr != m_new_inst_cpsr) 2091 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2092 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 2093 return false; 2094 } 2095 return true; 2096 } 2097 2098 // Branch with Link and Exchange (register) calls a subroutine at an address 2099 // and instruction set specified by a register. 2100 // BLX (register) 2101 bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode, 2102 const ARMEncoding encoding) { 2103 #if 0 2104 // ARM pseudo code... 2105 if (ConditionPassed()) 2106 { 2107 EncodingSpecificOperations(); 2108 target = R[m]; 2109 if CurrentInstrSet() == InstrSet_ARM then 2110 next_instr_addr = PC - 4; 2111 LR = next_instr_addr; 2112 else 2113 next_instr_addr = PC - 2; 2114 LR = next_instr_addr<31:1> : '1'; 2115 BXWritePC(target); 2116 } 2117 #endif 2118 2119 bool success = false; 2120 2121 if (ConditionPassed(opcode)) { 2122 EmulateInstruction::Context context; 2123 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 2124 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2125 addr_t lr; // next instruction address 2126 if (!success) 2127 return false; 2128 uint32_t Rm; // the register with the target address 2129 switch (encoding) { 2130 case eEncodingT1: 2131 lr = (pc - 2) | 1u; // return address 2132 Rm = Bits32(opcode, 6, 3); 2133 // if m == 15 then UNPREDICTABLE; 2134 if (Rm == 15) 2135 return false; 2136 if (InITBlock() && !LastInITBlock()) 2137 return false; 2138 break; 2139 case eEncodingA1: 2140 lr = pc - 4; // return address 2141 Rm = Bits32(opcode, 3, 0); 2142 // if m == 15 then UNPREDICTABLE; 2143 if (Rm == 15) 2144 return false; 2145 break; 2146 default: 2147 return false; 2148 } 2149 addr_t target = ReadCoreReg(Rm, &success); 2150 if (!success) 2151 return false; 2152 std::optional<RegisterInfo> dwarf_reg = 2153 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 2154 context.SetRegister(*dwarf_reg); 2155 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2156 LLDB_REGNUM_GENERIC_RA, lr)) 2157 return false; 2158 if (!BXWritePC(context, target)) 2159 return false; 2160 } 2161 return true; 2162 } 2163 2164 // Branch and Exchange causes a branch to an address and instruction set 2165 // specified by a register. 2166 bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode, 2167 const ARMEncoding encoding) { 2168 #if 0 2169 // ARM pseudo code... 2170 if (ConditionPassed()) 2171 { 2172 EncodingSpecificOperations(); 2173 BXWritePC(R[m]); 2174 } 2175 #endif 2176 2177 if (ConditionPassed(opcode)) { 2178 EmulateInstruction::Context context; 2179 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 2180 uint32_t Rm; // the register with the target address 2181 switch (encoding) { 2182 case eEncodingT1: 2183 Rm = Bits32(opcode, 6, 3); 2184 if (InITBlock() && !LastInITBlock()) 2185 return false; 2186 break; 2187 case eEncodingA1: 2188 Rm = Bits32(opcode, 3, 0); 2189 break; 2190 default: 2191 return false; 2192 } 2193 bool success = false; 2194 addr_t target = ReadCoreReg(Rm, &success); 2195 if (!success) 2196 return false; 2197 2198 std::optional<RegisterInfo> dwarf_reg = 2199 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 2200 context.SetRegister(*dwarf_reg); 2201 if (!BXWritePC(context, target)) 2202 return false; 2203 } 2204 return true; 2205 } 2206 2207 // Branch and Exchange Jazelle attempts to change to Jazelle state. If the 2208 // attempt fails, it branches to an address and instruction set specified by a 2209 // register as though it were a BX instruction. 2210 // 2211 // TODO: Emulate Jazelle architecture? 2212 // We currently assume that switching to Jazelle state fails, thus 2213 // treating BXJ as a BX operation. 2214 bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode, 2215 const ARMEncoding encoding) { 2216 #if 0 2217 // ARM pseudo code... 2218 if (ConditionPassed()) 2219 { 2220 EncodingSpecificOperations(); 2221 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then 2222 BXWritePC(R[m]); 2223 else 2224 if JazelleAcceptsExecution() then 2225 SwitchToJazelleExecution(); 2226 else 2227 SUBARCHITECTURE_DEFINED handler call; 2228 } 2229 #endif 2230 2231 if (ConditionPassed(opcode)) { 2232 EmulateInstruction::Context context; 2233 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 2234 uint32_t Rm; // the register with the target address 2235 switch (encoding) { 2236 case eEncodingT1: 2237 Rm = Bits32(opcode, 19, 16); 2238 if (BadReg(Rm)) 2239 return false; 2240 if (InITBlock() && !LastInITBlock()) 2241 return false; 2242 break; 2243 case eEncodingA1: 2244 Rm = Bits32(opcode, 3, 0); 2245 if (Rm == 15) 2246 return false; 2247 break; 2248 default: 2249 return false; 2250 } 2251 bool success = false; 2252 addr_t target = ReadCoreReg(Rm, &success); 2253 if (!success) 2254 return false; 2255 2256 std::optional<RegisterInfo> dwarf_reg = 2257 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 2258 context.SetRegister(*dwarf_reg); 2259 if (!BXWritePC(context, target)) 2260 return false; 2261 } 2262 return true; 2263 } 2264 2265 // Set r7 to point to some ip offset. 2266 // SUB (immediate) 2267 bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode, 2268 const ARMEncoding encoding) { 2269 #if 0 2270 // ARM pseudo code... 2271 if (ConditionPassed()) 2272 { 2273 EncodingSpecificOperations(); 2274 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 2275 if d == 15 then // Can only occur for ARM encoding 2276 ALUWritePC(result); // setflags is always FALSE here 2277 else 2278 R[d] = result; 2279 if setflags then 2280 APSR.N = result<31>; 2281 APSR.Z = IsZeroBit(result); 2282 APSR.C = carry; 2283 APSR.V = overflow; 2284 } 2285 #endif 2286 2287 if (ConditionPassed(opcode)) { 2288 bool success = false; 2289 const addr_t ip = ReadCoreReg(12, &success); 2290 if (!success) 2291 return false; 2292 uint32_t imm32; 2293 switch (encoding) { 2294 case eEncodingA1: 2295 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2296 break; 2297 default: 2298 return false; 2299 } 2300 addr_t ip_offset = imm32; 2301 addr_t addr = ip - ip_offset; // the adjusted ip value 2302 2303 EmulateInstruction::Context context; 2304 context.type = EmulateInstruction::eContextRegisterPlusOffset; 2305 std::optional<RegisterInfo> dwarf_reg = 2306 GetRegisterInfo(eRegisterKindDWARF, dwarf_r12); 2307 context.SetRegisterPlusOffset(*dwarf_reg, -ip_offset); 2308 2309 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr)) 2310 return false; 2311 } 2312 return true; 2313 } 2314 2315 // Set ip to point to some stack offset. 2316 // SUB (SP minus immediate) 2317 bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode, 2318 const ARMEncoding encoding) { 2319 #if 0 2320 // ARM pseudo code... 2321 if (ConditionPassed()) 2322 { 2323 EncodingSpecificOperations(); 2324 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 2325 if d == 15 then // Can only occur for ARM encoding 2326 ALUWritePC(result); // setflags is always FALSE here 2327 else 2328 R[d] = result; 2329 if setflags then 2330 APSR.N = result<31>; 2331 APSR.Z = IsZeroBit(result); 2332 APSR.C = carry; 2333 APSR.V = overflow; 2334 } 2335 #endif 2336 2337 if (ConditionPassed(opcode)) { 2338 bool success = false; 2339 const addr_t sp = ReadCoreReg(SP_REG, &success); 2340 if (!success) 2341 return false; 2342 uint32_t imm32; 2343 switch (encoding) { 2344 case eEncodingA1: 2345 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2346 break; 2347 default: 2348 return false; 2349 } 2350 addr_t sp_offset = imm32; 2351 addr_t addr = sp - sp_offset; // the adjusted stack pointer value 2352 2353 EmulateInstruction::Context context; 2354 context.type = EmulateInstruction::eContextRegisterPlusOffset; 2355 std::optional<RegisterInfo> dwarf_reg = 2356 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 2357 context.SetRegisterPlusOffset(*dwarf_reg, -sp_offset); 2358 2359 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr)) 2360 return false; 2361 } 2362 return true; 2363 } 2364 2365 // This instruction subtracts an immediate value from the SP value, and writes 2366 // the result to the destination register. 2367 // 2368 // If Rd == 13 => A sub operation to adjust the SP -- allocate space for local 2369 // storage. 2370 bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode, 2371 const ARMEncoding encoding) { 2372 #if 0 2373 // ARM pseudo code... 2374 if (ConditionPassed()) 2375 { 2376 EncodingSpecificOperations(); 2377 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 2378 if d == 15 then // Can only occur for ARM encoding 2379 ALUWritePC(result); // setflags is always FALSE here 2380 else 2381 R[d] = result; 2382 if setflags then 2383 APSR.N = result<31>; 2384 APSR.Z = IsZeroBit(result); 2385 APSR.C = carry; 2386 APSR.V = overflow; 2387 } 2388 #endif 2389 2390 bool success = false; 2391 if (ConditionPassed(opcode)) { 2392 const addr_t sp = ReadCoreReg(SP_REG, &success); 2393 if (!success) 2394 return false; 2395 2396 uint32_t Rd; 2397 bool setflags; 2398 uint32_t imm32; 2399 switch (encoding) { 2400 case eEncodingT1: 2401 Rd = 13; 2402 setflags = false; 2403 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 2404 break; 2405 case eEncodingT2: 2406 Rd = Bits32(opcode, 11, 8); 2407 setflags = BitIsSet(opcode, 20); 2408 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2409 if (Rd == 15 && setflags) 2410 return EmulateCMPImm(opcode, eEncodingT2); 2411 if (Rd == 15 && !setflags) 2412 return false; 2413 break; 2414 case eEncodingT3: 2415 Rd = Bits32(opcode, 11, 8); 2416 setflags = false; 2417 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 2418 if (Rd == 15) 2419 return false; 2420 break; 2421 case eEncodingA1: 2422 Rd = Bits32(opcode, 15, 12); 2423 setflags = BitIsSet(opcode, 20); 2424 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2425 2426 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 2427 // instructions; 2428 if (Rd == 15 && setflags) 2429 return EmulateSUBSPcLrEtc(opcode, encoding); 2430 break; 2431 default: 2432 return false; 2433 } 2434 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1); 2435 2436 EmulateInstruction::Context context; 2437 if (Rd == 13) { 2438 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting 2439 // to negate it, or the wrong 2440 // value gets passed down to context.SetImmediateSigned. 2441 context.type = EmulateInstruction::eContextAdjustStackPointer; 2442 context.SetImmediateSigned(-imm64); // the stack pointer offset 2443 } else { 2444 context.type = EmulateInstruction::eContextImmediate; 2445 context.SetNoArgs(); 2446 } 2447 2448 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 2449 res.carry_out, res.overflow)) 2450 return false; 2451 } 2452 return true; 2453 } 2454 2455 // A store operation to the stack that also updates the SP. 2456 bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode, 2457 const ARMEncoding encoding) { 2458 #if 0 2459 // ARM pseudo code... 2460 if (ConditionPassed()) 2461 { 2462 EncodingSpecificOperations(); 2463 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 2464 address = if index then offset_addr else R[n]; 2465 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 2466 if wback then R[n] = offset_addr; 2467 } 2468 #endif 2469 2470 bool success = false; 2471 if (ConditionPassed(opcode)) { 2472 const uint32_t addr_byte_size = GetAddressByteSize(); 2473 const addr_t sp = ReadCoreReg(SP_REG, &success); 2474 if (!success) 2475 return false; 2476 uint32_t Rt; // the source register 2477 uint32_t imm12; 2478 uint32_t 2479 Rn; // This function assumes Rn is the SP, but we should verify that. 2480 2481 bool index; 2482 bool add; 2483 bool wback; 2484 switch (encoding) { 2485 case eEncodingA1: 2486 Rt = Bits32(opcode, 15, 12); 2487 imm12 = Bits32(opcode, 11, 0); 2488 Rn = Bits32(opcode, 19, 16); 2489 2490 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP. 2491 return false; 2492 2493 index = BitIsSet(opcode, 24); 2494 add = BitIsSet(opcode, 23); 2495 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 2496 2497 if (wback && ((Rn == 15) || (Rn == Rt))) 2498 return false; 2499 break; 2500 default: 2501 return false; 2502 } 2503 addr_t offset_addr; 2504 if (add) 2505 offset_addr = sp + imm12; 2506 else 2507 offset_addr = sp - imm12; 2508 2509 addr_t addr; 2510 if (index) 2511 addr = offset_addr; 2512 else 2513 addr = sp; 2514 2515 EmulateInstruction::Context context; 2516 context.type = EmulateInstruction::eContextPushRegisterOnStack; 2517 std::optional<RegisterInfo> sp_reg = 2518 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 2519 std::optional<RegisterInfo> dwarf_reg = 2520 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt); 2521 2522 context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp); 2523 if (Rt != 15) { 2524 uint32_t reg_value = ReadCoreReg(Rt, &success); 2525 if (!success) 2526 return false; 2527 if (!MemUWrite(context, addr, reg_value, addr_byte_size)) 2528 return false; 2529 } else { 2530 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2531 if (!success) 2532 return false; 2533 if (!MemUWrite(context, addr, pc, addr_byte_size)) 2534 return false; 2535 } 2536 2537 if (wback) { 2538 context.type = EmulateInstruction::eContextAdjustStackPointer; 2539 context.SetImmediateSigned(addr - sp); 2540 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2541 LLDB_REGNUM_GENERIC_SP, offset_addr)) 2542 return false; 2543 } 2544 } 2545 return true; 2546 } 2547 2548 // Vector Push stores multiple extension registers to the stack. It also 2549 // updates SP to point to the start of the stored data. 2550 bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode, 2551 const ARMEncoding encoding) { 2552 #if 0 2553 // ARM pseudo code... 2554 if (ConditionPassed()) 2555 { 2556 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 2557 address = SP - imm32; 2558 SP = SP - imm32; 2559 if single_regs then 2560 for r = 0 to regs-1 2561 MemA[address,4] = S[d+r]; address = address+4; 2562 else 2563 for r = 0 to regs-1 2564 // Store as two word-aligned words in the correct order for 2565 // current endianness. 2566 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 2567 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 2568 address = address+8; 2569 } 2570 #endif 2571 2572 bool success = false; 2573 if (ConditionPassed(opcode)) { 2574 const uint32_t addr_byte_size = GetAddressByteSize(); 2575 const addr_t sp = ReadCoreReg(SP_REG, &success); 2576 if (!success) 2577 return false; 2578 bool single_regs; 2579 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 2580 uint32_t imm32; // stack offset 2581 uint32_t regs; // number of registers 2582 switch (encoding) { 2583 case eEncodingT1: 2584 case eEncodingA1: 2585 single_regs = false; 2586 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 2587 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2588 // If UInt(imm8) is odd, see "FSTMX". 2589 regs = Bits32(opcode, 7, 0) / 2; 2590 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2591 if (regs == 0 || regs > 16 || (d + regs) > 32) 2592 return false; 2593 break; 2594 case eEncodingT2: 2595 case eEncodingA2: 2596 single_regs = true; 2597 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 2598 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2599 regs = Bits32(opcode, 7, 0); 2600 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2601 if (regs == 0 || regs > 16 || (d + regs) > 32) 2602 return false; 2603 break; 2604 default: 2605 return false; 2606 } 2607 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 2608 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 2609 addr_t sp_offset = imm32; 2610 addr_t addr = sp - sp_offset; 2611 uint32_t i; 2612 2613 EmulateInstruction::Context context; 2614 context.type = EmulateInstruction::eContextPushRegisterOnStack; 2615 2616 std::optional<RegisterInfo> sp_reg = 2617 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 2618 for (i = 0; i < regs; ++i) { 2619 std::optional<RegisterInfo> dwarf_reg = 2620 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i); 2621 context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp); 2622 // uint64_t to accommodate 64-bit registers. 2623 uint64_t reg_value = ReadRegisterUnsigned(*dwarf_reg, 0, &success); 2624 if (!success) 2625 return false; 2626 if (!MemAWrite(context, addr, reg_value, reg_byte_size)) 2627 return false; 2628 addr += reg_byte_size; 2629 } 2630 2631 context.type = EmulateInstruction::eContextAdjustStackPointer; 2632 context.SetImmediateSigned(-sp_offset); 2633 2634 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2635 LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 2636 return false; 2637 } 2638 return true; 2639 } 2640 2641 // Vector Pop loads multiple extension registers from the stack. It also 2642 // updates SP to point just above the loaded data. 2643 bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode, 2644 const ARMEncoding encoding) { 2645 #if 0 2646 // ARM pseudo code... 2647 if (ConditionPassed()) 2648 { 2649 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 2650 address = SP; 2651 SP = SP + imm32; 2652 if single_regs then 2653 for r = 0 to regs-1 2654 S[d+r] = MemA[address,4]; address = address+4; 2655 else 2656 for r = 0 to regs-1 2657 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 2658 // Combine the word-aligned words in the correct order for 2659 // current endianness. 2660 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 2661 } 2662 #endif 2663 2664 bool success = false; 2665 if (ConditionPassed(opcode)) { 2666 const uint32_t addr_byte_size = GetAddressByteSize(); 2667 const addr_t sp = ReadCoreReg(SP_REG, &success); 2668 if (!success) 2669 return false; 2670 bool single_regs; 2671 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 2672 uint32_t imm32; // stack offset 2673 uint32_t regs; // number of registers 2674 switch (encoding) { 2675 case eEncodingT1: 2676 case eEncodingA1: 2677 single_regs = false; 2678 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 2679 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2680 // If UInt(imm8) is odd, see "FLDMX". 2681 regs = Bits32(opcode, 7, 0) / 2; 2682 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2683 if (regs == 0 || regs > 16 || (d + regs) > 32) 2684 return false; 2685 break; 2686 case eEncodingT2: 2687 case eEncodingA2: 2688 single_regs = true; 2689 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 2690 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2691 regs = Bits32(opcode, 7, 0); 2692 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2693 if (regs == 0 || regs > 16 || (d + regs) > 32) 2694 return false; 2695 break; 2696 default: 2697 return false; 2698 } 2699 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 2700 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 2701 addr_t sp_offset = imm32; 2702 addr_t addr = sp; 2703 uint32_t i; 2704 uint64_t data; // uint64_t to accommodate 64-bit registers. 2705 2706 EmulateInstruction::Context context; 2707 context.type = EmulateInstruction::eContextPopRegisterOffStack; 2708 2709 for (i = 0; i < regs; ++i) { 2710 std::optional<RegisterInfo> dwarf_reg = 2711 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i); 2712 context.SetAddress(addr); 2713 data = MemARead(context, addr, reg_byte_size, 0, &success); 2714 if (!success) 2715 return false; 2716 if (!WriteRegisterUnsigned(context, *dwarf_reg, data)) 2717 return false; 2718 addr += reg_byte_size; 2719 } 2720 2721 context.type = EmulateInstruction::eContextAdjustStackPointer; 2722 context.SetImmediateSigned(sp_offset); 2723 2724 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2725 LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 2726 return false; 2727 } 2728 return true; 2729 } 2730 2731 // SVC (previously SWI) 2732 bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode, 2733 const ARMEncoding encoding) { 2734 #if 0 2735 // ARM pseudo code... 2736 if (ConditionPassed()) 2737 { 2738 EncodingSpecificOperations(); 2739 CallSupervisor(); 2740 } 2741 #endif 2742 2743 bool success = false; 2744 2745 if (ConditionPassed(opcode)) { 2746 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2747 addr_t lr; // next instruction address 2748 if (!success) 2749 return false; 2750 uint32_t imm32; // the immediate constant 2751 uint32_t mode; // ARM or Thumb mode 2752 switch (encoding) { 2753 case eEncodingT1: 2754 lr = (pc + 2) | 1u; // return address 2755 imm32 = Bits32(opcode, 7, 0); 2756 mode = eModeThumb; 2757 break; 2758 case eEncodingA1: 2759 lr = pc + 4; // return address 2760 imm32 = Bits32(opcode, 23, 0); 2761 mode = eModeARM; 2762 break; 2763 default: 2764 return false; 2765 } 2766 2767 EmulateInstruction::Context context; 2768 context.type = EmulateInstruction::eContextSupervisorCall; 2769 context.SetISAAndImmediate(mode, imm32); 2770 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2771 LLDB_REGNUM_GENERIC_RA, lr)) 2772 return false; 2773 } 2774 return true; 2775 } 2776 2777 // If Then makes up to four following instructions (the IT block) conditional. 2778 bool EmulateInstructionARM::EmulateIT(const uint32_t opcode, 2779 const ARMEncoding encoding) { 2780 #if 0 2781 // ARM pseudo code... 2782 EncodingSpecificOperations(); 2783 ITSTATE.IT<7:0> = firstcond:mask; 2784 #endif 2785 2786 m_it_session.InitIT(Bits32(opcode, 7, 0)); 2787 return true; 2788 } 2789 2790 bool EmulateInstructionARM::EmulateNop(const uint32_t opcode, 2791 const ARMEncoding encoding) { 2792 // NOP, nothing to do... 2793 return true; 2794 } 2795 2796 // Branch causes a branch to a target address. 2797 bool EmulateInstructionARM::EmulateB(const uint32_t opcode, 2798 const ARMEncoding encoding) { 2799 #if 0 2800 // ARM pseudo code... 2801 if (ConditionPassed()) 2802 { 2803 EncodingSpecificOperations(); 2804 BranchWritePC(PC + imm32); 2805 } 2806 #endif 2807 2808 bool success = false; 2809 2810 if (ConditionPassed(opcode)) { 2811 EmulateInstruction::Context context; 2812 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2813 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2814 if (!success) 2815 return false; 2816 addr_t target; // target address 2817 int32_t imm32; // PC-relative offset 2818 switch (encoding) { 2819 case eEncodingT1: 2820 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2821 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1); 2822 target = pc + imm32; 2823 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2824 break; 2825 case eEncodingT2: 2826 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1); 2827 target = pc + imm32; 2828 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2829 break; 2830 case eEncodingT3: 2831 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2832 { 2833 if (Bits32(opcode, 25, 23) == 7) 2834 return false; // See Branches and miscellaneous control on page 2835 // A6-235. 2836 2837 uint32_t S = Bit32(opcode, 26); 2838 uint32_t imm6 = Bits32(opcode, 21, 16); 2839 uint32_t J1 = Bit32(opcode, 13); 2840 uint32_t J2 = Bit32(opcode, 11); 2841 uint32_t imm11 = Bits32(opcode, 10, 0); 2842 uint32_t imm21 = 2843 (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2844 imm32 = llvm::SignExtend32<21>(imm21); 2845 target = pc + imm32; 2846 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2847 break; 2848 } 2849 case eEncodingT4: { 2850 uint32_t S = Bit32(opcode, 26); 2851 uint32_t imm10 = Bits32(opcode, 25, 16); 2852 uint32_t J1 = Bit32(opcode, 13); 2853 uint32_t J2 = Bit32(opcode, 11); 2854 uint32_t imm11 = Bits32(opcode, 10, 0); 2855 uint32_t I1 = !(J1 ^ S); 2856 uint32_t I2 = !(J2 ^ S); 2857 uint32_t imm25 = 2858 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2859 imm32 = llvm::SignExtend32<25>(imm25); 2860 target = pc + imm32; 2861 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2862 break; 2863 } 2864 case eEncodingA1: 2865 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 2866 target = pc + imm32; 2867 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32); 2868 break; 2869 default: 2870 return false; 2871 } 2872 if (!BranchWritePC(context, target)) 2873 return false; 2874 } 2875 return true; 2876 } 2877 2878 // Compare and Branch on Nonzero and Compare and Branch on Zero compare the 2879 // value in a register with zero and conditionally branch forward a constant 2880 // value. They do not affect the condition flags. CBNZ, CBZ 2881 bool EmulateInstructionARM::EmulateCB(const uint32_t opcode, 2882 const ARMEncoding encoding) { 2883 #if 0 2884 // ARM pseudo code... 2885 EncodingSpecificOperations(); 2886 if nonzero ^ IsZero(R[n]) then 2887 BranchWritePC(PC + imm32); 2888 #endif 2889 2890 bool success = false; 2891 2892 // Read the register value from the operand register Rn. 2893 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success); 2894 if (!success) 2895 return false; 2896 2897 EmulateInstruction::Context context; 2898 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2899 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2900 if (!success) 2901 return false; 2902 2903 addr_t target; // target address 2904 uint32_t imm32; // PC-relative offset to branch forward 2905 bool nonzero; 2906 switch (encoding) { 2907 case eEncodingT1: 2908 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1; 2909 nonzero = BitIsSet(opcode, 11); 2910 target = pc + imm32; 2911 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2912 break; 2913 default: 2914 return false; 2915 } 2916 if (m_ignore_conditions || (nonzero ^ (reg_val == 0))) 2917 if (!BranchWritePC(context, target)) 2918 return false; 2919 2920 return true; 2921 } 2922 2923 // Table Branch Byte causes a PC-relative forward branch using a table of 2924 // single byte offsets. 2925 // A base register provides a pointer to the table, and a second register 2926 // supplies an index into the table. 2927 // The branch length is twice the value of the byte returned from the table. 2928 // 2929 // Table Branch Halfword causes a PC-relative forward branch using a table of 2930 // single halfword offsets. 2931 // A base register provides a pointer to the table, and a second register 2932 // supplies an index into the table. 2933 // The branch length is twice the value of the halfword returned from the 2934 // table. TBB, TBH 2935 bool EmulateInstructionARM::EmulateTB(const uint32_t opcode, 2936 const ARMEncoding encoding) { 2937 #if 0 2938 // ARM pseudo code... 2939 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 2940 if is_tbh then 2941 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]); 2942 else 2943 halfwords = UInt(MemU[R[n]+R[m], 1]); 2944 BranchWritePC(PC + 2*halfwords); 2945 #endif 2946 2947 bool success = false; 2948 2949 if (ConditionPassed(opcode)) { 2950 uint32_t Rn; // the base register which contains the address of the table of 2951 // branch lengths 2952 uint32_t Rm; // the index register which contains an integer pointing to a 2953 // byte/halfword in the table 2954 bool is_tbh; // true if table branch halfword 2955 switch (encoding) { 2956 case eEncodingT1: 2957 Rn = Bits32(opcode, 19, 16); 2958 Rm = Bits32(opcode, 3, 0); 2959 is_tbh = BitIsSet(opcode, 4); 2960 if (Rn == 13 || BadReg(Rm)) 2961 return false; 2962 if (InITBlock() && !LastInITBlock()) 2963 return false; 2964 break; 2965 default: 2966 return false; 2967 } 2968 2969 // Read the address of the table from the operand register Rn. The PC can 2970 // be used, in which case the table immediately follows this instruction. 2971 uint32_t base = ReadCoreReg(Rn, &success); 2972 if (!success) 2973 return false; 2974 2975 // the table index 2976 uint32_t index = ReadCoreReg(Rm, &success); 2977 if (!success) 2978 return false; 2979 2980 // the offsetted table address 2981 addr_t addr = base + (is_tbh ? index * 2 : index); 2982 2983 // PC-relative offset to branch forward 2984 EmulateInstruction::Context context; 2985 context.type = EmulateInstruction::eContextTableBranchReadMemory; 2986 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; 2987 if (!success) 2988 return false; 2989 2990 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2991 if (!success) 2992 return false; 2993 2994 // target address 2995 addr_t target = pc + offset; 2996 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2997 context.SetISAAndImmediateSigned(eModeThumb, 4 + offset); 2998 2999 if (!BranchWritePC(context, target)) 3000 return false; 3001 } 3002 3003 return true; 3004 } 3005 3006 // This instruction adds an immediate value to a register value, and writes the 3007 // result to the destination register. It can optionally update the condition 3008 // flags based on the result. 3009 bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode, 3010 const ARMEncoding encoding) { 3011 #if 0 3012 if ConditionPassed() then 3013 EncodingSpecificOperations(); 3014 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 3015 R[d] = result; 3016 if setflags then 3017 APSR.N = result<31>; 3018 APSR.Z = IsZeroBit(result); 3019 APSR.C = carry; 3020 APSR.V = overflow; 3021 #endif 3022 3023 bool success = false; 3024 3025 if (ConditionPassed(opcode)) { 3026 uint32_t d; 3027 uint32_t n; 3028 bool setflags; 3029 uint32_t imm32; 3030 uint32_t carry_out; 3031 3032 // EncodingSpecificOperations(); 3033 switch (encoding) { 3034 case eEncodingT1: 3035 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = 3036 // ZeroExtend(imm3, 32); 3037 d = Bits32(opcode, 2, 0); 3038 n = Bits32(opcode, 5, 3); 3039 setflags = !InITBlock(); 3040 imm32 = Bits32(opcode, 8, 6); 3041 3042 break; 3043 3044 case eEncodingT2: 3045 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = 3046 // ZeroExtend(imm8, 32); 3047 d = Bits32(opcode, 10, 8); 3048 n = Bits32(opcode, 10, 8); 3049 setflags = !InITBlock(); 3050 imm32 = Bits32(opcode, 7, 0); 3051 3052 break; 3053 3054 case eEncodingT3: 3055 // if Rd == '1111' && S == '1' then SEE CMN (immediate); 3056 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = 3057 // ThumbExpandImm(i:imm3:imm8); 3058 d = Bits32(opcode, 11, 8); 3059 n = Bits32(opcode, 19, 16); 3060 setflags = BitIsSet(opcode, 20); 3061 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out); 3062 3063 // if Rn == '1101' then SEE ADD (SP plus immediate); 3064 if (n == 13) 3065 return EmulateADDSPImm(opcode, eEncodingT3); 3066 3067 // if BadReg(d) || n == 15 then UNPREDICTABLE; 3068 if (BadReg(d) || (n == 15)) 3069 return false; 3070 3071 break; 3072 3073 case eEncodingT4: { 3074 // if Rn == '1111' then SEE ADR; 3075 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = 3076 // ZeroExtend(i:imm3:imm8, 32); 3077 d = Bits32(opcode, 11, 8); 3078 n = Bits32(opcode, 19, 16); 3079 setflags = false; 3080 uint32_t i = Bit32(opcode, 26); 3081 uint32_t imm3 = Bits32(opcode, 14, 12); 3082 uint32_t imm8 = Bits32(opcode, 7, 0); 3083 imm32 = (i << 11) | (imm3 << 8) | imm8; 3084 3085 // if Rn == '1101' then SEE ADD (SP plus immediate); 3086 if (n == 13) 3087 return EmulateADDSPImm(opcode, eEncodingT4); 3088 3089 // if BadReg(d) then UNPREDICTABLE; 3090 if (BadReg(d)) 3091 return false; 3092 3093 break; 3094 } 3095 3096 default: 3097 return false; 3098 } 3099 3100 uint64_t Rn = 3101 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3102 if (!success) 3103 return false; 3104 3105 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 3106 AddWithCarryResult res = AddWithCarry(Rn, imm32, 0); 3107 3108 std::optional<RegisterInfo> reg_n = 3109 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 3110 EmulateInstruction::Context context; 3111 context.type = eContextArithmetic; 3112 context.SetRegisterPlusOffset(*reg_n, imm32); 3113 3114 // R[d] = result; 3115 // if setflags then 3116 // APSR.N = result<31>; 3117 // APSR.Z = IsZeroBit(result); 3118 // APSR.C = carry; 3119 // APSR.V = overflow; 3120 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags, 3121 res.carry_out, res.overflow)) 3122 return false; 3123 } 3124 return true; 3125 } 3126 3127 // This instruction adds an immediate value to a register value, and writes the 3128 // result to the destination register. It can optionally update the condition 3129 // flags based on the result. 3130 bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode, 3131 const ARMEncoding encoding) { 3132 #if 0 3133 // ARM pseudo code... 3134 if ConditionPassed() then 3135 EncodingSpecificOperations(); 3136 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 3137 if d == 15 then 3138 ALUWritePC(result); // setflags is always FALSE here 3139 else 3140 R[d] = result; 3141 if setflags then 3142 APSR.N = result<31>; 3143 APSR.Z = IsZeroBit(result); 3144 APSR.C = carry; 3145 APSR.V = overflow; 3146 #endif 3147 3148 bool success = false; 3149 3150 if (ConditionPassed(opcode)) { 3151 uint32_t Rd, Rn; 3152 uint32_t 3153 imm32; // the immediate value to be added to the value obtained from Rn 3154 bool setflags; 3155 switch (encoding) { 3156 case eEncodingA1: 3157 Rd = Bits32(opcode, 15, 12); 3158 Rn = Bits32(opcode, 19, 16); 3159 setflags = BitIsSet(opcode, 20); 3160 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 3161 break; 3162 default: 3163 return false; 3164 } 3165 3166 // Read the first operand. 3167 uint32_t val1 = ReadCoreReg(Rn, &success); 3168 if (!success) 3169 return false; 3170 3171 AddWithCarryResult res = AddWithCarry(val1, imm32, 0); 3172 3173 EmulateInstruction::Context context; 3174 if (Rd == 13) 3175 context.type = EmulateInstruction::eContextAdjustStackPointer; 3176 else if (Rd == GetFramePointerRegisterNumber()) 3177 context.type = EmulateInstruction::eContextSetFramePointer; 3178 else 3179 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3180 3181 std::optional<RegisterInfo> dwarf_reg = 3182 GetRegisterInfo(eRegisterKindDWARF, Rn); 3183 context.SetRegisterPlusOffset(*dwarf_reg, imm32); 3184 3185 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 3186 res.carry_out, res.overflow)) 3187 return false; 3188 } 3189 return true; 3190 } 3191 3192 // This instruction adds a register value and an optionally-shifted register 3193 // value, and writes the result to the destination register. It can optionally 3194 // update the condition flags based on the result. 3195 bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode, 3196 const ARMEncoding encoding) { 3197 #if 0 3198 // ARM pseudo code... 3199 if ConditionPassed() then 3200 EncodingSpecificOperations(); 3201 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 3202 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 3203 if d == 15 then 3204 ALUWritePC(result); // setflags is always FALSE here 3205 else 3206 R[d] = result; 3207 if setflags then 3208 APSR.N = result<31>; 3209 APSR.Z = IsZeroBit(result); 3210 APSR.C = carry; 3211 APSR.V = overflow; 3212 #endif 3213 3214 bool success = false; 3215 3216 if (ConditionPassed(opcode)) { 3217 uint32_t Rd, Rn, Rm; 3218 ARM_ShifterType shift_t; 3219 uint32_t shift_n; // the shift applied to the value read from Rm 3220 bool setflags; 3221 switch (encoding) { 3222 case eEncodingT1: 3223 Rd = Bits32(opcode, 2, 0); 3224 Rn = Bits32(opcode, 5, 3); 3225 Rm = Bits32(opcode, 8, 6); 3226 setflags = !InITBlock(); 3227 shift_t = SRType_LSL; 3228 shift_n = 0; 3229 break; 3230 case eEncodingT2: 3231 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 3232 Rm = Bits32(opcode, 6, 3); 3233 setflags = false; 3234 shift_t = SRType_LSL; 3235 shift_n = 0; 3236 if (Rn == 15 && Rm == 15) 3237 return false; 3238 if (Rd == 15 && InITBlock() && !LastInITBlock()) 3239 return false; 3240 break; 3241 case eEncodingA1: 3242 Rd = Bits32(opcode, 15, 12); 3243 Rn = Bits32(opcode, 19, 16); 3244 Rm = Bits32(opcode, 3, 0); 3245 setflags = BitIsSet(opcode, 20); 3246 shift_n = DecodeImmShiftARM(opcode, shift_t); 3247 break; 3248 default: 3249 return false; 3250 } 3251 3252 // Read the first operand. 3253 uint32_t val1 = ReadCoreReg(Rn, &success); 3254 if (!success) 3255 return false; 3256 3257 // Read the second operand. 3258 uint32_t val2 = ReadCoreReg(Rm, &success); 3259 if (!success) 3260 return false; 3261 3262 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 3263 if (!success) 3264 return false; 3265 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 3266 3267 EmulateInstruction::Context context; 3268 context.type = eContextArithmetic; 3269 std::optional<RegisterInfo> op1_reg = 3270 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn); 3271 std::optional<RegisterInfo> op2_reg = 3272 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 3273 context.SetRegisterRegisterOperands(*op1_reg, *op2_reg); 3274 3275 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 3276 res.carry_out, res.overflow)) 3277 return false; 3278 } 3279 return true; 3280 } 3281 3282 // Compare Negative (immediate) adds a register value and an immediate value. 3283 // It updates the condition flags based on the result, and discards the result. 3284 bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode, 3285 const ARMEncoding encoding) { 3286 #if 0 3287 // ARM pseudo code... 3288 if ConditionPassed() then 3289 EncodingSpecificOperations(); 3290 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 3291 APSR.N = result<31>; 3292 APSR.Z = IsZeroBit(result); 3293 APSR.C = carry; 3294 APSR.V = overflow; 3295 #endif 3296 3297 bool success = false; 3298 3299 uint32_t Rn; // the first operand 3300 uint32_t imm32; // the immediate value to be compared with 3301 switch (encoding) { 3302 case eEncodingT1: 3303 Rn = Bits32(opcode, 19, 16); 3304 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 3305 if (Rn == 15) 3306 return false; 3307 break; 3308 case eEncodingA1: 3309 Rn = Bits32(opcode, 19, 16); 3310 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 3311 break; 3312 default: 3313 return false; 3314 } 3315 // Read the register value from the operand register Rn. 3316 uint32_t reg_val = ReadCoreReg(Rn, &success); 3317 if (!success) 3318 return false; 3319 3320 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0); 3321 3322 EmulateInstruction::Context context; 3323 context.type = EmulateInstruction::eContextImmediate; 3324 context.SetNoArgs(); 3325 return WriteFlags(context, res.result, res.carry_out, res.overflow); 3326 } 3327 3328 // Compare Negative (register) adds a register value and an optionally-shifted 3329 // register value. It updates the condition flags based on the result, and 3330 // discards the result. 3331 bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode, 3332 const ARMEncoding encoding) { 3333 #if 0 3334 // ARM pseudo code... 3335 if ConditionPassed() then 3336 EncodingSpecificOperations(); 3337 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 3338 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 3339 APSR.N = result<31>; 3340 APSR.Z = IsZeroBit(result); 3341 APSR.C = carry; 3342 APSR.V = overflow; 3343 #endif 3344 3345 bool success = false; 3346 3347 uint32_t Rn; // the first operand 3348 uint32_t Rm; // the second operand 3349 ARM_ShifterType shift_t; 3350 uint32_t shift_n; // the shift applied to the value read from Rm 3351 switch (encoding) { 3352 case eEncodingT1: 3353 Rn = Bits32(opcode, 2, 0); 3354 Rm = Bits32(opcode, 5, 3); 3355 shift_t = SRType_LSL; 3356 shift_n = 0; 3357 break; 3358 case eEncodingT2: 3359 Rn = Bits32(opcode, 19, 16); 3360 Rm = Bits32(opcode, 3, 0); 3361 shift_n = DecodeImmShiftThumb(opcode, shift_t); 3362 // if n == 15 || BadReg(m) then UNPREDICTABLE; 3363 if (Rn == 15 || BadReg(Rm)) 3364 return false; 3365 break; 3366 case eEncodingA1: 3367 Rn = Bits32(opcode, 19, 16); 3368 Rm = Bits32(opcode, 3, 0); 3369 shift_n = DecodeImmShiftARM(opcode, shift_t); 3370 break; 3371 default: 3372 return false; 3373 } 3374 // Read the register value from register Rn. 3375 uint32_t val1 = ReadCoreReg(Rn, &success); 3376 if (!success) 3377 return false; 3378 3379 // Read the register value from register Rm. 3380 uint32_t val2 = ReadCoreReg(Rm, &success); 3381 if (!success) 3382 return false; 3383 3384 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 3385 if (!success) 3386 return false; 3387 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 3388 3389 EmulateInstruction::Context context; 3390 context.type = EmulateInstruction::eContextImmediate; 3391 context.SetNoArgs(); 3392 return WriteFlags(context, res.result, res.carry_out, res.overflow); 3393 } 3394 3395 // Compare (immediate) subtracts an immediate value from a register value. It 3396 // updates the condition flags based on the result, and discards the result. 3397 bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode, 3398 const ARMEncoding encoding) { 3399 #if 0 3400 // ARM pseudo code... 3401 if ConditionPassed() then 3402 EncodingSpecificOperations(); 3403 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 3404 APSR.N = result<31>; 3405 APSR.Z = IsZeroBit(result); 3406 APSR.C = carry; 3407 APSR.V = overflow; 3408 #endif 3409 3410 bool success = false; 3411 3412 uint32_t Rn; // the first operand 3413 uint32_t imm32; // the immediate value to be compared with 3414 switch (encoding) { 3415 case eEncodingT1: 3416 Rn = Bits32(opcode, 10, 8); 3417 imm32 = Bits32(opcode, 7, 0); 3418 break; 3419 case eEncodingT2: 3420 Rn = Bits32(opcode, 19, 16); 3421 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 3422 if (Rn == 15) 3423 return false; 3424 break; 3425 case eEncodingA1: 3426 Rn = Bits32(opcode, 19, 16); 3427 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 3428 break; 3429 default: 3430 return false; 3431 } 3432 // Read the register value from the operand register Rn. 3433 uint32_t reg_val = ReadCoreReg(Rn, &success); 3434 if (!success) 3435 return false; 3436 3437 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 3438 3439 EmulateInstruction::Context context; 3440 context.type = EmulateInstruction::eContextImmediate; 3441 context.SetNoArgs(); 3442 return WriteFlags(context, res.result, res.carry_out, res.overflow); 3443 } 3444 3445 // Compare (register) subtracts an optionally-shifted register value from a 3446 // register value. It updates the condition flags based on the result, and 3447 // discards the result. 3448 bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode, 3449 const ARMEncoding encoding) { 3450 #if 0 3451 // ARM pseudo code... 3452 if ConditionPassed() then 3453 EncodingSpecificOperations(); 3454 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 3455 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 3456 APSR.N = result<31>; 3457 APSR.Z = IsZeroBit(result); 3458 APSR.C = carry; 3459 APSR.V = overflow; 3460 #endif 3461 3462 bool success = false; 3463 3464 uint32_t Rn; // the first operand 3465 uint32_t Rm; // the second operand 3466 ARM_ShifterType shift_t; 3467 uint32_t shift_n; // the shift applied to the value read from Rm 3468 switch (encoding) { 3469 case eEncodingT1: 3470 Rn = Bits32(opcode, 2, 0); 3471 Rm = Bits32(opcode, 5, 3); 3472 shift_t = SRType_LSL; 3473 shift_n = 0; 3474 break; 3475 case eEncodingT2: 3476 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 3477 Rm = Bits32(opcode, 6, 3); 3478 shift_t = SRType_LSL; 3479 shift_n = 0; 3480 if (Rn < 8 && Rm < 8) 3481 return false; 3482 if (Rn == 15 || Rm == 15) 3483 return false; 3484 break; 3485 case eEncodingT3: 3486 Rn = Bits32(opcode, 19, 16); 3487 Rm = Bits32(opcode, 3, 0); 3488 shift_n = DecodeImmShiftThumb(opcode, shift_t); 3489 if (Rn == 15 || BadReg(Rm)) 3490 return false; 3491 break; 3492 case eEncodingA1: 3493 Rn = Bits32(opcode, 19, 16); 3494 Rm = Bits32(opcode, 3, 0); 3495 shift_n = DecodeImmShiftARM(opcode, shift_t); 3496 break; 3497 default: 3498 return false; 3499 } 3500 // Read the register value from register Rn. 3501 uint32_t val1 = ReadCoreReg(Rn, &success); 3502 if (!success) 3503 return false; 3504 3505 // Read the register value from register Rm. 3506 uint32_t val2 = ReadCoreReg(Rm, &success); 3507 if (!success) 3508 return false; 3509 3510 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 3511 if (!success) 3512 return false; 3513 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); 3514 3515 EmulateInstruction::Context context; 3516 context.type = EmulateInstruction::eContextImmediate; 3517 context.SetNoArgs(); 3518 return WriteFlags(context, res.result, res.carry_out, res.overflow); 3519 } 3520 3521 // Arithmetic Shift Right (immediate) shifts a register value right by an 3522 // immediate number of bits, shifting in copies of its sign bit, and writes the 3523 // result to the destination register. It can optionally update the condition 3524 // flags based on the result. 3525 bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode, 3526 const ARMEncoding encoding) { 3527 #if 0 3528 // ARM pseudo code... 3529 if ConditionPassed() then 3530 EncodingSpecificOperations(); 3531 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 3532 if d == 15 then // Can only occur for ARM encoding 3533 ALUWritePC(result); // setflags is always FALSE here 3534 else 3535 R[d] = result; 3536 if setflags then 3537 APSR.N = result<31>; 3538 APSR.Z = IsZeroBit(result); 3539 APSR.C = carry; 3540 // APSR.V unchanged 3541 #endif 3542 3543 return EmulateShiftImm(opcode, encoding, SRType_ASR); 3544 } 3545 3546 // Arithmetic Shift Right (register) shifts a register value right by a 3547 // variable number of bits, shifting in copies of its sign bit, and writes the 3548 // result to the destination register. The variable number of bits is read from 3549 // the bottom byte of a register. It can optionally update the condition flags 3550 // based on the result. 3551 bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode, 3552 const ARMEncoding encoding) { 3553 #if 0 3554 // ARM pseudo code... 3555 if ConditionPassed() then 3556 EncodingSpecificOperations(); 3557 shift_n = UInt(R[m]<7:0>); 3558 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 3559 R[d] = result; 3560 if setflags then 3561 APSR.N = result<31>; 3562 APSR.Z = IsZeroBit(result); 3563 APSR.C = carry; 3564 // APSR.V unchanged 3565 #endif 3566 3567 return EmulateShiftReg(opcode, encoding, SRType_ASR); 3568 } 3569 3570 // Logical Shift Left (immediate) shifts a register value left by an immediate 3571 // number of bits, shifting in zeros, and writes the result to the destination 3572 // register. It can optionally update the condition flags based on the result. 3573 bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode, 3574 const ARMEncoding encoding) { 3575 #if 0 3576 // ARM pseudo code... 3577 if ConditionPassed() then 3578 EncodingSpecificOperations(); 3579 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 3580 if d == 15 then // Can only occur for ARM encoding 3581 ALUWritePC(result); // setflags is always FALSE here 3582 else 3583 R[d] = result; 3584 if setflags then 3585 APSR.N = result<31>; 3586 APSR.Z = IsZeroBit(result); 3587 APSR.C = carry; 3588 // APSR.V unchanged 3589 #endif 3590 3591 return EmulateShiftImm(opcode, encoding, SRType_LSL); 3592 } 3593 3594 // Logical Shift Left (register) shifts a register value left by a variable 3595 // number of bits, shifting in zeros, and writes the result to the destination 3596 // register. The variable number of bits is read from the bottom byte of a 3597 // register. It can optionally update the condition flags based on the result. 3598 bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode, 3599 const ARMEncoding encoding) { 3600 #if 0 3601 // ARM pseudo code... 3602 if ConditionPassed() then 3603 EncodingSpecificOperations(); 3604 shift_n = UInt(R[m]<7:0>); 3605 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 3606 R[d] = result; 3607 if setflags then 3608 APSR.N = result<31>; 3609 APSR.Z = IsZeroBit(result); 3610 APSR.C = carry; 3611 // APSR.V unchanged 3612 #endif 3613 3614 return EmulateShiftReg(opcode, encoding, SRType_LSL); 3615 } 3616 3617 // Logical Shift Right (immediate) shifts a register value right by an 3618 // immediate number of bits, shifting in zeros, and writes the result to the 3619 // destination register. It can optionally update the condition flags based on 3620 // the result. 3621 bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode, 3622 const ARMEncoding encoding) { 3623 #if 0 3624 // ARM pseudo code... 3625 if ConditionPassed() then 3626 EncodingSpecificOperations(); 3627 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 3628 if d == 15 then // Can only occur for ARM encoding 3629 ALUWritePC(result); // setflags is always FALSE here 3630 else 3631 R[d] = result; 3632 if setflags then 3633 APSR.N = result<31>; 3634 APSR.Z = IsZeroBit(result); 3635 APSR.C = carry; 3636 // APSR.V unchanged 3637 #endif 3638 3639 return EmulateShiftImm(opcode, encoding, SRType_LSR); 3640 } 3641 3642 // Logical Shift Right (register) shifts a register value right by a variable 3643 // number of bits, shifting in zeros, and writes the result to the destination 3644 // register. The variable number of bits is read from the bottom byte of a 3645 // register. It can optionally update the condition flags based on the result. 3646 bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode, 3647 const ARMEncoding encoding) { 3648 #if 0 3649 // ARM pseudo code... 3650 if ConditionPassed() then 3651 EncodingSpecificOperations(); 3652 shift_n = UInt(R[m]<7:0>); 3653 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 3654 R[d] = result; 3655 if setflags then 3656 APSR.N = result<31>; 3657 APSR.Z = IsZeroBit(result); 3658 APSR.C = carry; 3659 // APSR.V unchanged 3660 #endif 3661 3662 return EmulateShiftReg(opcode, encoding, SRType_LSR); 3663 } 3664 3665 // Rotate Right (immediate) provides the value of the contents of a register 3666 // rotated by a constant value. The bits that are rotated off the right end are 3667 // inserted into the vacated bit positions on the left. It can optionally 3668 // update the condition flags based on the result. 3669 bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode, 3670 const ARMEncoding encoding) { 3671 #if 0 3672 // ARM pseudo code... 3673 if ConditionPassed() then 3674 EncodingSpecificOperations(); 3675 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 3676 if d == 15 then // Can only occur for ARM encoding 3677 ALUWritePC(result); // setflags is always FALSE here 3678 else 3679 R[d] = result; 3680 if setflags then 3681 APSR.N = result<31>; 3682 APSR.Z = IsZeroBit(result); 3683 APSR.C = carry; 3684 // APSR.V unchanged 3685 #endif 3686 3687 return EmulateShiftImm(opcode, encoding, SRType_ROR); 3688 } 3689 3690 // Rotate Right (register) provides the value of the contents of a register 3691 // rotated by a variable number of bits. The bits that are rotated off the 3692 // right end are inserted into the vacated bit positions on the left. The 3693 // variable number of bits is read from the bottom byte of a register. It can 3694 // optionally update the condition flags based on the result. 3695 bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode, 3696 const ARMEncoding encoding) { 3697 #if 0 3698 // ARM pseudo code... 3699 if ConditionPassed() then 3700 EncodingSpecificOperations(); 3701 shift_n = UInt(R[m]<7:0>); 3702 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 3703 R[d] = result; 3704 if setflags then 3705 APSR.N = result<31>; 3706 APSR.Z = IsZeroBit(result); 3707 APSR.C = carry; 3708 // APSR.V unchanged 3709 #endif 3710 3711 return EmulateShiftReg(opcode, encoding, SRType_ROR); 3712 } 3713 3714 // Rotate Right with Extend provides the value of the contents of a register 3715 // shifted right by one place, with the carry flag shifted into bit [31]. 3716 // 3717 // RRX can optionally update the condition flags based on the result. 3718 // In that case, bit [0] is shifted into the carry flag. 3719 bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode, 3720 const ARMEncoding encoding) { 3721 #if 0 3722 // ARM pseudo code... 3723 if ConditionPassed() then 3724 EncodingSpecificOperations(); 3725 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C); 3726 if d == 15 then // Can only occur for ARM encoding 3727 ALUWritePC(result); // setflags is always FALSE here 3728 else 3729 R[d] = result; 3730 if setflags then 3731 APSR.N = result<31>; 3732 APSR.Z = IsZeroBit(result); 3733 APSR.C = carry; 3734 // APSR.V unchanged 3735 #endif 3736 3737 return EmulateShiftImm(opcode, encoding, SRType_RRX); 3738 } 3739 3740 bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode, 3741 const ARMEncoding encoding, 3742 ARM_ShifterType shift_type) { 3743 // assert(shift_type == SRType_ASR 3744 // || shift_type == SRType_LSL 3745 // || shift_type == SRType_LSR 3746 // || shift_type == SRType_ROR 3747 // || shift_type == SRType_RRX); 3748 3749 bool success = false; 3750 3751 if (ConditionPassed(opcode)) { 3752 uint32_t Rd; // the destination register 3753 uint32_t Rm; // the first operand register 3754 uint32_t imm5; // encoding for the shift amount 3755 uint32_t carry; // the carry bit after the shift operation 3756 bool setflags; 3757 3758 // Special case handling! 3759 // A8.6.139 ROR (immediate) -- Encoding T1 3760 ARMEncoding use_encoding = encoding; 3761 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) { 3762 // Morph the T1 encoding from the ARM Architecture Manual into T2 3763 // encoding to have the same decoding of bit fields as the other Thumb2 3764 // shift operations. 3765 use_encoding = eEncodingT2; 3766 } 3767 3768 switch (use_encoding) { 3769 case eEncodingT1: 3770 Rd = Bits32(opcode, 2, 0); 3771 Rm = Bits32(opcode, 5, 3); 3772 setflags = !InITBlock(); 3773 imm5 = Bits32(opcode, 10, 6); 3774 break; 3775 case eEncodingT2: 3776 // A8.6.141 RRX 3777 // There's no imm form of RRX instructions. 3778 if (shift_type == SRType_RRX) 3779 return false; 3780 3781 Rd = Bits32(opcode, 11, 8); 3782 Rm = Bits32(opcode, 3, 0); 3783 setflags = BitIsSet(opcode, 20); 3784 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6); 3785 if (BadReg(Rd) || BadReg(Rm)) 3786 return false; 3787 break; 3788 case eEncodingA1: 3789 Rd = Bits32(opcode, 15, 12); 3790 Rm = Bits32(opcode, 3, 0); 3791 setflags = BitIsSet(opcode, 20); 3792 imm5 = Bits32(opcode, 11, 7); 3793 break; 3794 default: 3795 return false; 3796 } 3797 3798 // A8.6.139 ROR (immediate) 3799 if (shift_type == SRType_ROR && imm5 == 0) 3800 shift_type = SRType_RRX; 3801 3802 // Get the first operand. 3803 uint32_t value = ReadCoreReg(Rm, &success); 3804 if (!success) 3805 return false; 3806 3807 // Decode the shift amount if not RRX. 3808 uint32_t amt = 3809 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5)); 3810 3811 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success); 3812 if (!success) 3813 return false; 3814 3815 // The context specifies that an immediate is to be moved into Rd. 3816 EmulateInstruction::Context context; 3817 context.type = EmulateInstruction::eContextImmediate; 3818 context.SetNoArgs(); 3819 3820 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3821 return false; 3822 } 3823 return true; 3824 } 3825 3826 bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode, 3827 const ARMEncoding encoding, 3828 ARM_ShifterType shift_type) { 3829 // assert(shift_type == SRType_ASR 3830 // || shift_type == SRType_LSL 3831 // || shift_type == SRType_LSR 3832 // || shift_type == SRType_ROR); 3833 3834 bool success = false; 3835 3836 if (ConditionPassed(opcode)) { 3837 uint32_t Rd; // the destination register 3838 uint32_t Rn; // the first operand register 3839 uint32_t 3840 Rm; // the register whose bottom byte contains the amount to shift by 3841 uint32_t carry; // the carry bit after the shift operation 3842 bool setflags; 3843 switch (encoding) { 3844 case eEncodingT1: 3845 Rd = Bits32(opcode, 2, 0); 3846 Rn = Rd; 3847 Rm = Bits32(opcode, 5, 3); 3848 setflags = !InITBlock(); 3849 break; 3850 case eEncodingT2: 3851 Rd = Bits32(opcode, 11, 8); 3852 Rn = Bits32(opcode, 19, 16); 3853 Rm = Bits32(opcode, 3, 0); 3854 setflags = BitIsSet(opcode, 20); 3855 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 3856 return false; 3857 break; 3858 case eEncodingA1: 3859 Rd = Bits32(opcode, 15, 12); 3860 Rn = Bits32(opcode, 3, 0); 3861 Rm = Bits32(opcode, 11, 8); 3862 setflags = BitIsSet(opcode, 20); 3863 if (Rd == 15 || Rn == 15 || Rm == 15) 3864 return false; 3865 break; 3866 default: 3867 return false; 3868 } 3869 3870 // Get the first operand. 3871 uint32_t value = ReadCoreReg(Rn, &success); 3872 if (!success) 3873 return false; 3874 // Get the Rm register content. 3875 uint32_t val = ReadCoreReg(Rm, &success); 3876 if (!success) 3877 return false; 3878 3879 // Get the shift amount. 3880 uint32_t amt = Bits32(val, 7, 0); 3881 3882 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success); 3883 if (!success) 3884 return false; 3885 3886 // The context specifies that an immediate is to be moved into Rd. 3887 EmulateInstruction::Context context; 3888 context.type = EmulateInstruction::eContextImmediate; 3889 context.SetNoArgs(); 3890 3891 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3892 return false; 3893 } 3894 return true; 3895 } 3896 3897 // LDM loads multiple registers from consecutive memory locations, using an 3898 // address from a base register. Optionally the address just above the highest 3899 // of those locations can be written back to the base register. 3900 bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode, 3901 const ARMEncoding encoding) { 3902 #if 0 3903 // ARM pseudo code... 3904 if ConditionPassed() 3905 EncodingSpecificOperations(); NullCheckIfThumbEE (n); 3906 address = R[n]; 3907 3908 for i = 0 to 14 3909 if registers<i> == '1' then 3910 R[i] = MemA[address, 4]; address = address + 4; 3911 if registers<15> == '1' then 3912 LoadWritePC (MemA[address, 4]); 3913 3914 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers); 3915 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3916 3917 #endif 3918 3919 bool success = false; 3920 if (ConditionPassed(opcode)) { 3921 uint32_t n; 3922 uint32_t registers = 0; 3923 bool wback; 3924 const uint32_t addr_byte_size = GetAddressByteSize(); 3925 switch (encoding) { 3926 case eEncodingT1: 3927 // n = UInt(Rn); registers = '00000000':register_list; wback = 3928 // (registers<n> == '0'); 3929 n = Bits32(opcode, 10, 8); 3930 registers = Bits32(opcode, 7, 0); 3931 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3932 wback = BitIsClear(registers, n); 3933 // if BitCount(registers) < 1 then UNPREDICTABLE; 3934 if (BitCount(registers) < 1) 3935 return false; 3936 break; 3937 case eEncodingT2: 3938 // if W == '1' && Rn == '1101' then SEE POP; 3939 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3940 n = Bits32(opcode, 19, 16); 3941 registers = Bits32(opcode, 15, 0); 3942 registers = registers & 0xdfff; // Make sure bit 13 is zero. 3943 wback = BitIsSet(opcode, 21); 3944 3945 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then 3946 // UNPREDICTABLE; 3947 if ((n == 15) || (BitCount(registers) < 2) || 3948 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15))) 3949 return false; 3950 3951 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then 3952 // UNPREDICTABLE; 3953 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 3954 return false; 3955 3956 // if wback && registers<n> == '1' then UNPREDICTABLE; 3957 if (wback && BitIsSet(registers, n)) 3958 return false; 3959 break; 3960 3961 case eEncodingA1: 3962 n = Bits32(opcode, 19, 16); 3963 registers = Bits32(opcode, 15, 0); 3964 wback = BitIsSet(opcode, 21); 3965 if ((n == 15) || (BitCount(registers) < 1)) 3966 return false; 3967 break; 3968 default: 3969 return false; 3970 } 3971 3972 int32_t offset = 0; 3973 const addr_t base_address = 3974 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3975 if (!success) 3976 return false; 3977 3978 EmulateInstruction::Context context; 3979 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3980 std::optional<RegisterInfo> dwarf_reg = 3981 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 3982 context.SetRegisterPlusOffset(*dwarf_reg, offset); 3983 3984 for (int i = 0; i < 14; ++i) { 3985 if (BitIsSet(registers, i)) { 3986 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3987 context.SetRegisterPlusOffset(*dwarf_reg, offset); 3988 if (wback && (n == 13)) // Pop Instruction 3989 { 3990 context.type = EmulateInstruction::eContextPopRegisterOffStack; 3991 context.SetAddress(base_address + offset); 3992 } 3993 3994 // R[i] = MemA [address, 4]; address = address + 4; 3995 uint32_t data = MemARead(context, base_address + offset, addr_byte_size, 3996 0, &success); 3997 if (!success) 3998 return false; 3999 4000 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, 4001 data)) 4002 return false; 4003 4004 offset += addr_byte_size; 4005 } 4006 } 4007 4008 if (BitIsSet(registers, 15)) { 4009 // LoadWritePC (MemA [address, 4]); 4010 context.type = EmulateInstruction::eContextRegisterPlusOffset; 4011 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4012 uint32_t data = 4013 MemARead(context, base_address + offset, addr_byte_size, 0, &success); 4014 if (!success) 4015 return false; 4016 // In ARMv5T and above, this is an interworking branch. 4017 if (!LoadWritePC(context, data)) 4018 return false; 4019 } 4020 4021 if (wback && BitIsClear(registers, n)) { 4022 // R[n] = R[n] + 4 * BitCount (registers) 4023 int32_t offset = addr_byte_size * BitCount(registers); 4024 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4025 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4026 4027 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4028 base_address + offset)) 4029 return false; 4030 } 4031 if (wback && BitIsSet(registers, n)) 4032 // R[n] bits(32) UNKNOWN; 4033 return WriteBits32Unknown(n); 4034 } 4035 return true; 4036 } 4037 4038 // LDMDA loads multiple registers from consecutive memory locations using an 4039 // address from a base register. 4040 // The consecutive memory locations end at this address and the address just 4041 // below the lowest of those locations can optionally be written back to the 4042 // base register. 4043 bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode, 4044 const ARMEncoding encoding) { 4045 #if 0 4046 // ARM pseudo code... 4047 if ConditionPassed() then 4048 EncodingSpecificOperations(); 4049 address = R[n] - 4*BitCount(registers) + 4; 4050 4051 for i = 0 to 14 4052 if registers<i> == '1' then 4053 R[i] = MemA[address,4]; address = address + 4; 4054 4055 if registers<15> == '1' then 4056 LoadWritePC(MemA[address,4]); 4057 4058 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 4059 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 4060 #endif 4061 4062 bool success = false; 4063 4064 if (ConditionPassed(opcode)) { 4065 uint32_t n; 4066 uint32_t registers = 0; 4067 bool wback; 4068 const uint32_t addr_byte_size = GetAddressByteSize(); 4069 4070 // EncodingSpecificOperations(); 4071 switch (encoding) { 4072 case eEncodingA1: 4073 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4074 n = Bits32(opcode, 19, 16); 4075 registers = Bits32(opcode, 15, 0); 4076 wback = BitIsSet(opcode, 21); 4077 4078 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4079 if ((n == 15) || (BitCount(registers) < 1)) 4080 return false; 4081 4082 break; 4083 4084 default: 4085 return false; 4086 } 4087 // address = R[n] - 4*BitCount(registers) + 4; 4088 4089 int32_t offset = 0; 4090 addr_t Rn = ReadCoreReg(n, &success); 4091 4092 if (!success) 4093 return false; 4094 4095 addr_t address = 4096 Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size; 4097 4098 EmulateInstruction::Context context; 4099 context.type = EmulateInstruction::eContextRegisterPlusOffset; 4100 std::optional<RegisterInfo> dwarf_reg = 4101 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4102 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4103 4104 // for i = 0 to 14 4105 for (int i = 0; i < 14; ++i) { 4106 // if registers<i> == '1' then 4107 if (BitIsSet(registers, i)) { 4108 // R[i] = MemA[address,4]; address = address + 4; 4109 context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset)); 4110 uint32_t data = 4111 MemARead(context, address + offset, addr_byte_size, 0, &success); 4112 if (!success) 4113 return false; 4114 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, 4115 data)) 4116 return false; 4117 offset += addr_byte_size; 4118 } 4119 } 4120 4121 // if registers<15> == '1' then 4122 // LoadWritePC(MemA[address,4]); 4123 if (BitIsSet(registers, 15)) { 4124 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4125 uint32_t data = 4126 MemARead(context, address + offset, addr_byte_size, 0, &success); 4127 if (!success) 4128 return false; 4129 // In ARMv5T and above, this is an interworking branch. 4130 if (!LoadWritePC(context, data)) 4131 return false; 4132 } 4133 4134 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 4135 if (wback && BitIsClear(registers, n)) { 4136 4137 offset = (addr_byte_size * BitCount(registers)) * -1; 4138 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4139 context.SetImmediateSigned(offset); 4140 addr_t addr = Rn + offset; 4141 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4142 addr)) 4143 return false; 4144 } 4145 4146 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 4147 if (wback && BitIsSet(registers, n)) 4148 return WriteBits32Unknown(n); 4149 } 4150 return true; 4151 } 4152 4153 // LDMDB loads multiple registers from consecutive memory locations using an 4154 // address from a base register. The 4155 // consecutive memory locations end just below this address, and the address of 4156 // the lowest of those locations can be optionally written back to the base 4157 // register. 4158 bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode, 4159 const ARMEncoding encoding) { 4160 #if 0 4161 // ARM pseudo code... 4162 if ConditionPassed() then 4163 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4164 address = R[n] - 4*BitCount(registers); 4165 4166 for i = 0 to 14 4167 if registers<i> == '1' then 4168 R[i] = MemA[address,4]; address = address + 4; 4169 if registers<15> == '1' then 4170 LoadWritePC(MemA[address,4]); 4171 4172 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 4173 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 4174 #endif 4175 4176 bool success = false; 4177 4178 if (ConditionPassed(opcode)) { 4179 uint32_t n; 4180 uint32_t registers = 0; 4181 bool wback; 4182 const uint32_t addr_byte_size = GetAddressByteSize(); 4183 switch (encoding) { 4184 case eEncodingT1: 4185 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 4186 n = Bits32(opcode, 19, 16); 4187 registers = Bits32(opcode, 15, 0); 4188 registers = registers & 0xdfff; // Make sure bit 13 is a zero. 4189 wback = BitIsSet(opcode, 21); 4190 4191 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then 4192 // UNPREDICTABLE; 4193 if ((n == 15) || (BitCount(registers) < 2) || 4194 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15))) 4195 return false; 4196 4197 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then 4198 // UNPREDICTABLE; 4199 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 4200 return false; 4201 4202 // if wback && registers<n> == '1' then UNPREDICTABLE; 4203 if (wback && BitIsSet(registers, n)) 4204 return false; 4205 4206 break; 4207 4208 case eEncodingA1: 4209 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4210 n = Bits32(opcode, 19, 16); 4211 registers = Bits32(opcode, 15, 0); 4212 wback = BitIsSet(opcode, 21); 4213 4214 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4215 if ((n == 15) || (BitCount(registers) < 1)) 4216 return false; 4217 4218 break; 4219 4220 default: 4221 return false; 4222 } 4223 4224 // address = R[n] - 4*BitCount(registers); 4225 4226 int32_t offset = 0; 4227 addr_t Rn = 4228 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4229 4230 if (!success) 4231 return false; 4232 4233 addr_t address = Rn - (addr_byte_size * BitCount(registers)); 4234 EmulateInstruction::Context context; 4235 context.type = EmulateInstruction::eContextRegisterPlusOffset; 4236 std::optional<RegisterInfo> dwarf_reg = 4237 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4238 context.SetRegisterPlusOffset(*dwarf_reg, Rn - address); 4239 4240 for (int i = 0; i < 14; ++i) { 4241 if (BitIsSet(registers, i)) { 4242 // R[i] = MemA[address,4]; address = address + 4; 4243 context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset)); 4244 uint32_t data = 4245 MemARead(context, address + offset, addr_byte_size, 0, &success); 4246 if (!success) 4247 return false; 4248 4249 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, 4250 data)) 4251 return false; 4252 4253 offset += addr_byte_size; 4254 } 4255 } 4256 4257 // if registers<15> == '1' then 4258 // LoadWritePC(MemA[address,4]); 4259 if (BitIsSet(registers, 15)) { 4260 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4261 uint32_t data = 4262 MemARead(context, address + offset, addr_byte_size, 0, &success); 4263 if (!success) 4264 return false; 4265 // In ARMv5T and above, this is an interworking branch. 4266 if (!LoadWritePC(context, data)) 4267 return false; 4268 } 4269 4270 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 4271 if (wback && BitIsClear(registers, n)) { 4272 4273 offset = (addr_byte_size * BitCount(registers)) * -1; 4274 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4275 context.SetImmediateSigned(offset); 4276 addr_t addr = Rn + offset; 4277 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4278 addr)) 4279 return false; 4280 } 4281 4282 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only 4283 // possible for encoding A1 4284 if (wback && BitIsSet(registers, n)) 4285 return WriteBits32Unknown(n); 4286 } 4287 return true; 4288 } 4289 4290 // LDMIB loads multiple registers from consecutive memory locations using an 4291 // address from a base register. The 4292 // consecutive memory locations start just above this address, and thea ddress 4293 // of the last of those locations can optinoally be written back to the base 4294 // register. 4295 bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode, 4296 const ARMEncoding encoding) { 4297 #if 0 4298 if ConditionPassed() then 4299 EncodingSpecificOperations(); 4300 address = R[n] + 4; 4301 4302 for i = 0 to 14 4303 if registers<i> == '1' then 4304 R[i] = MemA[address,4]; address = address + 4; 4305 if registers<15> == '1' then 4306 LoadWritePC(MemA[address,4]); 4307 4308 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 4309 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 4310 #endif 4311 4312 bool success = false; 4313 4314 if (ConditionPassed(opcode)) { 4315 uint32_t n; 4316 uint32_t registers = 0; 4317 bool wback; 4318 const uint32_t addr_byte_size = GetAddressByteSize(); 4319 switch (encoding) { 4320 case eEncodingA1: 4321 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4322 n = Bits32(opcode, 19, 16); 4323 registers = Bits32(opcode, 15, 0); 4324 wback = BitIsSet(opcode, 21); 4325 4326 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4327 if ((n == 15) || (BitCount(registers) < 1)) 4328 return false; 4329 4330 break; 4331 default: 4332 return false; 4333 } 4334 // address = R[n] + 4; 4335 4336 int32_t offset = 0; 4337 addr_t Rn = 4338 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4339 4340 if (!success) 4341 return false; 4342 4343 addr_t address = Rn + addr_byte_size; 4344 4345 EmulateInstruction::Context context; 4346 context.type = EmulateInstruction::eContextRegisterPlusOffset; 4347 std::optional<RegisterInfo> dwarf_reg = 4348 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4349 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4350 4351 for (int i = 0; i < 14; ++i) { 4352 if (BitIsSet(registers, i)) { 4353 // R[i] = MemA[address,4]; address = address + 4; 4354 4355 context.SetRegisterPlusOffset(*dwarf_reg, offset + addr_byte_size); 4356 uint32_t data = 4357 MemARead(context, address + offset, addr_byte_size, 0, &success); 4358 if (!success) 4359 return false; 4360 4361 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, 4362 data)) 4363 return false; 4364 4365 offset += addr_byte_size; 4366 } 4367 } 4368 4369 // if registers<15> == '1' then 4370 // LoadWritePC(MemA[address,4]); 4371 if (BitIsSet(registers, 15)) { 4372 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4373 uint32_t data = 4374 MemARead(context, address + offset, addr_byte_size, 0, &success); 4375 if (!success) 4376 return false; 4377 // In ARMv5T and above, this is an interworking branch. 4378 if (!LoadWritePC(context, data)) 4379 return false; 4380 } 4381 4382 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 4383 if (wback && BitIsClear(registers, n)) { 4384 4385 offset = addr_byte_size * BitCount(registers); 4386 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4387 context.SetImmediateSigned(offset); 4388 addr_t addr = Rn + offset; 4389 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4390 addr)) 4391 return false; 4392 } 4393 4394 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only 4395 // possible for encoding A1 4396 if (wback && BitIsSet(registers, n)) 4397 return WriteBits32Unknown(n); 4398 } 4399 return true; 4400 } 4401 4402 // Load Register (immediate) calculates an address from a base register value 4403 // and an immediate offset, loads a word from memory, and writes to a register. 4404 // LDR (immediate, Thumb) 4405 bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode, 4406 const ARMEncoding encoding) { 4407 #if 0 4408 // ARM pseudo code... 4409 if (ConditionPassed()) 4410 { 4411 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 4412 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4413 address = if index then offset_addr else R[n]; 4414 data = MemU[address,4]; 4415 if wback then R[n] = offset_addr; 4416 if t == 15 then 4417 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 4418 elsif UnalignedSupport() || address<1:0> = '00' then 4419 R[t] = data; 4420 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7 4421 } 4422 #endif 4423 4424 bool success = false; 4425 4426 if (ConditionPassed(opcode)) { 4427 uint32_t Rt; // the destination register 4428 uint32_t Rn; // the base register 4429 uint32_t imm32; // the immediate offset used to form the address 4430 addr_t offset_addr; // the offset address 4431 addr_t address; // the calculated address 4432 uint32_t data; // the literal data value from memory load 4433 bool add, index, wback; 4434 switch (encoding) { 4435 case eEncodingT1: 4436 Rt = Bits32(opcode, 2, 0); 4437 Rn = Bits32(opcode, 5, 3); 4438 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32); 4439 // index = TRUE; add = TRUE; wback = FALSE 4440 add = true; 4441 index = true; 4442 wback = false; 4443 4444 break; 4445 4446 case eEncodingT2: 4447 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 4448 Rt = Bits32(opcode, 10, 8); 4449 Rn = 13; 4450 imm32 = Bits32(opcode, 7, 0) << 2; 4451 4452 // index = TRUE; add = TRUE; wback = FALSE; 4453 index = true; 4454 add = true; 4455 wback = false; 4456 4457 break; 4458 4459 case eEncodingT3: 4460 // if Rn == '1111' then SEE LDR (literal); 4461 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4462 Rt = Bits32(opcode, 15, 12); 4463 Rn = Bits32(opcode, 19, 16); 4464 imm32 = Bits32(opcode, 11, 0); 4465 4466 // index = TRUE; add = TRUE; wback = FALSE; 4467 index = true; 4468 add = true; 4469 wback = false; 4470 4471 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 4472 if ((Rt == 15) && InITBlock() && !LastInITBlock()) 4473 return false; 4474 4475 break; 4476 4477 case eEncodingT4: 4478 // if Rn == '1111' then SEE LDR (literal); 4479 // if P == '1' && U == '1' && W == '0' then SEE LDRT; 4480 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == 4481 // '00000100' then SEE POP; 4482 // if P == '0' && W == '0' then UNDEFINED; 4483 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) 4484 return false; 4485 4486 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4487 Rt = Bits32(opcode, 15, 12); 4488 Rn = Bits32(opcode, 19, 16); 4489 imm32 = Bits32(opcode, 7, 0); 4490 4491 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4492 index = BitIsSet(opcode, 10); 4493 add = BitIsSet(opcode, 9); 4494 wback = BitIsSet(opcode, 8); 4495 4496 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) 4497 // then UNPREDICTABLE; 4498 if ((wback && (Rn == Rt)) || 4499 ((Rt == 15) && InITBlock() && !LastInITBlock())) 4500 return false; 4501 4502 break; 4503 4504 default: 4505 return false; 4506 } 4507 uint32_t base = ReadCoreReg(Rn, &success); 4508 if (!success) 4509 return false; 4510 if (add) 4511 offset_addr = base + imm32; 4512 else 4513 offset_addr = base - imm32; 4514 4515 address = (index ? offset_addr : base); 4516 4517 std::optional<RegisterInfo> base_reg = 4518 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn); 4519 if (wback) { 4520 EmulateInstruction::Context ctx; 4521 if (Rn == 13) { 4522 ctx.type = eContextAdjustStackPointer; 4523 ctx.SetImmediateSigned((int32_t)(offset_addr - base)); 4524 } else if (Rn == GetFramePointerRegisterNumber()) { 4525 ctx.type = eContextSetFramePointer; 4526 ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base)); 4527 } else { 4528 ctx.type = EmulateInstruction::eContextAdjustBaseRegister; 4529 ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base)); 4530 } 4531 4532 if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn, 4533 offset_addr)) 4534 return false; 4535 } 4536 4537 // Prepare to write to the Rt register. 4538 EmulateInstruction::Context context; 4539 context.type = EmulateInstruction::eContextRegisterLoad; 4540 context.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base)); 4541 4542 // Read memory from the address. 4543 data = MemURead(context, address, 4, 0, &success); 4544 if (!success) 4545 return false; 4546 4547 if (Rt == 15) { 4548 if (Bits32(address, 1, 0) == 0) { 4549 if (!LoadWritePC(context, data)) 4550 return false; 4551 } else 4552 return false; 4553 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) { 4554 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt, 4555 data)) 4556 return false; 4557 } else 4558 WriteBits32Unknown(Rt); 4559 } 4560 return true; 4561 } 4562 4563 // STM (Store Multiple Increment After) stores multiple registers to consecutive 4564 // memory locations using an address 4565 // from a base register. The consecutive memory locations start at this 4566 // address, and the address just above the last of those locations can 4567 // optionally be written back to the base register. 4568 bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode, 4569 const ARMEncoding encoding) { 4570 #if 0 4571 if ConditionPassed() then 4572 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4573 address = R[n]; 4574 4575 for i = 0 to 14 4576 if registers<i> == '1' then 4577 if i == n && wback && i != LowestSetBit(registers) then 4578 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 4579 else 4580 MemA[address,4] = R[i]; 4581 address = address + 4; 4582 4583 if registers<15> == '1' then // Only possible for encoding A1 4584 MemA[address,4] = PCStoreValue(); 4585 if wback then R[n] = R[n] + 4*BitCount(registers); 4586 #endif 4587 4588 bool success = false; 4589 4590 if (ConditionPassed(opcode)) { 4591 uint32_t n; 4592 uint32_t registers = 0; 4593 bool wback; 4594 const uint32_t addr_byte_size = GetAddressByteSize(); 4595 4596 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4597 switch (encoding) { 4598 case eEncodingT1: 4599 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE; 4600 n = Bits32(opcode, 10, 8); 4601 registers = Bits32(opcode, 7, 0); 4602 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 4603 wback = true; 4604 4605 // if BitCount(registers) < 1 then UNPREDICTABLE; 4606 if (BitCount(registers) < 1) 4607 return false; 4608 4609 break; 4610 4611 case eEncodingT2: 4612 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 4613 n = Bits32(opcode, 19, 16); 4614 registers = Bits32(opcode, 15, 0); 4615 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 4616 wback = BitIsSet(opcode, 21); 4617 4618 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 4619 if ((n == 15) || (BitCount(registers) < 2)) 4620 return false; 4621 4622 // if wback && registers<n> == '1' then UNPREDICTABLE; 4623 if (wback && BitIsSet(registers, n)) 4624 return false; 4625 4626 break; 4627 4628 case eEncodingA1: 4629 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4630 n = Bits32(opcode, 19, 16); 4631 registers = Bits32(opcode, 15, 0); 4632 wback = BitIsSet(opcode, 21); 4633 4634 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4635 if ((n == 15) || (BitCount(registers) < 1)) 4636 return false; 4637 4638 break; 4639 4640 default: 4641 return false; 4642 } 4643 4644 // address = R[n]; 4645 int32_t offset = 0; 4646 const addr_t address = 4647 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4648 if (!success) 4649 return false; 4650 4651 EmulateInstruction::Context context; 4652 context.type = EmulateInstruction::eContextRegisterStore; 4653 std::optional<RegisterInfo> base_reg = 4654 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4655 4656 // for i = 0 to 14 4657 uint32_t lowest_set_bit = 14; 4658 for (uint32_t i = 0; i < 14; ++i) { 4659 // if registers<i> == '1' then 4660 if (BitIsSet(registers, i)) { 4661 if (i < lowest_set_bit) 4662 lowest_set_bit = i; 4663 // if i == n && wback && i != LowestSetBit(registers) then 4664 if ((i == n) && wback && (i != lowest_set_bit)) 4665 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings 4666 // T1 and A1 4667 WriteBits32UnknownToMemory(address + offset); 4668 else { 4669 // MemA[address,4] = R[i]; 4670 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, 4671 0, &success); 4672 if (!success) 4673 return false; 4674 4675 std::optional<RegisterInfo> data_reg = 4676 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); 4677 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset); 4678 if (!MemAWrite(context, address + offset, data, addr_byte_size)) 4679 return false; 4680 } 4681 4682 // address = address + 4; 4683 offset += addr_byte_size; 4684 } 4685 } 4686 4687 // if registers<15> == '1' then // Only possible for encoding A1 4688 // MemA[address,4] = PCStoreValue(); 4689 if (BitIsSet(registers, 15)) { 4690 std::optional<RegisterInfo> pc_reg = 4691 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 4692 context.SetRegisterPlusOffset(*pc_reg, 8); 4693 const uint32_t pc = ReadCoreReg(PC_REG, &success); 4694 if (!success) 4695 return false; 4696 4697 if (!MemAWrite(context, address + offset, pc, addr_byte_size)) 4698 return false; 4699 } 4700 4701 // if wback then R[n] = R[n] + 4*BitCount(registers); 4702 if (wback) { 4703 offset = addr_byte_size * BitCount(registers); 4704 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4705 context.SetImmediateSigned(offset); 4706 addr_t data = address + offset; 4707 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4708 data)) 4709 return false; 4710 } 4711 } 4712 return true; 4713 } 4714 4715 // STMDA (Store Multiple Decrement After) stores multiple registers to 4716 // consecutive memory locations using an address from a base register. The 4717 // consecutive memory locations end at this address, and the address just below 4718 // the lowest of those locations can optionally be written back to the base 4719 // register. 4720 bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode, 4721 const ARMEncoding encoding) { 4722 #if 0 4723 if ConditionPassed() then 4724 EncodingSpecificOperations(); 4725 address = R[n] - 4*BitCount(registers) + 4; 4726 4727 for i = 0 to 14 4728 if registers<i> == '1' then 4729 if i == n && wback && i != LowestSetBit(registers) then 4730 MemA[address,4] = bits(32) UNKNOWN; 4731 else 4732 MemA[address,4] = R[i]; 4733 address = address + 4; 4734 4735 if registers<15> == '1' then 4736 MemA[address,4] = PCStoreValue(); 4737 4738 if wback then R[n] = R[n] - 4*BitCount(registers); 4739 #endif 4740 4741 bool success = false; 4742 4743 if (ConditionPassed(opcode)) { 4744 uint32_t n; 4745 uint32_t registers = 0; 4746 bool wback; 4747 const uint32_t addr_byte_size = GetAddressByteSize(); 4748 4749 // EncodingSpecificOperations(); 4750 switch (encoding) { 4751 case eEncodingA1: 4752 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4753 n = Bits32(opcode, 19, 16); 4754 registers = Bits32(opcode, 15, 0); 4755 wback = BitIsSet(opcode, 21); 4756 4757 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4758 if ((n == 15) || (BitCount(registers) < 1)) 4759 return false; 4760 break; 4761 default: 4762 return false; 4763 } 4764 4765 // address = R[n] - 4*BitCount(registers) + 4; 4766 int32_t offset = 0; 4767 addr_t Rn = ReadCoreReg(n, &success); 4768 if (!success) 4769 return false; 4770 4771 addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4; 4772 4773 EmulateInstruction::Context context; 4774 context.type = EmulateInstruction::eContextRegisterStore; 4775 std::optional<RegisterInfo> base_reg = 4776 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4777 4778 // for i = 0 to 14 4779 uint32_t lowest_bit_set = 14; 4780 for (uint32_t i = 0; i < 14; ++i) { 4781 // if registers<i> == '1' then 4782 if (BitIsSet(registers, i)) { 4783 if (i < lowest_bit_set) 4784 lowest_bit_set = i; 4785 // if i == n && wback && i != LowestSetBit(registers) then 4786 if ((i == n) && wback && (i != lowest_bit_set)) 4787 // MemA[address,4] = bits(32) UNKNOWN; 4788 WriteBits32UnknownToMemory(address + offset); 4789 else { 4790 // MemA[address,4] = R[i]; 4791 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, 4792 0, &success); 4793 if (!success) 4794 return false; 4795 4796 std::optional<RegisterInfo> data_reg = 4797 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); 4798 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 4799 Rn - (address + offset)); 4800 if (!MemAWrite(context, address + offset, data, addr_byte_size)) 4801 return false; 4802 } 4803 4804 // address = address + 4; 4805 offset += addr_byte_size; 4806 } 4807 } 4808 4809 // if registers<15> == '1' then 4810 // MemA[address,4] = PCStoreValue(); 4811 if (BitIsSet(registers, 15)) { 4812 std::optional<RegisterInfo> pc_reg = 4813 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 4814 context.SetRegisterPlusOffset(*pc_reg, 8); 4815 const uint32_t pc = ReadCoreReg(PC_REG, &success); 4816 if (!success) 4817 return false; 4818 4819 if (!MemAWrite(context, address + offset, pc, addr_byte_size)) 4820 return false; 4821 } 4822 4823 // if wback then R[n] = R[n] - 4*BitCount(registers); 4824 if (wback) { 4825 offset = (addr_byte_size * BitCount(registers)) * -1; 4826 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4827 context.SetImmediateSigned(offset); 4828 addr_t data = Rn + offset; 4829 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4830 data)) 4831 return false; 4832 } 4833 } 4834 return true; 4835 } 4836 4837 // STMDB (Store Multiple Decrement Before) stores multiple registers to 4838 // consecutive memory locations using an address from a base register. The 4839 // consecutive memory locations end just below this address, and the address of 4840 // the first of those locations can optionally be written back to the base 4841 // register. 4842 bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode, 4843 const ARMEncoding encoding) { 4844 #if 0 4845 if ConditionPassed() then 4846 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4847 address = R[n] - 4*BitCount(registers); 4848 4849 for i = 0 to 14 4850 if registers<i> == '1' then 4851 if i == n && wback && i != LowestSetBit(registers) then 4852 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4853 else 4854 MemA[address,4] = R[i]; 4855 address = address + 4; 4856 4857 if registers<15> == '1' then // Only possible for encoding A1 4858 MemA[address,4] = PCStoreValue(); 4859 4860 if wback then R[n] = R[n] - 4*BitCount(registers); 4861 #endif 4862 4863 bool success = false; 4864 4865 if (ConditionPassed(opcode)) { 4866 uint32_t n; 4867 uint32_t registers = 0; 4868 bool wback; 4869 const uint32_t addr_byte_size = GetAddressByteSize(); 4870 4871 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4872 switch (encoding) { 4873 case eEncodingT1: 4874 // if W == '1' && Rn == '1101' then SEE PUSH; 4875 if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) { 4876 // See PUSH 4877 } 4878 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 4879 n = Bits32(opcode, 19, 16); 4880 registers = Bits32(opcode, 15, 0); 4881 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 4882 wback = BitIsSet(opcode, 21); 4883 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 4884 if ((n == 15) || BitCount(registers) < 2) 4885 return false; 4886 // if wback && registers<n> == '1' then UNPREDICTABLE; 4887 if (wback && BitIsSet(registers, n)) 4888 return false; 4889 break; 4890 4891 case eEncodingA1: 4892 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE 4893 // PUSH; 4894 if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) && 4895 BitCount(Bits32(opcode, 15, 0)) >= 2) { 4896 // See Push 4897 } 4898 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4899 n = Bits32(opcode, 19, 16); 4900 registers = Bits32(opcode, 15, 0); 4901 wback = BitIsSet(opcode, 21); 4902 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4903 if ((n == 15) || BitCount(registers) < 1) 4904 return false; 4905 break; 4906 4907 default: 4908 return false; 4909 } 4910 4911 // address = R[n] - 4*BitCount(registers); 4912 4913 int32_t offset = 0; 4914 addr_t Rn = 4915 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4916 if (!success) 4917 return false; 4918 4919 addr_t address = Rn - (addr_byte_size * BitCount(registers)); 4920 4921 EmulateInstruction::Context context; 4922 context.type = EmulateInstruction::eContextRegisterStore; 4923 std::optional<RegisterInfo> base_reg = 4924 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4925 4926 // for i = 0 to 14 4927 uint32_t lowest_set_bit = 14; 4928 for (uint32_t i = 0; i < 14; ++i) { 4929 // if registers<i> == '1' then 4930 if (BitIsSet(registers, i)) { 4931 if (i < lowest_set_bit) 4932 lowest_set_bit = i; 4933 // if i == n && wback && i != LowestSetBit(registers) then 4934 if ((i == n) && wback && (i != lowest_set_bit)) 4935 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding 4936 // A1 4937 WriteBits32UnknownToMemory(address + offset); 4938 else { 4939 // MemA[address,4] = R[i]; 4940 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, 4941 0, &success); 4942 if (!success) 4943 return false; 4944 4945 std::optional<RegisterInfo> data_reg = 4946 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); 4947 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 4948 Rn - (address + offset)); 4949 if (!MemAWrite(context, address + offset, data, addr_byte_size)) 4950 return false; 4951 } 4952 4953 // address = address + 4; 4954 offset += addr_byte_size; 4955 } 4956 } 4957 4958 // if registers<15> == '1' then // Only possible for encoding A1 4959 // MemA[address,4] = PCStoreValue(); 4960 if (BitIsSet(registers, 15)) { 4961 std::optional<RegisterInfo> pc_reg = 4962 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 4963 context.SetRegisterPlusOffset(*pc_reg, 8); 4964 const uint32_t pc = ReadCoreReg(PC_REG, &success); 4965 if (!success) 4966 return false; 4967 4968 if (!MemAWrite(context, address + offset, pc, addr_byte_size)) 4969 return false; 4970 } 4971 4972 // if wback then R[n] = R[n] - 4*BitCount(registers); 4973 if (wback) { 4974 offset = (addr_byte_size * BitCount(registers)) * -1; 4975 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4976 context.SetImmediateSigned(offset); 4977 addr_t data = Rn + offset; 4978 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4979 data)) 4980 return false; 4981 } 4982 } 4983 return true; 4984 } 4985 4986 // STMIB (Store Multiple Increment Before) stores multiple registers to 4987 // consecutive memory locations using an address from a base register. The 4988 // consecutive memory locations start just above this address, and the address 4989 // of the last of those locations can optionally be written back to the base 4990 // register. 4991 bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode, 4992 const ARMEncoding encoding) { 4993 #if 0 4994 if ConditionPassed() then 4995 EncodingSpecificOperations(); 4996 address = R[n] + 4; 4997 4998 for i = 0 to 14 4999 if registers<i> == '1' then 5000 if i == n && wback && i != LowestSetBit(registers) then 5001 MemA[address,4] = bits(32) UNKNOWN; 5002 else 5003 MemA[address,4] = R[i]; 5004 address = address + 4; 5005 5006 if registers<15> == '1' then 5007 MemA[address,4] = PCStoreValue(); 5008 5009 if wback then R[n] = R[n] + 4*BitCount(registers); 5010 #endif 5011 5012 bool success = false; 5013 5014 if (ConditionPassed(opcode)) { 5015 uint32_t n; 5016 uint32_t registers = 0; 5017 bool wback; 5018 const uint32_t addr_byte_size = GetAddressByteSize(); 5019 5020 // EncodingSpecificOperations(); 5021 switch (encoding) { 5022 case eEncodingA1: 5023 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 5024 n = Bits32(opcode, 19, 16); 5025 registers = Bits32(opcode, 15, 0); 5026 wback = BitIsSet(opcode, 21); 5027 5028 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 5029 if ((n == 15) && (BitCount(registers) < 1)) 5030 return false; 5031 break; 5032 default: 5033 return false; 5034 } 5035 // address = R[n] + 4; 5036 5037 int32_t offset = 0; 5038 addr_t Rn = ReadCoreReg(n, &success); 5039 if (!success) 5040 return false; 5041 5042 addr_t address = Rn + addr_byte_size; 5043 5044 EmulateInstruction::Context context; 5045 context.type = EmulateInstruction::eContextRegisterStore; 5046 std::optional<RegisterInfo> base_reg = 5047 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 5048 5049 uint32_t lowest_set_bit = 14; 5050 // for i = 0 to 14 5051 for (uint32_t i = 0; i < 14; ++i) { 5052 // if registers<i> == '1' then 5053 if (BitIsSet(registers, i)) { 5054 if (i < lowest_set_bit) 5055 lowest_set_bit = i; 5056 // if i == n && wback && i != LowestSetBit(registers) then 5057 if ((i == n) && wback && (i != lowest_set_bit)) 5058 // MemA[address,4] = bits(32) UNKNOWN; 5059 WriteBits32UnknownToMemory(address + offset); 5060 // else 5061 else { 5062 // MemA[address,4] = R[i]; 5063 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, 5064 0, &success); 5065 if (!success) 5066 return false; 5067 5068 std::optional<RegisterInfo> data_reg = 5069 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); 5070 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 5071 offset + addr_byte_size); 5072 if (!MemAWrite(context, address + offset, data, addr_byte_size)) 5073 return false; 5074 } 5075 5076 // address = address + 4; 5077 offset += addr_byte_size; 5078 } 5079 } 5080 5081 // if registers<15> == '1' then 5082 // MemA[address,4] = PCStoreValue(); 5083 if (BitIsSet(registers, 15)) { 5084 std::optional<RegisterInfo> pc_reg = 5085 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 5086 context.SetRegisterPlusOffset(*pc_reg, 8); 5087 const uint32_t pc = ReadCoreReg(PC_REG, &success); 5088 if (!success) 5089 return false; 5090 5091 if (!MemAWrite(context, address + offset, pc, addr_byte_size)) 5092 return false; 5093 } 5094 5095 // if wback then R[n] = R[n] + 4*BitCount(registers); 5096 if (wback) { 5097 offset = addr_byte_size * BitCount(registers); 5098 context.type = EmulateInstruction::eContextAdjustBaseRegister; 5099 context.SetImmediateSigned(offset); 5100 addr_t data = Rn + offset; 5101 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 5102 data)) 5103 return false; 5104 } 5105 } 5106 return true; 5107 } 5108 5109 // STR (store immediate) calculates an address from a base register value and an 5110 // immediate offset, and stores a word 5111 // from a register to memory. It can use offset, post-indexed, or pre-indexed 5112 // addressing. 5113 bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode, 5114 const ARMEncoding encoding) { 5115 #if 0 5116 if ConditionPassed() then 5117 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5118 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5119 address = if index then offset_addr else R[n]; 5120 if UnalignedSupport() || address<1:0> == '00' then 5121 MemU[address,4] = R[t]; 5122 else // Can only occur before ARMv7 5123 MemU[address,4] = bits(32) UNKNOWN; 5124 if wback then R[n] = offset_addr; 5125 #endif 5126 5127 bool success = false; 5128 5129 if (ConditionPassed(opcode)) { 5130 const uint32_t addr_byte_size = GetAddressByteSize(); 5131 5132 uint32_t t; 5133 uint32_t n; 5134 uint32_t imm32; 5135 bool index; 5136 bool add; 5137 bool wback; 5138 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 5139 switch (encoding) { 5140 case eEncodingT1: 5141 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32); 5142 t = Bits32(opcode, 2, 0); 5143 n = Bits32(opcode, 5, 3); 5144 imm32 = Bits32(opcode, 10, 6) << 2; 5145 5146 // index = TRUE; add = TRUE; wback = FALSE; 5147 index = true; 5148 add = false; 5149 wback = false; 5150 break; 5151 5152 case eEncodingT2: 5153 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 5154 t = Bits32(opcode, 10, 8); 5155 n = 13; 5156 imm32 = Bits32(opcode, 7, 0) << 2; 5157 5158 // index = TRUE; add = TRUE; wback = FALSE; 5159 index = true; 5160 add = true; 5161 wback = false; 5162 break; 5163 5164 case eEncodingT3: 5165 // if Rn == '1111' then UNDEFINED; 5166 if (Bits32(opcode, 19, 16) == 15) 5167 return false; 5168 5169 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5170 t = Bits32(opcode, 15, 12); 5171 n = Bits32(opcode, 19, 16); 5172 imm32 = Bits32(opcode, 11, 0); 5173 5174 // index = TRUE; add = TRUE; wback = FALSE; 5175 index = true; 5176 add = true; 5177 wback = false; 5178 5179 // if t == 15 then UNPREDICTABLE; 5180 if (t == 15) 5181 return false; 5182 break; 5183 5184 case eEncodingT4: 5185 // if P == '1' && U == '1' && W == '0' then SEE STRT; 5186 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == 5187 // '00000100' then SEE PUSH; 5188 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 5189 if ((Bits32(opcode, 19, 16) == 15) || 5190 (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))) 5191 return false; 5192 5193 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 5194 t = Bits32(opcode, 15, 12); 5195 n = Bits32(opcode, 19, 16); 5196 imm32 = Bits32(opcode, 7, 0); 5197 5198 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 5199 index = BitIsSet(opcode, 10); 5200 add = BitIsSet(opcode, 9); 5201 wback = BitIsSet(opcode, 8); 5202 5203 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 5204 if ((t == 15) || (wback && (n == t))) 5205 return false; 5206 break; 5207 5208 default: 5209 return false; 5210 } 5211 5212 addr_t offset_addr; 5213 addr_t address; 5214 5215 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5216 uint32_t base_address = ReadCoreReg(n, &success); 5217 if (!success) 5218 return false; 5219 5220 if (add) 5221 offset_addr = base_address + imm32; 5222 else 5223 offset_addr = base_address - imm32; 5224 5225 // address = if index then offset_addr else R[n]; 5226 if (index) 5227 address = offset_addr; 5228 else 5229 address = base_address; 5230 5231 EmulateInstruction::Context context; 5232 if (n == 13) 5233 context.type = eContextPushRegisterOnStack; 5234 else 5235 context.type = eContextRegisterStore; 5236 5237 std::optional<RegisterInfo> base_reg = 5238 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 5239 5240 // if UnalignedSupport() || address<1:0> == '00' then 5241 if (UnalignedSupport() || 5242 (BitIsClear(address, 1) && BitIsClear(address, 0))) { 5243 // MemU[address,4] = R[t]; 5244 uint32_t data = 5245 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 5246 if (!success) 5247 return false; 5248 5249 std::optional<RegisterInfo> data_reg = 5250 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 5251 int32_t offset = address - base_address; 5252 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset); 5253 if (!MemUWrite(context, address, data, addr_byte_size)) 5254 return false; 5255 } else { 5256 // MemU[address,4] = bits(32) UNKNOWN; 5257 WriteBits32UnknownToMemory(address); 5258 } 5259 5260 // if wback then R[n] = offset_addr; 5261 if (wback) { 5262 if (n == 13) 5263 context.type = eContextAdjustStackPointer; 5264 else 5265 context.type = eContextAdjustBaseRegister; 5266 context.SetAddress(offset_addr); 5267 5268 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 5269 offset_addr)) 5270 return false; 5271 } 5272 } 5273 return true; 5274 } 5275 5276 // STR (Store Register) calculates an address from a base register value and an 5277 // offset register value, stores a 5278 // word from a register to memory. The offset register value can optionally 5279 // be shifted. 5280 bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode, 5281 const ARMEncoding encoding) { 5282 #if 0 5283 if ConditionPassed() then 5284 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5285 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5286 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5287 address = if index then offset_addr else R[n]; 5288 if t == 15 then // Only possible for encoding A1 5289 data = PCStoreValue(); 5290 else 5291 data = R[t]; 5292 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 5293 MemU[address,4] = data; 5294 else // Can only occur before ARMv7 5295 MemU[address,4] = bits(32) UNKNOWN; 5296 if wback then R[n] = offset_addr; 5297 #endif 5298 5299 bool success = false; 5300 5301 if (ConditionPassed(opcode)) { 5302 const uint32_t addr_byte_size = GetAddressByteSize(); 5303 5304 uint32_t t; 5305 uint32_t n; 5306 uint32_t m; 5307 ARM_ShifterType shift_t; 5308 uint32_t shift_n; 5309 bool index; 5310 bool add; 5311 bool wback; 5312 5313 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 5314 switch (encoding) { 5315 case eEncodingT1: 5316 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation 5317 // in ThumbEE"; 5318 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5319 t = Bits32(opcode, 2, 0); 5320 n = Bits32(opcode, 5, 3); 5321 m = Bits32(opcode, 8, 6); 5322 5323 // index = TRUE; add = TRUE; wback = FALSE; 5324 index = true; 5325 add = true; 5326 wback = false; 5327 5328 // (shift_t, shift_n) = (SRType_LSL, 0); 5329 shift_t = SRType_LSL; 5330 shift_n = 0; 5331 break; 5332 5333 case eEncodingT2: 5334 // if Rn == '1111' then UNDEFINED; 5335 if (Bits32(opcode, 19, 16) == 15) 5336 return false; 5337 5338 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5339 t = Bits32(opcode, 15, 12); 5340 n = Bits32(opcode, 19, 16); 5341 m = Bits32(opcode, 3, 0); 5342 5343 // index = TRUE; add = TRUE; wback = FALSE; 5344 index = true; 5345 add = true; 5346 wback = false; 5347 5348 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5349 shift_t = SRType_LSL; 5350 shift_n = Bits32(opcode, 5, 4); 5351 5352 // if t == 15 || BadReg(m) then UNPREDICTABLE; 5353 if ((t == 15) || (BadReg(m))) 5354 return false; 5355 break; 5356 5357 case eEncodingA1: { 5358 // if P == '0' && W == '1' then SEE STRT; 5359 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5360 t = Bits32(opcode, 15, 12); 5361 n = Bits32(opcode, 19, 16); 5362 m = Bits32(opcode, 3, 0); 5363 5364 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 5365 // (W == '1'); 5366 index = BitIsSet(opcode, 24); 5367 add = BitIsSet(opcode, 23); 5368 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 5369 5370 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 5371 uint32_t typ = Bits32(opcode, 6, 5); 5372 uint32_t imm5 = Bits32(opcode, 11, 7); 5373 shift_n = DecodeImmShift(typ, imm5, shift_t); 5374 5375 // if m == 15 then UNPREDICTABLE; 5376 if (m == 15) 5377 return false; 5378 5379 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5380 if (wback && ((n == 15) || (n == t))) 5381 return false; 5382 5383 break; 5384 } 5385 default: 5386 return false; 5387 } 5388 5389 addr_t offset_addr; 5390 addr_t address; 5391 int32_t offset = 0; 5392 5393 addr_t base_address = 5394 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5395 if (!success) 5396 return false; 5397 5398 uint32_t Rm_data = 5399 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 5400 if (!success) 5401 return false; 5402 5403 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 5404 offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success); 5405 if (!success) 5406 return false; 5407 5408 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5409 if (add) 5410 offset_addr = base_address + offset; 5411 else 5412 offset_addr = base_address - offset; 5413 5414 // address = if index then offset_addr else R[n]; 5415 if (index) 5416 address = offset_addr; 5417 else 5418 address = base_address; 5419 5420 uint32_t data; 5421 // if t == 15 then // Only possible for encoding A1 5422 if (t == 15) 5423 // data = PCStoreValue(); 5424 data = ReadCoreReg(PC_REG, &success); 5425 else 5426 // data = R[t]; 5427 data = 5428 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 5429 5430 if (!success) 5431 return false; 5432 5433 EmulateInstruction::Context context; 5434 context.type = eContextRegisterStore; 5435 5436 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == 5437 // InstrSet_ARM then 5438 if (UnalignedSupport() || 5439 (BitIsClear(address, 1) && BitIsClear(address, 0)) || 5440 CurrentInstrSet() == eModeARM) { 5441 // MemU[address,4] = data; 5442 5443 std::optional<RegisterInfo> base_reg = 5444 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 5445 std::optional<RegisterInfo> data_reg = 5446 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 5447 5448 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 5449 address - base_address); 5450 if (!MemUWrite(context, address, data, addr_byte_size)) 5451 return false; 5452 5453 } else 5454 // MemU[address,4] = bits(32) UNKNOWN; 5455 WriteBits32UnknownToMemory(address); 5456 5457 // if wback then R[n] = offset_addr; 5458 if (wback) { 5459 context.type = eContextRegisterLoad; 5460 context.SetAddress(offset_addr); 5461 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 5462 offset_addr)) 5463 return false; 5464 } 5465 } 5466 return true; 5467 } 5468 5469 bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode, 5470 const ARMEncoding encoding) { 5471 #if 0 5472 if ConditionPassed() then 5473 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5474 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5475 address = if index then offset_addr else R[n]; 5476 MemU[address,1] = R[t]<7:0>; 5477 if wback then R[n] = offset_addr; 5478 #endif 5479 5480 bool success = false; 5481 5482 if (ConditionPassed(opcode)) { 5483 uint32_t t; 5484 uint32_t n; 5485 uint32_t imm32; 5486 bool index; 5487 bool add; 5488 bool wback; 5489 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5490 switch (encoding) { 5491 case eEncodingT1: 5492 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 5493 t = Bits32(opcode, 2, 0); 5494 n = Bits32(opcode, 5, 3); 5495 imm32 = Bits32(opcode, 10, 6); 5496 5497 // index = TRUE; add = TRUE; wback = FALSE; 5498 index = true; 5499 add = true; 5500 wback = false; 5501 break; 5502 5503 case eEncodingT2: 5504 // if Rn == '1111' then UNDEFINED; 5505 if (Bits32(opcode, 19, 16) == 15) 5506 return false; 5507 5508 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5509 t = Bits32(opcode, 15, 12); 5510 n = Bits32(opcode, 19, 16); 5511 imm32 = Bits32(opcode, 11, 0); 5512 5513 // index = TRUE; add = TRUE; wback = FALSE; 5514 index = true; 5515 add = true; 5516 wback = false; 5517 5518 // if BadReg(t) then UNPREDICTABLE; 5519 if (BadReg(t)) 5520 return false; 5521 break; 5522 5523 case eEncodingT3: 5524 // if P == '1' && U == '1' && W == '0' then SEE STRBT; 5525 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 5526 if (Bits32(opcode, 19, 16) == 15) 5527 return false; 5528 5529 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 5530 t = Bits32(opcode, 15, 12); 5531 n = Bits32(opcode, 19, 16); 5532 imm32 = Bits32(opcode, 7, 0); 5533 5534 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 5535 index = BitIsSet(opcode, 10); 5536 add = BitIsSet(opcode, 9); 5537 wback = BitIsSet(opcode, 8); 5538 5539 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE 5540 if ((BadReg(t)) || (wback && (n == t))) 5541 return false; 5542 break; 5543 5544 default: 5545 return false; 5546 } 5547 5548 addr_t offset_addr; 5549 addr_t address; 5550 addr_t base_address = 5551 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5552 if (!success) 5553 return false; 5554 5555 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5556 if (add) 5557 offset_addr = base_address + imm32; 5558 else 5559 offset_addr = base_address - imm32; 5560 5561 // address = if index then offset_addr else R[n]; 5562 if (index) 5563 address = offset_addr; 5564 else 5565 address = base_address; 5566 5567 // MemU[address,1] = R[t]<7:0> 5568 std::optional<RegisterInfo> base_reg = 5569 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 5570 std::optional<RegisterInfo> data_reg = 5571 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 5572 5573 EmulateInstruction::Context context; 5574 context.type = eContextRegisterStore; 5575 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 5576 address - base_address); 5577 5578 uint32_t data = 5579 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 5580 if (!success) 5581 return false; 5582 5583 data = Bits32(data, 7, 0); 5584 5585 if (!MemUWrite(context, address, data, 1)) 5586 return false; 5587 5588 // if wback then R[n] = offset_addr; 5589 if (wback) { 5590 context.type = eContextRegisterLoad; 5591 context.SetAddress(offset_addr); 5592 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 5593 offset_addr)) 5594 return false; 5595 } 5596 } 5597 5598 return true; 5599 } 5600 5601 // STRH (register) calculates an address from a base register value and an 5602 // offset register value, and stores a 5603 // halfword from a register to memory. The offset register value can be 5604 // shifted left by 0, 1, 2, or 3 bits. 5605 bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode, 5606 const ARMEncoding encoding) { 5607 #if 0 5608 if ConditionPassed() then 5609 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5610 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5611 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5612 address = if index then offset_addr else R[n]; 5613 if UnalignedSupport() || address<0> == '0' then 5614 MemU[address,2] = R[t]<15:0>; 5615 else // Can only occur before ARMv7 5616 MemU[address,2] = bits(16) UNKNOWN; 5617 if wback then R[n] = offset_addr; 5618 #endif 5619 5620 bool success = false; 5621 5622 if (ConditionPassed(opcode)) { 5623 uint32_t t; 5624 uint32_t n; 5625 uint32_t m; 5626 bool index; 5627 bool add; 5628 bool wback; 5629 ARM_ShifterType shift_t; 5630 uint32_t shift_n; 5631 5632 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5633 switch (encoding) { 5634 case eEncodingT1: 5635 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation 5636 // in ThumbEE"; 5637 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5638 t = Bits32(opcode, 2, 0); 5639 n = Bits32(opcode, 5, 3); 5640 m = Bits32(opcode, 8, 6); 5641 5642 // index = TRUE; add = TRUE; wback = FALSE; 5643 index = true; 5644 add = true; 5645 wback = false; 5646 5647 // (shift_t, shift_n) = (SRType_LSL, 0); 5648 shift_t = SRType_LSL; 5649 shift_n = 0; 5650 5651 break; 5652 5653 case eEncodingT2: 5654 // if Rn == '1111' then UNDEFINED; 5655 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5656 t = Bits32(opcode, 15, 12); 5657 n = Bits32(opcode, 19, 16); 5658 m = Bits32(opcode, 3, 0); 5659 if (n == 15) 5660 return false; 5661 5662 // index = TRUE; add = TRUE; wback = FALSE; 5663 index = true; 5664 add = true; 5665 wback = false; 5666 5667 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5668 shift_t = SRType_LSL; 5669 shift_n = Bits32(opcode, 5, 4); 5670 5671 // if BadReg(t) || BadReg(m) then UNPREDICTABLE; 5672 if (BadReg(t) || BadReg(m)) 5673 return false; 5674 5675 break; 5676 5677 case eEncodingA1: 5678 // if P == '0' && W == '1' then SEE STRHT; 5679 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5680 t = Bits32(opcode, 15, 12); 5681 n = Bits32(opcode, 19, 16); 5682 m = Bits32(opcode, 3, 0); 5683 5684 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 5685 // (W == '1'); 5686 index = BitIsSet(opcode, 24); 5687 add = BitIsSet(opcode, 23); 5688 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 5689 5690 // (shift_t, shift_n) = (SRType_LSL, 0); 5691 shift_t = SRType_LSL; 5692 shift_n = 0; 5693 5694 // if t == 15 || m == 15 then UNPREDICTABLE; 5695 if ((t == 15) || (m == 15)) 5696 return false; 5697 5698 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5699 if (wback && ((n == 15) || (n == t))) 5700 return false; 5701 5702 break; 5703 5704 default: 5705 return false; 5706 } 5707 5708 uint32_t Rm = ReadCoreReg(m, &success); 5709 if (!success) 5710 return false; 5711 5712 uint32_t Rn = ReadCoreReg(n, &success); 5713 if (!success) 5714 return false; 5715 5716 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 5717 uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); 5718 if (!success) 5719 return false; 5720 5721 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5722 addr_t offset_addr; 5723 if (add) 5724 offset_addr = Rn + offset; 5725 else 5726 offset_addr = Rn - offset; 5727 5728 // address = if index then offset_addr else R[n]; 5729 addr_t address; 5730 if (index) 5731 address = offset_addr; 5732 else 5733 address = Rn; 5734 5735 EmulateInstruction::Context context; 5736 context.type = eContextRegisterStore; 5737 5738 // if UnalignedSupport() || address<0> == '0' then 5739 if (UnalignedSupport() || BitIsClear(address, 0)) { 5740 // MemU[address,2] = R[t]<15:0>; 5741 uint32_t Rt = ReadCoreReg(t, &success); 5742 if (!success) 5743 return false; 5744 5745 EmulateInstruction::Context context; 5746 context.type = eContextRegisterStore; 5747 std::optional<RegisterInfo> base_reg = 5748 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 5749 std::optional<RegisterInfo> offset_reg = 5750 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 5751 std::optional<RegisterInfo> data_reg = 5752 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 5753 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg, 5754 *data_reg); 5755 5756 if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2)) 5757 return false; 5758 } else // Can only occur before ARMv7 5759 { 5760 // MemU[address,2] = bits(16) UNKNOWN; 5761 } 5762 5763 // if wback then R[n] = offset_addr; 5764 if (wback) { 5765 context.type = eContextAdjustBaseRegister; 5766 context.SetAddress(offset_addr); 5767 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 5768 offset_addr)) 5769 return false; 5770 } 5771 } 5772 5773 return true; 5774 } 5775 5776 // Add with Carry (immediate) adds an immediate value and the carry flag value 5777 // to a register value, and writes the result to the destination register. It 5778 // can optionally update the condition flags based on the result. 5779 bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode, 5780 const ARMEncoding encoding) { 5781 #if 0 5782 // ARM pseudo code... 5783 if ConditionPassed() then 5784 EncodingSpecificOperations(); 5785 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C); 5786 if d == 15 then // Can only occur for ARM encoding 5787 ALUWritePC(result); // setflags is always FALSE here 5788 else 5789 R[d] = result; 5790 if setflags then 5791 APSR.N = result<31>; 5792 APSR.Z = IsZeroBit(result); 5793 APSR.C = carry; 5794 APSR.V = overflow; 5795 #endif 5796 5797 bool success = false; 5798 5799 if (ConditionPassed(opcode)) { 5800 uint32_t Rd, Rn; 5801 uint32_t 5802 imm32; // the immediate value to be added to the value obtained from Rn 5803 bool setflags; 5804 switch (encoding) { 5805 case eEncodingT1: 5806 Rd = Bits32(opcode, 11, 8); 5807 Rn = Bits32(opcode, 19, 16); 5808 setflags = BitIsSet(opcode, 20); 5809 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 5810 if (BadReg(Rd) || BadReg(Rn)) 5811 return false; 5812 break; 5813 case eEncodingA1: 5814 Rd = Bits32(opcode, 15, 12); 5815 Rn = Bits32(opcode, 19, 16); 5816 setflags = BitIsSet(opcode, 20); 5817 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5818 5819 if (Rd == 15 && setflags) 5820 return EmulateSUBSPcLrEtc(opcode, encoding); 5821 break; 5822 default: 5823 return false; 5824 } 5825 5826 // Read the first operand. 5827 int32_t val1 = ReadCoreReg(Rn, &success); 5828 if (!success) 5829 return false; 5830 5831 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C); 5832 5833 EmulateInstruction::Context context; 5834 context.type = EmulateInstruction::eContextImmediate; 5835 context.SetNoArgs(); 5836 5837 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 5838 res.carry_out, res.overflow)) 5839 return false; 5840 } 5841 return true; 5842 } 5843 5844 // Add with Carry (register) adds a register value, the carry flag value, and 5845 // an optionally-shifted register value, and writes the result to the 5846 // destination register. It can optionally update the condition flags based on 5847 // the result. 5848 bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode, 5849 const ARMEncoding encoding) { 5850 #if 0 5851 // ARM pseudo code... 5852 if ConditionPassed() then 5853 EncodingSpecificOperations(); 5854 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 5855 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C); 5856 if d == 15 then // Can only occur for ARM encoding 5857 ALUWritePC(result); // setflags is always FALSE here 5858 else 5859 R[d] = result; 5860 if setflags then 5861 APSR.N = result<31>; 5862 APSR.Z = IsZeroBit(result); 5863 APSR.C = carry; 5864 APSR.V = overflow; 5865 #endif 5866 5867 bool success = false; 5868 5869 if (ConditionPassed(opcode)) { 5870 uint32_t Rd, Rn, Rm; 5871 ARM_ShifterType shift_t; 5872 uint32_t shift_n; // the shift applied to the value read from Rm 5873 bool setflags; 5874 switch (encoding) { 5875 case eEncodingT1: 5876 Rd = Rn = Bits32(opcode, 2, 0); 5877 Rm = Bits32(opcode, 5, 3); 5878 setflags = !InITBlock(); 5879 shift_t = SRType_LSL; 5880 shift_n = 0; 5881 break; 5882 case eEncodingT2: 5883 Rd = Bits32(opcode, 11, 8); 5884 Rn = Bits32(opcode, 19, 16); 5885 Rm = Bits32(opcode, 3, 0); 5886 setflags = BitIsSet(opcode, 20); 5887 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5888 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5889 return false; 5890 break; 5891 case eEncodingA1: 5892 Rd = Bits32(opcode, 15, 12); 5893 Rn = Bits32(opcode, 19, 16); 5894 Rm = Bits32(opcode, 3, 0); 5895 setflags = BitIsSet(opcode, 20); 5896 shift_n = DecodeImmShiftARM(opcode, shift_t); 5897 5898 if (Rd == 15 && setflags) 5899 return EmulateSUBSPcLrEtc(opcode, encoding); 5900 break; 5901 default: 5902 return false; 5903 } 5904 5905 // Read the first operand. 5906 int32_t val1 = ReadCoreReg(Rn, &success); 5907 if (!success) 5908 return false; 5909 5910 // Read the second operand. 5911 int32_t val2 = ReadCoreReg(Rm, &success); 5912 if (!success) 5913 return false; 5914 5915 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 5916 if (!success) 5917 return false; 5918 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C); 5919 5920 EmulateInstruction::Context context; 5921 context.type = EmulateInstruction::eContextImmediate; 5922 context.SetNoArgs(); 5923 5924 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 5925 res.carry_out, res.overflow)) 5926 return false; 5927 } 5928 return true; 5929 } 5930 5931 // This instruction adds an immediate value to the PC value to form a PC- 5932 // relative address, and writes the result to the destination register. 5933 bool EmulateInstructionARM::EmulateADR(const uint32_t opcode, 5934 const ARMEncoding encoding) { 5935 #if 0 5936 // ARM pseudo code... 5937 if ConditionPassed() then 5938 EncodingSpecificOperations(); 5939 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32); 5940 if d == 15 then // Can only occur for ARM encodings 5941 ALUWritePC(result); 5942 else 5943 R[d] = result; 5944 #endif 5945 5946 bool success = false; 5947 5948 if (ConditionPassed(opcode)) { 5949 uint32_t Rd; 5950 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC 5951 bool add; 5952 switch (encoding) { 5953 case eEncodingT1: 5954 Rd = Bits32(opcode, 10, 8); 5955 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32) 5956 add = true; 5957 break; 5958 case eEncodingT2: 5959 case eEncodingT3: 5960 Rd = Bits32(opcode, 11, 8); 5961 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 5962 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB 5963 if (BadReg(Rd)) 5964 return false; 5965 break; 5966 case eEncodingA1: 5967 case eEncodingA2: 5968 Rd = Bits32(opcode, 15, 12); 5969 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5970 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB 5971 break; 5972 default: 5973 return false; 5974 } 5975 5976 // Read the PC value. 5977 uint32_t pc = ReadCoreReg(PC_REG, &success); 5978 if (!success) 5979 return false; 5980 5981 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32); 5982 5983 EmulateInstruction::Context context; 5984 context.type = EmulateInstruction::eContextImmediate; 5985 context.SetNoArgs(); 5986 5987 if (!WriteCoreReg(context, result, Rd)) 5988 return false; 5989 } 5990 return true; 5991 } 5992 5993 // This instruction performs a bitwise AND of a register value and an immediate 5994 // value, and writes the result to the destination register. It can optionally 5995 // update the condition flags based on the result. 5996 bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode, 5997 const ARMEncoding encoding) { 5998 #if 0 5999 // ARM pseudo code... 6000 if ConditionPassed() then 6001 EncodingSpecificOperations(); 6002 result = R[n] AND imm32; 6003 if d == 15 then // Can only occur for ARM encoding 6004 ALUWritePC(result); // setflags is always FALSE here 6005 else 6006 R[d] = result; 6007 if setflags then 6008 APSR.N = result<31>; 6009 APSR.Z = IsZeroBit(result); 6010 APSR.C = carry; 6011 // APSR.V unchanged 6012 #endif 6013 6014 bool success = false; 6015 6016 if (ConditionPassed(opcode)) { 6017 uint32_t Rd, Rn; 6018 uint32_t 6019 imm32; // the immediate value to be ANDed to the value obtained from Rn 6020 bool setflags; 6021 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 6022 switch (encoding) { 6023 case eEncodingT1: 6024 Rd = Bits32(opcode, 11, 8); 6025 Rn = Bits32(opcode, 19, 16); 6026 setflags = BitIsSet(opcode, 20); 6027 imm32 = ThumbExpandImm_C( 6028 opcode, APSR_C, 6029 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 6030 // if Rd == '1111' && S == '1' then SEE TST (immediate); 6031 if (Rd == 15 && setflags) 6032 return EmulateTSTImm(opcode, eEncodingT1); 6033 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 6034 return false; 6035 break; 6036 case eEncodingA1: 6037 Rd = Bits32(opcode, 15, 12); 6038 Rn = Bits32(opcode, 19, 16); 6039 setflags = BitIsSet(opcode, 20); 6040 imm32 = 6041 ARMExpandImm_C(opcode, APSR_C, 6042 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 6043 6044 if (Rd == 15 && setflags) 6045 return EmulateSUBSPcLrEtc(opcode, encoding); 6046 break; 6047 default: 6048 return false; 6049 } 6050 6051 // Read the first operand. 6052 uint32_t val1 = ReadCoreReg(Rn, &success); 6053 if (!success) 6054 return false; 6055 6056 uint32_t result = val1 & imm32; 6057 6058 EmulateInstruction::Context context; 6059 context.type = EmulateInstruction::eContextImmediate; 6060 context.SetNoArgs(); 6061 6062 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 6063 return false; 6064 } 6065 return true; 6066 } 6067 6068 // This instruction performs a bitwise AND of a register value and an 6069 // optionally-shifted register value, and writes the result to the destination 6070 // register. It can optionally update the condition flags based on the result. 6071 bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode, 6072 const ARMEncoding encoding) { 6073 #if 0 6074 // ARM pseudo code... 6075 if ConditionPassed() then 6076 EncodingSpecificOperations(); 6077 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 6078 result = R[n] AND shifted; 6079 if d == 15 then // Can only occur for ARM encoding 6080 ALUWritePC(result); // setflags is always FALSE here 6081 else 6082 R[d] = result; 6083 if setflags then 6084 APSR.N = result<31>; 6085 APSR.Z = IsZeroBit(result); 6086 APSR.C = carry; 6087 // APSR.V unchanged 6088 #endif 6089 6090 bool success = false; 6091 6092 if (ConditionPassed(opcode)) { 6093 uint32_t Rd, Rn, Rm; 6094 ARM_ShifterType shift_t; 6095 uint32_t shift_n; // the shift applied to the value read from Rm 6096 bool setflags; 6097 uint32_t carry; 6098 switch (encoding) { 6099 case eEncodingT1: 6100 Rd = Rn = Bits32(opcode, 2, 0); 6101 Rm = Bits32(opcode, 5, 3); 6102 setflags = !InITBlock(); 6103 shift_t = SRType_LSL; 6104 shift_n = 0; 6105 break; 6106 case eEncodingT2: 6107 Rd = Bits32(opcode, 11, 8); 6108 Rn = Bits32(opcode, 19, 16); 6109 Rm = Bits32(opcode, 3, 0); 6110 setflags = BitIsSet(opcode, 20); 6111 shift_n = DecodeImmShiftThumb(opcode, shift_t); 6112 // if Rd == '1111' && S == '1' then SEE TST (register); 6113 if (Rd == 15 && setflags) 6114 return EmulateTSTReg(opcode, eEncodingT2); 6115 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 6116 return false; 6117 break; 6118 case eEncodingA1: 6119 Rd = Bits32(opcode, 15, 12); 6120 Rn = Bits32(opcode, 19, 16); 6121 Rm = Bits32(opcode, 3, 0); 6122 setflags = BitIsSet(opcode, 20); 6123 shift_n = DecodeImmShiftARM(opcode, shift_t); 6124 6125 if (Rd == 15 && setflags) 6126 return EmulateSUBSPcLrEtc(opcode, encoding); 6127 break; 6128 default: 6129 return false; 6130 } 6131 6132 // Read the first operand. 6133 uint32_t val1 = ReadCoreReg(Rn, &success); 6134 if (!success) 6135 return false; 6136 6137 // Read the second operand. 6138 uint32_t val2 = ReadCoreReg(Rm, &success); 6139 if (!success) 6140 return false; 6141 6142 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 6143 if (!success) 6144 return false; 6145 uint32_t result = val1 & shifted; 6146 6147 EmulateInstruction::Context context; 6148 context.type = EmulateInstruction::eContextImmediate; 6149 context.SetNoArgs(); 6150 6151 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 6152 return false; 6153 } 6154 return true; 6155 } 6156 6157 // Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and 6158 // the complement of an immediate value, and writes the result to the 6159 // destination register. It can optionally update the condition flags based on 6160 // the result. 6161 bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode, 6162 const ARMEncoding encoding) { 6163 #if 0 6164 // ARM pseudo code... 6165 if ConditionPassed() then 6166 EncodingSpecificOperations(); 6167 result = R[n] AND NOT(imm32); 6168 if d == 15 then // Can only occur for ARM encoding 6169 ALUWritePC(result); // setflags is always FALSE here 6170 else 6171 R[d] = result; 6172 if setflags then 6173 APSR.N = result<31>; 6174 APSR.Z = IsZeroBit(result); 6175 APSR.C = carry; 6176 // APSR.V unchanged 6177 #endif 6178 6179 bool success = false; 6180 6181 if (ConditionPassed(opcode)) { 6182 uint32_t Rd, Rn; 6183 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to 6184 // the value obtained from Rn 6185 bool setflags; 6186 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 6187 switch (encoding) { 6188 case eEncodingT1: 6189 Rd = Bits32(opcode, 11, 8); 6190 Rn = Bits32(opcode, 19, 16); 6191 setflags = BitIsSet(opcode, 20); 6192 imm32 = ThumbExpandImm_C( 6193 opcode, APSR_C, 6194 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 6195 if (BadReg(Rd) || BadReg(Rn)) 6196 return false; 6197 break; 6198 case eEncodingA1: 6199 Rd = Bits32(opcode, 15, 12); 6200 Rn = Bits32(opcode, 19, 16); 6201 setflags = BitIsSet(opcode, 20); 6202 imm32 = 6203 ARMExpandImm_C(opcode, APSR_C, 6204 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 6205 6206 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 6207 // instructions; 6208 if (Rd == 15 && setflags) 6209 return EmulateSUBSPcLrEtc(opcode, encoding); 6210 break; 6211 default: 6212 return false; 6213 } 6214 6215 // Read the first operand. 6216 uint32_t val1 = ReadCoreReg(Rn, &success); 6217 if (!success) 6218 return false; 6219 6220 uint32_t result = val1 & ~imm32; 6221 6222 EmulateInstruction::Context context; 6223 context.type = EmulateInstruction::eContextImmediate; 6224 context.SetNoArgs(); 6225 6226 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 6227 return false; 6228 } 6229 return true; 6230 } 6231 6232 // Bitwise Bit Clear (register) performs a bitwise AND of a register value and 6233 // the complement of an optionally-shifted register value, and writes the 6234 // result to the destination register. It can optionally update the condition 6235 // flags based on the result. 6236 bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode, 6237 const ARMEncoding encoding) { 6238 #if 0 6239 // ARM pseudo code... 6240 if ConditionPassed() then 6241 EncodingSpecificOperations(); 6242 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 6243 result = R[n] AND NOT(shifted); 6244 if d == 15 then // Can only occur for ARM encoding 6245 ALUWritePC(result); // setflags is always FALSE here 6246 else 6247 R[d] = result; 6248 if setflags then 6249 APSR.N = result<31>; 6250 APSR.Z = IsZeroBit(result); 6251 APSR.C = carry; 6252 // APSR.V unchanged 6253 #endif 6254 6255 bool success = false; 6256 6257 if (ConditionPassed(opcode)) { 6258 uint32_t Rd, Rn, Rm; 6259 ARM_ShifterType shift_t; 6260 uint32_t shift_n; // the shift applied to the value read from Rm 6261 bool setflags; 6262 uint32_t carry; 6263 switch (encoding) { 6264 case eEncodingT1: 6265 Rd = Rn = Bits32(opcode, 2, 0); 6266 Rm = Bits32(opcode, 5, 3); 6267 setflags = !InITBlock(); 6268 shift_t = SRType_LSL; 6269 shift_n = 0; 6270 break; 6271 case eEncodingT2: 6272 Rd = Bits32(opcode, 11, 8); 6273 Rn = Bits32(opcode, 19, 16); 6274 Rm = Bits32(opcode, 3, 0); 6275 setflags = BitIsSet(opcode, 20); 6276 shift_n = DecodeImmShiftThumb(opcode, shift_t); 6277 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 6278 return false; 6279 break; 6280 case eEncodingA1: 6281 Rd = Bits32(opcode, 15, 12); 6282 Rn = Bits32(opcode, 19, 16); 6283 Rm = Bits32(opcode, 3, 0); 6284 setflags = BitIsSet(opcode, 20); 6285 shift_n = DecodeImmShiftARM(opcode, shift_t); 6286 6287 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 6288 // instructions; 6289 if (Rd == 15 && setflags) 6290 return EmulateSUBSPcLrEtc(opcode, encoding); 6291 break; 6292 default: 6293 return false; 6294 } 6295 6296 // Read the first operand. 6297 uint32_t val1 = ReadCoreReg(Rn, &success); 6298 if (!success) 6299 return false; 6300 6301 // Read the second operand. 6302 uint32_t val2 = ReadCoreReg(Rm, &success); 6303 if (!success) 6304 return false; 6305 6306 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 6307 if (!success) 6308 return false; 6309 uint32_t result = val1 & ~shifted; 6310 6311 EmulateInstruction::Context context; 6312 context.type = EmulateInstruction::eContextImmediate; 6313 context.SetNoArgs(); 6314 6315 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 6316 return false; 6317 } 6318 return true; 6319 } 6320 6321 // LDR (immediate, ARM) calculates an address from a base register value and an 6322 // immediate offset, loads a word 6323 // from memory, and writes it to a register. It can use offset, post-indexed, 6324 // or pre-indexed addressing. 6325 bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode, 6326 const ARMEncoding encoding) { 6327 #if 0 6328 if ConditionPassed() then 6329 EncodingSpecificOperations(); 6330 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6331 address = if index then offset_addr else R[n]; 6332 data = MemU[address,4]; 6333 if wback then R[n] = offset_addr; 6334 if t == 15 then 6335 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6336 elsif UnalignedSupport() || address<1:0> = '00' then 6337 R[t] = data; 6338 else // Can only apply before ARMv7 6339 R[t] = ROR(data, 8*UInt(address<1:0>)); 6340 #endif 6341 6342 bool success = false; 6343 6344 if (ConditionPassed(opcode)) { 6345 const uint32_t addr_byte_size = GetAddressByteSize(); 6346 6347 uint32_t t; 6348 uint32_t n; 6349 uint32_t imm32; 6350 bool index; 6351 bool add; 6352 bool wback; 6353 6354 switch (encoding) { 6355 case eEncodingA1: 6356 // if Rn == '1111' then SEE LDR (literal); 6357 // if P == '0' && W == '1' then SEE LDRT; 6358 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == 6359 // '000000000100' then SEE POP; 6360 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6361 t = Bits32(opcode, 15, 12); 6362 n = Bits32(opcode, 19, 16); 6363 imm32 = Bits32(opcode, 11, 0); 6364 6365 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 6366 // (W == '1'); 6367 index = BitIsSet(opcode, 24); 6368 add = BitIsSet(opcode, 23); 6369 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 6370 6371 // if wback && n == t then UNPREDICTABLE; 6372 if (wback && (n == t)) 6373 return false; 6374 6375 break; 6376 6377 default: 6378 return false; 6379 } 6380 6381 addr_t address; 6382 addr_t offset_addr; 6383 addr_t base_address = ReadCoreReg(n, &success); 6384 if (!success) 6385 return false; 6386 6387 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6388 if (add) 6389 offset_addr = base_address + imm32; 6390 else 6391 offset_addr = base_address - imm32; 6392 6393 // address = if index then offset_addr else R[n]; 6394 if (index) 6395 address = offset_addr; 6396 else 6397 address = base_address; 6398 6399 // data = MemU[address,4]; 6400 6401 std::optional<RegisterInfo> base_reg = 6402 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 6403 EmulateInstruction::Context context; 6404 context.type = eContextRegisterLoad; 6405 context.SetRegisterPlusOffset(*base_reg, address - base_address); 6406 6407 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success); 6408 if (!success) 6409 return false; 6410 6411 // if wback then R[n] = offset_addr; 6412 if (wback) { 6413 context.type = eContextAdjustBaseRegister; 6414 context.SetAddress(offset_addr); 6415 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 6416 offset_addr)) 6417 return false; 6418 } 6419 6420 // if t == 15 then 6421 if (t == 15) { 6422 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6423 if (BitIsClear(address, 1) && BitIsClear(address, 0)) { 6424 // LoadWritePC (data); 6425 context.type = eContextRegisterLoad; 6426 context.SetRegisterPlusOffset(*base_reg, address - base_address); 6427 LoadWritePC(context, data); 6428 } else 6429 return false; 6430 } 6431 // elsif UnalignedSupport() || address<1:0> = '00' then 6432 else if (UnalignedSupport() || 6433 (BitIsClear(address, 1) && BitIsClear(address, 0))) { 6434 // R[t] = data; 6435 context.type = eContextRegisterLoad; 6436 context.SetRegisterPlusOffset(*base_reg, address - base_address); 6437 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 6438 data)) 6439 return false; 6440 } 6441 // else // Can only apply before ARMv7 6442 else { 6443 // R[t] = ROR(data, 8*UInt(address<1:0>)); 6444 data = ROR(data, Bits32(address, 1, 0), &success); 6445 if (!success) 6446 return false; 6447 context.type = eContextRegisterLoad; 6448 context.SetImmediate(data); 6449 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 6450 data)) 6451 return false; 6452 } 6453 } 6454 return true; 6455 } 6456 6457 // LDR (register) calculates an address from a base register value and an offset 6458 // register value, loads a word 6459 // from memory, and writes it to a register. The offset register value can 6460 // optionally be shifted. 6461 bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode, 6462 const ARMEncoding encoding) { 6463 #if 0 6464 if ConditionPassed() then 6465 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6466 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6467 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6468 address = if index then offset_addr else R[n]; 6469 data = MemU[address,4]; 6470 if wback then R[n] = offset_addr; 6471 if t == 15 then 6472 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6473 elsif UnalignedSupport() || address<1:0> = '00' then 6474 R[t] = data; 6475 else // Can only apply before ARMv7 6476 if CurrentInstrSet() == InstrSet_ARM then 6477 R[t] = ROR(data, 8*UInt(address<1:0>)); 6478 else 6479 R[t] = bits(32) UNKNOWN; 6480 #endif 6481 6482 bool success = false; 6483 6484 if (ConditionPassed(opcode)) { 6485 const uint32_t addr_byte_size = GetAddressByteSize(); 6486 6487 uint32_t t; 6488 uint32_t n; 6489 uint32_t m; 6490 bool index; 6491 bool add; 6492 bool wback; 6493 ARM_ShifterType shift_t; 6494 uint32_t shift_n; 6495 6496 switch (encoding) { 6497 case eEncodingT1: 6498 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation 6499 // in ThumbEE"; 6500 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6501 t = Bits32(opcode, 2, 0); 6502 n = Bits32(opcode, 5, 3); 6503 m = Bits32(opcode, 8, 6); 6504 6505 // index = TRUE; add = TRUE; wback = FALSE; 6506 index = true; 6507 add = true; 6508 wback = false; 6509 6510 // (shift_t, shift_n) = (SRType_LSL, 0); 6511 shift_t = SRType_LSL; 6512 shift_n = 0; 6513 6514 break; 6515 6516 case eEncodingT2: 6517 // if Rn == '1111' then SEE LDR (literal); 6518 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6519 t = Bits32(opcode, 15, 12); 6520 n = Bits32(opcode, 19, 16); 6521 m = Bits32(opcode, 3, 0); 6522 6523 // index = TRUE; add = TRUE; wback = FALSE; 6524 index = true; 6525 add = true; 6526 wback = false; 6527 6528 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6529 shift_t = SRType_LSL; 6530 shift_n = Bits32(opcode, 5, 4); 6531 6532 // if BadReg(m) then UNPREDICTABLE; 6533 if (BadReg(m)) 6534 return false; 6535 6536 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 6537 if ((t == 15) && InITBlock() && !LastInITBlock()) 6538 return false; 6539 6540 break; 6541 6542 case eEncodingA1: { 6543 // if P == '0' && W == '1' then SEE LDRT; 6544 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6545 t = Bits32(opcode, 15, 12); 6546 n = Bits32(opcode, 19, 16); 6547 m = Bits32(opcode, 3, 0); 6548 6549 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 6550 // (W == '1'); 6551 index = BitIsSet(opcode, 24); 6552 add = BitIsSet(opcode, 23); 6553 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 6554 6555 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 6556 uint32_t type = Bits32(opcode, 6, 5); 6557 uint32_t imm5 = Bits32(opcode, 11, 7); 6558 shift_n = DecodeImmShift(type, imm5, shift_t); 6559 6560 // if m == 15 then UNPREDICTABLE; 6561 if (m == 15) 6562 return false; 6563 6564 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6565 if (wback && ((n == 15) || (n == t))) 6566 return false; 6567 } break; 6568 6569 default: 6570 return false; 6571 } 6572 6573 uint32_t Rm = 6574 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6575 if (!success) 6576 return false; 6577 6578 uint32_t Rn = 6579 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6580 if (!success) 6581 return false; 6582 6583 addr_t offset_addr; 6584 addr_t address; 6585 6586 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is 6587 // an application level alias for the CPSR". 6588 addr_t offset = 6589 Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success); 6590 if (!success) 6591 return false; 6592 6593 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6594 if (add) 6595 offset_addr = Rn + offset; 6596 else 6597 offset_addr = Rn - offset; 6598 6599 // address = if index then offset_addr else R[n]; 6600 if (index) 6601 address = offset_addr; 6602 else 6603 address = Rn; 6604 6605 // data = MemU[address,4]; 6606 std::optional<RegisterInfo> base_reg = 6607 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 6608 EmulateInstruction::Context context; 6609 context.type = eContextRegisterLoad; 6610 context.SetRegisterPlusOffset(*base_reg, address - Rn); 6611 6612 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success); 6613 if (!success) 6614 return false; 6615 6616 // if wback then R[n] = offset_addr; 6617 if (wback) { 6618 context.type = eContextAdjustBaseRegister; 6619 context.SetAddress(offset_addr); 6620 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 6621 offset_addr)) 6622 return false; 6623 } 6624 6625 // if t == 15 then 6626 if (t == 15) { 6627 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6628 if (BitIsClear(address, 1) && BitIsClear(address, 0)) { 6629 context.type = eContextRegisterLoad; 6630 context.SetRegisterPlusOffset(*base_reg, address - Rn); 6631 LoadWritePC(context, data); 6632 } else 6633 return false; 6634 } 6635 // elsif UnalignedSupport() || address<1:0> = '00' then 6636 else if (UnalignedSupport() || 6637 (BitIsClear(address, 1) && BitIsClear(address, 0))) { 6638 // R[t] = data; 6639 context.type = eContextRegisterLoad; 6640 context.SetRegisterPlusOffset(*base_reg, address - Rn); 6641 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 6642 data)) 6643 return false; 6644 } else // Can only apply before ARMv7 6645 { 6646 // if CurrentInstrSet() == InstrSet_ARM then 6647 if (CurrentInstrSet() == eModeARM) { 6648 // R[t] = ROR(data, 8*UInt(address<1:0>)); 6649 data = ROR(data, Bits32(address, 1, 0), &success); 6650 if (!success) 6651 return false; 6652 context.type = eContextRegisterLoad; 6653 context.SetImmediate(data); 6654 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 6655 data)) 6656 return false; 6657 } else { 6658 // R[t] = bits(32) UNKNOWN; 6659 WriteBits32Unknown(t); 6660 } 6661 } 6662 } 6663 return true; 6664 } 6665 6666 // LDRB (immediate, Thumb) 6667 bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode, 6668 const ARMEncoding encoding) { 6669 #if 0 6670 if ConditionPassed() then 6671 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6672 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6673 address = if index then offset_addr else R[n]; 6674 R[t] = ZeroExtend(MemU[address,1], 32); 6675 if wback then R[n] = offset_addr; 6676 #endif 6677 6678 bool success = false; 6679 6680 if (ConditionPassed(opcode)) { 6681 uint32_t t; 6682 uint32_t n; 6683 uint32_t imm32; 6684 bool index; 6685 bool add; 6686 bool wback; 6687 6688 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6689 switch (encoding) { 6690 case eEncodingT1: 6691 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 6692 t = Bits32(opcode, 2, 0); 6693 n = Bits32(opcode, 5, 3); 6694 imm32 = Bits32(opcode, 10, 6); 6695 6696 // index = TRUE; add = TRUE; wback = FALSE; 6697 index = true; 6698 add = true; 6699 wback = false; 6700 6701 break; 6702 6703 case eEncodingT2: 6704 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6705 t = Bits32(opcode, 15, 12); 6706 n = Bits32(opcode, 19, 16); 6707 imm32 = Bits32(opcode, 11, 0); 6708 6709 // index = TRUE; add = TRUE; wback = FALSE; 6710 index = true; 6711 add = true; 6712 wback = false; 6713 6714 // if Rt == '1111' then SEE PLD; 6715 if (t == 15) 6716 return false; // PLD is not implemented yet 6717 6718 // if Rn == '1111' then SEE LDRB (literal); 6719 if (n == 15) 6720 return EmulateLDRBLiteral(opcode, eEncodingT1); 6721 6722 // if t == 13 then UNPREDICTABLE; 6723 if (t == 13) 6724 return false; 6725 6726 break; 6727 6728 case eEncodingT3: 6729 // if P == '1' && U == '1' && W == '0' then SEE LDRBT; 6730 // if P == '0' && W == '0' then UNDEFINED; 6731 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) 6732 return false; 6733 6734 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6735 t = Bits32(opcode, 15, 12); 6736 n = Bits32(opcode, 19, 16); 6737 imm32 = Bits32(opcode, 7, 0); 6738 6739 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6740 index = BitIsSet(opcode, 10); 6741 add = BitIsSet(opcode, 9); 6742 wback = BitIsSet(opcode, 8); 6743 6744 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; 6745 if (t == 15) 6746 return false; // PLD is not implemented yet 6747 6748 // if Rn == '1111' then SEE LDRB (literal); 6749 if (n == 15) 6750 return EmulateLDRBLiteral(opcode, eEncodingT1); 6751 6752 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6753 if (BadReg(t) || (wback && (n == t))) 6754 return false; 6755 6756 break; 6757 6758 default: 6759 return false; 6760 } 6761 6762 uint32_t Rn = 6763 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6764 if (!success) 6765 return false; 6766 6767 addr_t address; 6768 addr_t offset_addr; 6769 6770 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6771 if (add) 6772 offset_addr = Rn + imm32; 6773 else 6774 offset_addr = Rn - imm32; 6775 6776 // address = if index then offset_addr else R[n]; 6777 if (index) 6778 address = offset_addr; 6779 else 6780 address = Rn; 6781 6782 // R[t] = ZeroExtend(MemU[address,1], 32); 6783 std::optional<RegisterInfo> base_reg = 6784 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 6785 std::optional<RegisterInfo> data_reg = 6786 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 6787 6788 EmulateInstruction::Context context; 6789 context.type = eContextRegisterLoad; 6790 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 6791 6792 uint64_t data = MemURead(context, address, 1, 0, &success); 6793 if (!success) 6794 return false; 6795 6796 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6797 return false; 6798 6799 // if wback then R[n] = offset_addr; 6800 if (wback) { 6801 context.type = eContextAdjustBaseRegister; 6802 context.SetAddress(offset_addr); 6803 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 6804 offset_addr)) 6805 return false; 6806 } 6807 } 6808 return true; 6809 } 6810 6811 // LDRB (literal) calculates an address from the PC value and an immediate 6812 // offset, loads a byte from memory, 6813 // zero-extends it to form a 32-bit word and writes it to a register. 6814 bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode, 6815 const ARMEncoding encoding) { 6816 #if 0 6817 if ConditionPassed() then 6818 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6819 base = Align(PC,4); 6820 address = if add then (base + imm32) else (base - imm32); 6821 R[t] = ZeroExtend(MemU[address,1], 32); 6822 #endif 6823 6824 bool success = false; 6825 6826 if (ConditionPassed(opcode)) { 6827 uint32_t t; 6828 uint32_t imm32; 6829 bool add; 6830 switch (encoding) { 6831 case eEncodingT1: 6832 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6833 t = Bits32(opcode, 15, 12); 6834 imm32 = Bits32(opcode, 11, 0); 6835 add = BitIsSet(opcode, 23); 6836 6837 // if Rt == '1111' then SEE PLD; 6838 if (t == 15) 6839 return false; // PLD is not implemented yet 6840 6841 // if t == 13 then UNPREDICTABLE; 6842 if (t == 13) 6843 return false; 6844 6845 break; 6846 6847 case eEncodingA1: 6848 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6849 t = Bits32(opcode, 15, 12); 6850 imm32 = Bits32(opcode, 11, 0); 6851 add = BitIsSet(opcode, 23); 6852 6853 // if t == 15 then UNPREDICTABLE; 6854 if (t == 15) 6855 return false; 6856 break; 6857 6858 default: 6859 return false; 6860 } 6861 6862 // base = Align(PC,4); 6863 uint32_t pc_val = ReadCoreReg(PC_REG, &success); 6864 if (!success) 6865 return false; 6866 6867 uint32_t base = AlignPC(pc_val); 6868 6869 addr_t address; 6870 // address = if add then (base + imm32) else (base - imm32); 6871 if (add) 6872 address = base + imm32; 6873 else 6874 address = base - imm32; 6875 6876 // R[t] = ZeroExtend(MemU[address,1], 32); 6877 EmulateInstruction::Context context; 6878 context.type = eContextRelativeBranchImmediate; 6879 context.SetImmediate(address - base); 6880 6881 uint64_t data = MemURead(context, address, 1, 0, &success); 6882 if (!success) 6883 return false; 6884 6885 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6886 return false; 6887 } 6888 return true; 6889 } 6890 6891 // LDRB (register) calculates an address from a base register value and an 6892 // offset rigister value, loads a byte from memory, zero-extends it to form a 6893 // 32-bit word, and writes it to a register. The offset register value can 6894 // optionally be shifted. 6895 bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode, 6896 const ARMEncoding encoding) { 6897 #if 0 6898 if ConditionPassed() then 6899 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6900 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6901 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6902 address = if index then offset_addr else R[n]; 6903 R[t] = ZeroExtend(MemU[address,1],32); 6904 if wback then R[n] = offset_addr; 6905 #endif 6906 6907 bool success = false; 6908 6909 if (ConditionPassed(opcode)) { 6910 uint32_t t; 6911 uint32_t n; 6912 uint32_t m; 6913 bool index; 6914 bool add; 6915 bool wback; 6916 ARM_ShifterType shift_t; 6917 uint32_t shift_n; 6918 6919 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6920 switch (encoding) { 6921 case eEncodingT1: 6922 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6923 t = Bits32(opcode, 2, 0); 6924 n = Bits32(opcode, 5, 3); 6925 m = Bits32(opcode, 8, 6); 6926 6927 // index = TRUE; add = TRUE; wback = FALSE; 6928 index = true; 6929 add = true; 6930 wback = false; 6931 6932 // (shift_t, shift_n) = (SRType_LSL, 0); 6933 shift_t = SRType_LSL; 6934 shift_n = 0; 6935 break; 6936 6937 case eEncodingT2: 6938 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6939 t = Bits32(opcode, 15, 12); 6940 n = Bits32(opcode, 19, 16); 6941 m = Bits32(opcode, 3, 0); 6942 6943 // index = TRUE; add = TRUE; wback = FALSE; 6944 index = true; 6945 add = true; 6946 wback = false; 6947 6948 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6949 shift_t = SRType_LSL; 6950 shift_n = Bits32(opcode, 5, 4); 6951 6952 // if Rt == '1111' then SEE PLD; 6953 if (t == 15) 6954 return false; // PLD is not implemented yet 6955 6956 // if Rn == '1111' then SEE LDRB (literal); 6957 if (n == 15) 6958 return EmulateLDRBLiteral(opcode, eEncodingT1); 6959 6960 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6961 if ((t == 13) || BadReg(m)) 6962 return false; 6963 break; 6964 6965 case eEncodingA1: { 6966 // if P == '0' && W == '1' then SEE LDRBT; 6967 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6968 t = Bits32(opcode, 15, 12); 6969 n = Bits32(opcode, 19, 16); 6970 m = Bits32(opcode, 3, 0); 6971 6972 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 6973 // (W == '1'); 6974 index = BitIsSet(opcode, 24); 6975 add = BitIsSet(opcode, 23); 6976 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 6977 6978 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 6979 uint32_t type = Bits32(opcode, 6, 5); 6980 uint32_t imm5 = Bits32(opcode, 11, 7); 6981 shift_n = DecodeImmShift(type, imm5, shift_t); 6982 6983 // if t == 15 || m == 15 then UNPREDICTABLE; 6984 if ((t == 15) || (m == 15)) 6985 return false; 6986 6987 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6988 if (wback && ((n == 15) || (n == t))) 6989 return false; 6990 } break; 6991 6992 default: 6993 return false; 6994 } 6995 6996 addr_t offset_addr; 6997 addr_t address; 6998 6999 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7000 uint32_t Rm = 7001 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7002 if (!success) 7003 return false; 7004 7005 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); 7006 if (!success) 7007 return false; 7008 7009 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7010 uint32_t Rn = 7011 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7012 if (!success) 7013 return false; 7014 7015 if (add) 7016 offset_addr = Rn + offset; 7017 else 7018 offset_addr = Rn - offset; 7019 7020 // address = if index then offset_addr else R[n]; 7021 if (index) 7022 address = offset_addr; 7023 else 7024 address = Rn; 7025 7026 // R[t] = ZeroExtend(MemU[address,1],32); 7027 std::optional<RegisterInfo> base_reg = 7028 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 7029 7030 EmulateInstruction::Context context; 7031 context.type = eContextRegisterLoad; 7032 context.SetRegisterPlusOffset(*base_reg, address - Rn); 7033 7034 uint64_t data = MemURead(context, address, 1, 0, &success); 7035 if (!success) 7036 return false; 7037 7038 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) 7039 return false; 7040 7041 // if wback then R[n] = offset_addr; 7042 if (wback) { 7043 context.type = eContextAdjustBaseRegister; 7044 context.SetAddress(offset_addr); 7045 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 7046 offset_addr)) 7047 return false; 7048 } 7049 } 7050 return true; 7051 } 7052 7053 // LDRH (immediate, Thumb) calculates an address from a base register value and 7054 // an immediate offset, loads a 7055 // halfword from memory, zero-extends it to form a 32-bit word, and writes it 7056 // to a register. It can use offset, post-indexed, or pre-indexed addressing. 7057 bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode, 7058 const ARMEncoding encoding) { 7059 #if 0 7060 if ConditionPassed() then 7061 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7062 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7063 address = if index then offset_addr else R[n]; 7064 data = MemU[address,2]; 7065 if wback then R[n] = offset_addr; 7066 if UnalignedSupport() || address<0> = '0' then 7067 R[t] = ZeroExtend(data, 32); 7068 else // Can only apply before ARMv7 7069 R[t] = bits(32) UNKNOWN; 7070 #endif 7071 7072 bool success = false; 7073 7074 if (ConditionPassed(opcode)) { 7075 uint32_t t; 7076 uint32_t n; 7077 uint32_t imm32; 7078 bool index; 7079 bool add; 7080 bool wback; 7081 7082 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7083 switch (encoding) { 7084 case eEncodingT1: 7085 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32); 7086 t = Bits32(opcode, 2, 0); 7087 n = Bits32(opcode, 5, 3); 7088 imm32 = Bits32(opcode, 10, 6) << 1; 7089 7090 // index = TRUE; add = TRUE; wback = FALSE; 7091 index = true; 7092 add = true; 7093 wback = false; 7094 7095 break; 7096 7097 case eEncodingT2: 7098 // if Rt == '1111' then SEE "Unallocated memory hints"; 7099 // if Rn == '1111' then SEE LDRH (literal); 7100 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7101 t = Bits32(opcode, 15, 12); 7102 n = Bits32(opcode, 19, 16); 7103 imm32 = Bits32(opcode, 11, 0); 7104 7105 // index = TRUE; add = TRUE; wback = FALSE; 7106 index = true; 7107 add = true; 7108 wback = false; 7109 7110 // if t == 13 then UNPREDICTABLE; 7111 if (t == 13) 7112 return false; 7113 break; 7114 7115 case eEncodingT3: 7116 // if Rn == '1111' then SEE LDRH (literal); 7117 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE 7118 // "Unallocated memory hints"; 7119 // if P == '1' && U == '1' && W == '0' then SEE LDRHT; 7120 // if P == '0' && W == '0' then UNDEFINED; 7121 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) 7122 return false; 7123 7124 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7125 t = Bits32(opcode, 15, 12); 7126 n = Bits32(opcode, 19, 16); 7127 imm32 = Bits32(opcode, 7, 0); 7128 7129 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7130 index = BitIsSet(opcode, 10); 7131 add = BitIsSet(opcode, 9); 7132 wback = BitIsSet(opcode, 8); 7133 7134 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7135 if (BadReg(t) || (wback && (n == t))) 7136 return false; 7137 break; 7138 7139 default: 7140 return false; 7141 } 7142 7143 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7144 uint32_t Rn = 7145 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7146 if (!success) 7147 return false; 7148 7149 addr_t offset_addr; 7150 addr_t address; 7151 7152 if (add) 7153 offset_addr = Rn + imm32; 7154 else 7155 offset_addr = Rn - imm32; 7156 7157 // address = if index then offset_addr else R[n]; 7158 if (index) 7159 address = offset_addr; 7160 else 7161 address = Rn; 7162 7163 // data = MemU[address,2]; 7164 std::optional<RegisterInfo> base_reg = 7165 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 7166 7167 EmulateInstruction::Context context; 7168 context.type = eContextRegisterLoad; 7169 context.SetRegisterPlusOffset(*base_reg, address - Rn); 7170 7171 uint64_t data = MemURead(context, address, 2, 0, &success); 7172 if (!success) 7173 return false; 7174 7175 // if wback then R[n] = offset_addr; 7176 if (wback) { 7177 context.type = eContextAdjustBaseRegister; 7178 context.SetAddress(offset_addr); 7179 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 7180 offset_addr)) 7181 return false; 7182 } 7183 7184 // if UnalignedSupport() || address<0> = '0' then 7185 if (UnalignedSupport() || BitIsClear(address, 0)) { 7186 // R[t] = ZeroExtend(data, 32); 7187 context.type = eContextRegisterLoad; 7188 context.SetRegisterPlusOffset(*base_reg, address - Rn); 7189 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7190 data)) 7191 return false; 7192 } else // Can only apply before ARMv7 7193 { 7194 // R[t] = bits(32) UNKNOWN; 7195 WriteBits32Unknown(t); 7196 } 7197 } 7198 return true; 7199 } 7200 7201 // LDRH (literal) calculates an address from the PC value and an immediate 7202 // offset, loads a halfword from memory, 7203 // zero-extends it to form a 32-bit word, and writes it to a register. 7204 bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode, 7205 const ARMEncoding encoding) { 7206 #if 0 7207 if ConditionPassed() then 7208 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7209 base = Align(PC,4); 7210 address = if add then (base + imm32) else (base - imm32); 7211 data = MemU[address,2]; 7212 if UnalignedSupport() || address<0> = '0' then 7213 R[t] = ZeroExtend(data, 32); 7214 else // Can only apply before ARMv7 7215 R[t] = bits(32) UNKNOWN; 7216 #endif 7217 7218 bool success = false; 7219 7220 if (ConditionPassed(opcode)) { 7221 uint32_t t; 7222 uint32_t imm32; 7223 bool add; 7224 7225 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7226 switch (encoding) { 7227 case eEncodingT1: 7228 // if Rt == '1111' then SEE "Unallocated memory hints"; 7229 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 7230 t = Bits32(opcode, 15, 12); 7231 imm32 = Bits32(opcode, 11, 0); 7232 add = BitIsSet(opcode, 23); 7233 7234 // if t == 13 then UNPREDICTABLE; 7235 if (t == 13) 7236 return false; 7237 7238 break; 7239 7240 case eEncodingA1: { 7241 uint32_t imm4H = Bits32(opcode, 11, 8); 7242 uint32_t imm4L = Bits32(opcode, 3, 0); 7243 7244 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 7245 t = Bits32(opcode, 15, 12); 7246 imm32 = (imm4H << 4) | imm4L; 7247 add = BitIsSet(opcode, 23); 7248 7249 // if t == 15 then UNPREDICTABLE; 7250 if (t == 15) 7251 return false; 7252 break; 7253 } 7254 7255 default: 7256 return false; 7257 } 7258 7259 // base = Align(PC,4); 7260 uint64_t pc_value = ReadCoreReg(PC_REG, &success); 7261 if (!success) 7262 return false; 7263 7264 addr_t base = AlignPC(pc_value); 7265 addr_t address; 7266 7267 // address = if add then (base + imm32) else (base - imm32); 7268 if (add) 7269 address = base + imm32; 7270 else 7271 address = base - imm32; 7272 7273 // data = MemU[address,2]; 7274 std::optional<RegisterInfo> base_reg = 7275 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 7276 7277 EmulateInstruction::Context context; 7278 context.type = eContextRegisterLoad; 7279 context.SetRegisterPlusOffset(*base_reg, address - base); 7280 7281 uint64_t data = MemURead(context, address, 2, 0, &success); 7282 if (!success) 7283 return false; 7284 7285 // if UnalignedSupport() || address<0> = '0' then 7286 if (UnalignedSupport() || BitIsClear(address, 0)) { 7287 // R[t] = ZeroExtend(data, 32); 7288 context.type = eContextRegisterLoad; 7289 context.SetRegisterPlusOffset(*base_reg, address - base); 7290 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7291 data)) 7292 return false; 7293 7294 } else // Can only apply before ARMv7 7295 { 7296 // R[t] = bits(32) UNKNOWN; 7297 WriteBits32Unknown(t); 7298 } 7299 } 7300 return true; 7301 } 7302 7303 // LDRH (literal) calculates an address from a base register value and an offset 7304 // register value, loads a halfword 7305 // from memory, zero-extends it to form a 32-bit word, and writes it to a 7306 // register. The offset register value can be shifted left by 0, 1, 2, or 3 7307 // bits. 7308 bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode, 7309 const ARMEncoding encoding) { 7310 #if 0 7311 if ConditionPassed() then 7312 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7313 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7314 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7315 address = if index then offset_addr else R[n]; 7316 data = MemU[address,2]; 7317 if wback then R[n] = offset_addr; 7318 if UnalignedSupport() || address<0> = '0' then 7319 R[t] = ZeroExtend(data, 32); 7320 else // Can only apply before ARMv7 7321 R[t] = bits(32) UNKNOWN; 7322 #endif 7323 7324 bool success = false; 7325 7326 if (ConditionPassed(opcode)) { 7327 uint32_t t; 7328 uint32_t n; 7329 uint32_t m; 7330 bool index; 7331 bool add; 7332 bool wback; 7333 ARM_ShifterType shift_t; 7334 uint32_t shift_n; 7335 7336 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7337 switch (encoding) { 7338 case eEncodingT1: 7339 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation 7340 // in ThumbEE"; 7341 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7342 t = Bits32(opcode, 2, 0); 7343 n = Bits32(opcode, 5, 3); 7344 m = Bits32(opcode, 8, 6); 7345 7346 // index = TRUE; add = TRUE; wback = FALSE; 7347 index = true; 7348 add = true; 7349 wback = false; 7350 7351 // (shift_t, shift_n) = (SRType_LSL, 0); 7352 shift_t = SRType_LSL; 7353 shift_n = 0; 7354 7355 break; 7356 7357 case eEncodingT2: 7358 // if Rn == '1111' then SEE LDRH (literal); 7359 // if Rt == '1111' then SEE "Unallocated memory hints"; 7360 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7361 t = Bits32(opcode, 15, 12); 7362 n = Bits32(opcode, 19, 16); 7363 m = Bits32(opcode, 3, 0); 7364 7365 // index = TRUE; add = TRUE; wback = FALSE; 7366 index = true; 7367 add = true; 7368 wback = false; 7369 7370 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7371 shift_t = SRType_LSL; 7372 shift_n = Bits32(opcode, 5, 4); 7373 7374 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7375 if ((t == 13) || BadReg(m)) 7376 return false; 7377 break; 7378 7379 case eEncodingA1: 7380 // if P == '0' && W == '1' then SEE LDRHT; 7381 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7382 t = Bits32(opcode, 15, 12); 7383 n = Bits32(opcode, 19, 16); 7384 m = Bits32(opcode, 3, 0); 7385 7386 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 7387 // (W == '1'); 7388 index = BitIsSet(opcode, 24); 7389 add = BitIsSet(opcode, 23); 7390 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 7391 7392 // (shift_t, shift_n) = (SRType_LSL, 0); 7393 shift_t = SRType_LSL; 7394 shift_n = 0; 7395 7396 // if t == 15 || m == 15 then UNPREDICTABLE; 7397 if ((t == 15) || (m == 15)) 7398 return false; 7399 7400 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7401 if (wback && ((n == 15) || (n == t))) 7402 return false; 7403 7404 break; 7405 7406 default: 7407 return false; 7408 } 7409 7410 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7411 7412 uint64_t Rm = 7413 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7414 if (!success) 7415 return false; 7416 7417 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); 7418 if (!success) 7419 return false; 7420 7421 addr_t offset_addr; 7422 addr_t address; 7423 7424 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7425 uint64_t Rn = 7426 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7427 if (!success) 7428 return false; 7429 7430 if (add) 7431 offset_addr = Rn + offset; 7432 else 7433 offset_addr = Rn - offset; 7434 7435 // address = if index then offset_addr else R[n]; 7436 if (index) 7437 address = offset_addr; 7438 else 7439 address = Rn; 7440 7441 // data = MemU[address,2]; 7442 std::optional<RegisterInfo> base_reg = 7443 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 7444 std::optional<RegisterInfo> offset_reg = 7445 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 7446 7447 EmulateInstruction::Context context; 7448 context.type = eContextRegisterLoad; 7449 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); 7450 uint64_t data = MemURead(context, address, 2, 0, &success); 7451 if (!success) 7452 return false; 7453 7454 // if wback then R[n] = offset_addr; 7455 if (wback) { 7456 context.type = eContextAdjustBaseRegister; 7457 context.SetAddress(offset_addr); 7458 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 7459 offset_addr)) 7460 return false; 7461 } 7462 7463 // if UnalignedSupport() || address<0> = '0' then 7464 if (UnalignedSupport() || BitIsClear(address, 0)) { 7465 // R[t] = ZeroExtend(data, 32); 7466 context.type = eContextRegisterLoad; 7467 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); 7468 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7469 data)) 7470 return false; 7471 } else // Can only apply before ARMv7 7472 { 7473 // R[t] = bits(32) UNKNOWN; 7474 WriteBits32Unknown(t); 7475 } 7476 } 7477 return true; 7478 } 7479 7480 // LDRSB (immediate) calculates an address from a base register value and an 7481 // immediate offset, loads a byte from 7482 // memory, sign-extends it to form a 32-bit word, and writes it to a register. 7483 // It can use offset, post-indexed, or pre-indexed addressing. 7484 bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode, 7485 const ARMEncoding encoding) { 7486 #if 0 7487 if ConditionPassed() then 7488 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7489 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7490 address = if index then offset_addr else R[n]; 7491 R[t] = SignExtend(MemU[address,1], 32); 7492 if wback then R[n] = offset_addr; 7493 #endif 7494 7495 bool success = false; 7496 7497 if (ConditionPassed(opcode)) { 7498 uint32_t t; 7499 uint32_t n; 7500 uint32_t imm32; 7501 bool index; 7502 bool add; 7503 bool wback; 7504 7505 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7506 switch (encoding) { 7507 case eEncodingT1: 7508 // if Rt == '1111' then SEE PLI; 7509 // if Rn == '1111' then SEE LDRSB (literal); 7510 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7511 t = Bits32(opcode, 15, 12); 7512 n = Bits32(opcode, 19, 16); 7513 imm32 = Bits32(opcode, 11, 0); 7514 7515 // index = TRUE; add = TRUE; wback = FALSE; 7516 index = true; 7517 add = true; 7518 wback = false; 7519 7520 // if t == 13 then UNPREDICTABLE; 7521 if (t == 13) 7522 return false; 7523 7524 break; 7525 7526 case eEncodingT2: 7527 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI; 7528 // if Rn == '1111' then SEE LDRSB (literal); 7529 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT; 7530 // if P == '0' && W == '0' then UNDEFINED; 7531 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) 7532 return false; 7533 7534 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7535 t = Bits32(opcode, 15, 12); 7536 n = Bits32(opcode, 19, 16); 7537 imm32 = Bits32(opcode, 7, 0); 7538 7539 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7540 index = BitIsSet(opcode, 10); 7541 add = BitIsSet(opcode, 9); 7542 wback = BitIsSet(opcode, 8); 7543 7544 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7545 if (((t == 13) || 7546 ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) || 7547 BitIsSet(opcode, 8)))) || 7548 (wback && (n == t))) 7549 return false; 7550 7551 break; 7552 7553 case eEncodingA1: { 7554 // if Rn == '1111' then SEE LDRSB (literal); 7555 // if P == '0' && W == '1' then SEE LDRSBT; 7556 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 7557 t = Bits32(opcode, 15, 12); 7558 n = Bits32(opcode, 19, 16); 7559 7560 uint32_t imm4H = Bits32(opcode, 11, 8); 7561 uint32_t imm4L = Bits32(opcode, 3, 0); 7562 imm32 = (imm4H << 4) | imm4L; 7563 7564 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 7565 // (W == '1'); 7566 index = BitIsSet(opcode, 24); 7567 add = BitIsSet(opcode, 23); 7568 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 7569 7570 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 7571 if ((t == 15) || (wback && (n == t))) 7572 return false; 7573 7574 break; 7575 } 7576 7577 default: 7578 return false; 7579 } 7580 7581 uint64_t Rn = ReadCoreReg(n, &success); 7582 if (!success) 7583 return false; 7584 7585 addr_t offset_addr; 7586 addr_t address; 7587 7588 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7589 if (add) 7590 offset_addr = Rn + imm32; 7591 else 7592 offset_addr = Rn - imm32; 7593 7594 // address = if index then offset_addr else R[n]; 7595 if (index) 7596 address = offset_addr; 7597 else 7598 address = Rn; 7599 7600 // R[t] = SignExtend(MemU[address,1], 32); 7601 std::optional<RegisterInfo> base_reg = 7602 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 7603 7604 EmulateInstruction::Context context; 7605 context.type = eContextRegisterLoad; 7606 context.SetRegisterPlusOffset(*base_reg, address - Rn); 7607 7608 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); 7609 if (!success) 7610 return false; 7611 7612 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7613 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7614 (uint64_t)signed_data)) 7615 return false; 7616 7617 // if wback then R[n] = offset_addr; 7618 if (wback) { 7619 context.type = eContextAdjustBaseRegister; 7620 context.SetAddress(offset_addr); 7621 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 7622 offset_addr)) 7623 return false; 7624 } 7625 } 7626 7627 return true; 7628 } 7629 7630 // LDRSB (literal) calculates an address from the PC value and an immediate 7631 // offset, loads a byte from memory, 7632 // sign-extends it to form a 32-bit word, and writes tit to a register. 7633 bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode, 7634 const ARMEncoding encoding) { 7635 #if 0 7636 if ConditionPassed() then 7637 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7638 base = Align(PC,4); 7639 address = if add then (base + imm32) else (base - imm32); 7640 R[t] = SignExtend(MemU[address,1], 32); 7641 #endif 7642 7643 bool success = false; 7644 7645 if (ConditionPassed(opcode)) { 7646 uint32_t t; 7647 uint32_t imm32; 7648 bool add; 7649 7650 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7651 switch (encoding) { 7652 case eEncodingT1: 7653 // if Rt == '1111' then SEE PLI; 7654 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 7655 t = Bits32(opcode, 15, 12); 7656 imm32 = Bits32(opcode, 11, 0); 7657 add = BitIsSet(opcode, 23); 7658 7659 // if t == 13 then UNPREDICTABLE; 7660 if (t == 13) 7661 return false; 7662 7663 break; 7664 7665 case eEncodingA1: { 7666 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 7667 t = Bits32(opcode, 15, 12); 7668 uint32_t imm4H = Bits32(opcode, 11, 8); 7669 uint32_t imm4L = Bits32(opcode, 3, 0); 7670 imm32 = (imm4H << 4) | imm4L; 7671 add = BitIsSet(opcode, 23); 7672 7673 // if t == 15 then UNPREDICTABLE; 7674 if (t == 15) 7675 return false; 7676 7677 break; 7678 } 7679 7680 default: 7681 return false; 7682 } 7683 7684 // base = Align(PC,4); 7685 uint64_t pc_value = ReadCoreReg(PC_REG, &success); 7686 if (!success) 7687 return false; 7688 uint64_t base = AlignPC(pc_value); 7689 7690 // address = if add then (base + imm32) else (base - imm32); 7691 addr_t address; 7692 if (add) 7693 address = base + imm32; 7694 else 7695 address = base - imm32; 7696 7697 // R[t] = SignExtend(MemU[address,1], 32); 7698 std::optional<RegisterInfo> base_reg = 7699 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 7700 7701 EmulateInstruction::Context context; 7702 context.type = eContextRegisterLoad; 7703 context.SetRegisterPlusOffset(*base_reg, address - base); 7704 7705 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); 7706 if (!success) 7707 return false; 7708 7709 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7710 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7711 (uint64_t)signed_data)) 7712 return false; 7713 } 7714 return true; 7715 } 7716 7717 // LDRSB (register) calculates an address from a base register value and an 7718 // offset register value, loadsa byte from 7719 // memory, sign-extends it to form a 32-bit word, and writes it to a register. 7720 // The offset register value can be shifted left by 0, 1, 2, or 3 bits. 7721 bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode, 7722 const ARMEncoding encoding) { 7723 #if 0 7724 if ConditionPassed() then 7725 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7726 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7727 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7728 address = if index then offset_addr else R[n]; 7729 R[t] = SignExtend(MemU[address,1], 32); 7730 if wback then R[n] = offset_addr; 7731 #endif 7732 7733 bool success = false; 7734 7735 if (ConditionPassed(opcode)) { 7736 uint32_t t; 7737 uint32_t n; 7738 uint32_t m; 7739 bool index; 7740 bool add; 7741 bool wback; 7742 ARM_ShifterType shift_t; 7743 uint32_t shift_n; 7744 7745 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7746 switch (encoding) { 7747 case eEncodingT1: 7748 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7749 t = Bits32(opcode, 2, 0); 7750 n = Bits32(opcode, 5, 3); 7751 m = Bits32(opcode, 8, 6); 7752 7753 // index = TRUE; add = TRUE; wback = FALSE; 7754 index = true; 7755 add = true; 7756 wback = false; 7757 7758 // (shift_t, shift_n) = (SRType_LSL, 0); 7759 shift_t = SRType_LSL; 7760 shift_n = 0; 7761 7762 break; 7763 7764 case eEncodingT2: 7765 // if Rt == '1111' then SEE PLI; 7766 // if Rn == '1111' then SEE LDRSB (literal); 7767 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7768 t = Bits32(opcode, 15, 12); 7769 n = Bits32(opcode, 19, 16); 7770 m = Bits32(opcode, 3, 0); 7771 7772 // index = TRUE; add = TRUE; wback = FALSE; 7773 index = true; 7774 add = true; 7775 wback = false; 7776 7777 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7778 shift_t = SRType_LSL; 7779 shift_n = Bits32(opcode, 5, 4); 7780 7781 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7782 if ((t == 13) || BadReg(m)) 7783 return false; 7784 break; 7785 7786 case eEncodingA1: 7787 // if P == '0' && W == '1' then SEE LDRSBT; 7788 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7789 t = Bits32(opcode, 15, 12); 7790 n = Bits32(opcode, 19, 16); 7791 m = Bits32(opcode, 3, 0); 7792 7793 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 7794 // (W == '1'); 7795 index = BitIsSet(opcode, 24); 7796 add = BitIsSet(opcode, 23); 7797 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 7798 7799 // (shift_t, shift_n) = (SRType_LSL, 0); 7800 shift_t = SRType_LSL; 7801 shift_n = 0; 7802 7803 // if t == 15 || m == 15 then UNPREDICTABLE; 7804 if ((t == 15) || (m == 15)) 7805 return false; 7806 7807 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7808 if (wback && ((n == 15) || (n == t))) 7809 return false; 7810 break; 7811 7812 default: 7813 return false; 7814 } 7815 7816 uint64_t Rm = 7817 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7818 if (!success) 7819 return false; 7820 7821 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7822 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); 7823 if (!success) 7824 return false; 7825 7826 addr_t offset_addr; 7827 addr_t address; 7828 7829 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7830 uint64_t Rn = 7831 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7832 if (!success) 7833 return false; 7834 7835 if (add) 7836 offset_addr = Rn + offset; 7837 else 7838 offset_addr = Rn - offset; 7839 7840 // address = if index then offset_addr else R[n]; 7841 if (index) 7842 address = offset_addr; 7843 else 7844 address = Rn; 7845 7846 // R[t] = SignExtend(MemU[address,1], 32); 7847 std::optional<RegisterInfo> base_reg = 7848 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 7849 std::optional<RegisterInfo> offset_reg = 7850 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 7851 7852 EmulateInstruction::Context context; 7853 context.type = eContextRegisterLoad; 7854 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); 7855 7856 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); 7857 if (!success) 7858 return false; 7859 7860 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7861 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7862 (uint64_t)signed_data)) 7863 return false; 7864 7865 // if wback then R[n] = offset_addr; 7866 if (wback) { 7867 context.type = eContextAdjustBaseRegister; 7868 context.SetAddress(offset_addr); 7869 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 7870 offset_addr)) 7871 return false; 7872 } 7873 } 7874 return true; 7875 } 7876 7877 // LDRSH (immediate) calculates an address from a base register value and an 7878 // immediate offset, loads a halfword from 7879 // memory, sign-extends it to form a 32-bit word, and writes it to a register. 7880 // It can use offset, post-indexed, or pre-indexed addressing. 7881 bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode, 7882 const ARMEncoding encoding) { 7883 #if 0 7884 if ConditionPassed() then 7885 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7886 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7887 address = if index then offset_addr else R[n]; 7888 data = MemU[address,2]; 7889 if wback then R[n] = offset_addr; 7890 if UnalignedSupport() || address<0> = '0' then 7891 R[t] = SignExtend(data, 32); 7892 else // Can only apply before ARMv7 7893 R[t] = bits(32) UNKNOWN; 7894 #endif 7895 7896 bool success = false; 7897 7898 if (ConditionPassed(opcode)) { 7899 uint32_t t; 7900 uint32_t n; 7901 uint32_t imm32; 7902 bool index; 7903 bool add; 7904 bool wback; 7905 7906 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7907 switch (encoding) { 7908 case eEncodingT1: 7909 // if Rn == '1111' then SEE LDRSH (literal); 7910 // if Rt == '1111' then SEE "Unallocated memory hints"; 7911 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7912 t = Bits32(opcode, 15, 12); 7913 n = Bits32(opcode, 19, 16); 7914 imm32 = Bits32(opcode, 11, 0); 7915 7916 // index = TRUE; add = TRUE; wback = FALSE; 7917 index = true; 7918 add = true; 7919 wback = false; 7920 7921 // if t == 13 then UNPREDICTABLE; 7922 if (t == 13) 7923 return false; 7924 7925 break; 7926 7927 case eEncodingT2: 7928 // if Rn == '1111' then SEE LDRSH (literal); 7929 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE 7930 // "Unallocated memory hints"; 7931 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT; 7932 // if P == '0' && W == '0' then UNDEFINED; 7933 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) 7934 return false; 7935 7936 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7937 t = Bits32(opcode, 15, 12); 7938 n = Bits32(opcode, 19, 16); 7939 imm32 = Bits32(opcode, 7, 0); 7940 7941 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7942 index = BitIsSet(opcode, 10); 7943 add = BitIsSet(opcode, 9); 7944 wback = BitIsSet(opcode, 8); 7945 7946 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7947 if (BadReg(t) || (wback && (n == t))) 7948 return false; 7949 7950 break; 7951 7952 case eEncodingA1: { 7953 // if Rn == '1111' then SEE LDRSH (literal); 7954 // if P == '0' && W == '1' then SEE LDRSHT; 7955 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 7956 t = Bits32(opcode, 15, 12); 7957 n = Bits32(opcode, 19, 16); 7958 uint32_t imm4H = Bits32(opcode, 11, 8); 7959 uint32_t imm4L = Bits32(opcode, 3, 0); 7960 imm32 = (imm4H << 4) | imm4L; 7961 7962 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 7963 // (W == '1'); 7964 index = BitIsSet(opcode, 24); 7965 add = BitIsSet(opcode, 23); 7966 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 7967 7968 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 7969 if ((t == 15) || (wback && (n == t))) 7970 return false; 7971 7972 break; 7973 } 7974 7975 default: 7976 return false; 7977 } 7978 7979 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7980 uint64_t Rn = 7981 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7982 if (!success) 7983 return false; 7984 7985 addr_t offset_addr; 7986 if (add) 7987 offset_addr = Rn + imm32; 7988 else 7989 offset_addr = Rn - imm32; 7990 7991 // address = if index then offset_addr else R[n]; 7992 addr_t address; 7993 if (index) 7994 address = offset_addr; 7995 else 7996 address = Rn; 7997 7998 // data = MemU[address,2]; 7999 std::optional<RegisterInfo> base_reg = 8000 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 8001 8002 EmulateInstruction::Context context; 8003 context.type = eContextRegisterLoad; 8004 context.SetRegisterPlusOffset(*base_reg, address - Rn); 8005 8006 uint64_t data = MemURead(context, address, 2, 0, &success); 8007 if (!success) 8008 return false; 8009 8010 // if wback then R[n] = offset_addr; 8011 if (wback) { 8012 context.type = eContextAdjustBaseRegister; 8013 context.SetAddress(offset_addr); 8014 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 8015 offset_addr)) 8016 return false; 8017 } 8018 8019 // if UnalignedSupport() || address<0> = '0' then 8020 if (UnalignedSupport() || BitIsClear(address, 0)) { 8021 // R[t] = SignExtend(data, 32); 8022 int64_t signed_data = llvm::SignExtend64<16>(data); 8023 context.type = eContextRegisterLoad; 8024 context.SetRegisterPlusOffset(*base_reg, address - Rn); 8025 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 8026 (uint64_t)signed_data)) 8027 return false; 8028 } else // Can only apply before ARMv7 8029 { 8030 // R[t] = bits(32) UNKNOWN; 8031 WriteBits32Unknown(t); 8032 } 8033 } 8034 return true; 8035 } 8036 8037 // LDRSH (literal) calculates an address from the PC value and an immediate 8038 // offset, loads a halfword from memory, 8039 // sign-extends it to from a 32-bit word, and writes it to a register. 8040 bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode, 8041 const ARMEncoding encoding) { 8042 #if 0 8043 if ConditionPassed() then 8044 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 8045 base = Align(PC,4); 8046 address = if add then (base + imm32) else (base - imm32); 8047 data = MemU[address,2]; 8048 if UnalignedSupport() || address<0> = '0' then 8049 R[t] = SignExtend(data, 32); 8050 else // Can only apply before ARMv7 8051 R[t] = bits(32) UNKNOWN; 8052 #endif 8053 8054 bool success = false; 8055 8056 if (ConditionPassed(opcode)) { 8057 uint32_t t; 8058 uint32_t imm32; 8059 bool add; 8060 8061 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 8062 switch (encoding) { 8063 case eEncodingT1: 8064 // if Rt == '1111' then SEE "Unallocated memory hints"; 8065 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 8066 t = Bits32(opcode, 15, 12); 8067 imm32 = Bits32(opcode, 11, 0); 8068 add = BitIsSet(opcode, 23); 8069 8070 // if t == 13 then UNPREDICTABLE; 8071 if (t == 13) 8072 return false; 8073 8074 break; 8075 8076 case eEncodingA1: { 8077 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 8078 t = Bits32(opcode, 15, 12); 8079 uint32_t imm4H = Bits32(opcode, 11, 8); 8080 uint32_t imm4L = Bits32(opcode, 3, 0); 8081 imm32 = (imm4H << 4) | imm4L; 8082 add = BitIsSet(opcode, 23); 8083 8084 // if t == 15 then UNPREDICTABLE; 8085 if (t == 15) 8086 return false; 8087 8088 break; 8089 } 8090 default: 8091 return false; 8092 } 8093 8094 // base = Align(PC,4); 8095 uint64_t pc_value = ReadCoreReg(PC_REG, &success); 8096 if (!success) 8097 return false; 8098 8099 uint64_t base = AlignPC(pc_value); 8100 8101 addr_t address; 8102 // address = if add then (base + imm32) else (base - imm32); 8103 if (add) 8104 address = base + imm32; 8105 else 8106 address = base - imm32; 8107 8108 // data = MemU[address,2]; 8109 std::optional<RegisterInfo> base_reg = 8110 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 8111 8112 EmulateInstruction::Context context; 8113 context.type = eContextRegisterLoad; 8114 context.SetRegisterPlusOffset(*base_reg, imm32); 8115 8116 uint64_t data = MemURead(context, address, 2, 0, &success); 8117 if (!success) 8118 return false; 8119 8120 // if UnalignedSupport() || address<0> = '0' then 8121 if (UnalignedSupport() || BitIsClear(address, 0)) { 8122 // R[t] = SignExtend(data, 32); 8123 int64_t signed_data = llvm::SignExtend64<16>(data); 8124 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 8125 (uint64_t)signed_data)) 8126 return false; 8127 } else // Can only apply before ARMv7 8128 { 8129 // R[t] = bits(32) UNKNOWN; 8130 WriteBits32Unknown(t); 8131 } 8132 } 8133 return true; 8134 } 8135 8136 // LDRSH (register) calculates an address from a base register value and an 8137 // offset register value, loads a halfword 8138 // from memory, sign-extends it to form a 32-bit word, and writes it to a 8139 // register. The offset register value can be shifted left by 0, 1, 2, or 3 8140 // bits. 8141 bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode, 8142 const ARMEncoding encoding) { 8143 #if 0 8144 if ConditionPassed() then 8145 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 8146 offset = Shift(R[m], shift_t, shift_n, APSR.C); 8147 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 8148 address = if index then offset_addr else R[n]; 8149 data = MemU[address,2]; 8150 if wback then R[n] = offset_addr; 8151 if UnalignedSupport() || address<0> = '0' then 8152 R[t] = SignExtend(data, 32); 8153 else // Can only apply before ARMv7 8154 R[t] = bits(32) UNKNOWN; 8155 #endif 8156 8157 bool success = false; 8158 8159 if (ConditionPassed(opcode)) { 8160 uint32_t t; 8161 uint32_t n; 8162 uint32_t m; 8163 bool index; 8164 bool add; 8165 bool wback; 8166 ARM_ShifterType shift_t; 8167 uint32_t shift_n; 8168 8169 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 8170 switch (encoding) { 8171 case eEncodingT1: 8172 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation 8173 // in ThumbEE"; 8174 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 8175 t = Bits32(opcode, 2, 0); 8176 n = Bits32(opcode, 5, 3); 8177 m = Bits32(opcode, 8, 6); 8178 8179 // index = TRUE; add = TRUE; wback = FALSE; 8180 index = true; 8181 add = true; 8182 wback = false; 8183 8184 // (shift_t, shift_n) = (SRType_LSL, 0); 8185 shift_t = SRType_LSL; 8186 shift_n = 0; 8187 8188 break; 8189 8190 case eEncodingT2: 8191 // if Rn == '1111' then SEE LDRSH (literal); 8192 // if Rt == '1111' then SEE "Unallocated memory hints"; 8193 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 8194 t = Bits32(opcode, 15, 12); 8195 n = Bits32(opcode, 19, 16); 8196 m = Bits32(opcode, 3, 0); 8197 8198 // index = TRUE; add = TRUE; wback = FALSE; 8199 index = true; 8200 add = true; 8201 wback = false; 8202 8203 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 8204 shift_t = SRType_LSL; 8205 shift_n = Bits32(opcode, 5, 4); 8206 8207 // if t == 13 || BadReg(m) then UNPREDICTABLE; 8208 if ((t == 13) || BadReg(m)) 8209 return false; 8210 8211 break; 8212 8213 case eEncodingA1: 8214 // if P == '0' && W == '1' then SEE LDRSHT; 8215 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 8216 t = Bits32(opcode, 15, 12); 8217 n = Bits32(opcode, 19, 16); 8218 m = Bits32(opcode, 3, 0); 8219 8220 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 8221 // (W == '1'); 8222 index = BitIsSet(opcode, 24); 8223 add = BitIsSet(opcode, 23); 8224 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 8225 8226 // (shift_t, shift_n) = (SRType_LSL, 0); 8227 shift_t = SRType_LSL; 8228 shift_n = 0; 8229 8230 // if t == 15 || m == 15 then UNPREDICTABLE; 8231 if ((t == 15) || (m == 15)) 8232 return false; 8233 8234 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 8235 if (wback && ((n == 15) || (n == t))) 8236 return false; 8237 8238 break; 8239 8240 default: 8241 return false; 8242 } 8243 8244 uint64_t Rm = 8245 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8246 if (!success) 8247 return false; 8248 8249 uint64_t Rn = 8250 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 8251 if (!success) 8252 return false; 8253 8254 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 8255 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); 8256 if (!success) 8257 return false; 8258 8259 addr_t offset_addr; 8260 addr_t address; 8261 8262 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 8263 if (add) 8264 offset_addr = Rn + offset; 8265 else 8266 offset_addr = Rn - offset; 8267 8268 // address = if index then offset_addr else R[n]; 8269 if (index) 8270 address = offset_addr; 8271 else 8272 address = Rn; 8273 8274 // data = MemU[address,2]; 8275 std::optional<RegisterInfo> base_reg = 8276 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 8277 std::optional<RegisterInfo> offset_reg = 8278 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 8279 8280 EmulateInstruction::Context context; 8281 context.type = eContextRegisterLoad; 8282 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); 8283 8284 uint64_t data = MemURead(context, address, 2, 0, &success); 8285 if (!success) 8286 return false; 8287 8288 // if wback then R[n] = offset_addr; 8289 if (wback) { 8290 context.type = eContextAdjustBaseRegister; 8291 context.SetAddress(offset_addr); 8292 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 8293 offset_addr)) 8294 return false; 8295 } 8296 8297 // if UnalignedSupport() || address<0> = '0' then 8298 if (UnalignedSupport() || BitIsClear(address, 0)) { 8299 // R[t] = SignExtend(data, 32); 8300 context.type = eContextRegisterLoad; 8301 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); 8302 8303 int64_t signed_data = llvm::SignExtend64<16>(data); 8304 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 8305 (uint64_t)signed_data)) 8306 return false; 8307 } else // Can only apply before ARMv7 8308 { 8309 // R[t] = bits(32) UNKNOWN; 8310 WriteBits32Unknown(t); 8311 } 8312 } 8313 return true; 8314 } 8315 8316 // SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and 8317 // writes the result to the destination 8318 // register. You can specifiy a rotation by 0, 8, 16, or 24 bits before 8319 // extracting the 8-bit value. 8320 bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode, 8321 const ARMEncoding encoding) { 8322 #if 0 8323 if ConditionPassed() then 8324 EncodingSpecificOperations(); 8325 rotated = ROR(R[m], rotation); 8326 R[d] = SignExtend(rotated<7:0>, 32); 8327 #endif 8328 8329 bool success = false; 8330 8331 if (ConditionPassed(opcode)) { 8332 uint32_t d; 8333 uint32_t m; 8334 uint32_t rotation; 8335 8336 // EncodingSpecificOperations(); 8337 switch (encoding) { 8338 case eEncodingT1: 8339 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 8340 d = Bits32(opcode, 2, 0); 8341 m = Bits32(opcode, 5, 3); 8342 rotation = 0; 8343 8344 break; 8345 8346 case eEncodingT2: 8347 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8348 d = Bits32(opcode, 11, 8); 8349 m = Bits32(opcode, 3, 0); 8350 rotation = Bits32(opcode, 5, 4) << 3; 8351 8352 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 8353 if (BadReg(d) || BadReg(m)) 8354 return false; 8355 8356 break; 8357 8358 case eEncodingA1: 8359 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8360 d = Bits32(opcode, 15, 12); 8361 m = Bits32(opcode, 3, 0); 8362 rotation = Bits32(opcode, 11, 10) << 3; 8363 8364 // if d == 15 || m == 15 then UNPREDICTABLE; 8365 if ((d == 15) || (m == 15)) 8366 return false; 8367 8368 break; 8369 8370 default: 8371 return false; 8372 } 8373 8374 uint64_t Rm = 8375 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8376 if (!success) 8377 return false; 8378 8379 // rotated = ROR(R[m], rotation); 8380 uint64_t rotated = ROR(Rm, rotation, &success); 8381 if (!success) 8382 return false; 8383 8384 // R[d] = SignExtend(rotated<7:0>, 32); 8385 int64_t data = llvm::SignExtend64<8>(rotated); 8386 8387 std::optional<RegisterInfo> source_reg = 8388 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 8389 8390 EmulateInstruction::Context context; 8391 context.type = eContextRegisterLoad; 8392 context.SetRegister(*source_reg); 8393 8394 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 8395 (uint64_t)data)) 8396 return false; 8397 } 8398 return true; 8399 } 8400 8401 // SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and 8402 // writes the result to the destination 8403 // register. You can specify a rotation by 0, 8, 16, or 24 bits before 8404 // extracting the 16-bit value. 8405 bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode, 8406 const ARMEncoding encoding) { 8407 #if 0 8408 if ConditionPassed() then 8409 EncodingSpecificOperations(); 8410 rotated = ROR(R[m], rotation); 8411 R[d] = SignExtend(rotated<15:0>, 32); 8412 #endif 8413 8414 bool success = false; 8415 8416 if (ConditionPassed(opcode)) { 8417 uint32_t d; 8418 uint32_t m; 8419 uint32_t rotation; 8420 8421 // EncodingSpecificOperations(); 8422 switch (encoding) { 8423 case eEncodingT1: 8424 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 8425 d = Bits32(opcode, 2, 0); 8426 m = Bits32(opcode, 5, 3); 8427 rotation = 0; 8428 8429 break; 8430 8431 case eEncodingT2: 8432 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8433 d = Bits32(opcode, 11, 8); 8434 m = Bits32(opcode, 3, 0); 8435 rotation = Bits32(opcode, 5, 4) << 3; 8436 8437 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 8438 if (BadReg(d) || BadReg(m)) 8439 return false; 8440 8441 break; 8442 8443 case eEncodingA1: 8444 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8445 d = Bits32(opcode, 15, 12); 8446 m = Bits32(opcode, 3, 0); 8447 rotation = Bits32(opcode, 11, 10) << 3; 8448 8449 // if d == 15 || m == 15 then UNPREDICTABLE; 8450 if ((d == 15) || (m == 15)) 8451 return false; 8452 8453 break; 8454 8455 default: 8456 return false; 8457 } 8458 8459 uint64_t Rm = 8460 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8461 if (!success) 8462 return false; 8463 8464 // rotated = ROR(R[m], rotation); 8465 uint64_t rotated = ROR(Rm, rotation, &success); 8466 if (!success) 8467 return false; 8468 8469 // R[d] = SignExtend(rotated<15:0>, 32); 8470 std::optional<RegisterInfo> source_reg = 8471 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 8472 8473 EmulateInstruction::Context context; 8474 context.type = eContextRegisterLoad; 8475 context.SetRegister(*source_reg); 8476 8477 int64_t data = llvm::SignExtend64<16>(rotated); 8478 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 8479 (uint64_t)data)) 8480 return false; 8481 } 8482 8483 return true; 8484 } 8485 8486 // UXTB extracts an 8-bit value from a register, zero-extends it to 32 bits, and 8487 // writes the result to the destination 8488 // register. You can specify a rotation by 0, 8, 16, or 24 bits before 8489 // extracting the 8-bit value. 8490 bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode, 8491 const ARMEncoding encoding) { 8492 #if 0 8493 if ConditionPassed() then 8494 EncodingSpecificOperations(); 8495 rotated = ROR(R[m], rotation); 8496 R[d] = ZeroExtend(rotated<7:0>, 32); 8497 #endif 8498 8499 bool success = false; 8500 8501 if (ConditionPassed(opcode)) { 8502 uint32_t d; 8503 uint32_t m; 8504 uint32_t rotation; 8505 8506 // EncodingSpecificOperations(); 8507 switch (encoding) { 8508 case eEncodingT1: 8509 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 8510 d = Bits32(opcode, 2, 0); 8511 m = Bits32(opcode, 5, 3); 8512 rotation = 0; 8513 8514 break; 8515 8516 case eEncodingT2: 8517 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8518 d = Bits32(opcode, 11, 8); 8519 m = Bits32(opcode, 3, 0); 8520 rotation = Bits32(opcode, 5, 4) << 3; 8521 8522 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 8523 if (BadReg(d) || BadReg(m)) 8524 return false; 8525 8526 break; 8527 8528 case eEncodingA1: 8529 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8530 d = Bits32(opcode, 15, 12); 8531 m = Bits32(opcode, 3, 0); 8532 rotation = Bits32(opcode, 11, 10) << 3; 8533 8534 // if d == 15 || m == 15 then UNPREDICTABLE; 8535 if ((d == 15) || (m == 15)) 8536 return false; 8537 8538 break; 8539 8540 default: 8541 return false; 8542 } 8543 8544 uint64_t Rm = 8545 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8546 if (!success) 8547 return false; 8548 8549 // rotated = ROR(R[m], rotation); 8550 uint64_t rotated = ROR(Rm, rotation, &success); 8551 if (!success) 8552 return false; 8553 8554 // R[d] = ZeroExtend(rotated<7:0>, 32); 8555 std::optional<RegisterInfo> source_reg = 8556 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 8557 8558 EmulateInstruction::Context context; 8559 context.type = eContextRegisterLoad; 8560 context.SetRegister(*source_reg); 8561 8562 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 8563 Bits32(rotated, 7, 0))) 8564 return false; 8565 } 8566 return true; 8567 } 8568 8569 // UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and 8570 // writes the result to the destination 8571 // register. You can specify a rotation by 0, 8, 16, or 24 bits before 8572 // extracting the 16-bit value. 8573 bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode, 8574 const ARMEncoding encoding) { 8575 #if 0 8576 if ConditionPassed() then 8577 EncodingSpecificOperations(); 8578 rotated = ROR(R[m], rotation); 8579 R[d] = ZeroExtend(rotated<15:0>, 32); 8580 #endif 8581 8582 bool success = false; 8583 8584 if (ConditionPassed(opcode)) { 8585 uint32_t d; 8586 uint32_t m; 8587 uint32_t rotation; 8588 8589 switch (encoding) { 8590 case eEncodingT1: 8591 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 8592 d = Bits32(opcode, 2, 0); 8593 m = Bits32(opcode, 5, 3); 8594 rotation = 0; 8595 8596 break; 8597 8598 case eEncodingT2: 8599 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8600 d = Bits32(opcode, 11, 8); 8601 m = Bits32(opcode, 3, 0); 8602 rotation = Bits32(opcode, 5, 4) << 3; 8603 8604 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 8605 if (BadReg(d) || BadReg(m)) 8606 return false; 8607 8608 break; 8609 8610 case eEncodingA1: 8611 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8612 d = Bits32(opcode, 15, 12); 8613 m = Bits32(opcode, 3, 0); 8614 rotation = Bits32(opcode, 11, 10) << 3; 8615 8616 // if d == 15 || m == 15 then UNPREDICTABLE; 8617 if ((d == 15) || (m == 15)) 8618 return false; 8619 8620 break; 8621 8622 default: 8623 return false; 8624 } 8625 8626 uint64_t Rm = 8627 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8628 if (!success) 8629 return false; 8630 8631 // rotated = ROR(R[m], rotation); 8632 uint64_t rotated = ROR(Rm, rotation, &success); 8633 if (!success) 8634 return false; 8635 8636 // R[d] = ZeroExtend(rotated<15:0>, 32); 8637 std::optional<RegisterInfo> source_reg = 8638 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 8639 8640 EmulateInstruction::Context context; 8641 context.type = eContextRegisterLoad; 8642 context.SetRegister(*source_reg); 8643 8644 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 8645 Bits32(rotated, 15, 0))) 8646 return false; 8647 } 8648 return true; 8649 } 8650 8651 // RFE (Return From Exception) loads the PC and the CPSR from the word at the 8652 // specified address and the following 8653 // word respectively. 8654 bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode, 8655 const ARMEncoding encoding) { 8656 #if 0 8657 if ConditionPassed() then 8658 EncodingSpecificOperations(); 8659 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 8660 UNPREDICTABLE; 8661 else 8662 address = if increment then R[n] else R[n]-8; 8663 if wordhigher then address = address+4; 8664 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 8665 BranchWritePC(MemA[address,4]); 8666 if wback then R[n] = if increment then R[n]+8 else R[n]-8; 8667 #endif 8668 8669 bool success = false; 8670 8671 if (ConditionPassed(opcode)) { 8672 uint32_t n; 8673 bool wback; 8674 bool increment; 8675 bool wordhigher; 8676 8677 // EncodingSpecificOperations(); 8678 switch (encoding) { 8679 case eEncodingT1: 8680 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = 8681 // FALSE; 8682 n = Bits32(opcode, 19, 16); 8683 wback = BitIsSet(opcode, 21); 8684 increment = false; 8685 wordhigher = false; 8686 8687 // if n == 15 then UNPREDICTABLE; 8688 if (n == 15) 8689 return false; 8690 8691 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 8692 if (InITBlock() && !LastInITBlock()) 8693 return false; 8694 8695 break; 8696 8697 case eEncodingT2: 8698 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE; 8699 n = Bits32(opcode, 19, 16); 8700 wback = BitIsSet(opcode, 21); 8701 increment = true; 8702 wordhigher = false; 8703 8704 // if n == 15 then UNPREDICTABLE; 8705 if (n == 15) 8706 return false; 8707 8708 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 8709 if (InITBlock() && !LastInITBlock()) 8710 return false; 8711 8712 break; 8713 8714 case eEncodingA1: 8715 // n = UInt(Rn); 8716 n = Bits32(opcode, 19, 16); 8717 8718 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U); 8719 wback = BitIsSet(opcode, 21); 8720 increment = BitIsSet(opcode, 23); 8721 wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23)); 8722 8723 // if n == 15 then UNPREDICTABLE; 8724 if (n == 15) 8725 return false; 8726 8727 break; 8728 8729 default: 8730 return false; 8731 } 8732 8733 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE 8734 // then 8735 if (!CurrentModeIsPrivileged()) 8736 // UNPREDICTABLE; 8737 return false; 8738 else { 8739 uint64_t Rn = 8740 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 8741 if (!success) 8742 return false; 8743 8744 addr_t address; 8745 // address = if increment then R[n] else R[n]-8; 8746 if (increment) 8747 address = Rn; 8748 else 8749 address = Rn - 8; 8750 8751 // if wordhigher then address = address+4; 8752 if (wordhigher) 8753 address = address + 4; 8754 8755 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 8756 std::optional<RegisterInfo> base_reg = 8757 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 8758 8759 EmulateInstruction::Context context; 8760 context.type = eContextReturnFromException; 8761 context.SetRegisterPlusOffset(*base_reg, address - Rn); 8762 8763 uint64_t data = MemARead(context, address + 4, 4, 0, &success); 8764 if (!success) 8765 return false; 8766 8767 CPSRWriteByInstr(data, 15, true); 8768 8769 // BranchWritePC(MemA[address,4]); 8770 uint64_t data2 = MemARead(context, address, 4, 0, &success); 8771 if (!success) 8772 return false; 8773 8774 BranchWritePC(context, data2); 8775 8776 // if wback then R[n] = if increment then R[n]+8 else R[n]-8; 8777 if (wback) { 8778 context.type = eContextAdjustBaseRegister; 8779 if (increment) { 8780 context.SetOffset(8); 8781 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 8782 Rn + 8)) 8783 return false; 8784 } else { 8785 context.SetOffset(-8); 8786 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 8787 Rn - 8)) 8788 return false; 8789 } 8790 } // if wback 8791 } 8792 } // if ConditionPassed() 8793 return true; 8794 } 8795 8796 // Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a 8797 // register value and an immediate value, and writes the result to the 8798 // destination register. It can optionally update the condition flags based on 8799 // the result. 8800 bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode, 8801 const ARMEncoding encoding) { 8802 #if 0 8803 // ARM pseudo code... 8804 if ConditionPassed() then 8805 EncodingSpecificOperations(); 8806 result = R[n] EOR imm32; 8807 if d == 15 then // Can only occur for ARM encoding 8808 ALUWritePC(result); // setflags is always FALSE here 8809 else 8810 R[d] = result; 8811 if setflags then 8812 APSR.N = result<31>; 8813 APSR.Z = IsZeroBit(result); 8814 APSR.C = carry; 8815 // APSR.V unchanged 8816 #endif 8817 8818 bool success = false; 8819 8820 if (ConditionPassed(opcode)) { 8821 uint32_t Rd, Rn; 8822 uint32_t 8823 imm32; // the immediate value to be ORed to the value obtained from Rn 8824 bool setflags; 8825 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8826 switch (encoding) { 8827 case eEncodingT1: 8828 Rd = Bits32(opcode, 11, 8); 8829 Rn = Bits32(opcode, 19, 16); 8830 setflags = BitIsSet(opcode, 20); 8831 imm32 = ThumbExpandImm_C( 8832 opcode, APSR_C, 8833 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8834 // if Rd == '1111' && S == '1' then SEE TEQ (immediate); 8835 if (Rd == 15 && setflags) 8836 return EmulateTEQImm(opcode, eEncodingT1); 8837 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 8838 return false; 8839 break; 8840 case eEncodingA1: 8841 Rd = Bits32(opcode, 15, 12); 8842 Rn = Bits32(opcode, 19, 16); 8843 setflags = BitIsSet(opcode, 20); 8844 imm32 = 8845 ARMExpandImm_C(opcode, APSR_C, 8846 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8847 8848 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 8849 // instructions; 8850 if (Rd == 15 && setflags) 8851 return EmulateSUBSPcLrEtc(opcode, encoding); 8852 break; 8853 default: 8854 return false; 8855 } 8856 8857 // Read the first operand. 8858 uint32_t val1 = ReadCoreReg(Rn, &success); 8859 if (!success) 8860 return false; 8861 8862 uint32_t result = val1 ^ imm32; 8863 8864 EmulateInstruction::Context context; 8865 context.type = EmulateInstruction::eContextImmediate; 8866 context.SetNoArgs(); 8867 8868 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8869 return false; 8870 } 8871 return true; 8872 } 8873 8874 // Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a 8875 // register value and an optionally-shifted register value, and writes the 8876 // result to the destination register. It can optionally update the condition 8877 // flags based on the result. 8878 bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode, 8879 const ARMEncoding encoding) { 8880 #if 0 8881 // ARM pseudo code... 8882 if ConditionPassed() then 8883 EncodingSpecificOperations(); 8884 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8885 result = R[n] EOR shifted; 8886 if d == 15 then // Can only occur for ARM encoding 8887 ALUWritePC(result); // setflags is always FALSE here 8888 else 8889 R[d] = result; 8890 if setflags then 8891 APSR.N = result<31>; 8892 APSR.Z = IsZeroBit(result); 8893 APSR.C = carry; 8894 // APSR.V unchanged 8895 #endif 8896 8897 bool success = false; 8898 8899 if (ConditionPassed(opcode)) { 8900 uint32_t Rd, Rn, Rm; 8901 ARM_ShifterType shift_t; 8902 uint32_t shift_n; // the shift applied to the value read from Rm 8903 bool setflags; 8904 uint32_t carry; 8905 switch (encoding) { 8906 case eEncodingT1: 8907 Rd = Rn = Bits32(opcode, 2, 0); 8908 Rm = Bits32(opcode, 5, 3); 8909 setflags = !InITBlock(); 8910 shift_t = SRType_LSL; 8911 shift_n = 0; 8912 break; 8913 case eEncodingT2: 8914 Rd = Bits32(opcode, 11, 8); 8915 Rn = Bits32(opcode, 19, 16); 8916 Rm = Bits32(opcode, 3, 0); 8917 setflags = BitIsSet(opcode, 20); 8918 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8919 // if Rd == '1111' && S == '1' then SEE TEQ (register); 8920 if (Rd == 15 && setflags) 8921 return EmulateTEQReg(opcode, eEncodingT1); 8922 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 8923 return false; 8924 break; 8925 case eEncodingA1: 8926 Rd = Bits32(opcode, 15, 12); 8927 Rn = Bits32(opcode, 19, 16); 8928 Rm = Bits32(opcode, 3, 0); 8929 setflags = BitIsSet(opcode, 20); 8930 shift_n = DecodeImmShiftARM(opcode, shift_t); 8931 8932 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 8933 // instructions; 8934 if (Rd == 15 && setflags) 8935 return EmulateSUBSPcLrEtc(opcode, encoding); 8936 break; 8937 default: 8938 return false; 8939 } 8940 8941 // Read the first operand. 8942 uint32_t val1 = ReadCoreReg(Rn, &success); 8943 if (!success) 8944 return false; 8945 8946 // Read the second operand. 8947 uint32_t val2 = ReadCoreReg(Rm, &success); 8948 if (!success) 8949 return false; 8950 8951 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 8952 if (!success) 8953 return false; 8954 uint32_t result = val1 ^ shifted; 8955 8956 EmulateInstruction::Context context; 8957 context.type = EmulateInstruction::eContextImmediate; 8958 context.SetNoArgs(); 8959 8960 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8961 return false; 8962 } 8963 return true; 8964 } 8965 8966 // Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value 8967 // and an immediate value, and writes the result to the destination register. 8968 // It can optionally update the condition flags based on the result. 8969 bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode, 8970 const ARMEncoding encoding) { 8971 #if 0 8972 // ARM pseudo code... 8973 if ConditionPassed() then 8974 EncodingSpecificOperations(); 8975 result = R[n] OR imm32; 8976 if d == 15 then // Can only occur for ARM encoding 8977 ALUWritePC(result); // setflags is always FALSE here 8978 else 8979 R[d] = result; 8980 if setflags then 8981 APSR.N = result<31>; 8982 APSR.Z = IsZeroBit(result); 8983 APSR.C = carry; 8984 // APSR.V unchanged 8985 #endif 8986 8987 bool success = false; 8988 8989 if (ConditionPassed(opcode)) { 8990 uint32_t Rd, Rn; 8991 uint32_t 8992 imm32; // the immediate value to be ORed to the value obtained from Rn 8993 bool setflags; 8994 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8995 switch (encoding) { 8996 case eEncodingT1: 8997 Rd = Bits32(opcode, 11, 8); 8998 Rn = Bits32(opcode, 19, 16); 8999 setflags = BitIsSet(opcode, 20); 9000 imm32 = ThumbExpandImm_C( 9001 opcode, APSR_C, 9002 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9003 // if Rn == '1111' then SEE MOV (immediate); 9004 if (Rn == 15) 9005 return EmulateMOVRdImm(opcode, eEncodingT2); 9006 if (BadReg(Rd) || Rn == 13) 9007 return false; 9008 break; 9009 case eEncodingA1: 9010 Rd = Bits32(opcode, 15, 12); 9011 Rn = Bits32(opcode, 19, 16); 9012 setflags = BitIsSet(opcode, 20); 9013 imm32 = 9014 ARMExpandImm_C(opcode, APSR_C, 9015 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9016 9017 if (Rd == 15 && setflags) 9018 return EmulateSUBSPcLrEtc(opcode, encoding); 9019 break; 9020 default: 9021 return false; 9022 } 9023 9024 // Read the first operand. 9025 uint32_t val1 = ReadCoreReg(Rn, &success); 9026 if (!success) 9027 return false; 9028 9029 uint32_t result = val1 | imm32; 9030 9031 EmulateInstruction::Context context; 9032 context.type = EmulateInstruction::eContextImmediate; 9033 context.SetNoArgs(); 9034 9035 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 9036 return false; 9037 } 9038 return true; 9039 } 9040 9041 // Bitwise OR (register) performs a bitwise (inclusive) OR of a register value 9042 // and an optionally-shifted register value, and writes the result to the 9043 // destination register. It can optionally update the condition flags based on 9044 // the result. 9045 bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode, 9046 const ARMEncoding encoding) { 9047 #if 0 9048 // ARM pseudo code... 9049 if ConditionPassed() then 9050 EncodingSpecificOperations(); 9051 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9052 result = R[n] OR shifted; 9053 if d == 15 then // Can only occur for ARM encoding 9054 ALUWritePC(result); // setflags is always FALSE here 9055 else 9056 R[d] = result; 9057 if setflags then 9058 APSR.N = result<31>; 9059 APSR.Z = IsZeroBit(result); 9060 APSR.C = carry; 9061 // APSR.V unchanged 9062 #endif 9063 9064 bool success = false; 9065 9066 if (ConditionPassed(opcode)) { 9067 uint32_t Rd, Rn, Rm; 9068 ARM_ShifterType shift_t; 9069 uint32_t shift_n; // the shift applied to the value read from Rm 9070 bool setflags; 9071 uint32_t carry; 9072 switch (encoding) { 9073 case eEncodingT1: 9074 Rd = Rn = Bits32(opcode, 2, 0); 9075 Rm = Bits32(opcode, 5, 3); 9076 setflags = !InITBlock(); 9077 shift_t = SRType_LSL; 9078 shift_n = 0; 9079 break; 9080 case eEncodingT2: 9081 Rd = Bits32(opcode, 11, 8); 9082 Rn = Bits32(opcode, 19, 16); 9083 Rm = Bits32(opcode, 3, 0); 9084 setflags = BitIsSet(opcode, 20); 9085 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9086 // if Rn == '1111' then SEE MOV (register); 9087 if (Rn == 15) 9088 return EmulateMOVRdRm(opcode, eEncodingT3); 9089 if (BadReg(Rd) || Rn == 13 || BadReg(Rm)) 9090 return false; 9091 break; 9092 case eEncodingA1: 9093 Rd = Bits32(opcode, 15, 12); 9094 Rn = Bits32(opcode, 19, 16); 9095 Rm = Bits32(opcode, 3, 0); 9096 setflags = BitIsSet(opcode, 20); 9097 shift_n = DecodeImmShiftARM(opcode, shift_t); 9098 9099 if (Rd == 15 && setflags) 9100 return EmulateSUBSPcLrEtc(opcode, encoding); 9101 break; 9102 default: 9103 return false; 9104 } 9105 9106 // Read the first operand. 9107 uint32_t val1 = ReadCoreReg(Rn, &success); 9108 if (!success) 9109 return false; 9110 9111 // Read the second operand. 9112 uint32_t val2 = ReadCoreReg(Rm, &success); 9113 if (!success) 9114 return false; 9115 9116 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 9117 if (!success) 9118 return false; 9119 uint32_t result = val1 | shifted; 9120 9121 EmulateInstruction::Context context; 9122 context.type = EmulateInstruction::eContextImmediate; 9123 context.SetNoArgs(); 9124 9125 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 9126 return false; 9127 } 9128 return true; 9129 } 9130 9131 // Reverse Subtract (immediate) subtracts a register value from an immediate 9132 // value, and writes the result to the destination register. It can optionally 9133 // update the condition flags based on the result. 9134 bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode, 9135 const ARMEncoding encoding) { 9136 #if 0 9137 // ARM pseudo code... 9138 if ConditionPassed() then 9139 EncodingSpecificOperations(); 9140 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1'); 9141 if d == 15 then // Can only occur for ARM encoding 9142 ALUWritePC(result); // setflags is always FALSE here 9143 else 9144 R[d] = result; 9145 if setflags then 9146 APSR.N = result<31>; 9147 APSR.Z = IsZeroBit(result); 9148 APSR.C = carry; 9149 APSR.V = overflow; 9150 #endif 9151 9152 bool success = false; 9153 9154 uint32_t Rd; // the destination register 9155 uint32_t Rn; // the first operand 9156 bool setflags; 9157 uint32_t 9158 imm32; // the immediate value to be added to the value obtained from Rn 9159 switch (encoding) { 9160 case eEncodingT1: 9161 Rd = Bits32(opcode, 2, 0); 9162 Rn = Bits32(opcode, 5, 3); 9163 setflags = !InITBlock(); 9164 imm32 = 0; 9165 break; 9166 case eEncodingT2: 9167 Rd = Bits32(opcode, 11, 8); 9168 Rn = Bits32(opcode, 19, 16); 9169 setflags = BitIsSet(opcode, 20); 9170 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 9171 if (BadReg(Rd) || BadReg(Rn)) 9172 return false; 9173 break; 9174 case eEncodingA1: 9175 Rd = Bits32(opcode, 15, 12); 9176 Rn = Bits32(opcode, 19, 16); 9177 setflags = BitIsSet(opcode, 20); 9178 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 9179 9180 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9181 // instructions; 9182 if (Rd == 15 && setflags) 9183 return EmulateSUBSPcLrEtc(opcode, encoding); 9184 break; 9185 default: 9186 return false; 9187 } 9188 // Read the register value from the operand register Rn. 9189 uint32_t reg_val = ReadCoreReg(Rn, &success); 9190 if (!success) 9191 return false; 9192 9193 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1); 9194 9195 EmulateInstruction::Context context; 9196 context.type = EmulateInstruction::eContextImmediate; 9197 context.SetNoArgs(); 9198 9199 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9200 res.carry_out, res.overflow); 9201 } 9202 9203 // Reverse Subtract (register) subtracts a register value from an optionally- 9204 // shifted register value, and writes the result to the destination register. 9205 // It can optionally update the condition flags based on the result. 9206 bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode, 9207 const ARMEncoding encoding) { 9208 #if 0 9209 // ARM pseudo code... 9210 if ConditionPassed() then 9211 EncodingSpecificOperations(); 9212 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9213 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1'); 9214 if d == 15 then // Can only occur for ARM encoding 9215 ALUWritePC(result); // setflags is always FALSE here 9216 else 9217 R[d] = result; 9218 if setflags then 9219 APSR.N = result<31>; 9220 APSR.Z = IsZeroBit(result); 9221 APSR.C = carry; 9222 APSR.V = overflow; 9223 #endif 9224 9225 bool success = false; 9226 9227 uint32_t Rd; // the destination register 9228 uint32_t Rn; // the first operand 9229 uint32_t Rm; // the second operand 9230 bool setflags; 9231 ARM_ShifterType shift_t; 9232 uint32_t shift_n; // the shift applied to the value read from Rm 9233 switch (encoding) { 9234 case eEncodingT1: 9235 Rd = Bits32(opcode, 11, 8); 9236 Rn = Bits32(opcode, 19, 16); 9237 Rm = Bits32(opcode, 3, 0); 9238 setflags = BitIsSet(opcode, 20); 9239 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9240 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 9241 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 9242 return false; 9243 break; 9244 case eEncodingA1: 9245 Rd = Bits32(opcode, 15, 12); 9246 Rn = Bits32(opcode, 19, 16); 9247 Rm = Bits32(opcode, 3, 0); 9248 setflags = BitIsSet(opcode, 20); 9249 shift_n = DecodeImmShiftARM(opcode, shift_t); 9250 9251 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9252 // instructions; 9253 if (Rd == 15 && setflags) 9254 return EmulateSUBSPcLrEtc(opcode, encoding); 9255 break; 9256 default: 9257 return false; 9258 } 9259 // Read the register value from register Rn. 9260 uint32_t val1 = ReadCoreReg(Rn, &success); 9261 if (!success) 9262 return false; 9263 9264 // Read the register value from register Rm. 9265 uint32_t val2 = ReadCoreReg(Rm, &success); 9266 if (!success) 9267 return false; 9268 9269 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 9270 if (!success) 9271 return false; 9272 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1); 9273 9274 EmulateInstruction::Context context; 9275 context.type = EmulateInstruction::eContextImmediate; 9276 context.SetNoArgs(); 9277 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9278 res.carry_out, res.overflow); 9279 } 9280 9281 // Reverse Subtract with Carry (immediate) subtracts a register value and the 9282 // value of NOT (Carry flag) from an immediate value, and writes the result to 9283 // the destination register. It can optionally update the condition flags based 9284 // on the result. 9285 bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode, 9286 const ARMEncoding encoding) { 9287 #if 0 9288 // ARM pseudo code... 9289 if ConditionPassed() then 9290 EncodingSpecificOperations(); 9291 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C); 9292 if d == 15 then 9293 ALUWritePC(result); // setflags is always FALSE here 9294 else 9295 R[d] = result; 9296 if setflags then 9297 APSR.N = result<31>; 9298 APSR.Z = IsZeroBit(result); 9299 APSR.C = carry; 9300 APSR.V = overflow; 9301 #endif 9302 9303 bool success = false; 9304 9305 uint32_t Rd; // the destination register 9306 uint32_t Rn; // the first operand 9307 bool setflags; 9308 uint32_t 9309 imm32; // the immediate value to be added to the value obtained from Rn 9310 switch (encoding) { 9311 case eEncodingA1: 9312 Rd = Bits32(opcode, 15, 12); 9313 Rn = Bits32(opcode, 19, 16); 9314 setflags = BitIsSet(opcode, 20); 9315 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 9316 9317 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9318 // instructions; 9319 if (Rd == 15 && setflags) 9320 return EmulateSUBSPcLrEtc(opcode, encoding); 9321 break; 9322 default: 9323 return false; 9324 } 9325 // Read the register value from the operand register Rn. 9326 uint32_t reg_val = ReadCoreReg(Rn, &success); 9327 if (!success) 9328 return false; 9329 9330 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C); 9331 9332 EmulateInstruction::Context context; 9333 context.type = EmulateInstruction::eContextImmediate; 9334 context.SetNoArgs(); 9335 9336 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9337 res.carry_out, res.overflow); 9338 } 9339 9340 // Reverse Subtract with Carry (register) subtracts a register value and the 9341 // value of NOT (Carry flag) from an optionally-shifted register value, and 9342 // writes the result to the destination register. It can optionally update the 9343 // condition flags based on the result. 9344 bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode, 9345 const ARMEncoding encoding) { 9346 #if 0 9347 // ARM pseudo code... 9348 if ConditionPassed() then 9349 EncodingSpecificOperations(); 9350 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9351 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C); 9352 if d == 15 then 9353 ALUWritePC(result); // setflags is always FALSE here 9354 else 9355 R[d] = result; 9356 if setflags then 9357 APSR.N = result<31>; 9358 APSR.Z = IsZeroBit(result); 9359 APSR.C = carry; 9360 APSR.V = overflow; 9361 #endif 9362 9363 bool success = false; 9364 9365 uint32_t Rd; // the destination register 9366 uint32_t Rn; // the first operand 9367 uint32_t Rm; // the second operand 9368 bool setflags; 9369 ARM_ShifterType shift_t; 9370 uint32_t shift_n; // the shift applied to the value read from Rm 9371 switch (encoding) { 9372 case eEncodingA1: 9373 Rd = Bits32(opcode, 15, 12); 9374 Rn = Bits32(opcode, 19, 16); 9375 Rm = Bits32(opcode, 3, 0); 9376 setflags = BitIsSet(opcode, 20); 9377 shift_n = DecodeImmShiftARM(opcode, shift_t); 9378 9379 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9380 // instructions; 9381 if (Rd == 15 && setflags) 9382 return EmulateSUBSPcLrEtc(opcode, encoding); 9383 break; 9384 default: 9385 return false; 9386 } 9387 // Read the register value from register Rn. 9388 uint32_t val1 = ReadCoreReg(Rn, &success); 9389 if (!success) 9390 return false; 9391 9392 // Read the register value from register Rm. 9393 uint32_t val2 = ReadCoreReg(Rm, &success); 9394 if (!success) 9395 return false; 9396 9397 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 9398 if (!success) 9399 return false; 9400 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C); 9401 9402 EmulateInstruction::Context context; 9403 context.type = EmulateInstruction::eContextImmediate; 9404 context.SetNoArgs(); 9405 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9406 res.carry_out, res.overflow); 9407 } 9408 9409 // Subtract with Carry (immediate) subtracts an immediate value and the value 9410 // of 9411 // NOT (Carry flag) from a register value, and writes the result to the 9412 // destination register. 9413 // It can optionally update the condition flags based on the result. 9414 bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode, 9415 const ARMEncoding encoding) { 9416 #if 0 9417 // ARM pseudo code... 9418 if ConditionPassed() then 9419 EncodingSpecificOperations(); 9420 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C); 9421 if d == 15 then // Can only occur for ARM encoding 9422 ALUWritePC(result); // setflags is always FALSE here 9423 else 9424 R[d] = result; 9425 if setflags then 9426 APSR.N = result<31>; 9427 APSR.Z = IsZeroBit(result); 9428 APSR.C = carry; 9429 APSR.V = overflow; 9430 #endif 9431 9432 bool success = false; 9433 9434 uint32_t Rd; // the destination register 9435 uint32_t Rn; // the first operand 9436 bool setflags; 9437 uint32_t 9438 imm32; // the immediate value to be added to the value obtained from Rn 9439 switch (encoding) { 9440 case eEncodingT1: 9441 Rd = Bits32(opcode, 11, 8); 9442 Rn = Bits32(opcode, 19, 16); 9443 setflags = BitIsSet(opcode, 20); 9444 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 9445 if (BadReg(Rd) || BadReg(Rn)) 9446 return false; 9447 break; 9448 case eEncodingA1: 9449 Rd = Bits32(opcode, 15, 12); 9450 Rn = Bits32(opcode, 19, 16); 9451 setflags = BitIsSet(opcode, 20); 9452 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 9453 9454 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9455 // instructions; 9456 if (Rd == 15 && setflags) 9457 return EmulateSUBSPcLrEtc(opcode, encoding); 9458 break; 9459 default: 9460 return false; 9461 } 9462 // Read the register value from the operand register Rn. 9463 uint32_t reg_val = ReadCoreReg(Rn, &success); 9464 if (!success) 9465 return false; 9466 9467 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C); 9468 9469 EmulateInstruction::Context context; 9470 context.type = EmulateInstruction::eContextImmediate; 9471 context.SetNoArgs(); 9472 9473 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9474 res.carry_out, res.overflow); 9475 } 9476 9477 // Subtract with Carry (register) subtracts an optionally-shifted register 9478 // value and the value of 9479 // NOT (Carry flag) from a register value, and writes the result to the 9480 // destination register. 9481 // It can optionally update the condition flags based on the result. 9482 bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode, 9483 const ARMEncoding encoding) { 9484 #if 0 9485 // ARM pseudo code... 9486 if ConditionPassed() then 9487 EncodingSpecificOperations(); 9488 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9489 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C); 9490 if d == 15 then // Can only occur for ARM encoding 9491 ALUWritePC(result); // setflags is always FALSE here 9492 else 9493 R[d] = result; 9494 if setflags then 9495 APSR.N = result<31>; 9496 APSR.Z = IsZeroBit(result); 9497 APSR.C = carry; 9498 APSR.V = overflow; 9499 #endif 9500 9501 bool success = false; 9502 9503 uint32_t Rd; // the destination register 9504 uint32_t Rn; // the first operand 9505 uint32_t Rm; // the second operand 9506 bool setflags; 9507 ARM_ShifterType shift_t; 9508 uint32_t shift_n; // the shift applied to the value read from Rm 9509 switch (encoding) { 9510 case eEncodingT1: 9511 Rd = Rn = Bits32(opcode, 2, 0); 9512 Rm = Bits32(opcode, 5, 3); 9513 setflags = !InITBlock(); 9514 shift_t = SRType_LSL; 9515 shift_n = 0; 9516 break; 9517 case eEncodingT2: 9518 Rd = Bits32(opcode, 11, 8); 9519 Rn = Bits32(opcode, 19, 16); 9520 Rm = Bits32(opcode, 3, 0); 9521 setflags = BitIsSet(opcode, 20); 9522 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9523 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 9524 return false; 9525 break; 9526 case eEncodingA1: 9527 Rd = Bits32(opcode, 15, 12); 9528 Rn = Bits32(opcode, 19, 16); 9529 Rm = Bits32(opcode, 3, 0); 9530 setflags = BitIsSet(opcode, 20); 9531 shift_n = DecodeImmShiftARM(opcode, shift_t); 9532 9533 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9534 // instructions; 9535 if (Rd == 15 && setflags) 9536 return EmulateSUBSPcLrEtc(opcode, encoding); 9537 break; 9538 default: 9539 return false; 9540 } 9541 // Read the register value from register Rn. 9542 uint32_t val1 = ReadCoreReg(Rn, &success); 9543 if (!success) 9544 return false; 9545 9546 // Read the register value from register Rm. 9547 uint32_t val2 = ReadCoreReg(Rm, &success); 9548 if (!success) 9549 return false; 9550 9551 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 9552 if (!success) 9553 return false; 9554 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C); 9555 9556 EmulateInstruction::Context context; 9557 context.type = EmulateInstruction::eContextImmediate; 9558 context.SetNoArgs(); 9559 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9560 res.carry_out, res.overflow); 9561 } 9562 9563 // This instruction subtracts an immediate value from a register value, and 9564 // writes the result to the destination register. It can optionally update the 9565 // condition flags based on the result. 9566 bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode, 9567 const ARMEncoding encoding) { 9568 #if 0 9569 // ARM pseudo code... 9570 if ConditionPassed() then 9571 EncodingSpecificOperations(); 9572 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 9573 R[d] = result; 9574 if setflags then 9575 APSR.N = result<31>; 9576 APSR.Z = IsZeroBit(result); 9577 APSR.C = carry; 9578 APSR.V = overflow; 9579 #endif 9580 9581 bool success = false; 9582 9583 uint32_t Rd; // the destination register 9584 uint32_t Rn; // the first operand 9585 bool setflags; 9586 uint32_t imm32; // the immediate value to be subtracted from the value 9587 // obtained from Rn 9588 switch (encoding) { 9589 case eEncodingT1: 9590 Rd = Bits32(opcode, 2, 0); 9591 Rn = Bits32(opcode, 5, 3); 9592 setflags = !InITBlock(); 9593 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32) 9594 break; 9595 case eEncodingT2: 9596 Rd = Rn = Bits32(opcode, 10, 8); 9597 setflags = !InITBlock(); 9598 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 9599 break; 9600 case eEncodingT3: 9601 Rd = Bits32(opcode, 11, 8); 9602 Rn = Bits32(opcode, 19, 16); 9603 setflags = BitIsSet(opcode, 20); 9604 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 9605 9606 // if Rd == '1111' && S == '1' then SEE CMP (immediate); 9607 if (Rd == 15 && setflags) 9608 return EmulateCMPImm(opcode, eEncodingT2); 9609 9610 // if Rn == '1101' then SEE SUB (SP minus immediate); 9611 if (Rn == 13) 9612 return EmulateSUBSPImm(opcode, eEncodingT2); 9613 9614 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE; 9615 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15) 9616 return false; 9617 break; 9618 case eEncodingT4: 9619 Rd = Bits32(opcode, 11, 8); 9620 Rn = Bits32(opcode, 19, 16); 9621 setflags = BitIsSet(opcode, 20); 9622 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 9623 9624 // if Rn == '1111' then SEE ADR; 9625 if (Rn == 15) 9626 return EmulateADR(opcode, eEncodingT2); 9627 9628 // if Rn == '1101' then SEE SUB (SP minus immediate); 9629 if (Rn == 13) 9630 return EmulateSUBSPImm(opcode, eEncodingT3); 9631 9632 if (BadReg(Rd)) 9633 return false; 9634 break; 9635 default: 9636 return false; 9637 } 9638 // Read the register value from the operand register Rn. 9639 uint32_t reg_val = ReadCoreReg(Rn, &success); 9640 if (!success) 9641 return false; 9642 9643 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 9644 9645 EmulateInstruction::Context context; 9646 context.type = EmulateInstruction::eContextImmediate; 9647 context.SetNoArgs(); 9648 9649 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9650 res.carry_out, res.overflow); 9651 } 9652 9653 // This instruction subtracts an immediate value from a register value, and 9654 // writes the result to the destination register. It can optionally update the 9655 // condition flags based on the result. 9656 bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode, 9657 const ARMEncoding encoding) { 9658 #if 0 9659 // ARM pseudo code... 9660 if ConditionPassed() then 9661 EncodingSpecificOperations(); 9662 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 9663 if d == 15 then 9664 ALUWritePC(result); // setflags is always FALSE here 9665 else 9666 R[d] = result; 9667 if setflags then 9668 APSR.N = result<31>; 9669 APSR.Z = IsZeroBit(result); 9670 APSR.C = carry; 9671 APSR.V = overflow; 9672 #endif 9673 9674 bool success = false; 9675 9676 if (ConditionPassed(opcode)) { 9677 uint32_t Rd; // the destination register 9678 uint32_t Rn; // the first operand 9679 bool setflags; 9680 uint32_t imm32; // the immediate value to be subtracted from the value 9681 // obtained from Rn 9682 switch (encoding) { 9683 case eEncodingA1: 9684 Rd = Bits32(opcode, 15, 12); 9685 Rn = Bits32(opcode, 19, 16); 9686 setflags = BitIsSet(opcode, 20); 9687 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 9688 9689 // if Rn == '1111' && S == '0' then SEE ADR; 9690 if (Rn == 15 && !setflags) 9691 return EmulateADR(opcode, eEncodingA2); 9692 9693 // if Rn == '1101' then SEE SUB (SP minus immediate); 9694 if (Rn == 13) 9695 return EmulateSUBSPImm(opcode, eEncodingA1); 9696 9697 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9698 // instructions; 9699 if (Rd == 15 && setflags) 9700 return EmulateSUBSPcLrEtc(opcode, encoding); 9701 break; 9702 default: 9703 return false; 9704 } 9705 // Read the register value from the operand register Rn. 9706 uint32_t reg_val = ReadCoreReg(Rn, &success); 9707 if (!success) 9708 return false; 9709 9710 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 9711 9712 EmulateInstruction::Context context; 9713 if (Rd == 13) 9714 context.type = EmulateInstruction::eContextAdjustStackPointer; 9715 else 9716 context.type = EmulateInstruction::eContextRegisterPlusOffset; 9717 9718 std::optional<RegisterInfo> dwarf_reg = 9719 GetRegisterInfo(eRegisterKindDWARF, Rn); 9720 int64_t imm32_signed = imm32; 9721 context.SetRegisterPlusOffset(*dwarf_reg, -imm32_signed); 9722 9723 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9724 res.carry_out, res.overflow)) 9725 return false; 9726 } 9727 return true; 9728 } 9729 9730 // Test Equivalence (immediate) performs a bitwise exclusive OR operation on a 9731 // register value and an immediate value. It updates the condition flags based 9732 // on the result, and discards the result. 9733 bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode, 9734 const ARMEncoding encoding) { 9735 #if 0 9736 // ARM pseudo code... 9737 if ConditionPassed() then 9738 EncodingSpecificOperations(); 9739 result = R[n] EOR imm32; 9740 APSR.N = result<31>; 9741 APSR.Z = IsZeroBit(result); 9742 APSR.C = carry; 9743 // APSR.V unchanged 9744 #endif 9745 9746 bool success = false; 9747 9748 if (ConditionPassed(opcode)) { 9749 uint32_t Rn; 9750 uint32_t 9751 imm32; // the immediate value to be ANDed to the value obtained from Rn 9752 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9753 switch (encoding) { 9754 case eEncodingT1: 9755 Rn = Bits32(opcode, 19, 16); 9756 imm32 = ThumbExpandImm_C( 9757 opcode, APSR_C, 9758 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9759 if (BadReg(Rn)) 9760 return false; 9761 break; 9762 case eEncodingA1: 9763 Rn = Bits32(opcode, 19, 16); 9764 imm32 = 9765 ARMExpandImm_C(opcode, APSR_C, 9766 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9767 break; 9768 default: 9769 return false; 9770 } 9771 9772 // Read the first operand. 9773 uint32_t val1 = ReadCoreReg(Rn, &success); 9774 if (!success) 9775 return false; 9776 9777 uint32_t result = val1 ^ imm32; 9778 9779 EmulateInstruction::Context context; 9780 context.type = EmulateInstruction::eContextImmediate; 9781 context.SetNoArgs(); 9782 9783 if (!WriteFlags(context, result, carry)) 9784 return false; 9785 } 9786 return true; 9787 } 9788 9789 // Test Equivalence (register) performs a bitwise exclusive OR operation on a 9790 // register value and an optionally-shifted register value. It updates the 9791 // condition flags based on the result, and discards the result. 9792 bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode, 9793 const ARMEncoding encoding) { 9794 #if 0 9795 // ARM pseudo code... 9796 if ConditionPassed() then 9797 EncodingSpecificOperations(); 9798 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9799 result = R[n] EOR shifted; 9800 APSR.N = result<31>; 9801 APSR.Z = IsZeroBit(result); 9802 APSR.C = carry; 9803 // APSR.V unchanged 9804 #endif 9805 9806 bool success = false; 9807 9808 if (ConditionPassed(opcode)) { 9809 uint32_t Rn, Rm; 9810 ARM_ShifterType shift_t; 9811 uint32_t shift_n; // the shift applied to the value read from Rm 9812 uint32_t carry; 9813 switch (encoding) { 9814 case eEncodingT1: 9815 Rn = Bits32(opcode, 19, 16); 9816 Rm = Bits32(opcode, 3, 0); 9817 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9818 if (BadReg(Rn) || BadReg(Rm)) 9819 return false; 9820 break; 9821 case eEncodingA1: 9822 Rn = Bits32(opcode, 19, 16); 9823 Rm = Bits32(opcode, 3, 0); 9824 shift_n = DecodeImmShiftARM(opcode, shift_t); 9825 break; 9826 default: 9827 return false; 9828 } 9829 9830 // Read the first operand. 9831 uint32_t val1 = ReadCoreReg(Rn, &success); 9832 if (!success) 9833 return false; 9834 9835 // Read the second operand. 9836 uint32_t val2 = ReadCoreReg(Rm, &success); 9837 if (!success) 9838 return false; 9839 9840 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 9841 if (!success) 9842 return false; 9843 uint32_t result = val1 ^ shifted; 9844 9845 EmulateInstruction::Context context; 9846 context.type = EmulateInstruction::eContextImmediate; 9847 context.SetNoArgs(); 9848 9849 if (!WriteFlags(context, result, carry)) 9850 return false; 9851 } 9852 return true; 9853 } 9854 9855 // Test (immediate) performs a bitwise AND operation on a register value and an 9856 // immediate value. It updates the condition flags based on the result, and 9857 // discards the result. 9858 bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode, 9859 const ARMEncoding encoding) { 9860 #if 0 9861 // ARM pseudo code... 9862 if ConditionPassed() then 9863 EncodingSpecificOperations(); 9864 result = R[n] AND imm32; 9865 APSR.N = result<31>; 9866 APSR.Z = IsZeroBit(result); 9867 APSR.C = carry; 9868 // APSR.V unchanged 9869 #endif 9870 9871 bool success = false; 9872 9873 if (ConditionPassed(opcode)) { 9874 uint32_t Rn; 9875 uint32_t 9876 imm32; // the immediate value to be ANDed to the value obtained from Rn 9877 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9878 switch (encoding) { 9879 case eEncodingT1: 9880 Rn = Bits32(opcode, 19, 16); 9881 imm32 = ThumbExpandImm_C( 9882 opcode, APSR_C, 9883 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9884 if (BadReg(Rn)) 9885 return false; 9886 break; 9887 case eEncodingA1: 9888 Rn = Bits32(opcode, 19, 16); 9889 imm32 = 9890 ARMExpandImm_C(opcode, APSR_C, 9891 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9892 break; 9893 default: 9894 return false; 9895 } 9896 9897 // Read the first operand. 9898 uint32_t val1 = ReadCoreReg(Rn, &success); 9899 if (!success) 9900 return false; 9901 9902 uint32_t result = val1 & imm32; 9903 9904 EmulateInstruction::Context context; 9905 context.type = EmulateInstruction::eContextImmediate; 9906 context.SetNoArgs(); 9907 9908 if (!WriteFlags(context, result, carry)) 9909 return false; 9910 } 9911 return true; 9912 } 9913 9914 // Test (register) performs a bitwise AND operation on a register value and an 9915 // optionally-shifted register value. It updates the condition flags based on 9916 // the result, and discards the result. 9917 bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode, 9918 const ARMEncoding encoding) { 9919 #if 0 9920 // ARM pseudo code... 9921 if ConditionPassed() then 9922 EncodingSpecificOperations(); 9923 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9924 result = R[n] AND shifted; 9925 APSR.N = result<31>; 9926 APSR.Z = IsZeroBit(result); 9927 APSR.C = carry; 9928 // APSR.V unchanged 9929 #endif 9930 9931 bool success = false; 9932 9933 if (ConditionPassed(opcode)) { 9934 uint32_t Rn, Rm; 9935 ARM_ShifterType shift_t; 9936 uint32_t shift_n; // the shift applied to the value read from Rm 9937 uint32_t carry; 9938 switch (encoding) { 9939 case eEncodingT1: 9940 Rn = Bits32(opcode, 2, 0); 9941 Rm = Bits32(opcode, 5, 3); 9942 shift_t = SRType_LSL; 9943 shift_n = 0; 9944 break; 9945 case eEncodingT2: 9946 Rn = Bits32(opcode, 19, 16); 9947 Rm = Bits32(opcode, 3, 0); 9948 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9949 if (BadReg(Rn) || BadReg(Rm)) 9950 return false; 9951 break; 9952 case eEncodingA1: 9953 Rn = Bits32(opcode, 19, 16); 9954 Rm = Bits32(opcode, 3, 0); 9955 shift_n = DecodeImmShiftARM(opcode, shift_t); 9956 break; 9957 default: 9958 return false; 9959 } 9960 9961 // Read the first operand. 9962 uint32_t val1 = ReadCoreReg(Rn, &success); 9963 if (!success) 9964 return false; 9965 9966 // Read the second operand. 9967 uint32_t val2 = ReadCoreReg(Rm, &success); 9968 if (!success) 9969 return false; 9970 9971 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 9972 if (!success) 9973 return false; 9974 uint32_t result = val1 & shifted; 9975 9976 EmulateInstruction::Context context; 9977 context.type = EmulateInstruction::eContextImmediate; 9978 context.SetNoArgs(); 9979 9980 if (!WriteFlags(context, result, carry)) 9981 return false; 9982 } 9983 return true; 9984 } 9985 9986 // A8.6.216 SUB (SP minus register) 9987 bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode, 9988 const ARMEncoding encoding) { 9989 #if 0 9990 if ConditionPassed() then 9991 EncodingSpecificOperations(); 9992 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9993 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1'); 9994 if d == 15 then // Can only occur for ARM encoding 9995 ALUWritePC(result); // setflags is always FALSE here 9996 else 9997 R[d] = result; 9998 if setflags then 9999 APSR.N = result<31>; 10000 APSR.Z = IsZeroBit(result); 10001 APSR.C = carry; 10002 APSR.V = overflow; 10003 #endif 10004 10005 bool success = false; 10006 10007 if (ConditionPassed(opcode)) { 10008 uint32_t d; 10009 uint32_t m; 10010 bool setflags; 10011 ARM_ShifterType shift_t; 10012 uint32_t shift_n; 10013 10014 switch (encoding) { 10015 case eEncodingT1: 10016 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); 10017 d = Bits32(opcode, 11, 8); 10018 m = Bits32(opcode, 3, 0); 10019 setflags = BitIsSet(opcode, 20); 10020 10021 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 10022 shift_n = DecodeImmShiftThumb(opcode, shift_t); 10023 10024 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then 10025 // UNPREDICTABLE; 10026 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3))) 10027 return false; 10028 10029 // if d == 15 || BadReg(m) then UNPREDICTABLE; 10030 if ((d == 15) || BadReg(m)) 10031 return false; 10032 break; 10033 10034 case eEncodingA1: 10035 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); 10036 d = Bits32(opcode, 15, 12); 10037 m = Bits32(opcode, 3, 0); 10038 setflags = BitIsSet(opcode, 20); 10039 10040 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 10041 // instructions; 10042 if (d == 15 && setflags) 10043 EmulateSUBSPcLrEtc(opcode, encoding); 10044 10045 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 10046 shift_n = DecodeImmShiftARM(opcode, shift_t); 10047 break; 10048 10049 default: 10050 return false; 10051 } 10052 10053 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 10054 uint32_t Rm = ReadCoreReg(m, &success); 10055 if (!success) 10056 return false; 10057 10058 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success); 10059 if (!success) 10060 return false; 10061 10062 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1'); 10063 uint32_t sp_val = ReadCoreReg(SP_REG, &success); 10064 if (!success) 10065 return false; 10066 10067 AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1); 10068 10069 EmulateInstruction::Context context; 10070 context.type = eContextArithmetic; 10071 std::optional<RegisterInfo> sp_reg = 10072 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 10073 std::optional<RegisterInfo> dwarf_reg = 10074 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 10075 context.SetRegisterRegisterOperands(*sp_reg, *dwarf_reg); 10076 10077 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, 10078 res.carry_out, res.overflow)) 10079 return false; 10080 } 10081 return true; 10082 } 10083 10084 // A8.6.7 ADD (register-shifted register) 10085 bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode, 10086 const ARMEncoding encoding) { 10087 #if 0 10088 if ConditionPassed() then 10089 EncodingSpecificOperations(); 10090 shift_n = UInt(R[s]<7:0>); 10091 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 10092 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 10093 R[d] = result; 10094 if setflags then 10095 APSR.N = result<31>; 10096 APSR.Z = IsZeroBit(result); 10097 APSR.C = carry; 10098 APSR.V = overflow; 10099 #endif 10100 10101 bool success = false; 10102 10103 if (ConditionPassed(opcode)) { 10104 uint32_t d; 10105 uint32_t n; 10106 uint32_t m; 10107 uint32_t s; 10108 bool setflags; 10109 ARM_ShifterType shift_t; 10110 10111 switch (encoding) { 10112 case eEncodingA1: 10113 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs); 10114 d = Bits32(opcode, 15, 12); 10115 n = Bits32(opcode, 19, 16); 10116 m = Bits32(opcode, 3, 0); 10117 s = Bits32(opcode, 11, 8); 10118 10119 // setflags = (S == '1'); shift_t = DecodeRegShift(type); 10120 setflags = BitIsSet(opcode, 20); 10121 shift_t = DecodeRegShift(Bits32(opcode, 6, 5)); 10122 10123 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE; 10124 if ((d == 15) || (n == 15) || (m == 15) || (s == 15)) 10125 return false; 10126 break; 10127 10128 default: 10129 return false; 10130 } 10131 10132 // shift_n = UInt(R[s]<7:0>); 10133 uint32_t Rs = ReadCoreReg(s, &success); 10134 if (!success) 10135 return false; 10136 10137 uint32_t shift_n = Bits32(Rs, 7, 0); 10138 10139 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 10140 uint32_t Rm = ReadCoreReg(m, &success); 10141 if (!success) 10142 return false; 10143 10144 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success); 10145 if (!success) 10146 return false; 10147 10148 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 10149 uint32_t Rn = ReadCoreReg(n, &success); 10150 if (!success) 10151 return false; 10152 10153 AddWithCarryResult res = AddWithCarry(Rn, shifted, 0); 10154 10155 // R[d] = result; 10156 EmulateInstruction::Context context; 10157 context.type = eContextArithmetic; 10158 std::optional<RegisterInfo> reg_n = 10159 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10160 std::optional<RegisterInfo> reg_m = 10161 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 10162 10163 context.SetRegisterRegisterOperands(*reg_n, *reg_m); 10164 10165 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 10166 res.result)) 10167 return false; 10168 10169 // if setflags then 10170 // APSR.N = result<31>; 10171 // APSR.Z = IsZeroBit(result); 10172 // APSR.C = carry; 10173 // APSR.V = overflow; 10174 if (setflags) 10175 return WriteFlags(context, res.result, res.carry_out, res.overflow); 10176 } 10177 return true; 10178 } 10179 10180 // A8.6.213 SUB (register) 10181 bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode, 10182 const ARMEncoding encoding) { 10183 #if 0 10184 if ConditionPassed() then 10185 EncodingSpecificOperations(); 10186 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 10187 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 10188 if d == 15 then // Can only occur for ARM encoding 10189 ALUWritePC(result); // setflags is always FALSE here 10190 else 10191 R[d] = result; 10192 if setflags then 10193 APSR.N = result<31>; 10194 APSR.Z = IsZeroBit(result); 10195 APSR.C = carry; 10196 APSR.V = overflow; 10197 #endif 10198 10199 bool success = false; 10200 10201 if (ConditionPassed(opcode)) { 10202 uint32_t d; 10203 uint32_t n; 10204 uint32_t m; 10205 bool setflags; 10206 ARM_ShifterType shift_t; 10207 uint32_t shift_n; 10208 10209 switch (encoding) { 10210 case eEncodingT1: 10211 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock(); 10212 d = Bits32(opcode, 2, 0); 10213 n = Bits32(opcode, 5, 3); 10214 m = Bits32(opcode, 8, 6); 10215 setflags = !InITBlock(); 10216 10217 // (shift_t, shift_n) = (SRType_LSL, 0); 10218 shift_t = SRType_LSL; 10219 shift_n = 0; 10220 10221 break; 10222 10223 case eEncodingT2: 10224 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1"); 10225 d = Bits32(opcode, 11, 8); 10226 n = Bits32(opcode, 19, 16); 10227 m = Bits32(opcode, 3, 0); 10228 setflags = BitIsSet(opcode, 20); 10229 10230 // if Rd == "1111" && S == "1" then SEE CMP (register); 10231 if (d == 15 && setflags == 1) 10232 return EmulateCMPImm(opcode, eEncodingT3); 10233 10234 // if Rn == "1101" then SEE SUB (SP minus register); 10235 if (n == 13) 10236 return EmulateSUBSPReg(opcode, eEncodingT1); 10237 10238 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 10239 shift_n = DecodeImmShiftThumb(opcode, shift_t); 10240 10241 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then 10242 // UNPREDICTABLE; 10243 if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) || 10244 BadReg(m)) 10245 return false; 10246 10247 break; 10248 10249 case eEncodingA1: 10250 // if Rn == '1101' then SEE SUB (SP minus register); 10251 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); 10252 d = Bits32(opcode, 15, 12); 10253 n = Bits32(opcode, 19, 16); 10254 m = Bits32(opcode, 3, 0); 10255 setflags = BitIsSet(opcode, 20); 10256 10257 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 10258 // instructions; 10259 if ((d == 15) && setflags) 10260 EmulateSUBSPcLrEtc(opcode, encoding); 10261 10262 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 10263 shift_n = DecodeImmShiftARM(opcode, shift_t); 10264 10265 break; 10266 10267 default: 10268 return false; 10269 } 10270 10271 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 10272 uint32_t Rm = ReadCoreReg(m, &success); 10273 if (!success) 10274 return false; 10275 10276 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success); 10277 if (!success) 10278 return false; 10279 10280 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 10281 uint32_t Rn = ReadCoreReg(n, &success); 10282 if (!success) 10283 return false; 10284 10285 AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1); 10286 10287 // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result); 10288 // // setflags is always FALSE here else 10289 // R[d] = result; 10290 // if setflags then 10291 // APSR.N = result<31>; 10292 // APSR.Z = IsZeroBit(result); 10293 // APSR.C = carry; 10294 // APSR.V = overflow; 10295 10296 EmulateInstruction::Context context; 10297 context.type = eContextArithmetic; 10298 std::optional<RegisterInfo> reg_n = 10299 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10300 std::optional<RegisterInfo> reg_m = 10301 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 10302 context.SetRegisterRegisterOperands(*reg_n, *reg_m); 10303 10304 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, 10305 res.carry_out, res.overflow)) 10306 return false; 10307 } 10308 return true; 10309 } 10310 10311 // A8.6.202 STREX 10312 // Store Register Exclusive calculates an address from a base register value 10313 // and an immediate offset, and stores a word from a register to memory if the 10314 // executing processor has exclusive access to the memory addressed. 10315 bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode, 10316 const ARMEncoding encoding) { 10317 #if 0 10318 if ConditionPassed() then 10319 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10320 address = R[n] + imm32; 10321 if ExclusiveMonitorsPass(address,4) then 10322 MemA[address,4] = R[t]; 10323 R[d] = 0; 10324 else 10325 R[d] = 1; 10326 #endif 10327 10328 bool success = false; 10329 10330 if (ConditionPassed(opcode)) { 10331 uint32_t d; 10332 uint32_t t; 10333 uint32_t n; 10334 uint32_t imm32; 10335 const uint32_t addr_byte_size = GetAddressByteSize(); 10336 10337 switch (encoding) { 10338 case eEncodingT1: 10339 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = 10340 // ZeroExtend(imm8:'00', 10341 // 32); 10342 d = Bits32(opcode, 11, 8); 10343 t = Bits32(opcode, 15, 12); 10344 n = Bits32(opcode, 19, 16); 10345 imm32 = Bits32(opcode, 7, 0) << 2; 10346 10347 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE; 10348 if (BadReg(d) || BadReg(t) || (n == 15)) 10349 return false; 10350 10351 // if d == n || d == t then UNPREDICTABLE; 10352 if ((d == n) || (d == t)) 10353 return false; 10354 10355 break; 10356 10357 case eEncodingA1: 10358 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero 10359 // offset 10360 d = Bits32(opcode, 15, 12); 10361 t = Bits32(opcode, 3, 0); 10362 n = Bits32(opcode, 19, 16); 10363 imm32 = 0; 10364 10365 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE; 10366 if ((d == 15) || (t == 15) || (n == 15)) 10367 return false; 10368 10369 // if d == n || d == t then UNPREDICTABLE; 10370 if ((d == n) || (d == t)) 10371 return false; 10372 10373 break; 10374 10375 default: 10376 return false; 10377 } 10378 10379 // address = R[n] + imm32; 10380 uint32_t Rn = ReadCoreReg(n, &success); 10381 if (!success) 10382 return false; 10383 10384 addr_t address = Rn + imm32; 10385 10386 std::optional<RegisterInfo> base_reg = 10387 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10388 std::optional<RegisterInfo> data_reg = 10389 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 10390 EmulateInstruction::Context context; 10391 context.type = eContextRegisterStore; 10392 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, imm32); 10393 10394 // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass 10395 // (address, addr_byte_size)) -- For now, for the sake of emulation, we 10396 // will say this 10397 // always return 10398 // true. 10399 if (true) { 10400 // MemA[address,4] = R[t]; 10401 uint32_t Rt = 10402 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 10403 if (!success) 10404 return false; 10405 10406 if (!MemAWrite(context, address, Rt, addr_byte_size)) 10407 return false; 10408 10409 // R[d] = 0; 10410 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0)) 10411 return false; 10412 } 10413 #if 0 // unreachable because if true 10414 else 10415 { 10416 // R[d] = 1; 10417 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1)) 10418 return false; 10419 } 10420 #endif // unreachable because if true 10421 } 10422 return true; 10423 } 10424 10425 // A8.6.197 STRB (immediate, ARM) 10426 bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode, 10427 const ARMEncoding encoding) { 10428 #if 0 10429 if ConditionPassed() then 10430 EncodingSpecificOperations(); 10431 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10432 address = if index then offset_addr else R[n]; 10433 MemU[address,1] = R[t]<7:0>; 10434 if wback then R[n] = offset_addr; 10435 #endif 10436 10437 bool success = false; 10438 10439 if (ConditionPassed(opcode)) { 10440 uint32_t t; 10441 uint32_t n; 10442 uint32_t imm32; 10443 bool index; 10444 bool add; 10445 bool wback; 10446 10447 switch (encoding) { 10448 case eEncodingA1: 10449 // if P == '0' && W == '1' then SEE STRBT; 10450 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 10451 t = Bits32(opcode, 15, 12); 10452 n = Bits32(opcode, 19, 16); 10453 imm32 = Bits32(opcode, 11, 0); 10454 10455 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 10456 index = BitIsSet(opcode, 24); 10457 add = BitIsSet(opcode, 23); 10458 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 10459 10460 // if t == 15 then UNPREDICTABLE; 10461 if (t == 15) 10462 return false; 10463 10464 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 10465 if (wback && ((n == 15) || (n == t))) 10466 return false; 10467 10468 break; 10469 10470 default: 10471 return false; 10472 } 10473 10474 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10475 uint32_t Rn = ReadCoreReg(n, &success); 10476 if (!success) 10477 return false; 10478 10479 addr_t offset_addr; 10480 if (add) 10481 offset_addr = Rn + imm32; 10482 else 10483 offset_addr = Rn - imm32; 10484 10485 // address = if index then offset_addr else R[n]; 10486 addr_t address; 10487 if (index) 10488 address = offset_addr; 10489 else 10490 address = Rn; 10491 10492 // MemU[address,1] = R[t]<7:0>; 10493 uint32_t Rt = ReadCoreReg(t, &success); 10494 if (!success) 10495 return false; 10496 10497 std::optional<RegisterInfo> base_reg = 10498 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10499 std::optional<RegisterInfo> data_reg = 10500 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 10501 EmulateInstruction::Context context; 10502 context.type = eContextRegisterStore; 10503 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 10504 10505 if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1)) 10506 return false; 10507 10508 // if wback then R[n] = offset_addr; 10509 if (wback) { 10510 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 10511 offset_addr)) 10512 return false; 10513 } 10514 } 10515 return true; 10516 } 10517 10518 // A8.6.194 STR (immediate, ARM) 10519 bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode, 10520 const ARMEncoding encoding) { 10521 #if 0 10522 if ConditionPassed() then 10523 EncodingSpecificOperations(); 10524 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10525 address = if index then offset_addr else R[n]; 10526 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 10527 if wback then R[n] = offset_addr; 10528 #endif 10529 10530 bool success = false; 10531 10532 if (ConditionPassed(opcode)) { 10533 uint32_t t; 10534 uint32_t n; 10535 uint32_t imm32; 10536 bool index; 10537 bool add; 10538 bool wback; 10539 10540 const uint32_t addr_byte_size = GetAddressByteSize(); 10541 10542 switch (encoding) { 10543 case eEncodingA1: 10544 // if P == '0' && W == '1' then SEE STRT; 10545 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == 10546 // '000000000100' then SEE PUSH; 10547 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 10548 t = Bits32(opcode, 15, 12); 10549 n = Bits32(opcode, 19, 16); 10550 imm32 = Bits32(opcode, 11, 0); 10551 10552 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 10553 index = BitIsSet(opcode, 24); 10554 add = BitIsSet(opcode, 23); 10555 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 10556 10557 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 10558 if (wback && ((n == 15) || (n == t))) 10559 return false; 10560 10561 break; 10562 10563 default: 10564 return false; 10565 } 10566 10567 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10568 uint32_t Rn = ReadCoreReg(n, &success); 10569 if (!success) 10570 return false; 10571 10572 addr_t offset_addr; 10573 if (add) 10574 offset_addr = Rn + imm32; 10575 else 10576 offset_addr = Rn - imm32; 10577 10578 // address = if index then offset_addr else R[n]; 10579 addr_t address; 10580 if (index) 10581 address = offset_addr; 10582 else 10583 address = Rn; 10584 10585 std::optional<RegisterInfo> base_reg = 10586 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10587 std::optional<RegisterInfo> data_reg = 10588 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 10589 EmulateInstruction::Context context; 10590 context.type = eContextRegisterStore; 10591 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 10592 10593 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 10594 uint32_t Rt = ReadCoreReg(t, &success); 10595 if (!success) 10596 return false; 10597 10598 if (t == 15) { 10599 uint32_t pc_value = ReadCoreReg(PC_REG, &success); 10600 if (!success) 10601 return false; 10602 10603 if (!MemUWrite(context, address, pc_value, addr_byte_size)) 10604 return false; 10605 } else { 10606 if (!MemUWrite(context, address, Rt, addr_byte_size)) 10607 return false; 10608 } 10609 10610 // if wback then R[n] = offset_addr; 10611 if (wback) { 10612 context.type = eContextAdjustBaseRegister; 10613 context.SetImmediate(offset_addr); 10614 10615 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 10616 offset_addr)) 10617 return false; 10618 } 10619 } 10620 return true; 10621 } 10622 10623 // A8.6.66 LDRD (immediate) 10624 // Load Register Dual (immediate) calculates an address from a base register 10625 // value and an immediate offset, loads two words from memory, and writes them 10626 // to two registers. It can use offset, post-indexed, or pre-indexed 10627 // addressing. 10628 bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode, 10629 const ARMEncoding encoding) { 10630 #if 0 10631 if ConditionPassed() then 10632 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10633 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10634 address = if index then offset_addr else R[n]; 10635 R[t] = MemA[address,4]; 10636 R[t2] = MemA[address+4,4]; 10637 if wback then R[n] = offset_addr; 10638 #endif 10639 10640 bool success = false; 10641 10642 if (ConditionPassed(opcode)) { 10643 uint32_t t; 10644 uint32_t t2; 10645 uint32_t n; 10646 uint32_t imm32; 10647 bool index; 10648 bool add; 10649 bool wback; 10650 10651 switch (encoding) { 10652 case eEncodingT1: 10653 // if P == '0' && W == '0' then SEE 'Related encodings'; 10654 // if Rn == '1111' then SEE LDRD (literal); 10655 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = 10656 // ZeroExtend(imm8:'00', 32); 10657 t = Bits32(opcode, 15, 12); 10658 t2 = Bits32(opcode, 11, 8); 10659 n = Bits32(opcode, 19, 16); 10660 imm32 = Bits32(opcode, 7, 0) << 2; 10661 10662 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 10663 index = BitIsSet(opcode, 24); 10664 add = BitIsSet(opcode, 23); 10665 wback = BitIsSet(opcode, 21); 10666 10667 // if wback && (n == t || n == t2) then UNPREDICTABLE; 10668 if (wback && ((n == t) || (n == t2))) 10669 return false; 10670 10671 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE; 10672 if (BadReg(t) || BadReg(t2) || (t == t2)) 10673 return false; 10674 10675 break; 10676 10677 case eEncodingA1: 10678 // if Rn == '1111' then SEE LDRD (literal); 10679 // if Rt<0> == '1' then UNPREDICTABLE; 10680 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 10681 // 32); 10682 t = Bits32(opcode, 15, 12); 10683 if (BitIsSet(t, 0)) 10684 return false; 10685 t2 = t + 1; 10686 n = Bits32(opcode, 19, 16); 10687 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0); 10688 10689 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 10690 index = BitIsSet(opcode, 24); 10691 add = BitIsSet(opcode, 23); 10692 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 10693 10694 // if P == '0' && W == '1' then UNPREDICTABLE; 10695 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) 10696 return false; 10697 10698 // if wback && (n == t || n == t2) then UNPREDICTABLE; 10699 if (wback && ((n == t) || (n == t2))) 10700 return false; 10701 10702 // if t2 == 15 then UNPREDICTABLE; 10703 if (t2 == 15) 10704 return false; 10705 10706 break; 10707 10708 default: 10709 return false; 10710 } 10711 10712 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10713 uint32_t Rn = ReadCoreReg(n, &success); 10714 if (!success) 10715 return false; 10716 10717 addr_t offset_addr; 10718 if (add) 10719 offset_addr = Rn + imm32; 10720 else 10721 offset_addr = Rn - imm32; 10722 10723 // address = if index then offset_addr else R[n]; 10724 addr_t address; 10725 if (index) 10726 address = offset_addr; 10727 else 10728 address = Rn; 10729 10730 // R[t] = MemA[address,4]; 10731 10732 EmulateInstruction::Context context; 10733 if (n == 13) 10734 context.type = eContextPopRegisterOffStack; 10735 else 10736 context.type = eContextRegisterLoad; 10737 context.SetAddress(address); 10738 10739 const uint32_t addr_byte_size = GetAddressByteSize(); 10740 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); 10741 if (!success) 10742 return false; 10743 10744 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) 10745 return false; 10746 10747 // R[t2] = MemA[address+4,4]; 10748 context.SetAddress(address + 4); 10749 data = MemARead(context, address + 4, addr_byte_size, 0, &success); 10750 if (!success) 10751 return false; 10752 10753 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2, 10754 data)) 10755 return false; 10756 10757 // if wback then R[n] = offset_addr; 10758 if (wback) { 10759 context.type = eContextAdjustBaseRegister; 10760 context.SetAddress(offset_addr); 10761 10762 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 10763 offset_addr)) 10764 return false; 10765 } 10766 } 10767 return true; 10768 } 10769 10770 // A8.6.68 LDRD (register) 10771 // Load Register Dual (register) calculates an address from a base register 10772 // value and a register offset, loads two words from memory, and writes them to 10773 // two registers. It can use offset, post-indexed or pre-indexed addressing. 10774 bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode, 10775 const ARMEncoding encoding) { 10776 #if 0 10777 if ConditionPassed() then 10778 EncodingSpecificOperations(); 10779 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10780 address = if index then offset_addr else R[n]; 10781 R[t] = MemA[address,4]; 10782 R[t2] = MemA[address+4,4]; 10783 if wback then R[n] = offset_addr; 10784 #endif 10785 10786 bool success = false; 10787 10788 if (ConditionPassed(opcode)) { 10789 uint32_t t; 10790 uint32_t t2; 10791 uint32_t n; 10792 uint32_t m; 10793 bool index; 10794 bool add; 10795 bool wback; 10796 10797 switch (encoding) { 10798 case eEncodingA1: 10799 // if Rt<0> == '1' then UNPREDICTABLE; 10800 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 10801 t = Bits32(opcode, 15, 12); 10802 if (BitIsSet(t, 0)) 10803 return false; 10804 t2 = t + 1; 10805 n = Bits32(opcode, 19, 16); 10806 m = Bits32(opcode, 3, 0); 10807 10808 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 10809 index = BitIsSet(opcode, 24); 10810 add = BitIsSet(opcode, 23); 10811 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 10812 10813 // if P == '0' && W == '1' then UNPREDICTABLE; 10814 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) 10815 return false; 10816 10817 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE; 10818 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2)) 10819 return false; 10820 10821 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10822 if (wback && ((n == 15) || (n == t) || (n == t2))) 10823 return false; 10824 10825 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 10826 if ((ArchVersion() < 6) && wback && (m == n)) 10827 return false; 10828 break; 10829 10830 default: 10831 return false; 10832 } 10833 10834 uint32_t Rn = ReadCoreReg(n, &success); 10835 if (!success) 10836 return false; 10837 10838 uint32_t Rm = ReadCoreReg(m, &success); 10839 if (!success) 10840 return false; 10841 10842 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10843 addr_t offset_addr; 10844 if (add) 10845 offset_addr = Rn + Rm; 10846 else 10847 offset_addr = Rn - Rm; 10848 10849 // address = if index then offset_addr else R[n]; 10850 addr_t address; 10851 if (index) 10852 address = offset_addr; 10853 else 10854 address = Rn; 10855 10856 EmulateInstruction::Context context; 10857 if (n == 13) 10858 context.type = eContextPopRegisterOffStack; 10859 else 10860 context.type = eContextRegisterLoad; 10861 context.SetAddress(address); 10862 10863 // R[t] = MemA[address,4]; 10864 const uint32_t addr_byte_size = GetAddressByteSize(); 10865 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); 10866 if (!success) 10867 return false; 10868 10869 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) 10870 return false; 10871 10872 // R[t2] = MemA[address+4,4]; 10873 10874 data = MemARead(context, address + 4, addr_byte_size, 0, &success); 10875 if (!success) 10876 return false; 10877 10878 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2, 10879 data)) 10880 return false; 10881 10882 // if wback then R[n] = offset_addr; 10883 if (wback) { 10884 context.type = eContextAdjustBaseRegister; 10885 context.SetAddress(offset_addr); 10886 10887 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 10888 offset_addr)) 10889 return false; 10890 } 10891 } 10892 return true; 10893 } 10894 10895 // A8.6.200 STRD (immediate) 10896 // Store Register Dual (immediate) calculates an address from a base register 10897 // value and an immediate offset, and stores two words from two registers to 10898 // memory. It can use offset, post-indexed, or pre-indexed addressing. 10899 bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode, 10900 const ARMEncoding encoding) { 10901 #if 0 10902 if ConditionPassed() then 10903 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10904 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10905 address = if index then offset_addr else R[n]; 10906 MemA[address,4] = R[t]; 10907 MemA[address+4,4] = R[t2]; 10908 if wback then R[n] = offset_addr; 10909 #endif 10910 10911 bool success = false; 10912 10913 if (ConditionPassed(opcode)) { 10914 uint32_t t; 10915 uint32_t t2; 10916 uint32_t n; 10917 uint32_t imm32; 10918 bool index; 10919 bool add; 10920 bool wback; 10921 10922 switch (encoding) { 10923 case eEncodingT1: 10924 // if P == '0' && W == '0' then SEE 'Related encodings'; 10925 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = 10926 // ZeroExtend(imm8:'00', 32); 10927 t = Bits32(opcode, 15, 12); 10928 t2 = Bits32(opcode, 11, 8); 10929 n = Bits32(opcode, 19, 16); 10930 imm32 = Bits32(opcode, 7, 0) << 2; 10931 10932 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 10933 index = BitIsSet(opcode, 24); 10934 add = BitIsSet(opcode, 23); 10935 wback = BitIsSet(opcode, 21); 10936 10937 // if wback && (n == t || n == t2) then UNPREDICTABLE; 10938 if (wback && ((n == t) || (n == t2))) 10939 return false; 10940 10941 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE; 10942 if ((n == 15) || BadReg(t) || BadReg(t2)) 10943 return false; 10944 10945 break; 10946 10947 case eEncodingA1: 10948 // if Rt<0> == '1' then UNPREDICTABLE; 10949 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 10950 // 32); 10951 t = Bits32(opcode, 15, 12); 10952 if (BitIsSet(t, 0)) 10953 return false; 10954 10955 t2 = t + 1; 10956 n = Bits32(opcode, 19, 16); 10957 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0); 10958 10959 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 10960 index = BitIsSet(opcode, 24); 10961 add = BitIsSet(opcode, 23); 10962 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 10963 10964 // if P == '0' && W == '1' then UNPREDICTABLE; 10965 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) 10966 return false; 10967 10968 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10969 if (wback && ((n == 15) || (n == t) || (n == t2))) 10970 return false; 10971 10972 // if t2 == 15 then UNPREDICTABLE; 10973 if (t2 == 15) 10974 return false; 10975 10976 break; 10977 10978 default: 10979 return false; 10980 } 10981 10982 std::optional<RegisterInfo> base_reg = 10983 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10984 10985 uint32_t Rn = ReadCoreReg(n, &success); 10986 if (!success) 10987 return false; 10988 10989 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10990 addr_t offset_addr; 10991 if (add) 10992 offset_addr = Rn + imm32; 10993 else 10994 offset_addr = Rn - imm32; 10995 10996 // address = if index then offset_addr else R[n]; 10997 addr_t address; 10998 if (index) 10999 address = offset_addr; 11000 else 11001 address = Rn; 11002 11003 // MemA[address,4] = R[t]; 11004 std::optional<RegisterInfo> data_reg = 11005 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 11006 11007 uint32_t data = ReadCoreReg(t, &success); 11008 if (!success) 11009 return false; 11010 11011 EmulateInstruction::Context context; 11012 if (n == 13) 11013 context.type = eContextPushRegisterOnStack; 11014 else 11015 context.type = eContextRegisterStore; 11016 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 11017 11018 const uint32_t addr_byte_size = GetAddressByteSize(); 11019 11020 if (!MemAWrite(context, address, data, addr_byte_size)) 11021 return false; 11022 11023 // MemA[address+4,4] = R[t2]; 11024 data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2); 11025 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11026 (address + 4) - Rn); 11027 11028 data = ReadCoreReg(t2, &success); 11029 if (!success) 11030 return false; 11031 11032 if (!MemAWrite(context, address + 4, data, addr_byte_size)) 11033 return false; 11034 11035 // if wback then R[n] = offset_addr; 11036 if (wback) { 11037 if (n == 13) 11038 context.type = eContextAdjustStackPointer; 11039 else 11040 context.type = eContextAdjustBaseRegister; 11041 context.SetAddress(offset_addr); 11042 11043 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 11044 offset_addr)) 11045 return false; 11046 } 11047 } 11048 return true; 11049 } 11050 11051 // A8.6.201 STRD (register) 11052 bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode, 11053 const ARMEncoding encoding) { 11054 #if 0 11055 if ConditionPassed() then 11056 EncodingSpecificOperations(); 11057 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 11058 address = if index then offset_addr else R[n]; 11059 MemA[address,4] = R[t]; 11060 MemA[address+4,4] = R[t2]; 11061 if wback then R[n] = offset_addr; 11062 #endif 11063 11064 bool success = false; 11065 11066 if (ConditionPassed(opcode)) { 11067 uint32_t t; 11068 uint32_t t2; 11069 uint32_t n; 11070 uint32_t m; 11071 bool index; 11072 bool add; 11073 bool wback; 11074 11075 switch (encoding) { 11076 case eEncodingA1: 11077 // if Rt<0> == '1' then UNPREDICTABLE; 11078 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 11079 t = Bits32(opcode, 15, 12); 11080 if (BitIsSet(t, 0)) 11081 return false; 11082 11083 t2 = t + 1; 11084 n = Bits32(opcode, 19, 16); 11085 m = Bits32(opcode, 3, 0); 11086 11087 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 11088 index = BitIsSet(opcode, 24); 11089 add = BitIsSet(opcode, 23); 11090 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 11091 11092 // if P == '0' && W == '1' then UNPREDICTABLE; 11093 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) 11094 return false; 11095 11096 // if t2 == 15 || m == 15 then UNPREDICTABLE; 11097 if ((t2 == 15) || (m == 15)) 11098 return false; 11099 11100 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 11101 if (wback && ((n == 15) || (n == t) || (n == t2))) 11102 return false; 11103 11104 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 11105 if ((ArchVersion() < 6) && wback && (m == n)) 11106 return false; 11107 11108 break; 11109 11110 default: 11111 return false; 11112 } 11113 11114 uint32_t Rn = ReadCoreReg(n, &success); 11115 if (!success) 11116 return false; 11117 11118 uint32_t Rm = ReadCoreReg(m, &success); 11119 if (!success) 11120 return false; 11121 11122 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 11123 addr_t offset_addr; 11124 if (add) 11125 offset_addr = Rn + Rm; 11126 else 11127 offset_addr = Rn - Rm; 11128 11129 // address = if index then offset_addr else R[n]; 11130 addr_t address; 11131 if (index) 11132 address = offset_addr; 11133 else 11134 address = Rn; 11135 // MemA[address,4] = R[t]; 11136 uint32_t Rt = ReadCoreReg(t, &success); 11137 if (!success) 11138 return false; 11139 11140 EmulateInstruction::Context context; 11141 if (t == 13) 11142 context.type = eContextPushRegisterOnStack; 11143 else 11144 context.type = eContextRegisterStore; 11145 11146 std::optional<RegisterInfo> base_reg = 11147 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11148 std::optional<RegisterInfo> offset_reg = 11149 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 11150 std::optional<RegisterInfo> data_reg = 11151 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 11152 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg, 11153 *data_reg); 11154 11155 const uint32_t addr_byte_size = GetAddressByteSize(); 11156 11157 if (!MemAWrite(context, address, Rt, addr_byte_size)) 11158 return false; 11159 11160 // MemA[address+4,4] = R[t2]; 11161 uint32_t Rt2 = ReadCoreReg(t2, &success); 11162 if (!success) 11163 return false; 11164 11165 data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2); 11166 11167 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg, 11168 *data_reg); 11169 11170 if (!MemAWrite(context, address + 4, Rt2, addr_byte_size)) 11171 return false; 11172 11173 // if wback then R[n] = offset_addr; 11174 if (wback) { 11175 context.type = eContextAdjustBaseRegister; 11176 context.SetAddress(offset_addr); 11177 11178 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 11179 offset_addr)) 11180 return false; 11181 } 11182 } 11183 return true; 11184 } 11185 11186 // A8.6.319 VLDM 11187 // Vector Load Multiple loads multiple extension registers from consecutive 11188 // memory locations using an address from an ARM core register. 11189 bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode, 11190 const ARMEncoding encoding) { 11191 #if 0 11192 if ConditionPassed() then 11193 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 11194 address = if add then R[n] else R[n]-imm32; 11195 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 11196 for r = 0 to regs-1 11197 if single_regs then 11198 S[d+r] = MemA[address,4]; address = address+4; 11199 else 11200 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 11201 // Combine the word-aligned words in the correct order for 11202 // current endianness. 11203 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 11204 #endif 11205 11206 bool success = false; 11207 11208 if (ConditionPassed(opcode)) { 11209 bool single_regs; 11210 bool add; 11211 bool wback; 11212 uint32_t d; 11213 uint32_t n; 11214 uint32_t imm32; 11215 uint32_t regs; 11216 11217 switch (encoding) { 11218 case eEncodingT1: 11219 case eEncodingA1: 11220 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; 11221 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; 11222 // if P == '1' && W == '0' then SEE VLDR; 11223 // if P == U && W == '1' then UNDEFINED; 11224 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) 11225 return false; 11226 11227 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with 11228 // !), 101 (DB with !) 11229 // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); 11230 single_regs = false; 11231 add = BitIsSet(opcode, 23); 11232 wback = BitIsSet(opcode, 21); 11233 11234 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); 11235 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 11236 n = Bits32(opcode, 19, 16); 11237 imm32 = Bits32(opcode, 7, 0) << 2; 11238 11239 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'. 11240 regs = Bits32(opcode, 7, 0) / 2; 11241 11242 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then 11243 // UNPREDICTABLE; 11244 if (n == 15 && (wback || CurrentInstrSet() != eModeARM)) 11245 return false; 11246 11247 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 11248 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 11249 return false; 11250 11251 break; 11252 11253 case eEncodingT2: 11254 case eEncodingA2: 11255 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; 11256 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; 11257 // if P == '1' && W == '0' then SEE VLDR; 11258 // if P == U && W == '1' then UNDEFINED; 11259 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) 11260 return false; 11261 11262 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with 11263 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W 11264 // == '1'); d = 11265 // UInt(Vd:D); n = UInt(Rn); 11266 single_regs = true; 11267 add = BitIsSet(opcode, 23); 11268 wback = BitIsSet(opcode, 21); 11269 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); 11270 n = Bits32(opcode, 19, 16); 11271 11272 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); 11273 imm32 = Bits32(opcode, 7, 0) << 2; 11274 regs = Bits32(opcode, 7, 0); 11275 11276 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then 11277 // UNPREDICTABLE; 11278 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 11279 return false; 11280 11281 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 11282 if ((regs == 0) || ((d + regs) > 32)) 11283 return false; 11284 break; 11285 11286 default: 11287 return false; 11288 } 11289 11290 uint32_t Rn = ReadCoreReg(n, &success); 11291 if (!success) 11292 return false; 11293 11294 // address = if add then R[n] else R[n]-imm32; 11295 addr_t address; 11296 if (add) 11297 address = Rn; 11298 else 11299 address = Rn - imm32; 11300 11301 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 11302 EmulateInstruction::Context context; 11303 11304 if (wback) { 11305 uint32_t value; 11306 if (add) 11307 value = Rn + imm32; 11308 else 11309 value = Rn - imm32; 11310 11311 context.type = eContextAdjustBaseRegister; 11312 context.SetImmediateSigned(value - Rn); 11313 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 11314 value)) 11315 return false; 11316 } 11317 11318 const uint32_t addr_byte_size = GetAddressByteSize(); 11319 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 11320 11321 context.type = eContextRegisterLoad; 11322 11323 std::optional<RegisterInfo> base_reg = 11324 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11325 11326 // for r = 0 to regs-1 11327 for (uint32_t r = 0; r < regs; ++r) { 11328 if (single_regs) { 11329 // S[d+r] = MemA[address,4]; address = address+4; 11330 context.SetRegisterPlusOffset(*base_reg, address - Rn); 11331 11332 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); 11333 if (!success) 11334 return false; 11335 11336 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, 11337 start_reg + d + r, data)) 11338 return false; 11339 11340 address = address + 4; 11341 } else { 11342 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = 11343 // address+8; 11344 context.SetRegisterPlusOffset(*base_reg, address - Rn); 11345 uint32_t word1 = 11346 MemARead(context, address, addr_byte_size, 0, &success); 11347 if (!success) 11348 return false; 11349 11350 context.SetRegisterPlusOffset(*base_reg, (address + 4) - Rn); 11351 uint32_t word2 = 11352 MemARead(context, address + 4, addr_byte_size, 0, &success); 11353 if (!success) 11354 return false; 11355 11356 address = address + 8; 11357 // // Combine the word-aligned words in the correct order for current 11358 // endianness. 11359 // D[d+r] = if BigEndian() then word1:word2 else word2:word1; 11360 uint64_t data; 11361 if (GetByteOrder() == eByteOrderBig) { 11362 data = word1; 11363 data = (data << 32) | word2; 11364 } else { 11365 data = word2; 11366 data = (data << 32) | word1; 11367 } 11368 11369 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, 11370 start_reg + d + r, data)) 11371 return false; 11372 } 11373 } 11374 } 11375 return true; 11376 } 11377 11378 // A8.6.399 VSTM 11379 // Vector Store Multiple stores multiple extension registers to consecutive 11380 // memory locations using an address from an 11381 // ARM core register. 11382 bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode, 11383 const ARMEncoding encoding) { 11384 #if 0 11385 if ConditionPassed() then 11386 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 11387 address = if add then R[n] else R[n]-imm32; 11388 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 11389 for r = 0 to regs-1 11390 if single_regs then 11391 MemA[address,4] = S[d+r]; address = address+4; 11392 else 11393 // Store as two word-aligned words in the correct order for 11394 // current endianness. 11395 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 11396 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 11397 address = address+8; 11398 #endif 11399 11400 bool success = false; 11401 11402 if (ConditionPassed(opcode)) { 11403 bool single_regs; 11404 bool add; 11405 bool wback; 11406 uint32_t d; 11407 uint32_t n; 11408 uint32_t imm32; 11409 uint32_t regs; 11410 11411 switch (encoding) { 11412 case eEncodingT1: 11413 case eEncodingA1: 11414 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; 11415 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; 11416 // if P == '1' && W == '0' then SEE VSTR; 11417 // if P == U && W == '1' then UNDEFINED; 11418 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) 11419 return false; 11420 11421 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with 11422 // !), 101 (DB with !) 11423 // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); 11424 single_regs = false; 11425 add = BitIsSet(opcode, 23); 11426 wback = BitIsSet(opcode, 21); 11427 11428 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); 11429 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 11430 n = Bits32(opcode, 19, 16); 11431 imm32 = Bits32(opcode, 7, 0) << 2; 11432 11433 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'. 11434 regs = Bits32(opcode, 7, 0) / 2; 11435 11436 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then 11437 // UNPREDICTABLE; 11438 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 11439 return false; 11440 11441 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 11442 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 11443 return false; 11444 11445 break; 11446 11447 case eEncodingT2: 11448 case eEncodingA2: 11449 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; 11450 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; 11451 // if P == '1' && W == '0' then SEE VSTR; 11452 // if P == U && W == '1' then UNDEFINED; 11453 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) 11454 return false; 11455 11456 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with 11457 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W 11458 // == '1'); d = 11459 // UInt(Vd:D); n = UInt(Rn); 11460 single_regs = true; 11461 add = BitIsSet(opcode, 23); 11462 wback = BitIsSet(opcode, 21); 11463 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); 11464 n = Bits32(opcode, 19, 16); 11465 11466 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); 11467 imm32 = Bits32(opcode, 7, 0) << 2; 11468 regs = Bits32(opcode, 7, 0); 11469 11470 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then 11471 // UNPREDICTABLE; 11472 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 11473 return false; 11474 11475 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 11476 if ((regs == 0) || ((d + regs) > 32)) 11477 return false; 11478 11479 break; 11480 11481 default: 11482 return false; 11483 } 11484 11485 std::optional<RegisterInfo> base_reg = 11486 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11487 11488 uint32_t Rn = ReadCoreReg(n, &success); 11489 if (!success) 11490 return false; 11491 11492 // address = if add then R[n] else R[n]-imm32; 11493 addr_t address; 11494 if (add) 11495 address = Rn; 11496 else 11497 address = Rn - imm32; 11498 11499 EmulateInstruction::Context context; 11500 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 11501 if (wback) { 11502 uint32_t value; 11503 if (add) 11504 value = Rn + imm32; 11505 else 11506 value = Rn - imm32; 11507 11508 context.type = eContextAdjustBaseRegister; 11509 context.SetRegisterPlusOffset(*base_reg, value - Rn); 11510 11511 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 11512 value)) 11513 return false; 11514 } 11515 11516 const uint32_t addr_byte_size = GetAddressByteSize(); 11517 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 11518 11519 context.type = eContextRegisterStore; 11520 // for r = 0 to regs-1 11521 for (uint32_t r = 0; r < regs; ++r) { 11522 11523 if (single_regs) { 11524 // MemA[address,4] = S[d+r]; address = address+4; 11525 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, 11526 start_reg + d + r, 0, &success); 11527 if (!success) 11528 return false; 11529 11530 std::optional<RegisterInfo> data_reg = 11531 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r); 11532 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11533 address - Rn); 11534 if (!MemAWrite(context, address, data, addr_byte_size)) 11535 return false; 11536 11537 address = address + 4; 11538 } else { 11539 // // Store as two word-aligned words in the correct order for current 11540 // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else 11541 // D[d+r]<31:0>; 11542 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else 11543 // D[d+r]<63:32>; 11544 uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF, 11545 start_reg + d + r, 0, &success); 11546 if (!success) 11547 return false; 11548 11549 std::optional<RegisterInfo> data_reg = 11550 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r); 11551 11552 if (GetByteOrder() == eByteOrderBig) { 11553 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11554 address - Rn); 11555 if (!MemAWrite(context, address, Bits64(data, 63, 32), 11556 addr_byte_size)) 11557 return false; 11558 11559 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11560 (address + 4) - Rn); 11561 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0), 11562 addr_byte_size)) 11563 return false; 11564 } else { 11565 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11566 address - Rn); 11567 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size)) 11568 return false; 11569 11570 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11571 (address + 4) - Rn); 11572 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32), 11573 addr_byte_size)) 11574 return false; 11575 } 11576 // address = address+8; 11577 address = address + 8; 11578 } 11579 } 11580 } 11581 return true; 11582 } 11583 11584 // A8.6.320 11585 // This instruction loads a single extension register from memory, using an 11586 // address from an ARM core register, with an optional offset. 11587 bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode, 11588 ARMEncoding encoding) { 11589 #if 0 11590 if ConditionPassed() then 11591 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 11592 base = if n == 15 then Align(PC,4) else R[n]; 11593 address = if add then (base + imm32) else (base - imm32); 11594 if single_reg then 11595 S[d] = MemA[address,4]; 11596 else 11597 word1 = MemA[address,4]; word2 = MemA[address+4,4]; 11598 // Combine the word-aligned words in the correct order for current 11599 // endianness. 11600 D[d] = if BigEndian() then word1:word2 else word2:word1; 11601 #endif 11602 11603 bool success = false; 11604 11605 if (ConditionPassed(opcode)) { 11606 bool single_reg; 11607 bool add; 11608 uint32_t imm32; 11609 uint32_t d; 11610 uint32_t n; 11611 11612 switch (encoding) { 11613 case eEncodingT1: 11614 case eEncodingA1: 11615 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 11616 // 32); 11617 single_reg = false; 11618 add = BitIsSet(opcode, 23); 11619 imm32 = Bits32(opcode, 7, 0) << 2; 11620 11621 // d = UInt(D:Vd); n = UInt(Rn); 11622 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 11623 n = Bits32(opcode, 19, 16); 11624 11625 break; 11626 11627 case eEncodingT2: 11628 case eEncodingA2: 11629 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); 11630 single_reg = true; 11631 add = BitIsSet(opcode, 23); 11632 imm32 = Bits32(opcode, 7, 0) << 2; 11633 11634 // d = UInt(Vd:D); n = UInt(Rn); 11635 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); 11636 n = Bits32(opcode, 19, 16); 11637 11638 break; 11639 11640 default: 11641 return false; 11642 } 11643 std::optional<RegisterInfo> base_reg = 11644 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11645 11646 uint32_t Rn = ReadCoreReg(n, &success); 11647 if (!success) 11648 return false; 11649 11650 // base = if n == 15 then Align(PC,4) else R[n]; 11651 uint32_t base; 11652 if (n == 15) 11653 base = AlignPC(Rn); 11654 else 11655 base = Rn; 11656 11657 // address = if add then (base + imm32) else (base - imm32); 11658 addr_t address; 11659 if (add) 11660 address = base + imm32; 11661 else 11662 address = base - imm32; 11663 11664 const uint32_t addr_byte_size = GetAddressByteSize(); 11665 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 11666 11667 EmulateInstruction::Context context; 11668 context.type = eContextRegisterLoad; 11669 context.SetRegisterPlusOffset(*base_reg, address - base); 11670 11671 if (single_reg) { 11672 // S[d] = MemA[address,4]; 11673 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); 11674 if (!success) 11675 return false; 11676 11677 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d, 11678 data)) 11679 return false; 11680 } else { 11681 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; 11682 uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success); 11683 if (!success) 11684 return false; 11685 11686 context.SetRegisterPlusOffset(*base_reg, (address + 4) - base); 11687 uint32_t word2 = 11688 MemARead(context, address + 4, addr_byte_size, 0, &success); 11689 if (!success) 11690 return false; 11691 // // Combine the word-aligned words in the correct order for current 11692 // endianness. 11693 // D[d] = if BigEndian() then word1:word2 else word2:word1; 11694 uint64_t data64; 11695 if (GetByteOrder() == eByteOrderBig) { 11696 data64 = word1; 11697 data64 = (data64 << 32) | word2; 11698 } else { 11699 data64 = word2; 11700 data64 = (data64 << 32) | word1; 11701 } 11702 11703 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d, 11704 data64)) 11705 return false; 11706 } 11707 } 11708 return true; 11709 } 11710 11711 // A8.6.400 VSTR 11712 // This instruction stores a signle extension register to memory, using an 11713 // address from an ARM core register, with an optional offset. 11714 bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode, 11715 ARMEncoding encoding) { 11716 #if 0 11717 if ConditionPassed() then 11718 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 11719 address = if add then (R[n] + imm32) else (R[n] - imm32); 11720 if single_reg then 11721 MemA[address,4] = S[d]; 11722 else 11723 // Store as two word-aligned words in the correct order for current 11724 // endianness. 11725 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 11726 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 11727 #endif 11728 11729 bool success = false; 11730 11731 if (ConditionPassed(opcode)) { 11732 bool single_reg; 11733 bool add; 11734 uint32_t imm32; 11735 uint32_t d; 11736 uint32_t n; 11737 11738 switch (encoding) { 11739 case eEncodingT1: 11740 case eEncodingA1: 11741 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 11742 // 32); 11743 single_reg = false; 11744 add = BitIsSet(opcode, 23); 11745 imm32 = Bits32(opcode, 7, 0) << 2; 11746 11747 // d = UInt(D:Vd); n = UInt(Rn); 11748 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 11749 n = Bits32(opcode, 19, 16); 11750 11751 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 11752 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 11753 return false; 11754 11755 break; 11756 11757 case eEncodingT2: 11758 case eEncodingA2: 11759 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); 11760 single_reg = true; 11761 add = BitIsSet(opcode, 23); 11762 imm32 = Bits32(opcode, 7, 0) << 2; 11763 11764 // d = UInt(Vd:D); n = UInt(Rn); 11765 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); 11766 n = Bits32(opcode, 19, 16); 11767 11768 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 11769 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 11770 return false; 11771 11772 break; 11773 11774 default: 11775 return false; 11776 } 11777 11778 uint32_t Rn = ReadCoreReg(n, &success); 11779 if (!success) 11780 return false; 11781 11782 // address = if add then (R[n] + imm32) else (R[n] - imm32); 11783 addr_t address; 11784 if (add) 11785 address = Rn + imm32; 11786 else 11787 address = Rn - imm32; 11788 11789 const uint32_t addr_byte_size = GetAddressByteSize(); 11790 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 11791 11792 std::optional<RegisterInfo> base_reg = 11793 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11794 std::optional<RegisterInfo> data_reg = 11795 GetRegisterInfo(eRegisterKindDWARF, start_reg + d); 11796 EmulateInstruction::Context context; 11797 context.type = eContextRegisterStore; 11798 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 11799 11800 if (single_reg) { 11801 // MemA[address,4] = S[d]; 11802 uint32_t data = 11803 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success); 11804 if (!success) 11805 return false; 11806 11807 if (!MemAWrite(context, address, data, addr_byte_size)) 11808 return false; 11809 } else { 11810 // // Store as two word-aligned words in the correct order for current 11811 // endianness. 11812 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 11813 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 11814 uint64_t data = 11815 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success); 11816 if (!success) 11817 return false; 11818 11819 if (GetByteOrder() == eByteOrderBig) { 11820 if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size)) 11821 return false; 11822 11823 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11824 (address + 4) - Rn); 11825 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0), 11826 addr_byte_size)) 11827 return false; 11828 } else { 11829 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size)) 11830 return false; 11831 11832 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11833 (address + 4) - Rn); 11834 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32), 11835 addr_byte_size)) 11836 return false; 11837 } 11838 } 11839 } 11840 return true; 11841 } 11842 11843 // A8.6.307 VLDI1 (multiple single elements) This instruction loads elements 11844 // from memory into one, two, three or four registers, without de-interleaving. 11845 // Every element of each register is loaded. 11846 bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode, 11847 ARMEncoding encoding) { 11848 #if 0 11849 if ConditionPassed() then 11850 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11851 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11852 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11853 for r = 0 to regs-1 11854 for e = 0 to elements-1 11855 Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11856 address = address + ebytes; 11857 #endif 11858 11859 bool success = false; 11860 11861 if (ConditionPassed(opcode)) { 11862 uint32_t regs; 11863 uint32_t alignment; 11864 uint32_t ebytes; 11865 uint32_t esize; 11866 uint32_t elements; 11867 uint32_t d; 11868 uint32_t n; 11869 uint32_t m; 11870 bool wback; 11871 bool register_index; 11872 11873 switch (encoding) { 11874 case eEncodingT1: 11875 case eEncodingA1: { 11876 // case type of 11877 // when '0111' 11878 // regs = 1; if align<1> == '1' then UNDEFINED; 11879 // when '1010' 11880 // regs = 2; if align == '11' then UNDEFINED; 11881 // when '0110' 11882 // regs = 3; if align<1> == '1' then UNDEFINED; 11883 // when '0010' 11884 // regs = 4; 11885 // otherwise 11886 // SEE 'Related encodings'; 11887 uint32_t type = Bits32(opcode, 11, 8); 11888 uint32_t align = Bits32(opcode, 5, 4); 11889 if (type == 7) // '0111' 11890 { 11891 regs = 1; 11892 if (BitIsSet(align, 1)) 11893 return false; 11894 } else if (type == 10) // '1010' 11895 { 11896 regs = 2; 11897 if (align == 3) 11898 return false; 11899 11900 } else if (type == 6) // '0110' 11901 { 11902 regs = 3; 11903 if (BitIsSet(align, 1)) 11904 return false; 11905 } else if (type == 2) // '0010' 11906 { 11907 regs = 4; 11908 } else 11909 return false; 11910 11911 // alignment = if align == '00' then 1 else 4 << UInt(align); 11912 if (align == 0) 11913 alignment = 1; 11914 else 11915 alignment = 4 << align; 11916 11917 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 11918 ebytes = 1 << Bits32(opcode, 7, 6); 11919 esize = 8 * ebytes; 11920 elements = 8 / ebytes; 11921 11922 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11923 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 11924 n = Bits32(opcode, 19, 15); 11925 m = Bits32(opcode, 3, 0); 11926 11927 // wback = (m != 15); register_index = (m != 15 && m != 13); 11928 wback = (m != 15); 11929 register_index = ((m != 15) && (m != 13)); 11930 11931 // if d+regs > 32 then UNPREDICTABLE; 11932 if ((d + regs) > 32) 11933 return false; 11934 } break; 11935 11936 default: 11937 return false; 11938 } 11939 11940 std::optional<RegisterInfo> base_reg = 11941 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11942 11943 uint32_t Rn = ReadCoreReg(n, &success); 11944 if (!success) 11945 return false; 11946 11947 // address = R[n]; if (address MOD alignment) != 0 then 11948 // GenerateAlignmentException(); 11949 addr_t address = Rn; 11950 if ((address % alignment) != 0) 11951 return false; 11952 11953 EmulateInstruction::Context context; 11954 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11955 if (wback) { 11956 uint32_t Rm = ReadCoreReg(m, &success); 11957 if (!success) 11958 return false; 11959 11960 uint32_t offset; 11961 if (register_index) 11962 offset = Rm; 11963 else 11964 offset = 8 * regs; 11965 11966 uint32_t value = Rn + offset; 11967 context.type = eContextAdjustBaseRegister; 11968 context.SetRegisterPlusOffset(*base_reg, offset); 11969 11970 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 11971 value)) 11972 return false; 11973 } 11974 11975 // for r = 0 to regs-1 11976 for (uint32_t r = 0; r < regs; ++r) { 11977 // for e = 0 to elements-1 11978 uint64_t assembled_data = 0; 11979 for (uint32_t e = 0; e < elements; ++e) { 11980 // Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11981 context.type = eContextRegisterLoad; 11982 context.SetRegisterPlusOffset(*base_reg, address - Rn); 11983 uint64_t data = MemURead(context, address, ebytes, 0, &success); 11984 if (!success) 11985 return false; 11986 11987 assembled_data = 11988 (data << (e * esize)) | 11989 assembled_data; // New data goes to the left of existing data 11990 11991 // address = address + ebytes; 11992 address = address + ebytes; 11993 } 11994 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r, 11995 assembled_data)) 11996 return false; 11997 } 11998 } 11999 return true; 12000 } 12001 12002 // A8.6.308 VLD1 (single element to one lane) 12003 // 12004 bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode, 12005 const ARMEncoding encoding) { 12006 #if 0 12007 if ConditionPassed() then 12008 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 12009 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 12010 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12011 Elem[D[d],index,esize] = MemU[address,ebytes]; 12012 #endif 12013 12014 bool success = false; 12015 12016 if (ConditionPassed(opcode)) { 12017 uint32_t ebytes; 12018 uint32_t esize; 12019 uint32_t index; 12020 uint32_t alignment; 12021 uint32_t d; 12022 uint32_t n; 12023 uint32_t m; 12024 bool wback; 12025 bool register_index; 12026 12027 switch (encoding) { 12028 case eEncodingT1: 12029 case eEncodingA1: { 12030 uint32_t size = Bits32(opcode, 11, 10); 12031 uint32_t index_align = Bits32(opcode, 7, 4); 12032 // if size == '11' then SEE VLD1 (single element to all lanes); 12033 if (size == 3) 12034 return EmulateVLD1SingleAll(opcode, encoding); 12035 // case size of 12036 if (size == 0) // when '00' 12037 { 12038 // if index_align<0> != '0' then UNDEFINED; 12039 if (BitIsClear(index_align, 0)) 12040 return false; 12041 12042 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 12043 ebytes = 1; 12044 esize = 8; 12045 index = Bits32(index_align, 3, 1); 12046 alignment = 1; 12047 } else if (size == 1) // when '01' 12048 { 12049 // if index_align<1> != '0' then UNDEFINED; 12050 if (BitIsClear(index_align, 1)) 12051 return false; 12052 12053 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 12054 ebytes = 2; 12055 esize = 16; 12056 index = Bits32(index_align, 3, 2); 12057 12058 // alignment = if index_align<0> == '0' then 1 else 2; 12059 if (BitIsClear(index_align, 0)) 12060 alignment = 1; 12061 else 12062 alignment = 2; 12063 } else if (size == 2) // when '10' 12064 { 12065 // if index_align<2> != '0' then UNDEFINED; 12066 if (BitIsClear(index_align, 2)) 12067 return false; 12068 12069 // if index_align<1:0> != '00' && index_align<1:0> != '11' then 12070 // UNDEFINED; 12071 if ((Bits32(index_align, 1, 0) != 0) && 12072 (Bits32(index_align, 1, 0) != 3)) 12073 return false; 12074 12075 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 12076 ebytes = 4; 12077 esize = 32; 12078 index = Bit32(index_align, 3); 12079 12080 // alignment = if index_align<1:0> == '00' then 1 else 4; 12081 if (Bits32(index_align, 1, 0) == 0) 12082 alignment = 1; 12083 else 12084 alignment = 4; 12085 } else { 12086 return false; 12087 } 12088 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 12089 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 12090 n = Bits32(opcode, 19, 16); 12091 m = Bits32(opcode, 3, 0); 12092 12093 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 12094 // then UNPREDICTABLE; 12095 wback = (m != 15); 12096 register_index = ((m != 15) && (m != 13)); 12097 12098 if (n == 15) 12099 return false; 12100 12101 } break; 12102 12103 default: 12104 return false; 12105 } 12106 12107 uint32_t Rn = ReadCoreReg(n, &success); 12108 if (!success) 12109 return false; 12110 12111 // address = R[n]; if (address MOD alignment) != 0 then 12112 // GenerateAlignmentException(); 12113 addr_t address = Rn; 12114 if ((address % alignment) != 0) 12115 return false; 12116 12117 EmulateInstruction::Context context; 12118 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12119 if (wback) { 12120 uint32_t Rm = ReadCoreReg(m, &success); 12121 if (!success) 12122 return false; 12123 12124 uint32_t offset; 12125 if (register_index) 12126 offset = Rm; 12127 else 12128 offset = ebytes; 12129 12130 uint32_t value = Rn + offset; 12131 12132 context.type = eContextAdjustBaseRegister; 12133 std::optional<RegisterInfo> base_reg = 12134 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 12135 context.SetRegisterPlusOffset(*base_reg, offset); 12136 12137 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 12138 value)) 12139 return false; 12140 } 12141 12142 // Elem[D[d],index,esize] = MemU[address,ebytes]; 12143 uint32_t element = MemURead(context, address, esize, 0, &success); 12144 if (!success) 12145 return false; 12146 12147 element = element << (index * esize); 12148 12149 uint64_t reg_data = 12150 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 12151 if (!success) 12152 return false; 12153 12154 uint64_t all_ones = -1; 12155 uint64_t mask = all_ones 12156 << ((index + 1) * esize); // mask is all 1's to left of 12157 // where 'element' goes, & all 0's 12158 // at element & to the right of element. 12159 if (index > 0) 12160 mask = mask | Bits64(all_ones, (index * esize) - 1, 12161 0); // add 1's to the right of where 'element' goes. 12162 // now mask should be 0's where element goes & 1's everywhere else. 12163 12164 uint64_t masked_reg = 12165 reg_data & mask; // Take original reg value & zero out 'element' bits 12166 reg_data = 12167 masked_reg & element; // Put 'element' into those bits in reg_data. 12168 12169 context.type = eContextRegisterLoad; 12170 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 12171 reg_data)) 12172 return false; 12173 } 12174 return true; 12175 } 12176 12177 // A8.6.391 VST1 (multiple single elements) Vector Store (multiple single 12178 // elements) stores elements to memory from one, two, three, or four registers, 12179 // without interleaving. Every element of each register is stored. 12180 bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode, 12181 ARMEncoding encoding) { 12182 #if 0 12183 if ConditionPassed() then 12184 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 12185 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 12186 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 12187 for r = 0 to regs-1 12188 for e = 0 to elements-1 12189 MemU[address,ebytes] = Elem[D[d+r],e,esize]; 12190 address = address + ebytes; 12191 #endif 12192 12193 bool success = false; 12194 12195 if (ConditionPassed(opcode)) { 12196 uint32_t regs; 12197 uint32_t alignment; 12198 uint32_t ebytes; 12199 uint32_t esize; 12200 uint32_t elements; 12201 uint32_t d; 12202 uint32_t n; 12203 uint32_t m; 12204 bool wback; 12205 bool register_index; 12206 12207 switch (encoding) { 12208 case eEncodingT1: 12209 case eEncodingA1: { 12210 uint32_t type = Bits32(opcode, 11, 8); 12211 uint32_t align = Bits32(opcode, 5, 4); 12212 12213 // case type of 12214 if (type == 7) // when '0111' 12215 { 12216 // regs = 1; if align<1> == '1' then UNDEFINED; 12217 regs = 1; 12218 if (BitIsSet(align, 1)) 12219 return false; 12220 } else if (type == 10) // when '1010' 12221 { 12222 // regs = 2; if align == '11' then UNDEFINED; 12223 regs = 2; 12224 if (align == 3) 12225 return false; 12226 } else if (type == 6) // when '0110' 12227 { 12228 // regs = 3; if align<1> == '1' then UNDEFINED; 12229 regs = 3; 12230 if (BitIsSet(align, 1)) 12231 return false; 12232 } else if (type == 2) // when '0010' 12233 // regs = 4; 12234 regs = 4; 12235 else // otherwise 12236 // SEE 'Related encodings'; 12237 return false; 12238 12239 // alignment = if align == '00' then 1 else 4 << UInt(align); 12240 if (align == 0) 12241 alignment = 1; 12242 else 12243 alignment = 4 << align; 12244 12245 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 12246 ebytes = 1 << Bits32(opcode, 7, 6); 12247 esize = 8 * ebytes; 12248 elements = 8 / ebytes; 12249 12250 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 12251 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 12252 n = Bits32(opcode, 19, 16); 12253 m = Bits32(opcode, 3, 0); 12254 12255 // wback = (m != 15); register_index = (m != 15 && m != 13); 12256 wback = (m != 15); 12257 register_index = ((m != 15) && (m != 13)); 12258 12259 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 12260 if ((d + regs) > 32) 12261 return false; 12262 12263 if (n == 15) 12264 return false; 12265 12266 } break; 12267 12268 default: 12269 return false; 12270 } 12271 12272 std::optional<RegisterInfo> base_reg = 12273 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 12274 12275 uint32_t Rn = ReadCoreReg(n, &success); 12276 if (!success) 12277 return false; 12278 12279 // address = R[n]; if (address MOD alignment) != 0 then 12280 // GenerateAlignmentException(); 12281 addr_t address = Rn; 12282 if ((address % alignment) != 0) 12283 return false; 12284 12285 EmulateInstruction::Context context; 12286 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 12287 if (wback) { 12288 uint32_t Rm = ReadCoreReg(m, &success); 12289 if (!success) 12290 return false; 12291 12292 uint32_t offset; 12293 if (register_index) 12294 offset = Rm; 12295 else 12296 offset = 8 * regs; 12297 12298 context.type = eContextAdjustBaseRegister; 12299 context.SetRegisterPlusOffset(*base_reg, offset); 12300 12301 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 12302 Rn + offset)) 12303 return false; 12304 } 12305 12306 context.type = eContextRegisterStore; 12307 // for r = 0 to regs-1 12308 for (uint32_t r = 0; r < regs; ++r) { 12309 std::optional<RegisterInfo> data_reg = 12310 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r); 12311 uint64_t register_data = ReadRegisterUnsigned( 12312 eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success); 12313 if (!success) 12314 return false; 12315 12316 // for e = 0 to elements-1 12317 for (uint32_t e = 0; e < elements; ++e) { 12318 // MemU[address,ebytes] = Elem[D[d+r],e,esize]; 12319 uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize); 12320 12321 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 12322 address - Rn); 12323 if (!MemUWrite(context, address, word, ebytes)) 12324 return false; 12325 12326 // address = address + ebytes; 12327 address = address + ebytes; 12328 } 12329 } 12330 } 12331 return true; 12332 } 12333 12334 // A8.6.392 VST1 (single element from one lane) This instruction stores one 12335 // element to memory from one element of a register. 12336 bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode, 12337 ARMEncoding encoding) { 12338 #if 0 12339 if ConditionPassed() then 12340 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 12341 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 12342 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12343 MemU[address,ebytes] = Elem[D[d],index,esize]; 12344 #endif 12345 12346 bool success = false; 12347 12348 if (ConditionPassed(opcode)) { 12349 uint32_t ebytes; 12350 uint32_t esize; 12351 uint32_t index; 12352 uint32_t alignment; 12353 uint32_t d; 12354 uint32_t n; 12355 uint32_t m; 12356 bool wback; 12357 bool register_index; 12358 12359 switch (encoding) { 12360 case eEncodingT1: 12361 case eEncodingA1: { 12362 uint32_t size = Bits32(opcode, 11, 10); 12363 uint32_t index_align = Bits32(opcode, 7, 4); 12364 12365 // if size == '11' then UNDEFINED; 12366 if (size == 3) 12367 return false; 12368 12369 // case size of 12370 if (size == 0) // when '00' 12371 { 12372 // if index_align<0> != '0' then UNDEFINED; 12373 if (BitIsClear(index_align, 0)) 12374 return false; 12375 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 12376 ebytes = 1; 12377 esize = 8; 12378 index = Bits32(index_align, 3, 1); 12379 alignment = 1; 12380 } else if (size == 1) // when '01' 12381 { 12382 // if index_align<1> != '0' then UNDEFINED; 12383 if (BitIsClear(index_align, 1)) 12384 return false; 12385 12386 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 12387 ebytes = 2; 12388 esize = 16; 12389 index = Bits32(index_align, 3, 2); 12390 12391 // alignment = if index_align<0> == '0' then 1 else 2; 12392 if (BitIsClear(index_align, 0)) 12393 alignment = 1; 12394 else 12395 alignment = 2; 12396 } else if (size == 2) // when '10' 12397 { 12398 // if index_align<2> != '0' then UNDEFINED; 12399 if (BitIsClear(index_align, 2)) 12400 return false; 12401 12402 // if index_align<1:0> != '00' && index_align<1:0> != '11' then 12403 // UNDEFINED; 12404 if ((Bits32(index_align, 1, 0) != 0) && 12405 (Bits32(index_align, 1, 0) != 3)) 12406 return false; 12407 12408 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 12409 ebytes = 4; 12410 esize = 32; 12411 index = Bit32(index_align, 3); 12412 12413 // alignment = if index_align<1:0> == '00' then 1 else 4; 12414 if (Bits32(index_align, 1, 0) == 0) 12415 alignment = 1; 12416 else 12417 alignment = 4; 12418 } else { 12419 return false; 12420 } 12421 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 12422 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 12423 n = Bits32(opcode, 19, 16); 12424 m = Bits32(opcode, 3, 0); 12425 12426 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 12427 // then UNPREDICTABLE; 12428 wback = (m != 15); 12429 register_index = ((m != 15) && (m != 13)); 12430 12431 if (n == 15) 12432 return false; 12433 } break; 12434 12435 default: 12436 return false; 12437 } 12438 12439 std::optional<RegisterInfo> base_reg = 12440 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 12441 12442 uint32_t Rn = ReadCoreReg(n, &success); 12443 if (!success) 12444 return false; 12445 12446 // address = R[n]; if (address MOD alignment) != 0 then 12447 // GenerateAlignmentException(); 12448 addr_t address = Rn; 12449 if ((address % alignment) != 0) 12450 return false; 12451 12452 EmulateInstruction::Context context; 12453 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12454 if (wback) { 12455 uint32_t Rm = ReadCoreReg(m, &success); 12456 if (!success) 12457 return false; 12458 12459 uint32_t offset; 12460 if (register_index) 12461 offset = Rm; 12462 else 12463 offset = ebytes; 12464 12465 context.type = eContextAdjustBaseRegister; 12466 context.SetRegisterPlusOffset(*base_reg, offset); 12467 12468 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 12469 Rn + offset)) 12470 return false; 12471 } 12472 12473 // MemU[address,ebytes] = Elem[D[d],index,esize]; 12474 uint64_t register_data = 12475 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 12476 if (!success) 12477 return false; 12478 12479 uint64_t word = 12480 Bits64(register_data, ((index + 1) * esize) - 1, index * esize); 12481 12482 std::optional<RegisterInfo> data_reg = 12483 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d); 12484 context.type = eContextRegisterStore; 12485 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 12486 12487 if (!MemUWrite(context, address, word, ebytes)) 12488 return false; 12489 } 12490 return true; 12491 } 12492 12493 // A8.6.309 VLD1 (single element to all lanes) This instruction loads one 12494 // element from memory into every element of one or two vectors. 12495 bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode, 12496 const ARMEncoding encoding) { 12497 #if 0 12498 if ConditionPassed() then 12499 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 12500 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 12501 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12502 replicated_element = Replicate(MemU[address,ebytes], elements); 12503 for r = 0 to regs-1 12504 D[d+r] = replicated_element; 12505 #endif 12506 12507 bool success = false; 12508 12509 if (ConditionPassed(opcode)) { 12510 uint32_t ebytes; 12511 uint32_t elements; 12512 uint32_t regs; 12513 uint32_t alignment; 12514 uint32_t d; 12515 uint32_t n; 12516 uint32_t m; 12517 bool wback; 12518 bool register_index; 12519 12520 switch (encoding) { 12521 case eEncodingT1: 12522 case eEncodingA1: { 12523 // if size == '11' || (size == '00' && a == '1') then UNDEFINED; 12524 uint32_t size = Bits32(opcode, 7, 6); 12525 if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4))) 12526 return false; 12527 12528 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0' 12529 // then 1 else 2; 12530 ebytes = 1 << size; 12531 elements = 8 / ebytes; 12532 if (BitIsClear(opcode, 5)) 12533 regs = 1; 12534 else 12535 regs = 2; 12536 12537 // alignment = if a == '0' then 1 else ebytes; 12538 if (BitIsClear(opcode, 4)) 12539 alignment = 1; 12540 else 12541 alignment = ebytes; 12542 12543 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 12544 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 12545 n = Bits32(opcode, 19, 16); 12546 m = Bits32(opcode, 3, 0); 12547 12548 // wback = (m != 15); register_index = (m != 15 && m != 13); 12549 wback = (m != 15); 12550 register_index = ((m != 15) && (m != 13)); 12551 12552 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 12553 if ((d + regs) > 32) 12554 return false; 12555 12556 if (n == 15) 12557 return false; 12558 } break; 12559 12560 default: 12561 return false; 12562 } 12563 12564 uint32_t Rn = ReadCoreReg(n, &success); 12565 if (!success) 12566 return false; 12567 12568 // address = R[n]; if (address MOD alignment) != 0 then 12569 // GenerateAlignmentException(); 12570 addr_t address = Rn; 12571 if ((address % alignment) != 0) 12572 return false; 12573 12574 EmulateInstruction::Context context; 12575 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12576 if (wback) { 12577 uint32_t Rm = ReadCoreReg(m, &success); 12578 if (!success) 12579 return false; 12580 12581 uint32_t offset; 12582 if (register_index) 12583 offset = Rm; 12584 else 12585 offset = ebytes; 12586 12587 context.type = eContextAdjustBaseRegister; 12588 std::optional<RegisterInfo> base_reg = 12589 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 12590 context.SetRegisterPlusOffset(*base_reg, offset); 12591 12592 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 12593 Rn + offset)) 12594 return false; 12595 } 12596 12597 // replicated_element = Replicate(MemU[address,ebytes], elements); 12598 12599 context.type = eContextRegisterLoad; 12600 uint64_t word = MemURead(context, address, ebytes, 0, &success); 12601 if (!success) 12602 return false; 12603 12604 uint64_t replicated_element = 0; 12605 uint32_t esize = ebytes * 8; 12606 for (uint32_t e = 0; e < elements; ++e) 12607 replicated_element = 12608 (replicated_element << esize) | Bits64(word, esize - 1, 0); 12609 12610 // for r = 0 to regs-1 12611 for (uint32_t r = 0; r < regs; ++r) { 12612 // D[d+r] = replicated_element; 12613 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r, 12614 replicated_element)) 12615 return false; 12616 } 12617 } 12618 return true; 12619 } 12620 12621 // B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const? 12622 // instruction provides an exception return without the use of the stack. It 12623 // subtracts the immediate constant from the LR, branches to the resulting 12624 // address, and also copies the SPSR to the CPSR. 12625 bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode, 12626 const ARMEncoding encoding) { 12627 #if 0 12628 if ConditionPassed() then 12629 EncodingSpecificOperations(); 12630 if CurrentInstrSet() == InstrSet_ThumbEE then 12631 UNPREDICTABLE; 12632 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; 12633 case opcode of 12634 when '0000' result = R[n] AND operand2; // AND 12635 when '0001' result = R[n] EOR operand2; // EOR 12636 when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB 12637 when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB 12638 when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD 12639 when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC 12640 when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC 12641 when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC 12642 when '1100' result = R[n] OR operand2; // ORR 12643 when '1101' result = operand2; // MOV 12644 when '1110' result = R[n] AND NOT(operand2); // BIC 12645 when '1111' result = NOT(operand2); // MVN 12646 CPSRWriteByInstr(SPSR[], '1111', TRUE); 12647 BranchWritePC(result); 12648 #endif 12649 12650 bool success = false; 12651 12652 if (ConditionPassed(opcode)) { 12653 uint32_t n; 12654 uint32_t m; 12655 uint32_t imm32; 12656 bool register_form; 12657 ARM_ShifterType shift_t; 12658 uint32_t shift_n; 12659 uint32_t code; 12660 12661 switch (encoding) { 12662 case eEncodingT1: 12663 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14; 12664 // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010'; 12665 // // = SUB 12666 n = 14; 12667 imm32 = Bits32(opcode, 7, 0); 12668 register_form = false; 12669 code = 2; 12670 12671 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 12672 if (InITBlock() && !LastInITBlock()) 12673 return false; 12674 12675 break; 12676 12677 case eEncodingA1: 12678 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE; 12679 n = Bits32(opcode, 19, 16); 12680 imm32 = ARMExpandImm(opcode); 12681 register_form = false; 12682 code = Bits32(opcode, 24, 21); 12683 12684 break; 12685 12686 case eEncodingA2: 12687 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE; 12688 n = Bits32(opcode, 19, 16); 12689 m = Bits32(opcode, 3, 0); 12690 register_form = true; 12691 12692 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 12693 shift_n = DecodeImmShiftARM(opcode, shift_t); 12694 12695 break; 12696 12697 default: 12698 return false; 12699 } 12700 12701 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) 12702 // else imm32; 12703 uint32_t operand2; 12704 if (register_form) { 12705 uint32_t Rm = ReadCoreReg(m, &success); 12706 if (!success) 12707 return false; 12708 12709 operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success); 12710 if (!success) 12711 return false; 12712 } else { 12713 operand2 = imm32; 12714 } 12715 12716 uint32_t Rn = ReadCoreReg(n, &success); 12717 if (!success) 12718 return false; 12719 12720 AddWithCarryResult result; 12721 12722 // case opcode of 12723 switch (code) { 12724 case 0: // when '0000' 12725 // result = R[n] AND operand2; // AND 12726 result.result = Rn & operand2; 12727 break; 12728 12729 case 1: // when '0001' 12730 // result = R[n] EOR operand2; // EOR 12731 result.result = Rn ^ operand2; 12732 break; 12733 12734 case 2: // when '0010' 12735 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB 12736 result = AddWithCarry(Rn, ~(operand2), 1); 12737 break; 12738 12739 case 3: // when '0011' 12740 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB 12741 result = AddWithCarry(~(Rn), operand2, 1); 12742 break; 12743 12744 case 4: // when '0100' 12745 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD 12746 result = AddWithCarry(Rn, operand2, 0); 12747 break; 12748 12749 case 5: // when '0101' 12750 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC 12751 result = AddWithCarry(Rn, operand2, APSR_C); 12752 break; 12753 12754 case 6: // when '0110' 12755 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC 12756 result = AddWithCarry(Rn, ~(operand2), APSR_C); 12757 break; 12758 12759 case 7: // when '0111' 12760 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC 12761 result = AddWithCarry(~(Rn), operand2, APSR_C); 12762 break; 12763 12764 case 10: // when '1100' 12765 // result = R[n] OR operand2; // ORR 12766 result.result = Rn | operand2; 12767 break; 12768 12769 case 11: // when '1101' 12770 // result = operand2; // MOV 12771 result.result = operand2; 12772 break; 12773 12774 case 12: // when '1110' 12775 // result = R[n] AND NOT(operand2); // BIC 12776 result.result = Rn & ~(operand2); 12777 break; 12778 12779 case 15: // when '1111' 12780 // result = NOT(operand2); // MVN 12781 result.result = ~(operand2); 12782 break; 12783 12784 default: 12785 return false; 12786 } 12787 // CPSRWriteByInstr(SPSR[], '1111', TRUE); 12788 12789 // For now, in emulation mode, we don't have access to the SPSR, so we will 12790 // use the CPSR instead, and hope for the best. 12791 uint32_t spsr = 12792 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success); 12793 if (!success) 12794 return false; 12795 12796 CPSRWriteByInstr(spsr, 15, true); 12797 12798 // BranchWritePC(result); 12799 EmulateInstruction::Context context; 12800 context.type = eContextAdjustPC; 12801 context.SetImmediate(result.result); 12802 12803 BranchWritePC(context, result.result); 12804 } 12805 return true; 12806 } 12807 12808 EmulateInstructionARM::ARMOpcode * 12809 EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode, 12810 uint32_t arm_isa) { 12811 static ARMOpcode g_arm_opcodes[] = { 12812 // Prologue instructions 12813 12814 // push register(s) 12815 {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12816 &EmulateInstructionARM::EmulatePUSH, "push <registers>"}, 12817 {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, 12818 &EmulateInstructionARM::EmulatePUSH, "push <register>"}, 12819 12820 // set r7 to point to a stack offset 12821 {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12822 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"}, 12823 {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12824 &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"}, 12825 // copy the stack pointer to ip 12826 {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, 12827 &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"}, 12828 {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12829 &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"}, 12830 {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12831 &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"}, 12832 12833 // adjust the stack pointer 12834 {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12835 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"}, 12836 {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12837 &EmulateInstructionARM::EmulateSUBSPReg, 12838 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"}, 12839 12840 // push one register 12841 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH; 12842 {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12843 &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"}, 12844 12845 // vector push consecutive extension register(s) 12846 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, 12847 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 12848 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, 12849 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 12850 12851 // Epilogue instructions 12852 12853 {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12854 &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 12855 {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, 12856 &EmulateInstructionARM::EmulatePOP, "pop <register>"}, 12857 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, 12858 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 12859 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, 12860 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 12861 12862 // Supervisor Call (previously Software Interrupt) 12863 {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12864 &EmulateInstructionARM::EmulateSVC, "svc #imm24"}, 12865 12866 // Branch instructions 12867 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and 12868 // "bl <label>". 12869 {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, 12870 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 12871 {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12872 &EmulateInstructionARM::EmulateB, "b #imm24"}, 12873 {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12874 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 12875 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, 12876 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 12877 // for example, "bx lr" 12878 {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, 12879 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 12880 // bxj 12881 {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, 12882 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 12883 12884 // Data-processing instructions 12885 // adc (immediate) 12886 {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12887 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"}, 12888 // adc (register) 12889 {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12890 &EmulateInstructionARM::EmulateADCReg, 12891 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12892 // add (immediate) 12893 {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12894 &EmulateInstructionARM::EmulateADDImmARM, 12895 "add{s}<c> <Rd>, <Rn>, #const"}, 12896 // add (register) 12897 {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12898 &EmulateInstructionARM::EmulateADDReg, 12899 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12900 // add (register-shifted register) 12901 {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, 12902 &EmulateInstructionARM::EmulateADDRegShift, 12903 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"}, 12904 // adr 12905 {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12906 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12907 {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, 12908 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 12909 // and (immediate) 12910 {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12911 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"}, 12912 // and (register) 12913 {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12914 &EmulateInstructionARM::EmulateANDReg, 12915 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12916 // bic (immediate) 12917 {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12918 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"}, 12919 // bic (register) 12920 {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12921 &EmulateInstructionARM::EmulateBICReg, 12922 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12923 // eor (immediate) 12924 {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12925 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"}, 12926 // eor (register) 12927 {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12928 &EmulateInstructionARM::EmulateEORReg, 12929 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12930 // orr (immediate) 12931 {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12932 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"}, 12933 // orr (register) 12934 {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12935 &EmulateInstructionARM::EmulateORRReg, 12936 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12937 // rsb (immediate) 12938 {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12939 &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"}, 12940 // rsb (register) 12941 {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12942 &EmulateInstructionARM::EmulateRSBReg, 12943 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12944 // rsc (immediate) 12945 {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12946 &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"}, 12947 // rsc (register) 12948 {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12949 &EmulateInstructionARM::EmulateRSCReg, 12950 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12951 // sbc (immediate) 12952 {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12953 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 12954 // sbc (register) 12955 {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12956 &EmulateInstructionARM::EmulateSBCReg, 12957 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12958 // sub (immediate, ARM) 12959 {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12960 &EmulateInstructionARM::EmulateSUBImmARM, 12961 "sub{s}<c> <Rd>, <Rn>, #<const>"}, 12962 // sub (sp minus immediate) 12963 {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12964 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"}, 12965 // sub (register) 12966 {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12967 &EmulateInstructionARM::EmulateSUBReg, 12968 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"}, 12969 // teq (immediate) 12970 {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12971 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"}, 12972 // teq (register) 12973 {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12974 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 12975 // tst (immediate) 12976 {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12977 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"}, 12978 // tst (register) 12979 {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12980 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"}, 12981 12982 // mov (immediate) 12983 {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12984 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"}, 12985 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, 12986 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"}, 12987 // mov (register) 12988 {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12989 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"}, 12990 // mvn (immediate) 12991 {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12992 &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"}, 12993 // mvn (register) 12994 {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12995 &EmulateInstructionARM::EmulateMVNReg, 12996 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"}, 12997 // cmn (immediate) 12998 {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12999 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 13000 // cmn (register) 13001 {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13002 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 13003 // cmp (immediate) 13004 {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13005 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"}, 13006 // cmp (register) 13007 {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13008 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"}, 13009 // asr (immediate) 13010 {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, 13011 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"}, 13012 // asr (register) 13013 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, 13014 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"}, 13015 // lsl (immediate) 13016 {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13017 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"}, 13018 // lsl (register) 13019 {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, 13020 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"}, 13021 // lsr (immediate) 13022 {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, 13023 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"}, 13024 // lsr (register) 13025 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, 13026 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"}, 13027 // rrx is a special case encoding of ror (immediate) 13028 {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, 13029 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"}, 13030 // ror (immediate) 13031 {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, 13032 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"}, 13033 // ror (register) 13034 {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, 13035 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"}, 13036 // mul 13037 {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, 13038 &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"}, 13039 13040 // subs pc, lr and related instructions 13041 {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13042 &EmulateInstructionARM::EmulateSUBSPcLrEtc, 13043 "<opc>S<c> PC,#<const> | <Rn>,#<const>"}, 13044 {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, 13045 &EmulateInstructionARM::EmulateSUBSPcLrEtc, 13046 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"}, 13047 13048 // Load instructions 13049 {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13050 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"}, 13051 {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13052 &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"}, 13053 {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13054 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"}, 13055 {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13056 &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"}, 13057 {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13058 &EmulateInstructionARM::EmulateLDRImmediateARM, 13059 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"}, 13060 {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13061 &EmulateInstructionARM::EmulateLDRRegister, 13062 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"}, 13063 {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13064 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"}, 13065 {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13066 &EmulateInstructionARM::EmulateLDRBRegister, 13067 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"}, 13068 {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13069 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"}, 13070 {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13071 &EmulateInstructionARM::EmulateLDRHRegister, 13072 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"}, 13073 {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13074 &EmulateInstructionARM::EmulateLDRSBImmediate, 13075 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"}, 13076 {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13077 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"}, 13078 {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13079 &EmulateInstructionARM::EmulateLDRSBRegister, 13080 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"}, 13081 {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13082 &EmulateInstructionARM::EmulateLDRSHImmediate, 13083 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"}, 13084 {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13085 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"}, 13086 {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13087 &EmulateInstructionARM::EmulateLDRSHRegister, 13088 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"}, 13089 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, 13090 &EmulateInstructionARM::EmulateLDRDImmediate, 13091 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"}, 13092 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, 13093 &EmulateInstructionARM::EmulateLDRDRegister, 13094 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 13095 {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, 13096 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 13097 {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, 13098 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 13099 {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, 13100 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 13101 {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, 13102 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 13103 {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, 13104 &EmulateInstructionARM::EmulateVLD1Multiple, 13105 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13106 {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, 13107 &EmulateInstructionARM::EmulateVLD1Single, 13108 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13109 {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, 13110 &EmulateInstructionARM::EmulateVLD1SingleAll, 13111 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13112 13113 // Store instructions 13114 {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13115 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"}, 13116 {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13117 &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"}, 13118 {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13119 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"}, 13120 {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13121 &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"}, 13122 {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13123 &EmulateInstructionARM::EmulateSTRRegister, 13124 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"}, 13125 {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13126 &EmulateInstructionARM::EmulateSTRHRegister, 13127 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"}, 13128 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13129 &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"}, 13130 {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13131 &EmulateInstructionARM::EmulateSTRBImmARM, 13132 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 13133 {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13134 &EmulateInstructionARM::EmulateSTRImmARM, 13135 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 13136 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, 13137 &EmulateInstructionARM::EmulateSTRDImm, 13138 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"}, 13139 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, 13140 &EmulateInstructionARM::EmulateSTRDReg, 13141 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 13142 {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, 13143 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 13144 {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, 13145 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 13146 {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, 13147 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"}, 13148 {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, 13149 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"}, 13150 {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, 13151 &EmulateInstructionARM::EmulateVST1Multiple, 13152 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13153 {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, 13154 &EmulateInstructionARM::EmulateVST1Single, 13155 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13156 13157 // Other instructions 13158 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13159 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"}, 13160 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13161 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"}, 13162 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13163 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"}, 13164 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13165 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"}, 13166 {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13167 &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"} 13168 13169 }; 13170 static const size_t k_num_arm_opcodes = std::size(g_arm_opcodes); 13171 13172 for (size_t i = 0; i < k_num_arm_opcodes; ++i) { 13173 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value && 13174 (g_arm_opcodes[i].variants & arm_isa) != 0) 13175 return &g_arm_opcodes[i]; 13176 } 13177 return nullptr; 13178 } 13179 13180 EmulateInstructionARM::ARMOpcode * 13181 EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode, 13182 uint32_t arm_isa) { 13183 13184 static ARMOpcode g_thumb_opcodes[] = { 13185 // Prologue instructions 13186 13187 // push register(s) 13188 {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, 13189 &EmulateInstructionARM::EmulatePUSH, "push <registers>"}, 13190 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13191 &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"}, 13192 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13193 &EmulateInstructionARM::EmulatePUSH, "push.w <register>"}, 13194 13195 // set r7 to point to a stack offset 13196 {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, 13197 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"}, 13198 // copy the stack pointer to r7 13199 {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, 13200 &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"}, 13201 // move from high register to low register (comes after "mov r7, sp" to 13202 // resolve ambiguity) 13203 {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, 13204 &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"}, 13205 13206 // PC-relative load into register (see also EmulateADDSPRm) 13207 {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, 13208 &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"}, 13209 13210 // adjust the stack pointer 13211 {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, 13212 &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"}, 13213 {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, 13214 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"}, 13215 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13216 &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"}, 13217 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13218 &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"}, 13219 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13220 &EmulateInstructionARM::EmulateSUBSPReg, 13221 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"}, 13222 13223 // vector push consecutive extension register(s) 13224 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13225 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 13226 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13227 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 13228 13229 // Epilogue instructions 13230 13231 {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13232 &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"}, 13233 {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, 13234 &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"}, 13235 {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, 13236 &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 13237 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13238 &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"}, 13239 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13240 &EmulateInstructionARM::EmulatePOP, "pop.w <register>"}, 13241 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13242 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 13243 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13244 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 13245 13246 // Supervisor Call (previously Software Interrupt) 13247 {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, 13248 &EmulateInstructionARM::EmulateSVC, "svc #imm8"}, 13249 13250 // If Then makes up to four following instructions conditional. 13251 // The next 5 opcode _must_ come before the if then instruction 13252 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, 13253 &EmulateInstructionARM::EmulateNop, "nop"}, 13254 {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, 13255 &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"}, 13256 {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, 13257 &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"}, 13258 {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, 13259 &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"}, 13260 {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, 13261 &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"}, 13262 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, 13263 &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, 13264 13265 // Branch instructions 13266 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8". 13267 {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13268 &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"}, 13269 {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, 13270 &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"}, 13271 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13272 &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"}, 13273 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, 13274 &EmulateInstructionARM::EmulateB, 13275 "b<c>.w #imm8 (outside or last in IT)"}, 13276 // J1 == J2 == 1 13277 {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, 13278 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 13279 // J1 == J2 == 1 13280 {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, 13281 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 13282 {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, 13283 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 13284 // for example, "bx lr" 13285 {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32, 13286 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 13287 // bxj 13288 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, 13289 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 13290 // compare and branch 13291 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, 13292 &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"}, 13293 // table branch byte 13294 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13295 &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"}, 13296 // table branch halfword 13297 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13298 &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"}, 13299 13300 // Data-processing instructions 13301 // adc (immediate) 13302 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13303 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"}, 13304 // adc (register) 13305 {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, 13306 &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"}, 13307 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13308 &EmulateInstructionARM::EmulateADCReg, 13309 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13310 // add (register) 13311 {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, 13312 &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"}, 13313 // Make sure "add sp, <Rm>" comes before this instruction, so there's no 13314 // ambiguity decoding the two. 13315 {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, 13316 &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"}, 13317 // adr 13318 {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13319 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 13320 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13321 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 13322 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13323 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 13324 // and (immediate) 13325 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13326 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"}, 13327 // and (register) 13328 {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13329 &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"}, 13330 {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13331 &EmulateInstructionARM::EmulateANDReg, 13332 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13333 // bic (immediate) 13334 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13335 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"}, 13336 // bic (register) 13337 {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, 13338 &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"}, 13339 {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13340 &EmulateInstructionARM::EmulateBICReg, 13341 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13342 // eor (immediate) 13343 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13344 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"}, 13345 // eor (register) 13346 {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, 13347 &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"}, 13348 {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13349 &EmulateInstructionARM::EmulateEORReg, 13350 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13351 // orr (immediate) 13352 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13353 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"}, 13354 // orr (register) 13355 {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, 13356 &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"}, 13357 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13358 &EmulateInstructionARM::EmulateORRReg, 13359 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13360 // rsb (immediate) 13361 {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, 13362 &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"}, 13363 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13364 &EmulateInstructionARM::EmulateRSBImm, 13365 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"}, 13366 // rsb (register) 13367 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13368 &EmulateInstructionARM::EmulateRSBReg, 13369 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13370 // sbc (immediate) 13371 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13372 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 13373 // sbc (register) 13374 {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, 13375 &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"}, 13376 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13377 &EmulateInstructionARM::EmulateSBCReg, 13378 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13379 // add (immediate, Thumb) 13380 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13381 &EmulateInstructionARM::EmulateADDImmThumb, 13382 "adds|add<c> <Rd>,<Rn>,#<imm3>"}, 13383 {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, 13384 &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"}, 13385 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13386 &EmulateInstructionARM::EmulateADDImmThumb, 13387 "add{s}<c>.w <Rd>,<Rn>,#<const>"}, 13388 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, 13389 &EmulateInstructionARM::EmulateADDImmThumb, 13390 "addw<c> <Rd>,<Rn>,#<imm12>"}, 13391 // sub (immediate, Thumb) 13392 {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, 13393 &EmulateInstructionARM::EmulateSUBImmThumb, 13394 "subs|sub<c> <Rd>, <Rn> #imm3"}, 13395 {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, 13396 &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"}, 13397 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13398 &EmulateInstructionARM::EmulateSUBImmThumb, 13399 "sub{s}<c>.w <Rd>, <Rn>, #<const>"}, 13400 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, 13401 &EmulateInstructionARM::EmulateSUBImmThumb, 13402 "subw<c> <Rd>, <Rn>, #imm12"}, 13403 // sub (sp minus immediate) 13404 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13405 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"}, 13406 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13407 &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"}, 13408 // sub (register) 13409 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13410 &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"}, 13411 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13412 &EmulateInstructionARM::EmulateSUBReg, 13413 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"}, 13414 // teq (immediate) 13415 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13416 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"}, 13417 // teq (register) 13418 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13419 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 13420 // tst (immediate) 13421 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13422 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"}, 13423 // tst (register) 13424 {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, 13425 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"}, 13426 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13427 &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"}, 13428 13429 // move from high register to high register 13430 {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, 13431 &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"}, 13432 // move from low register to low register 13433 {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, 13434 &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"}, 13435 // mov{s}<c>.w <Rd>, <Rm> 13436 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13437 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"}, 13438 // move immediate 13439 {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13440 &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"}, 13441 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13442 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"}, 13443 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13444 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"}, 13445 // mvn (immediate) 13446 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13447 &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"}, 13448 // mvn (register) 13449 {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, 13450 &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"}, 13451 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13452 &EmulateInstructionARM::EmulateMVNReg, 13453 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"}, 13454 // cmn (immediate) 13455 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13456 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 13457 // cmn (register) 13458 {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, 13459 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"}, 13460 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13461 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 13462 // cmp (immediate) 13463 {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, 13464 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"}, 13465 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13466 &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"}, 13467 // cmp (register) (Rn and Rm both from r0-r7) 13468 {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, 13469 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 13470 // cmp (register) (Rn and Rm not both from r0-r7) 13471 {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, 13472 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 13473 {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16, 13474 &EmulateInstructionARM::EmulateCMPReg, 13475 "cmp<c>.w <Rn>, <Rm> {, <shift>}"}, 13476 // asr (immediate) 13477 {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13478 &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"}, 13479 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13480 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"}, 13481 // asr (register) 13482 {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, 13483 &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"}, 13484 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13485 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 13486 // lsl (immediate) 13487 {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13488 &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"}, 13489 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13490 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"}, 13491 // lsl (register) 13492 {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, 13493 &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"}, 13494 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13495 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"}, 13496 // lsr (immediate) 13497 {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, 13498 &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"}, 13499 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13500 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"}, 13501 // lsr (register) 13502 {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, 13503 &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"}, 13504 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13505 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 13506 // rrx is a special case encoding of ror (immediate) 13507 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13508 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"}, 13509 // ror (immediate) 13510 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13511 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"}, 13512 // ror (register) 13513 {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, 13514 &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"}, 13515 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13516 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"}, 13517 // mul 13518 {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13519 &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"}, 13520 // mul 13521 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13522 &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"}, 13523 13524 // subs pc, lr and related instructions 13525 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13526 &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"}, 13527 13528 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE 13529 // LDM.. Instructions in this table; 13530 // otherwise the wrong instructions will be selected. 13531 13532 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13533 &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"}, 13534 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13535 &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"}, 13536 13537 // Load instructions 13538 {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13539 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"}, 13540 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13541 &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"}, 13542 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13543 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"}, 13544 {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13545 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}, 13546 {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, 13547 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"}, 13548 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13549 &EmulateInstructionARM::EmulateLDRRtRnImm, 13550 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"}, 13551 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, 13552 &EmulateInstructionARM::EmulateLDRRtRnImm, 13553 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"}, 13554 // Thumb2 PC-relative load into register 13555 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13556 &EmulateInstructionARM::EmulateLDRRtPCRelative, 13557 "ldr<c>.w <Rt>, [PC, +/-#imm}]"}, 13558 {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13559 &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"}, 13560 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13561 &EmulateInstructionARM::EmulateLDRRegister, 13562 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"}, 13563 {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13564 &EmulateInstructionARM::EmulateLDRBImmediate, 13565 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"}, 13566 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13567 &EmulateInstructionARM::EmulateLDRBImmediate, 13568 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"}, 13569 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13570 &EmulateInstructionARM::EmulateLDRBImmediate, 13571 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"}, 13572 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13573 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"}, 13574 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, 13575 &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"}, 13576 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13577 &EmulateInstructionARM::EmulateLDRBRegister, 13578 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"}, 13579 {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13580 &EmulateInstructionARM::EmulateLDRHImmediate, 13581 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"}, 13582 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13583 &EmulateInstructionARM::EmulateLDRHImmediate, 13584 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"}, 13585 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13586 &EmulateInstructionARM::EmulateLDRHImmediate, 13587 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"}, 13588 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13589 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"}, 13590 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13591 &EmulateInstructionARM::EmulateLDRHRegister, 13592 "ldrh<c> <Rt>, [<Rn>,<Rm>]"}, 13593 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13594 &EmulateInstructionARM::EmulateLDRHRegister, 13595 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"}, 13596 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13597 &EmulateInstructionARM::EmulateLDRSBImmediate, 13598 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"}, 13599 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13600 &EmulateInstructionARM::EmulateLDRSBImmediate, 13601 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"}, 13602 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13603 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"}, 13604 {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13605 &EmulateInstructionARM::EmulateLDRSBRegister, 13606 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"}, 13607 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13608 &EmulateInstructionARM::EmulateLDRSBRegister, 13609 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"}, 13610 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13611 &EmulateInstructionARM::EmulateLDRSHImmediate, 13612 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"}, 13613 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13614 &EmulateInstructionARM::EmulateLDRSHImmediate, 13615 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"}, 13616 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13617 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"}, 13618 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13619 &EmulateInstructionARM::EmulateLDRSHRegister, 13620 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"}, 13621 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13622 &EmulateInstructionARM::EmulateLDRSHRegister, 13623 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"}, 13624 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13625 &EmulateInstructionARM::EmulateLDRDImmediate, 13626 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"}, 13627 {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, 13628 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 13629 {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, 13630 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 13631 {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, 13632 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 13633 {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, 13634 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"}, 13635 {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, 13636 &EmulateInstructionARM::EmulateVLD1Multiple, 13637 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 13638 {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, 13639 &EmulateInstructionARM::EmulateVLD1Single, 13640 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 13641 {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, 13642 &EmulateInstructionARM::EmulateVLD1SingleAll, 13643 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13644 13645 // Store instructions 13646 {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13647 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"}, 13648 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13649 &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"}, 13650 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13651 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"}, 13652 {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13653 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"}, 13654 {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, 13655 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"}, 13656 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13657 &EmulateInstructionARM::EmulateSTRThumb, 13658 "str<c>.w <Rt>, [<Rn>,#<imm12>]"}, 13659 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, 13660 &EmulateInstructionARM::EmulateSTRThumb, 13661 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"}, 13662 {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13663 &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"}, 13664 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13665 &EmulateInstructionARM::EmulateSTRRegister, 13666 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"}, 13667 {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13668 &EmulateInstructionARM::EmulateSTRBThumb, 13669 "strb<c> <Rt>, [<Rn>, #<imm5>]"}, 13670 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13671 &EmulateInstructionARM::EmulateSTRBThumb, 13672 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"}, 13673 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13674 &EmulateInstructionARM::EmulateSTRBThumb, 13675 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"}, 13676 {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13677 &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"}, 13678 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13679 &EmulateInstructionARM::EmulateSTRHRegister, 13680 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"}, 13681 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13682 &EmulateInstructionARM::EmulateSTREX, 13683 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"}, 13684 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13685 &EmulateInstructionARM::EmulateSTRDImm, 13686 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"}, 13687 {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, 13688 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 13689 {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, 13690 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 13691 {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, 13692 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 13693 {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, 13694 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 13695 {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, 13696 &EmulateInstructionARM::EmulateVST1Multiple, 13697 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13698 {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, 13699 &EmulateInstructionARM::EmulateVST1Single, 13700 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13701 13702 // Other instructions 13703 {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, 13704 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"}, 13705 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, 13706 &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"}, 13707 {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, 13708 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"}, 13709 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13710 &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"}, 13711 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, 13712 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"}, 13713 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13714 &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"}, 13715 {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, 13716 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"}, 13717 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13718 &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"}, 13719 }; 13720 13721 const size_t k_num_thumb_opcodes = std::size(g_thumb_opcodes); 13722 for (size_t i = 0; i < k_num_thumb_opcodes; ++i) { 13723 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value && 13724 (g_thumb_opcodes[i].variants & arm_isa) != 0) 13725 return &g_thumb_opcodes[i]; 13726 } 13727 return nullptr; 13728 } 13729 13730 bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) { 13731 m_arch = arch; 13732 m_arm_isa = 0; 13733 llvm::StringRef arch_cstr = arch.GetArchitectureName(); 13734 if (arch_cstr.equals_insensitive("armv4t")) 13735 m_arm_isa = ARMv4T; 13736 else if (arch_cstr.equals_insensitive("armv5tej")) 13737 m_arm_isa = ARMv5TEJ; 13738 else if (arch_cstr.equals_insensitive("armv5te")) 13739 m_arm_isa = ARMv5TE; 13740 else if (arch_cstr.equals_insensitive("armv5t")) 13741 m_arm_isa = ARMv5T; 13742 else if (arch_cstr.equals_insensitive("armv6k")) 13743 m_arm_isa = ARMv6K; 13744 else if (arch_cstr.equals_insensitive("armv6t2")) 13745 m_arm_isa = ARMv6T2; 13746 else if (arch_cstr.equals_insensitive("armv7s")) 13747 m_arm_isa = ARMv7S; 13748 else if (arch_cstr.equals_insensitive("arm")) 13749 m_arm_isa = ARMvAll; 13750 else if (arch_cstr.equals_insensitive("thumb")) 13751 m_arm_isa = ARMvAll; 13752 else if (arch_cstr.starts_with_insensitive("armv4")) 13753 m_arm_isa = ARMv4; 13754 else if (arch_cstr.starts_with_insensitive("armv6")) 13755 m_arm_isa = ARMv6; 13756 else if (arch_cstr.starts_with_insensitive("armv7")) 13757 m_arm_isa = ARMv7; 13758 else if (arch_cstr.starts_with_insensitive("armv8")) 13759 m_arm_isa = ARMv8; 13760 return m_arm_isa != 0; 13761 } 13762 13763 bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode, 13764 const Address &inst_addr, 13765 Target *target) { 13766 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) { 13767 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb || 13768 m_arch.IsAlwaysThumbInstructions()) 13769 m_opcode_mode = eModeThumb; 13770 else { 13771 AddressClass addr_class = inst_addr.GetAddressClass(); 13772 13773 if ((addr_class == AddressClass::eCode) || 13774 (addr_class == AddressClass::eUnknown)) 13775 m_opcode_mode = eModeARM; 13776 else if (addr_class == AddressClass::eCodeAlternateISA) 13777 m_opcode_mode = eModeThumb; 13778 else 13779 return false; 13780 } 13781 if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions()) 13782 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T; 13783 else 13784 m_opcode_cpsr = CPSR_MODE_USR; 13785 return true; 13786 } 13787 return false; 13788 } 13789 13790 bool EmulateInstructionARM::ReadInstruction() { 13791 bool success = false; 13792 m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric, 13793 LLDB_REGNUM_GENERIC_FLAGS, 0, &success); 13794 if (success) { 13795 addr_t pc = 13796 ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 13797 LLDB_INVALID_ADDRESS, &success); 13798 if (success) { 13799 Context read_inst_context; 13800 read_inst_context.type = eContextReadOpcode; 13801 read_inst_context.SetNoArgs(); 13802 13803 if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) { 13804 m_opcode_mode = eModeThumb; 13805 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); 13806 13807 if (success) { 13808 if ((thumb_opcode & 0xe000) != 0xe000 || 13809 ((thumb_opcode & 0x1800u) == 0)) { 13810 m_opcode.SetOpcode16(thumb_opcode, GetByteOrder()); 13811 } else { 13812 m_opcode.SetOpcode32( 13813 (thumb_opcode << 16) | 13814 MemARead(read_inst_context, pc + 2, 2, 0, &success), 13815 GetByteOrder()); 13816 } 13817 } 13818 } else { 13819 m_opcode_mode = eModeARM; 13820 m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success), 13821 GetByteOrder()); 13822 } 13823 13824 if (!m_ignore_conditions) { 13825 // If we are not ignoreing the conditions then init the it session from 13826 // the current value of cpsr. 13827 uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) | 13828 Bits32(m_opcode_cpsr, 26, 25); 13829 if (it != 0) 13830 m_it_session.InitIT(it); 13831 } 13832 } 13833 } 13834 if (!success) { 13835 m_opcode_mode = eModeInvalid; 13836 m_addr = LLDB_INVALID_ADDRESS; 13837 } 13838 return success; 13839 } 13840 13841 uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; } 13842 13843 bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) { 13844 // If we are ignoring conditions, then always return true. this allows us to 13845 // iterate over disassembly code and still emulate an instruction even if we 13846 // don't have all the right bits set in the CPSR register... 13847 if (m_ignore_conditions) 13848 return true; 13849 13850 const uint32_t cond = CurrentCond(opcode); 13851 if (cond == UINT32_MAX) 13852 return false; 13853 13854 bool result = false; 13855 switch (UnsignedBits(cond, 3, 1)) { 13856 case 0: 13857 if (m_opcode_cpsr == 0) 13858 result = true; 13859 else 13860 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; 13861 break; 13862 case 1: 13863 if (m_opcode_cpsr == 0) 13864 result = true; 13865 else 13866 result = (m_opcode_cpsr & MASK_CPSR_C) != 0; 13867 break; 13868 case 2: 13869 if (m_opcode_cpsr == 0) 13870 result = true; 13871 else 13872 result = (m_opcode_cpsr & MASK_CPSR_N) != 0; 13873 break; 13874 case 3: 13875 if (m_opcode_cpsr == 0) 13876 result = true; 13877 else 13878 result = (m_opcode_cpsr & MASK_CPSR_V) != 0; 13879 break; 13880 case 4: 13881 if (m_opcode_cpsr == 0) 13882 result = true; 13883 else 13884 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && 13885 ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 13886 break; 13887 case 5: 13888 if (m_opcode_cpsr == 0) 13889 result = true; 13890 else { 13891 bool n = (m_opcode_cpsr & MASK_CPSR_N); 13892 bool v = (m_opcode_cpsr & MASK_CPSR_V); 13893 result = n == v; 13894 } 13895 break; 13896 case 6: 13897 if (m_opcode_cpsr == 0) 13898 result = true; 13899 else { 13900 bool n = (m_opcode_cpsr & MASK_CPSR_N); 13901 bool v = (m_opcode_cpsr & MASK_CPSR_V); 13902 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 13903 } 13904 break; 13905 case 7: 13906 // Always execute (cond == 0b1110, or the special 0b1111 which gives 13907 // opcodes different meanings, but always means execution happens. 13908 return true; 13909 } 13910 13911 if (cond & 1) 13912 result = !result; 13913 return result; 13914 } 13915 13916 uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) { 13917 switch (m_opcode_mode) { 13918 case eModeInvalid: 13919 break; 13920 13921 case eModeARM: 13922 return UnsignedBits(opcode, 31, 28); 13923 13924 case eModeThumb: 13925 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit 13926 // 'cond' field of the encoding. 13927 { 13928 const uint32_t byte_size = m_opcode.GetByteSize(); 13929 if (byte_size == 2) { 13930 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f) 13931 return Bits32(opcode, 11, 8); 13932 } else if (byte_size == 4) { 13933 if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 && 13934 Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) { 13935 return Bits32(opcode, 25, 22); 13936 } 13937 } else 13938 // We have an invalid thumb instruction, let's bail out. 13939 break; 13940 13941 return m_it_session.GetCond(); 13942 } 13943 } 13944 return UINT32_MAX; // Return invalid value 13945 } 13946 13947 bool EmulateInstructionARM::InITBlock() { 13948 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock(); 13949 } 13950 13951 bool EmulateInstructionARM::LastInITBlock() { 13952 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock(); 13953 } 13954 13955 bool EmulateInstructionARM::BadMode(uint32_t mode) { 13956 13957 switch (mode) { 13958 case 16: 13959 return false; // '10000' 13960 case 17: 13961 return false; // '10001' 13962 case 18: 13963 return false; // '10010' 13964 case 19: 13965 return false; // '10011' 13966 case 22: 13967 return false; // '10110' 13968 case 23: 13969 return false; // '10111' 13970 case 27: 13971 return false; // '11011' 13972 case 31: 13973 return false; // '11111' 13974 default: 13975 return true; 13976 } 13977 return true; 13978 } 13979 13980 bool EmulateInstructionARM::CurrentModeIsPrivileged() { 13981 uint32_t mode = Bits32(m_opcode_cpsr, 4, 0); 13982 13983 if (BadMode(mode)) 13984 return false; 13985 13986 if (mode == 16) 13987 return false; 13988 13989 return true; 13990 } 13991 13992 void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask, 13993 bool affect_execstate) { 13994 bool privileged = CurrentModeIsPrivileged(); 13995 13996 uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20; 13997 13998 if (BitIsSet(bytemask, 3)) { 13999 tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27); 14000 if (affect_execstate) 14001 tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24); 14002 } 14003 14004 if (BitIsSet(bytemask, 2)) { 14005 tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16); 14006 } 14007 14008 if (BitIsSet(bytemask, 1)) { 14009 if (affect_execstate) 14010 tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10); 14011 tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9); 14012 if (privileged) 14013 tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8); 14014 } 14015 14016 if (BitIsSet(bytemask, 0)) { 14017 if (privileged) 14018 tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6); 14019 if (affect_execstate) 14020 tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5); 14021 if (privileged) 14022 tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0); 14023 } 14024 14025 m_opcode_cpsr = tmp_cpsr; 14026 } 14027 14028 bool EmulateInstructionARM::BranchWritePC(const Context &context, 14029 uint32_t addr) { 14030 addr_t target; 14031 14032 // Check the current instruction set. 14033 if (CurrentInstrSet() == eModeARM) 14034 target = addr & 0xfffffffc; 14035 else 14036 target = addr & 0xfffffffe; 14037 14038 return WriteRegisterUnsigned(context, eRegisterKindGeneric, 14039 LLDB_REGNUM_GENERIC_PC, target); 14040 } 14041 14042 // As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by 14043 // inspecting addr. 14044 bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) { 14045 addr_t target; 14046 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE, 14047 // we want to record it and issue a WriteRegister callback so the clients can 14048 // track the mode changes accordingly. 14049 bool cpsr_changed = false; 14050 14051 if (BitIsSet(addr, 0)) { 14052 if (CurrentInstrSet() != eModeThumb) { 14053 SelectInstrSet(eModeThumb); 14054 cpsr_changed = true; 14055 } 14056 target = addr & 0xfffffffe; 14057 context.SetISA(eModeThumb); 14058 } else if (BitIsClear(addr, 1)) { 14059 if (CurrentInstrSet() != eModeARM) { 14060 SelectInstrSet(eModeARM); 14061 cpsr_changed = true; 14062 } 14063 target = addr & 0xfffffffc; 14064 context.SetISA(eModeARM); 14065 } else 14066 return false; // address<1:0> == '10' => UNPREDICTABLE 14067 14068 if (cpsr_changed) { 14069 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 14070 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 14071 return false; 14072 } 14073 return WriteRegisterUnsigned(context, eRegisterKindGeneric, 14074 LLDB_REGNUM_GENERIC_PC, target); 14075 } 14076 14077 // Dispatches to either BXWritePC or BranchWritePC based on architecture 14078 // versions. 14079 bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) { 14080 if (ArchVersion() >= ARMv5T) 14081 return BXWritePC(context, addr); 14082 else 14083 return BranchWritePC((const Context)context, addr); 14084 } 14085 14086 // Dispatches to either BXWritePC or BranchWritePC based on architecture 14087 // versions and current instruction set. 14088 bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) { 14089 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM) 14090 return BXWritePC(context, addr); 14091 else 14092 return BranchWritePC((const Context)context, addr); 14093 } 14094 14095 EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() { 14096 return m_opcode_mode; 14097 } 14098 14099 // Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next 14100 // ReadInstruction() is performed. This function has a side effect of updating 14101 // the m_new_inst_cpsr member variable if necessary. 14102 bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) { 14103 m_new_inst_cpsr = m_opcode_cpsr; 14104 switch (arm_or_thumb) { 14105 default: 14106 return false; 14107 case eModeARM: 14108 // Clear the T bit. 14109 m_new_inst_cpsr &= ~MASK_CPSR_T; 14110 break; 14111 case eModeThumb: 14112 // Set the T bit. 14113 m_new_inst_cpsr |= MASK_CPSR_T; 14114 break; 14115 } 14116 return true; 14117 } 14118 14119 // This function returns TRUE if the processor currently provides support for 14120 // unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7, 14121 // controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6. 14122 bool EmulateInstructionARM::UnalignedSupport() { 14123 return (ArchVersion() >= ARMv7); 14124 } 14125 14126 // The main addition and subtraction instructions can produce status 14127 // information about both unsigned carry and signed overflow conditions. This 14128 // status information can be used to synthesize multi-word additions and 14129 // subtractions. 14130 EmulateInstructionARM::AddWithCarryResult 14131 EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) { 14132 uint32_t result; 14133 uint8_t carry_out; 14134 uint8_t overflow; 14135 14136 uint64_t unsigned_sum = x + y + carry_in; 14137 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; 14138 14139 result = UnsignedBits(unsigned_sum, 31, 0); 14140 // carry_out = (result == unsigned_sum ? 0 : 1); 14141 overflow = ((int32_t)result == signed_sum ? 0 : 1); 14142 14143 if (carry_in) 14144 carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0; 14145 else 14146 carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0; 14147 14148 AddWithCarryResult res = {result, carry_out, overflow}; 14149 return res; 14150 } 14151 14152 uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) { 14153 lldb::RegisterKind reg_kind; 14154 uint32_t reg_num; 14155 switch (num) { 14156 case SP_REG: 14157 reg_kind = eRegisterKindGeneric; 14158 reg_num = LLDB_REGNUM_GENERIC_SP; 14159 break; 14160 case LR_REG: 14161 reg_kind = eRegisterKindGeneric; 14162 reg_num = LLDB_REGNUM_GENERIC_RA; 14163 break; 14164 case PC_REG: 14165 reg_kind = eRegisterKindGeneric; 14166 reg_num = LLDB_REGNUM_GENERIC_PC; 14167 break; 14168 default: 14169 if (num < SP_REG) { 14170 reg_kind = eRegisterKindDWARF; 14171 reg_num = dwarf_r0 + num; 14172 } else { 14173 // assert(0 && "Invalid register number"); 14174 *success = false; 14175 return UINT32_MAX; 14176 } 14177 break; 14178 } 14179 14180 // Read our register. 14181 uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success); 14182 14183 // When executing an ARM instruction , PC reads as the address of the current 14184 // instruction plus 8. When executing a Thumb instruction , PC reads as the 14185 // address of the current instruction plus 4. 14186 if (num == 15) { 14187 if (CurrentInstrSet() == eModeARM) 14188 val += 8; 14189 else 14190 val += 4; 14191 } 14192 14193 return val; 14194 } 14195 14196 // Write the result to the ARM core register Rd, and optionally update the 14197 // condition flags based on the result. 14198 // 14199 // This helper method tries to encapsulate the following pseudocode from the 14200 // ARM Architecture Reference Manual: 14201 // 14202 // if d == 15 then // Can only occur for encoding A1 14203 // ALUWritePC(result); // setflags is always FALSE here 14204 // else 14205 // R[d] = result; 14206 // if setflags then 14207 // APSR.N = result<31>; 14208 // APSR.Z = IsZeroBit(result); 14209 // APSR.C = carry; 14210 // // APSR.V unchanged 14211 // 14212 // In the above case, the API client does not pass in the overflow arg, which 14213 // defaults to ~0u. 14214 bool EmulateInstructionARM::WriteCoreRegOptionalFlags( 14215 Context &context, const uint32_t result, const uint32_t Rd, bool setflags, 14216 const uint32_t carry, const uint32_t overflow) { 14217 if (Rd == 15) { 14218 if (!ALUWritePC(context, result)) 14219 return false; 14220 } else { 14221 lldb::RegisterKind reg_kind; 14222 uint32_t reg_num; 14223 switch (Rd) { 14224 case SP_REG: 14225 reg_kind = eRegisterKindGeneric; 14226 reg_num = LLDB_REGNUM_GENERIC_SP; 14227 break; 14228 case LR_REG: 14229 reg_kind = eRegisterKindGeneric; 14230 reg_num = LLDB_REGNUM_GENERIC_RA; 14231 break; 14232 default: 14233 reg_kind = eRegisterKindDWARF; 14234 reg_num = dwarf_r0 + Rd; 14235 } 14236 if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result)) 14237 return false; 14238 if (setflags) 14239 return WriteFlags(context, result, carry, overflow); 14240 } 14241 return true; 14242 } 14243 14244 // This helper method tries to encapsulate the following pseudocode from the 14245 // ARM Architecture Reference Manual: 14246 // 14247 // APSR.N = result<31>; 14248 // APSR.Z = IsZeroBit(result); 14249 // APSR.C = carry; 14250 // APSR.V = overflow 14251 // 14252 // Default arguments can be specified for carry and overflow parameters, which 14253 // means not to update the respective flags. 14254 bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result, 14255 const uint32_t carry, 14256 const uint32_t overflow) { 14257 m_new_inst_cpsr = m_opcode_cpsr; 14258 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS)); 14259 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 14260 if (carry != ~0u) 14261 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry); 14262 if (overflow != ~0u) 14263 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow); 14264 if (m_new_inst_cpsr != m_opcode_cpsr) { 14265 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 14266 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 14267 return false; 14268 } 14269 return true; 14270 } 14271 14272 bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) { 14273 ARMOpcode *opcode_data = nullptr; 14274 14275 if (m_opcode_mode == eModeThumb) 14276 opcode_data = 14277 GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa); 14278 else if (m_opcode_mode == eModeARM) 14279 opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa); 14280 14281 const bool auto_advance_pc = 14282 evaluate_options & eEmulateInstructionOptionAutoAdvancePC; 14283 m_ignore_conditions = 14284 evaluate_options & eEmulateInstructionOptionIgnoreConditions; 14285 14286 bool success = false; 14287 if (m_opcode_cpsr == 0 || !m_ignore_conditions) { 14288 m_opcode_cpsr = 14289 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success); 14290 } 14291 14292 // Only return false if we are unable to read the CPSR if we care about 14293 // conditions 14294 if (!success && !m_ignore_conditions) 14295 return false; 14296 14297 uint32_t orig_pc_value = 0; 14298 if (auto_advance_pc) { 14299 orig_pc_value = 14300 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success); 14301 if (!success) 14302 return false; 14303 } 14304 14305 // Call the Emulate... function if we managed to decode the opcode. 14306 if (opcode_data) { 14307 success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(), 14308 opcode_data->encoding); 14309 if (!success) 14310 return false; 14311 } 14312 14313 // Advance the ITSTATE bits to their values for the next instruction if we 14314 // haven't just executed an IT instruction what initialized it. 14315 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() && 14316 (opcode_data == nullptr || 14317 opcode_data->callback != &EmulateInstructionARM::EmulateIT)) 14318 m_it_session.ITAdvance(); 14319 14320 if (auto_advance_pc) { 14321 uint32_t after_pc_value = 14322 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success); 14323 if (!success) 14324 return false; 14325 14326 if (after_pc_value == orig_pc_value) { 14327 after_pc_value += m_opcode.GetByteSize(); 14328 14329 EmulateInstruction::Context context; 14330 context.type = eContextAdvancePC; 14331 context.SetNoArgs(); 14332 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc, 14333 after_pc_value)) 14334 return false; 14335 } 14336 } 14337 return true; 14338 } 14339 14340 EmulateInstruction::InstructionCondition 14341 EmulateInstructionARM::GetInstructionCondition() { 14342 const uint32_t cond = CurrentCond(m_opcode.GetOpcode32()); 14343 if (cond == 0xe || cond == 0xf || cond == UINT32_MAX) 14344 return EmulateInstruction::UnconditionalCondition; 14345 return cond; 14346 } 14347 14348 bool EmulateInstructionARM::TestEmulation(Stream &out_stream, ArchSpec &arch, 14349 OptionValueDictionary *test_data) { 14350 if (!test_data) { 14351 out_stream.Printf("TestEmulation: Missing test data.\n"); 14352 return false; 14353 } 14354 14355 static constexpr llvm::StringLiteral opcode_key("opcode"); 14356 static constexpr llvm::StringLiteral before_key("before_state"); 14357 static constexpr llvm::StringLiteral after_key("after_state"); 14358 14359 OptionValueSP value_sp = test_data->GetValueForKey(opcode_key); 14360 14361 uint32_t test_opcode; 14362 if ((value_sp.get() == nullptr) || 14363 (value_sp->GetType() != OptionValue::eTypeUInt64)) { 14364 out_stream.Printf("TestEmulation: Error reading opcode from test file.\n"); 14365 return false; 14366 } 14367 test_opcode = value_sp->GetValueAs<uint64_t>().value_or(0); 14368 14369 if (arch.GetTriple().getArch() == llvm::Triple::thumb || 14370 arch.IsAlwaysThumbInstructions()) { 14371 m_opcode_mode = eModeThumb; 14372 if (test_opcode < 0x10000) 14373 m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder()); 14374 else 14375 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder()); 14376 } else if (arch.GetTriple().getArch() == llvm::Triple::arm) { 14377 m_opcode_mode = eModeARM; 14378 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder()); 14379 } else { 14380 out_stream.Printf("TestEmulation: Invalid arch.\n"); 14381 return false; 14382 } 14383 14384 EmulationStateARM before_state; 14385 EmulationStateARM after_state; 14386 14387 value_sp = test_data->GetValueForKey(before_key); 14388 if ((value_sp.get() == nullptr) || 14389 (value_sp->GetType() != OptionValue::eTypeDictionary)) { 14390 out_stream.Printf("TestEmulation: Failed to find 'before' state.\n"); 14391 return false; 14392 } 14393 14394 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary(); 14395 if (!before_state.LoadStateFromDictionary(state_dictionary)) { 14396 out_stream.Printf("TestEmulation: Failed loading 'before' state.\n"); 14397 return false; 14398 } 14399 14400 value_sp = test_data->GetValueForKey(after_key); 14401 if ((value_sp.get() == nullptr) || 14402 (value_sp->GetType() != OptionValue::eTypeDictionary)) { 14403 out_stream.Printf("TestEmulation: Failed to find 'after' state.\n"); 14404 return false; 14405 } 14406 14407 state_dictionary = value_sp->GetAsDictionary(); 14408 if (!after_state.LoadStateFromDictionary(state_dictionary)) { 14409 out_stream.Printf("TestEmulation: Failed loading 'after' state.\n"); 14410 return false; 14411 } 14412 14413 SetBaton((void *)&before_state); 14414 SetCallbacks(&EmulationStateARM::ReadPseudoMemory, 14415 &EmulationStateARM::WritePseudoMemory, 14416 &EmulationStateARM::ReadPseudoRegister, 14417 &EmulationStateARM::WritePseudoRegister); 14418 14419 bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); 14420 if (!success) { 14421 out_stream.Printf("TestEmulation: EvaluateInstruction() failed.\n"); 14422 return false; 14423 } 14424 14425 success = before_state.CompareState(after_state, out_stream); 14426 if (!success) 14427 out_stream.Printf("TestEmulation: State after emulation does not match " 14428 "'after' state.\n"); 14429 14430 return success; 14431 } 14432 // 14433 // 14434 // const char * 14435 // EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num) 14436 //{ 14437 // if (reg_kind == eRegisterKindGeneric) 14438 // { 14439 // switch (reg_num) 14440 // { 14441 // case LLDB_REGNUM_GENERIC_PC: return "pc"; 14442 // case LLDB_REGNUM_GENERIC_SP: return "sp"; 14443 // case LLDB_REGNUM_GENERIC_FP: return "fp"; 14444 // case LLDB_REGNUM_GENERIC_RA: return "lr"; 14445 // case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr"; 14446 // default: return NULL; 14447 // } 14448 // } 14449 // else if (reg_kind == eRegisterKindDWARF) 14450 // { 14451 // return GetARMDWARFRegisterName (reg_num); 14452 // } 14453 // return NULL; 14454 //} 14455 // 14456 bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) { 14457 unwind_plan.Clear(); 14458 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 14459 14460 UnwindPlan::RowSP row(new UnwindPlan::Row); 14461 14462 // Our previous Call Frame Address is the stack pointer 14463 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0); 14464 14465 unwind_plan.AppendRow(row); 14466 unwind_plan.SetSourceName("EmulateInstructionARM"); 14467 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 14468 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); 14469 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 14470 unwind_plan.SetReturnAddressRegister(dwarf_lr); 14471 return true; 14472 } 14473