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 30using namespace lldb; 31using namespace lldb_private; 32 33LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionARM, InstructionARM) 34 35// Convenient macro definitions. 36#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS) 37#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS) 38 39#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC) 40 41// 42// ITSession implementation 43// 44 45static std::optional<RegisterInfo> GetARMDWARFRegisterInfo(unsigned reg_num) { 46 RegisterInfo reg_info; 47 ::memset(®_info, 0, sizeof(RegisterInfo)); 48 ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds)); 49 50 if (reg_num >= dwarf_q0 && reg_num <= dwarf_q15) { 51 reg_info.byte_size = 16; 52 reg_info.format = eFormatVectorOfUInt8; 53 reg_info.encoding = eEncodingVector; 54 } 55 56 if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) { 57 reg_info.byte_size = 8; 58 reg_info.format = eFormatFloat; 59 reg_info.encoding = eEncodingIEEE754; 60 } else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) { 61 reg_info.byte_size = 4; 62 reg_info.format = eFormatFloat; 63 reg_info.encoding = eEncodingIEEE754; 64 } else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) { 65 reg_info.byte_size = 12; 66 reg_info.format = eFormatFloat; 67 reg_info.encoding = eEncodingIEEE754; 68 } else { 69 reg_info.byte_size = 4; 70 reg_info.format = eFormatHex; 71 reg_info.encoding = eEncodingUint; 72 } 73 74 reg_info.kinds[eRegisterKindDWARF] = reg_num; 75 76 switch (reg_num) { 77 case dwarf_r0: 78 reg_info.name = "r0"; 79 break; 80 case dwarf_r1: 81 reg_info.name = "r1"; 82 break; 83 case dwarf_r2: 84 reg_info.name = "r2"; 85 break; 86 case dwarf_r3: 87 reg_info.name = "r3"; 88 break; 89 case dwarf_r4: 90 reg_info.name = "r4"; 91 break; 92 case dwarf_r5: 93 reg_info.name = "r5"; 94 break; 95 case dwarf_r6: 96 reg_info.name = "r6"; 97 break; 98 case dwarf_r7: 99 reg_info.name = "r7"; 100 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP; 101 break; 102 case dwarf_r8: 103 reg_info.name = "r8"; 104 break; 105 case dwarf_r9: 106 reg_info.name = "r9"; 107 break; 108 case dwarf_r10: 109 reg_info.name = "r10"; 110 break; 111 case dwarf_r11: 112 reg_info.name = "r11"; 113 break; 114 case dwarf_r12: 115 reg_info.name = "r12"; 116 break; 117 case dwarf_sp: 118 reg_info.name = "sp"; 119 reg_info.alt_name = "r13"; 120 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP; 121 break; 122 case dwarf_lr: 123 reg_info.name = "lr"; 124 reg_info.alt_name = "r14"; 125 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA; 126 break; 127 case dwarf_pc: 128 reg_info.name = "pc"; 129 reg_info.alt_name = "r15"; 130 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC; 131 break; 132 case dwarf_cpsr: 133 reg_info.name = "cpsr"; 134 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; 135 break; 136 137 case dwarf_s0: 138 reg_info.name = "s0"; 139 break; 140 case dwarf_s1: 141 reg_info.name = "s1"; 142 break; 143 case dwarf_s2: 144 reg_info.name = "s2"; 145 break; 146 case dwarf_s3: 147 reg_info.name = "s3"; 148 break; 149 case dwarf_s4: 150 reg_info.name = "s4"; 151 break; 152 case dwarf_s5: 153 reg_info.name = "s5"; 154 break; 155 case dwarf_s6: 156 reg_info.name = "s6"; 157 break; 158 case dwarf_s7: 159 reg_info.name = "s7"; 160 break; 161 case dwarf_s8: 162 reg_info.name = "s8"; 163 break; 164 case dwarf_s9: 165 reg_info.name = "s9"; 166 break; 167 case dwarf_s10: 168 reg_info.name = "s10"; 169 break; 170 case dwarf_s11: 171 reg_info.name = "s11"; 172 break; 173 case dwarf_s12: 174 reg_info.name = "s12"; 175 break; 176 case dwarf_s13: 177 reg_info.name = "s13"; 178 break; 179 case dwarf_s14: 180 reg_info.name = "s14"; 181 break; 182 case dwarf_s15: 183 reg_info.name = "s15"; 184 break; 185 case dwarf_s16: 186 reg_info.name = "s16"; 187 break; 188 case dwarf_s17: 189 reg_info.name = "s17"; 190 break; 191 case dwarf_s18: 192 reg_info.name = "s18"; 193 break; 194 case dwarf_s19: 195 reg_info.name = "s19"; 196 break; 197 case dwarf_s20: 198 reg_info.name = "s20"; 199 break; 200 case dwarf_s21: 201 reg_info.name = "s21"; 202 break; 203 case dwarf_s22: 204 reg_info.name = "s22"; 205 break; 206 case dwarf_s23: 207 reg_info.name = "s23"; 208 break; 209 case dwarf_s24: 210 reg_info.name = "s24"; 211 break; 212 case dwarf_s25: 213 reg_info.name = "s25"; 214 break; 215 case dwarf_s26: 216 reg_info.name = "s26"; 217 break; 218 case dwarf_s27: 219 reg_info.name = "s27"; 220 break; 221 case dwarf_s28: 222 reg_info.name = "s28"; 223 break; 224 case dwarf_s29: 225 reg_info.name = "s29"; 226 break; 227 case dwarf_s30: 228 reg_info.name = "s30"; 229 break; 230 case dwarf_s31: 231 reg_info.name = "s31"; 232 break; 233 234 // FPA Registers 0-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. 605static uint32_t CountITSize(uint32_t ITMask) { 606 // First count the trailing zeros of the IT mask. 607 uint32_t TZ = llvm::countr_zero(ITMask); 608 if (TZ > 3) { 609 return 0; 610 } 611 return (4 - TZ); 612} 613 614// Init ITState. Note that at least one bit is always 1 in mask. 615bool ITSession::InitIT(uint32_t bits7_0) { 616 ITCounter = CountITSize(Bits32(bits7_0, 3, 0)); 617 if (ITCounter == 0) 618 return false; 619 620 // A8.6.50 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. 634void ITSession::ITAdvance() { 635 // assert(ITCounter); 636 --ITCounter; 637 if (ITCounter == 0) 638 ITState = 0; 639 else { 640 unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1; 641 SetBits32(ITState, 4, 0, NewITState4_0); 642 } 643} 644 645// Return true if we're inside an IT Block. 646bool ITSession::InITBlock() { return ITCounter != 0; } 647 648// Return true if we're the last instruction inside an IT Block. 649bool ITSession::LastInITBlock() { return ITCounter == 1; } 650 651// Get condition bits for the current thumb instruction. 652uint32_t ITSession::GetCond() { 653 if (InITBlock()) 654 return Bits32(ITState, 7, 4); 655 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 708void EmulateInstructionARM::Initialize() { 709 PluginManager::RegisterPlugin(GetPluginNameStatic(), 710 GetPluginDescriptionStatic(), CreateInstance); 711} 712 713void EmulateInstructionARM::Terminate() { 714 PluginManager::UnregisterPlugin(CreateInstance); 715} 716 717llvm::StringRef EmulateInstructionARM::GetPluginDescriptionStatic() { 718 return "Emulate instructions for the ARM architecture."; 719} 720 721EmulateInstruction * 722EmulateInstructionARM::CreateInstance(const ArchSpec &arch, 723 InstructionType inst_type) { 724 if (EmulateInstructionARM::SupportsEmulatingInstructionsOfTypeStatic( 725 inst_type)) { 726 if (arch.GetTriple().getArch() == llvm::Triple::arm) { 727 std::unique_ptr<EmulateInstructionARM> emulate_insn_up( 728 new EmulateInstructionARM(arch)); 729 730 if (emulate_insn_up) 731 return emulate_insn_up.release(); 732 } else if (arch.GetTriple().getArch() == llvm::Triple::thumb) { 733 std::unique_ptr<EmulateInstructionARM> emulate_insn_up( 734 new EmulateInstructionARM(arch)); 735 736 if (emulate_insn_up) 737 return emulate_insn_up.release(); 738 } 739 } 740 741 return nullptr; 742} 743 744bool EmulateInstructionARM::SetTargetTriple(const ArchSpec &arch) { 745 if (arch.GetTriple().getArch() == llvm::Triple::arm) 746 return true; 747 else if (arch.GetTriple().getArch() == llvm::Triple::thumb) 748 return true; 749 750 return false; 751} 752 753// Write "bits (32) UNKNOWN" to memory address "address". Helper function for 754// many ARM instructions. 755bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) { 756 EmulateInstruction::Context context; 757 context.type = EmulateInstruction::eContextWriteMemoryRandomBits; 758 context.SetNoArgs(); 759 760 uint32_t random_data = rand(); 761 const uint32_t addr_byte_size = GetAddressByteSize(); 762 763 return MemAWrite(context, address, random_data, addr_byte_size); 764} 765 766// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM 767// instructions. 768bool EmulateInstructionARM::WriteBits32Unknown(int n) { 769 EmulateInstruction::Context context; 770 context.type = EmulateInstruction::eContextWriteRegisterRandomBits; 771 context.SetNoArgs(); 772 773 bool success; 774 uint32_t data = 775 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 776 777 if (!success) 778 return false; 779 780 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, data)) 781 return false; 782 783 return true; 784} 785 786std::optional<RegisterInfo> 787EmulateInstructionARM::GetRegisterInfo(lldb::RegisterKind reg_kind, 788 uint32_t reg_num) { 789 if (reg_kind == eRegisterKindGeneric) { 790 switch (reg_num) { 791 case LLDB_REGNUM_GENERIC_PC: 792 reg_kind = eRegisterKindDWARF; 793 reg_num = dwarf_pc; 794 break; 795 case LLDB_REGNUM_GENERIC_SP: 796 reg_kind = eRegisterKindDWARF; 797 reg_num = dwarf_sp; 798 break; 799 case LLDB_REGNUM_GENERIC_FP: 800 reg_kind = eRegisterKindDWARF; 801 reg_num = dwarf_r7; 802 break; 803 case LLDB_REGNUM_GENERIC_RA: 804 reg_kind = eRegisterKindDWARF; 805 reg_num = dwarf_lr; 806 break; 807 case LLDB_REGNUM_GENERIC_FLAGS: 808 reg_kind = eRegisterKindDWARF; 809 reg_num = dwarf_cpsr; 810 break; 811 default: 812 return {}; 813 } 814 } 815 816 if (reg_kind == eRegisterKindDWARF) 817 return GetARMDWARFRegisterInfo(reg_num); 818 return {}; 819} 820 821uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const { 822 if (m_arch.GetTriple().isAndroid()) 823 return LLDB_INVALID_REGNUM; // Don't use frame pointer on 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 case llvm::Triple::XROS: 834 // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS: 835 is_apple = true; 836 break; 837 default: 838 break; 839 } 840 841 /* On Apple iOS et al, the frame pointer register is always r7. 842 * Typically on other ARM systems, thumb code uses r7; arm code uses r11. 843 * Windows on ARM, which is in thumb mode, uses r11 though. 844 */ 845 846 uint32_t fp_regnum = 11; 847 848 if (is_apple) 849 fp_regnum = 7; 850 851 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows()) 852 fp_regnum = 7; 853 854 return fp_regnum; 855} 856 857uint32_t EmulateInstructionARM::GetFramePointerDWARFRegisterNumber() const { 858 bool is_apple = false; 859 if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) 860 is_apple = true; 861 switch (m_arch.GetTriple().getOS()) { 862 case llvm::Triple::Darwin: 863 case llvm::Triple::MacOSX: 864 case llvm::Triple::IOS: 865 is_apple = true; 866 break; 867 default: 868 break; 869 } 870 871 /* On Apple iOS et al, the frame pointer register is always r7. 872 * Typically on other ARM systems, thumb code uses r7; arm code uses r11. 873 * Windows on ARM, which is in thumb mode, uses r11 though. 874 */ 875 876 uint32_t fp_regnum = dwarf_r11; 877 878 if (is_apple) 879 fp_regnum = dwarf_r7; 880 881 if (m_opcode_mode == eModeThumb && !m_arch.GetTriple().isOSWindows()) 882 fp_regnum = dwarf_r7; 883 884 return fp_regnum; 885} 886 887// Push Multiple Registers stores multiple registers to the stack, storing to 888// consecutive memory locations ending just below the address in SP, and 889// updates 890// SP to point to the start of the stored data. 891bool EmulateInstructionARM::EmulatePUSH(const uint32_t opcode, 892 const ARMEncoding encoding) { 893#if 0 894 // ARM pseudo code... 895 if (ConditionPassed()) 896 { 897 EncodingSpecificOperations(); 898 NullCheckIfThumbEE(13); 899 address = SP - 4*BitCount(registers); 900 901 for (i = 0 to 14) 902 { 903 if (registers<i> == '1') 904 { 905 if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1 906 MemA[address,4] = bits(32) UNKNOWN; 907 else 908 MemA[address,4] = R[i]; 909 address = address + 4; 910 } 911 } 912 913 if (registers<15> == '1') // Only possible for encoding A1 or A2 914 MemA[address,4] = PCStoreValue(); 915 916 SP = SP - 4*BitCount(registers); 917 } 918#endif 919 920 bool success = false; 921 if (ConditionPassed(opcode)) { 922 const uint32_t addr_byte_size = GetAddressByteSize(); 923 const addr_t sp = ReadCoreReg(SP_REG, &success); 924 if (!success) 925 return false; 926 uint32_t registers = 0; 927 uint32_t Rt; // the source register 928 switch (encoding) { 929 case eEncodingT1: 930 registers = Bits32(opcode, 7, 0); 931 // The M bit represents LR. 932 if (Bit32(opcode, 8)) 933 registers |= (1u << 14); 934 // if BitCount(registers) < 1 then UNPREDICTABLE; 935 if (BitCount(registers) < 1) 936 return false; 937 break; 938 case eEncodingT2: 939 // Ignore bits 15 & 13. 940 registers = Bits32(opcode, 15, 0) & ~0xa000; 941 // if BitCount(registers) < 2 then UNPREDICTABLE; 942 if (BitCount(registers) < 2) 943 return false; 944 break; 945 case eEncodingT3: 946 Rt = Bits32(opcode, 15, 12); 947 // if BadReg(t) then UNPREDICTABLE; 948 if (BadReg(Rt)) 949 return false; 950 registers = (1u << Rt); 951 break; 952 case eEncodingA1: 953 registers = Bits32(opcode, 15, 0); 954 // Instead of return false, let's handle the following case as well, 955 // which amounts to pushing one reg onto the full descending stacks. 956 // if BitCount(register_list) < 2 then SEE STMDB / STMFD; 957 break; 958 case eEncodingA2: 959 Rt = Bits32(opcode, 15, 12); 960 // if t == 13 then UNPREDICTABLE; 961 if (Rt == dwarf_sp) 962 return false; 963 registers = (1u << Rt); 964 break; 965 default: 966 return false; 967 } 968 addr_t sp_offset = addr_byte_size * BitCount(registers); 969 addr_t addr = sp - sp_offset; 970 uint32_t i; 971 972 EmulateInstruction::Context context; 973 context.type = EmulateInstruction::eContextPushRegisterOnStack; 974 std::optional<RegisterInfo> sp_reg = 975 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 976 for (i = 0; i < 15; ++i) { 977 if (BitIsSet(registers, i)) { 978 std::optional<RegisterInfo> reg_info = 979 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); 980 context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp); 981 uint32_t reg_value = ReadCoreReg(i, &success); 982 if (!success) 983 return false; 984 if (!MemAWrite(context, addr, reg_value, addr_byte_size)) 985 return false; 986 addr += addr_byte_size; 987 } 988 } 989 990 if (BitIsSet(registers, 15)) { 991 std::optional<RegisterInfo> reg_info = 992 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 993 context.SetRegisterToRegisterPlusOffset(*reg_info, *sp_reg, addr - sp); 994 const uint32_t pc = ReadCoreReg(PC_REG, &success); 995 if (!success) 996 return false; 997 if (!MemAWrite(context, addr, pc, addr_byte_size)) 998 return false; 999 } 1000 1001 context.type = EmulateInstruction::eContextAdjustStackPointer; 1002 context.SetImmediateSigned(-sp_offset); 1003 1004 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 1005 LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 1006 return false; 1007 } 1008 return true; 1009} 1010 1011// Pop Multiple Registers loads multiple registers from the stack, loading from 1012// consecutive memory locations staring at the address in SP, and updates 1013// SP to point just above the loaded data. 1014bool EmulateInstructionARM::EmulatePOP(const uint32_t opcode, 1015 const ARMEncoding encoding) { 1016#if 0 1017 // ARM pseudo code... 1018 if (ConditionPassed()) 1019 { 1020 EncodingSpecificOperations(); NullCheckIfThumbEE(13); 1021 address = SP; 1022 for i = 0 to 14 1023 if registers<i> == '1' then 1024 R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4; 1025 if registers<15> == '1' then 1026 if UnalignedAllowed then 1027 LoadWritePC(MemU[address,4]); 1028 else 1029 LoadWritePC(MemA[address,4]); 1030 if registers<13> == '0' then SP = SP + 4*BitCount(registers); 1031 if registers<13> == '1' then SP = bits(32) UNKNOWN; 1032 } 1033#endif 1034 1035 bool success = false; 1036 1037 if (ConditionPassed(opcode)) { 1038 const uint32_t addr_byte_size = GetAddressByteSize(); 1039 const addr_t sp = ReadCoreReg(SP_REG, &success); 1040 if (!success) 1041 return false; 1042 uint32_t registers = 0; 1043 uint32_t Rt; // the destination register 1044 switch (encoding) { 1045 case eEncodingT1: 1046 registers = Bits32(opcode, 7, 0); 1047 // The P bit represents PC. 1048 if (Bit32(opcode, 8)) 1049 registers |= (1u << 15); 1050 // if BitCount(registers) < 1 then UNPREDICTABLE; 1051 if (BitCount(registers) < 1) 1052 return false; 1053 break; 1054 case eEncodingT2: 1055 // Ignore bit 13. 1056 registers = Bits32(opcode, 15, 0) & ~0x2000; 1057 // if BitCount(registers) < 2 || (P == '1' && M == '1') then 1058 // UNPREDICTABLE; 1059 if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14))) 1060 return false; 1061 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then 1062 // UNPREDICTABLE; 1063 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 1064 return false; 1065 break; 1066 case eEncodingT3: 1067 Rt = Bits32(opcode, 15, 12); 1068 // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then 1069 // UNPREDICTABLE; 1070 if (Rt == 13) 1071 return false; 1072 if (Rt == 15 && InITBlock() && !LastInITBlock()) 1073 return false; 1074 registers = (1u << Rt); 1075 break; 1076 case eEncodingA1: 1077 registers = Bits32(opcode, 15, 0); 1078 // Instead of return false, let's handle the following case as well, 1079 // which amounts to popping one reg from the full descending stacks. 1080 // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD; 1081 1082 // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE; 1083 if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7) 1084 return false; 1085 break; 1086 case eEncodingA2: 1087 Rt = Bits32(opcode, 15, 12); 1088 // if t == 13 then UNPREDICTABLE; 1089 if (Rt == dwarf_sp) 1090 return false; 1091 registers = (1u << Rt); 1092 break; 1093 default: 1094 return false; 1095 } 1096 addr_t sp_offset = addr_byte_size * BitCount(registers); 1097 addr_t addr = sp; 1098 uint32_t i, data; 1099 1100 EmulateInstruction::Context context; 1101 context.type = EmulateInstruction::eContextPopRegisterOffStack; 1102 1103 std::optional<RegisterInfo> sp_reg = 1104 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 1105 1106 for (i = 0; i < 15; ++i) { 1107 if (BitIsSet(registers, i)) { 1108 context.SetAddress(addr); 1109 data = MemARead(context, addr, 4, 0, &success); 1110 if (!success) 1111 return false; 1112 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, 1113 data)) 1114 return false; 1115 addr += addr_byte_size; 1116 } 1117 } 1118 1119 if (BitIsSet(registers, 15)) { 1120 context.SetRegisterPlusOffset(*sp_reg, addr - sp); 1121 data = MemARead(context, addr, 4, 0, &success); 1122 if (!success) 1123 return false; 1124 // In ARMv5T and above, this is an interworking branch. 1125 if (!LoadWritePC(context, data)) 1126 return false; 1127 // addr += addr_byte_size; 1128 } 1129 1130 context.type = EmulateInstruction::eContextAdjustStackPointer; 1131 context.SetImmediateSigned(sp_offset); 1132 1133 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 1134 LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 1135 return false; 1136 } 1137 return true; 1138} 1139 1140// Set r7 or ip to point to saved value residing within the stack. 1141// ADD (SP plus immediate) 1142bool EmulateInstructionARM::EmulateADDRdSPImm(const uint32_t opcode, 1143 const ARMEncoding encoding) { 1144#if 0 1145 // ARM pseudo code... 1146 if (ConditionPassed()) 1147 { 1148 EncodingSpecificOperations(); 1149 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 1150 if d == 15 then 1151 ALUWritePC(result); // setflags is always FALSE here 1152 else 1153 R[d] = result; 1154 if setflags then 1155 APSR.N = result<31>; 1156 APSR.Z = IsZeroBit(result); 1157 APSR.C = carry; 1158 APSR.V = overflow; 1159 } 1160#endif 1161 1162 bool success = false; 1163 1164 if (ConditionPassed(opcode)) { 1165 const addr_t sp = ReadCoreReg(SP_REG, &success); 1166 if (!success) 1167 return false; 1168 uint32_t Rd; // the destination register 1169 uint32_t imm32; 1170 switch (encoding) { 1171 case eEncodingT1: 1172 Rd = 7; 1173 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32) 1174 break; 1175 case eEncodingA1: 1176 Rd = Bits32(opcode, 15, 12); 1177 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 1178 break; 1179 default: 1180 return false; 1181 } 1182 addr_t sp_offset = imm32; 1183 addr_t addr = sp + sp_offset; // a pointer to the stack area 1184 1185 EmulateInstruction::Context context; 1186 if (Rd == GetFramePointerRegisterNumber()) 1187 context.type = eContextSetFramePointer; 1188 else 1189 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1190 std::optional<RegisterInfo> sp_reg = 1191 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 1192 context.SetRegisterPlusOffset(*sp_reg, sp_offset); 1193 1194 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, 1195 addr)) 1196 return false; 1197 } 1198 return true; 1199} 1200 1201// Set r7 or ip to the current stack pointer. 1202// MOV (register) 1203bool EmulateInstructionARM::EmulateMOVRdSP(const uint32_t opcode, 1204 const ARMEncoding encoding) { 1205#if 0 1206 // ARM pseudo code... 1207 if (ConditionPassed()) 1208 { 1209 EncodingSpecificOperations(); 1210 result = R[m]; 1211 if d == 15 then 1212 ALUWritePC(result); // setflags is always FALSE here 1213 else 1214 R[d] = result; 1215 if setflags then 1216 APSR.N = result<31>; 1217 APSR.Z = IsZeroBit(result); 1218 // APSR.C unchanged 1219 // APSR.V unchanged 1220 } 1221#endif 1222 1223 bool success = false; 1224 1225 if (ConditionPassed(opcode)) { 1226 const addr_t sp = ReadCoreReg(SP_REG, &success); 1227 if (!success) 1228 return false; 1229 uint32_t Rd; // the destination register 1230 switch (encoding) { 1231 case eEncodingT1: 1232 Rd = 7; 1233 break; 1234 case eEncodingA1: 1235 Rd = 12; 1236 break; 1237 default: 1238 return false; 1239 } 1240 1241 EmulateInstruction::Context context; 1242 if (Rd == GetFramePointerRegisterNumber()) 1243 context.type = EmulateInstruction::eContextSetFramePointer; 1244 else 1245 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1246 std::optional<RegisterInfo> sp_reg = 1247 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 1248 context.SetRegisterPlusOffset(*sp_reg, 0); 1249 1250 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rd, sp)) 1251 return false; 1252 } 1253 return true; 1254} 1255 1256// Move from high register (r8-r15) to low register (r0-r7). 1257// MOV (register) 1258bool EmulateInstructionARM::EmulateMOVLowHigh(const uint32_t opcode, 1259 const ARMEncoding encoding) { 1260 return EmulateMOVRdRm(opcode, encoding); 1261} 1262 1263// Move from register to register. 1264// MOV (register) 1265bool EmulateInstructionARM::EmulateMOVRdRm(const uint32_t opcode, 1266 const ARMEncoding encoding) { 1267#if 0 1268 // ARM pseudo code... 1269 if (ConditionPassed()) 1270 { 1271 EncodingSpecificOperations(); 1272 result = R[m]; 1273 if d == 15 then 1274 ALUWritePC(result); // setflags is always FALSE here 1275 else 1276 R[d] = result; 1277 if setflags then 1278 APSR.N = result<31>; 1279 APSR.Z = IsZeroBit(result); 1280 // APSR.C unchanged 1281 // APSR.V unchanged 1282 } 1283#endif 1284 1285 bool success = false; 1286 1287 if (ConditionPassed(opcode)) { 1288 uint32_t Rm; // the source register 1289 uint32_t Rd; // the destination register 1290 bool setflags; 1291 switch (encoding) { 1292 case eEncodingT1: 1293 Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 1294 Rm = Bits32(opcode, 6, 3); 1295 setflags = false; 1296 if (Rd == 15 && InITBlock() && !LastInITBlock()) 1297 return false; 1298 break; 1299 case eEncodingT2: 1300 Rd = Bits32(opcode, 2, 0); 1301 Rm = Bits32(opcode, 5, 3); 1302 setflags = true; 1303 if (InITBlock()) 1304 return false; 1305 break; 1306 case eEncodingT3: 1307 Rd = Bits32(opcode, 11, 8); 1308 Rm = Bits32(opcode, 3, 0); 1309 setflags = BitIsSet(opcode, 20); 1310 // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 1311 if (setflags && (BadReg(Rd) || BadReg(Rm))) 1312 return false; 1313 // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then 1314 // UNPREDICTABLE; 1315 if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13))) 1316 return false; 1317 break; 1318 case eEncodingA1: 1319 Rd = Bits32(opcode, 15, 12); 1320 Rm = Bits32(opcode, 3, 0); 1321 setflags = BitIsSet(opcode, 20); 1322 1323 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 1324 // instructions; 1325 if (Rd == 15 && setflags) 1326 return EmulateSUBSPcLrEtc(opcode, encoding); 1327 break; 1328 default: 1329 return false; 1330 } 1331 uint32_t result = ReadCoreReg(Rm, &success); 1332 if (!success) 1333 return false; 1334 1335 // The context specifies that Rm is to be moved into Rd. 1336 EmulateInstruction::Context context; 1337 if (Rd == 13) 1338 context.type = EmulateInstruction::eContextAdjustStackPointer; 1339 else if (Rd == GetFramePointerRegisterNumber() && Rm == 13) 1340 context.type = EmulateInstruction::eContextSetFramePointer; 1341 else 1342 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1343 std::optional<RegisterInfo> dwarf_reg = 1344 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 1345 context.SetRegisterPlusOffset(*dwarf_reg, 0); 1346 1347 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags)) 1348 return false; 1349 } 1350 return true; 1351} 1352 1353// Move (immediate) writes an immediate value to the destination register. It 1354// can optionally update the condition flags based on the value. 1355// MOV (immediate) 1356bool EmulateInstructionARM::EmulateMOVRdImm(const uint32_t opcode, 1357 const ARMEncoding encoding) { 1358#if 0 1359 // ARM pseudo code... 1360 if (ConditionPassed()) 1361 { 1362 EncodingSpecificOperations(); 1363 result = imm32; 1364 if d == 15 then // Can only occur for ARM encoding 1365 ALUWritePC(result); // setflags is always FALSE here 1366 else 1367 R[d] = result; 1368 if setflags then 1369 APSR.N = result<31>; 1370 APSR.Z = IsZeroBit(result); 1371 APSR.C = carry; 1372 // APSR.V unchanged 1373 } 1374#endif 1375 1376 if (ConditionPassed(opcode)) { 1377 uint32_t Rd; // the destination register 1378 uint32_t imm32; // the immediate value to be written to Rd 1379 uint32_t carry = 1380 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C. 1381 // for setflags == false, this value is a don't care initialized to 1382 // 0 to silence the static analyzer 1383 bool setflags; 1384 switch (encoding) { 1385 case eEncodingT1: 1386 Rd = Bits32(opcode, 10, 8); 1387 setflags = !InITBlock(); 1388 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 1389 carry = APSR_C; 1390 1391 break; 1392 1393 case eEncodingT2: 1394 Rd = Bits32(opcode, 11, 8); 1395 setflags = BitIsSet(opcode, 20); 1396 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 1397 if (BadReg(Rd)) 1398 return false; 1399 1400 break; 1401 1402 case eEncodingT3: { 1403 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 1404 // 32); 1405 Rd = Bits32(opcode, 11, 8); 1406 setflags = false; 1407 uint32_t imm4 = Bits32(opcode, 19, 16); 1408 uint32_t imm3 = Bits32(opcode, 14, 12); 1409 uint32_t i = Bit32(opcode, 26); 1410 uint32_t imm8 = Bits32(opcode, 7, 0); 1411 imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8; 1412 1413 // if BadReg(d) then UNPREDICTABLE; 1414 if (BadReg(Rd)) 1415 return false; 1416 } break; 1417 1418 case eEncodingA1: 1419 // d = UInt(Rd); setflags = (S == '1'); (imm32, carry) = 1420 // ARMExpandImm_C(imm12, APSR.C); 1421 Rd = Bits32(opcode, 15, 12); 1422 setflags = BitIsSet(opcode, 20); 1423 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); 1424 1425 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 1426 // instructions; 1427 if ((Rd == 15) && setflags) 1428 return EmulateSUBSPcLrEtc(opcode, encoding); 1429 1430 break; 1431 1432 case eEncodingA2: { 1433 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32); 1434 Rd = Bits32(opcode, 15, 12); 1435 setflags = false; 1436 uint32_t imm4 = Bits32(opcode, 19, 16); 1437 uint32_t imm12 = Bits32(opcode, 11, 0); 1438 imm32 = (imm4 << 12) | imm12; 1439 1440 // if d == 15 then UNPREDICTABLE; 1441 if (Rd == 15) 1442 return false; 1443 } break; 1444 1445 default: 1446 return false; 1447 } 1448 uint32_t result = imm32; 1449 1450 // The context specifies that an immediate is to be moved into Rd. 1451 EmulateInstruction::Context context; 1452 context.type = EmulateInstruction::eContextImmediate; 1453 context.SetNoArgs(); 1454 1455 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1456 return false; 1457 } 1458 return true; 1459} 1460 1461// MUL multiplies two register values. The least significant 32 bits of the 1462// result are written to the destination 1463// register. These 32 bits do not depend on whether the source register values 1464// are considered to be signed values or unsigned values. 1465// 1466// Optionally, it can update the condition flags based on the result. In the 1467// Thumb instruction set, this option is limited to only a few forms of the 1468// instruction. 1469bool EmulateInstructionARM::EmulateMUL(const uint32_t opcode, 1470 const ARMEncoding encoding) { 1471#if 0 1472 if ConditionPassed() then 1473 EncodingSpecificOperations(); 1474 operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 1475 operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 1476 result = operand1 * operand2; 1477 R[d] = result<31:0>; 1478 if setflags then 1479 APSR.N = result<31>; 1480 APSR.Z = IsZeroBit(result); 1481 if ArchVersion() == 4 then 1482 APSR.C = bit UNKNOWN; 1483 // else APSR.C unchanged 1484 // APSR.V always unchanged 1485#endif 1486 1487 if (ConditionPassed(opcode)) { 1488 uint32_t d; 1489 uint32_t n; 1490 uint32_t m; 1491 bool setflags; 1492 1493 // EncodingSpecificOperations(); 1494 switch (encoding) { 1495 case eEncodingT1: 1496 // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock(); 1497 d = Bits32(opcode, 2, 0); 1498 n = Bits32(opcode, 5, 3); 1499 m = Bits32(opcode, 2, 0); 1500 setflags = !InITBlock(); 1501 1502 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 1503 if ((ArchVersion() < ARMv6) && (d == n)) 1504 return false; 1505 1506 break; 1507 1508 case eEncodingT2: 1509 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE; 1510 d = Bits32(opcode, 11, 8); 1511 n = Bits32(opcode, 19, 16); 1512 m = Bits32(opcode, 3, 0); 1513 setflags = false; 1514 1515 // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE; 1516 if (BadReg(d) || BadReg(n) || BadReg(m)) 1517 return false; 1518 1519 break; 1520 1521 case eEncodingA1: 1522 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); 1523 d = Bits32(opcode, 19, 16); 1524 n = Bits32(opcode, 3, 0); 1525 m = Bits32(opcode, 11, 8); 1526 setflags = BitIsSet(opcode, 20); 1527 1528 // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; 1529 if ((d == 15) || (n == 15) || (m == 15)) 1530 return false; 1531 1532 // if ArchVersion() < 6 && d == n then UNPREDICTABLE; 1533 if ((ArchVersion() < ARMv6) && (d == n)) 1534 return false; 1535 1536 break; 1537 1538 default: 1539 return false; 1540 } 1541 1542 bool success = false; 1543 1544 // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final 1545 // results 1546 uint64_t operand1 = 1547 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 1548 if (!success) 1549 return false; 1550 1551 // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final 1552 // results 1553 uint64_t operand2 = 1554 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 1555 if (!success) 1556 return false; 1557 1558 // result = operand1 * operand2; 1559 uint64_t result = operand1 * operand2; 1560 1561 // R[d] = result<31:0>; 1562 std::optional<RegisterInfo> op1_reg = 1563 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 1564 std::optional<RegisterInfo> op2_reg = 1565 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 1566 1567 EmulateInstruction::Context context; 1568 context.type = eContextArithmetic; 1569 context.SetRegisterRegisterOperands(*op1_reg, *op2_reg); 1570 1571 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 1572 (0x0000ffff & result))) 1573 return false; 1574 1575 // if setflags then 1576 if (setflags) { 1577 // APSR.N = result<31>; 1578 // APSR.Z = IsZeroBit(result); 1579 m_new_inst_cpsr = m_opcode_cpsr; 1580 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, 31)); 1581 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 1582 if (m_new_inst_cpsr != m_opcode_cpsr) { 1583 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 1584 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 1585 return false; 1586 } 1587 1588 // if ArchVersion() == 4 then 1589 // APSR.C = bit UNKNOWN; 1590 } 1591 } 1592 return true; 1593} 1594 1595// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to 1596// the destination register. It can optionally update the condition flags based 1597// on the value. 1598bool EmulateInstructionARM::EmulateMVNImm(const uint32_t opcode, 1599 const ARMEncoding encoding) { 1600#if 0 1601 // ARM pseudo code... 1602 if (ConditionPassed()) 1603 { 1604 EncodingSpecificOperations(); 1605 result = NOT(imm32); 1606 if d == 15 then // Can only occur for ARM encoding 1607 ALUWritePC(result); // setflags is always FALSE here 1608 else 1609 R[d] = result; 1610 if setflags then 1611 APSR.N = result<31>; 1612 APSR.Z = IsZeroBit(result); 1613 APSR.C = carry; 1614 // APSR.V unchanged 1615 } 1616#endif 1617 1618 if (ConditionPassed(opcode)) { 1619 uint32_t Rd; // the destination register 1620 uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C 1621 uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C 1622 bool setflags; 1623 switch (encoding) { 1624 case eEncodingT1: 1625 Rd = Bits32(opcode, 11, 8); 1626 setflags = BitIsSet(opcode, 20); 1627 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); 1628 break; 1629 case eEncodingA1: 1630 Rd = Bits32(opcode, 15, 12); 1631 setflags = BitIsSet(opcode, 20); 1632 imm32 = ARMExpandImm_C(opcode, APSR_C, carry); 1633 1634 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 1635 // instructions; 1636 if (Rd == 15 && setflags) 1637 return EmulateSUBSPcLrEtc(opcode, encoding); 1638 break; 1639 default: 1640 return false; 1641 } 1642 uint32_t result = ~imm32; 1643 1644 // The context specifies that an immediate is to be moved into Rd. 1645 EmulateInstruction::Context context; 1646 context.type = EmulateInstruction::eContextImmediate; 1647 context.SetNoArgs(); 1648 1649 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1650 return false; 1651 } 1652 return true; 1653} 1654 1655// Bitwise NOT (register) writes the bitwise inverse of a register value to the 1656// destination register. It can optionally update the condition flags based on 1657// the result. 1658bool EmulateInstructionARM::EmulateMVNReg(const uint32_t opcode, 1659 const ARMEncoding encoding) { 1660#if 0 1661 // ARM pseudo code... 1662 if (ConditionPassed()) 1663 { 1664 EncodingSpecificOperations(); 1665 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 1666 result = NOT(shifted); 1667 if d == 15 then // Can only occur for ARM encoding 1668 ALUWritePC(result); // setflags is always FALSE here 1669 else 1670 R[d] = result; 1671 if setflags then 1672 APSR.N = result<31>; 1673 APSR.Z = IsZeroBit(result); 1674 APSR.C = carry; 1675 // APSR.V unchanged 1676 } 1677#endif 1678 1679 if (ConditionPassed(opcode)) { 1680 uint32_t Rm; // the source register 1681 uint32_t Rd; // the destination register 1682 ARM_ShifterType shift_t; 1683 uint32_t shift_n; // the shift applied to the value read from Rm 1684 bool setflags; 1685 uint32_t carry; // the carry bit after the shift operation 1686 switch (encoding) { 1687 case eEncodingT1: 1688 Rd = Bits32(opcode, 2, 0); 1689 Rm = Bits32(opcode, 5, 3); 1690 setflags = !InITBlock(); 1691 shift_t = SRType_LSL; 1692 shift_n = 0; 1693 if (InITBlock()) 1694 return false; 1695 break; 1696 case eEncodingT2: 1697 Rd = Bits32(opcode, 11, 8); 1698 Rm = Bits32(opcode, 3, 0); 1699 setflags = BitIsSet(opcode, 20); 1700 shift_n = DecodeImmShiftThumb(opcode, shift_t); 1701 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 1702 if (BadReg(Rd) || BadReg(Rm)) 1703 return false; 1704 break; 1705 case eEncodingA1: 1706 Rd = Bits32(opcode, 15, 12); 1707 Rm = Bits32(opcode, 3, 0); 1708 setflags = BitIsSet(opcode, 20); 1709 shift_n = DecodeImmShiftARM(opcode, shift_t); 1710 break; 1711 default: 1712 return false; 1713 } 1714 bool success = false; 1715 uint32_t value = ReadCoreReg(Rm, &success); 1716 if (!success) 1717 return false; 1718 1719 uint32_t shifted = 1720 Shift_C(value, shift_t, shift_n, APSR_C, carry, &success); 1721 if (!success) 1722 return false; 1723 uint32_t result = ~shifted; 1724 1725 // The context specifies that an immediate is to be moved into Rd. 1726 EmulateInstruction::Context context; 1727 context.type = EmulateInstruction::eContextImmediate; 1728 context.SetNoArgs(); 1729 1730 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 1731 return false; 1732 } 1733 return true; 1734} 1735 1736// PC relative immediate load into register, possibly followed by ADD (SP plus 1737// register). 1738// LDR (literal) 1739bool EmulateInstructionARM::EmulateLDRRtPCRelative(const uint32_t opcode, 1740 const ARMEncoding encoding) { 1741#if 0 1742 // ARM pseudo code... 1743 if (ConditionPassed()) 1744 { 1745 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 1746 base = Align(PC,4); 1747 address = if add then (base + imm32) else (base - imm32); 1748 data = MemU[address,4]; 1749 if t == 15 then 1750 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 1751 elsif UnalignedSupport() || address<1:0> = '00' then 1752 R[t] = data; 1753 else // Can only apply before ARMv7 1754 if CurrentInstrSet() == InstrSet_ARM then 1755 R[t] = ROR(data, 8*UInt(address<1:0>)); 1756 else 1757 R[t] = bits(32) UNKNOWN; 1758 } 1759#endif 1760 1761 if (ConditionPassed(opcode)) { 1762 bool success = false; 1763 const uint32_t pc = ReadCoreReg(PC_REG, &success); 1764 if (!success) 1765 return false; 1766 1767 // PC relative immediate load context 1768 EmulateInstruction::Context context; 1769 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1770 std::optional<RegisterInfo> pc_reg = 1771 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 1772 context.SetRegisterPlusOffset(*pc_reg, 0); 1773 1774 uint32_t Rt; // the destination register 1775 uint32_t imm32; // immediate offset from the PC 1776 bool add; // +imm32 or -imm32? 1777 addr_t base; // the base address 1778 addr_t address; // the PC relative address 1779 uint32_t data; // the literal data value from the PC relative load 1780 switch (encoding) { 1781 case eEncodingT1: 1782 Rt = Bits32(opcode, 10, 8); 1783 imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32); 1784 add = true; 1785 break; 1786 case eEncodingT2: 1787 Rt = Bits32(opcode, 15, 12); 1788 imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32); 1789 add = BitIsSet(opcode, 23); 1790 if (Rt == 15 && InITBlock() && !LastInITBlock()) 1791 return false; 1792 break; 1793 default: 1794 return false; 1795 } 1796 1797 base = Align(pc, 4); 1798 if (add) 1799 address = base + imm32; 1800 else 1801 address = base - imm32; 1802 1803 context.SetRegisterPlusOffset(*pc_reg, address - base); 1804 data = MemURead(context, address, 4, 0, &success); 1805 if (!success) 1806 return false; 1807 1808 if (Rt == 15) { 1809 if (Bits32(address, 1, 0) == 0) { 1810 // In ARMv5T and above, this is an interworking branch. 1811 if (!LoadWritePC(context, data)) 1812 return false; 1813 } else 1814 return false; 1815 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) { 1816 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt, 1817 data)) 1818 return false; 1819 } else // We don't handle ARM for now. 1820 return false; 1821 } 1822 return true; 1823} 1824 1825// An add operation to adjust the SP. 1826// ADD (SP plus immediate) 1827bool EmulateInstructionARM::EmulateADDSPImm(const uint32_t opcode, 1828 const ARMEncoding encoding) { 1829#if 0 1830 // ARM pseudo code... 1831 if (ConditionPassed()) 1832 { 1833 EncodingSpecificOperations(); 1834 (result, carry, overflow) = AddWithCarry(SP, imm32, '0'); 1835 if d == 15 then // Can only occur for ARM encoding 1836 ALUWritePC(result); // setflags is always FALSE here 1837 else 1838 R[d] = result; 1839 if setflags then 1840 APSR.N = result<31>; 1841 APSR.Z = IsZeroBit(result); 1842 APSR.C = carry; 1843 APSR.V = overflow; 1844 } 1845#endif 1846 1847 bool success = false; 1848 1849 if (ConditionPassed(opcode)) { 1850 const addr_t sp = ReadCoreReg(SP_REG, &success); 1851 if (!success) 1852 return false; 1853 uint32_t imm32; // the immediate operand 1854 uint32_t d; 1855 bool setflags; 1856 switch (encoding) { 1857 case eEncodingT1: 1858 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32); 1859 d = Bits32(opcode, 10, 8); 1860 imm32 = (Bits32(opcode, 7, 0) << 2); 1861 setflags = false; 1862 break; 1863 1864 case eEncodingT2: 1865 // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32); 1866 d = 13; 1867 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 1868 setflags = false; 1869 break; 1870 1871 case eEncodingT3: 1872 // d = UInt(Rd); setflags = (S == "1"); imm32 = 1873 // ThumbExpandImm(i:imm3:imm8); 1874 d = Bits32(opcode, 11, 8); 1875 imm32 = ThumbExpandImm(opcode); 1876 setflags = Bit32(opcode, 20); 1877 1878 // if Rd == "1111" && S == "1" then SEE CMN (immediate); 1879 if (d == 15 && setflags == 1) 1880 return false; // CMN (immediate) not yet supported 1881 1882 // if d == 15 && S == "0" then UNPREDICTABLE; 1883 if (d == 15 && setflags == 0) 1884 return false; 1885 break; 1886 1887 case eEncodingT4: { 1888 // if Rn == '1111' then SEE ADR; 1889 // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); 1890 d = Bits32(opcode, 11, 8); 1891 setflags = false; 1892 uint32_t i = Bit32(opcode, 26); 1893 uint32_t imm3 = Bits32(opcode, 14, 12); 1894 uint32_t imm8 = Bits32(opcode, 7, 0); 1895 imm32 = (i << 11) | (imm3 << 8) | imm8; 1896 1897 // if d == 15 then UNPREDICTABLE; 1898 if (d == 15) 1899 return false; 1900 } break; 1901 1902 default: 1903 return false; 1904 } 1905 // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 1906 AddWithCarryResult res = AddWithCarry(sp, imm32, 0); 1907 1908 EmulateInstruction::Context context; 1909 if (d == 13) 1910 context.type = EmulateInstruction::eContextAdjustStackPointer; 1911 else 1912 context.type = EmulateInstruction::eContextRegisterPlusOffset; 1913 1914 std::optional<RegisterInfo> sp_reg = 1915 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 1916 context.SetRegisterPlusOffset(*sp_reg, res.result - sp); 1917 1918 if (d == 15) { 1919 if (!ALUWritePC(context, res.result)) 1920 return false; 1921 } else { 1922 // R[d] = result; 1923 // if setflags then 1924 // APSR.N = result<31>; 1925 // APSR.Z = IsZeroBit(result); 1926 // APSR.C = carry; 1927 // APSR.V = overflow; 1928 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags, 1929 res.carry_out, res.overflow)) 1930 return false; 1931 } 1932 } 1933 return true; 1934} 1935 1936// An add operation to adjust the SP. 1937// ADD (SP plus register) 1938bool EmulateInstructionARM::EmulateADDSPRm(const uint32_t opcode, 1939 const ARMEncoding encoding) { 1940#if 0 1941 // ARM pseudo code... 1942 if (ConditionPassed()) 1943 { 1944 EncodingSpecificOperations(); 1945 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 1946 (result, carry, overflow) = AddWithCarry(SP, shifted, '0'); 1947 if d == 15 then 1948 ALUWritePC(result); // setflags is always FALSE here 1949 else 1950 R[d] = result; 1951 if setflags then 1952 APSR.N = result<31>; 1953 APSR.Z = IsZeroBit(result); 1954 APSR.C = carry; 1955 APSR.V = overflow; 1956 } 1957#endif 1958 1959 bool success = false; 1960 1961 if (ConditionPassed(opcode)) { 1962 const addr_t sp = ReadCoreReg(SP_REG, &success); 1963 if (!success) 1964 return false; 1965 uint32_t Rm; // the second operand 1966 switch (encoding) { 1967 case eEncodingT2: 1968 Rm = Bits32(opcode, 6, 3); 1969 break; 1970 default: 1971 return false; 1972 } 1973 int32_t reg_value = ReadCoreReg(Rm, &success); 1974 if (!success) 1975 return false; 1976 1977 addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value 1978 1979 EmulateInstruction::Context context; 1980 context.type = eContextArithmetic; 1981 std::optional<RegisterInfo> sp_reg = 1982 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 1983 std::optional<RegisterInfo> other_reg = 1984 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 1985 context.SetRegisterRegisterOperands(*sp_reg, *other_reg); 1986 1987 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 1988 LLDB_REGNUM_GENERIC_SP, addr)) 1989 return false; 1990 } 1991 return true; 1992} 1993 1994// Branch with Link and Exchange Instruction Sets (immediate) calls a 1995// subroutine at a PC-relative address, and changes instruction set from ARM to 1996// Thumb, or from Thumb to ARM. 1997// BLX (immediate) 1998bool EmulateInstructionARM::EmulateBLXImmediate(const uint32_t opcode, 1999 const ARMEncoding encoding) { 2000#if 0 2001 // ARM pseudo code... 2002 if (ConditionPassed()) 2003 { 2004 EncodingSpecificOperations(); 2005 if CurrentInstrSet() == InstrSet_ARM then 2006 LR = PC - 4; 2007 else 2008 LR = PC<31:1> : '1'; 2009 if targetInstrSet == InstrSet_ARM then 2010 targetAddress = Align(PC,4) + imm32; 2011 else 2012 targetAddress = PC + imm32; 2013 SelectInstrSet(targetInstrSet); 2014 BranchWritePC(targetAddress); 2015 } 2016#endif 2017 2018 bool success = true; 2019 2020 if (ConditionPassed(opcode)) { 2021 EmulateInstruction::Context context; 2022 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2023 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2024 if (!success) 2025 return false; 2026 addr_t lr; // next instruction address 2027 addr_t target; // target address 2028 int32_t imm32; // PC-relative offset 2029 switch (encoding) { 2030 case eEncodingT1: { 2031 lr = pc | 1u; // return address 2032 uint32_t S = Bit32(opcode, 26); 2033 uint32_t imm10 = Bits32(opcode, 25, 16); 2034 uint32_t J1 = Bit32(opcode, 13); 2035 uint32_t J2 = Bit32(opcode, 11); 2036 uint32_t imm11 = Bits32(opcode, 10, 0); 2037 uint32_t I1 = !(J1 ^ S); 2038 uint32_t I2 = !(J2 ^ S); 2039 uint32_t imm25 = 2040 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2041 imm32 = llvm::SignExtend32<25>(imm25); 2042 target = pc + imm32; 2043 SelectInstrSet(eModeThumb); 2044 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2045 if (InITBlock() && !LastInITBlock()) 2046 return false; 2047 break; 2048 } 2049 case eEncodingT2: { 2050 lr = pc | 1u; // return address 2051 uint32_t S = Bit32(opcode, 26); 2052 uint32_t imm10H = Bits32(opcode, 25, 16); 2053 uint32_t J1 = Bit32(opcode, 13); 2054 uint32_t J2 = Bit32(opcode, 11); 2055 uint32_t imm10L = Bits32(opcode, 10, 1); 2056 uint32_t I1 = !(J1 ^ S); 2057 uint32_t I2 = !(J2 ^ S); 2058 uint32_t imm25 = 2059 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2); 2060 imm32 = llvm::SignExtend32<25>(imm25); 2061 target = Align(pc, 4) + imm32; 2062 SelectInstrSet(eModeARM); 2063 context.SetISAAndImmediateSigned(eModeARM, 4 + imm32); 2064 if (InITBlock() && !LastInITBlock()) 2065 return false; 2066 break; 2067 } 2068 case eEncodingA1: 2069 lr = pc - 4; // return address 2070 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 2071 target = Align(pc, 4) + imm32; 2072 SelectInstrSet(eModeARM); 2073 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32); 2074 break; 2075 case eEncodingA2: 2076 lr = pc - 4; // return address 2077 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | 2078 Bits32(opcode, 24, 24) << 1); 2079 target = pc + imm32; 2080 SelectInstrSet(eModeThumb); 2081 context.SetISAAndImmediateSigned(eModeThumb, 8 + imm32); 2082 break; 2083 default: 2084 return false; 2085 } 2086 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2087 LLDB_REGNUM_GENERIC_RA, lr)) 2088 return false; 2089 if (!BranchWritePC(context, target)) 2090 return false; 2091 if (m_opcode_cpsr != m_new_inst_cpsr) 2092 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2093 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 2094 return false; 2095 } 2096 return true; 2097} 2098 2099// Branch with Link and Exchange (register) calls a subroutine at an address 2100// and instruction set specified by a register. 2101// BLX (register) 2102bool EmulateInstructionARM::EmulateBLXRm(const uint32_t opcode, 2103 const ARMEncoding encoding) { 2104#if 0 2105 // ARM pseudo code... 2106 if (ConditionPassed()) 2107 { 2108 EncodingSpecificOperations(); 2109 target = R[m]; 2110 if CurrentInstrSet() == InstrSet_ARM then 2111 next_instr_addr = PC - 4; 2112 LR = next_instr_addr; 2113 else 2114 next_instr_addr = PC - 2; 2115 LR = next_instr_addr<31:1> : '1'; 2116 BXWritePC(target); 2117 } 2118#endif 2119 2120 bool success = false; 2121 2122 if (ConditionPassed(opcode)) { 2123 EmulateInstruction::Context context; 2124 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 2125 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2126 addr_t lr; // next instruction address 2127 if (!success) 2128 return false; 2129 uint32_t Rm; // the register with the target address 2130 switch (encoding) { 2131 case eEncodingT1: 2132 lr = (pc - 2) | 1u; // return address 2133 Rm = Bits32(opcode, 6, 3); 2134 // if m == 15 then UNPREDICTABLE; 2135 if (Rm == 15) 2136 return false; 2137 if (InITBlock() && !LastInITBlock()) 2138 return false; 2139 break; 2140 case eEncodingA1: 2141 lr = pc - 4; // return address 2142 Rm = Bits32(opcode, 3, 0); 2143 // if m == 15 then UNPREDICTABLE; 2144 if (Rm == 15) 2145 return false; 2146 break; 2147 default: 2148 return false; 2149 } 2150 addr_t target = ReadCoreReg(Rm, &success); 2151 if (!success) 2152 return false; 2153 std::optional<RegisterInfo> dwarf_reg = 2154 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 2155 context.SetRegister(*dwarf_reg); 2156 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2157 LLDB_REGNUM_GENERIC_RA, lr)) 2158 return false; 2159 if (!BXWritePC(context, target)) 2160 return false; 2161 } 2162 return true; 2163} 2164 2165// Branch and Exchange causes a branch to an address and instruction set 2166// specified by a register. 2167bool EmulateInstructionARM::EmulateBXRm(const uint32_t opcode, 2168 const ARMEncoding encoding) { 2169#if 0 2170 // ARM pseudo code... 2171 if (ConditionPassed()) 2172 { 2173 EncodingSpecificOperations(); 2174 BXWritePC(R[m]); 2175 } 2176#endif 2177 2178 if (ConditionPassed(opcode)) { 2179 EmulateInstruction::Context context; 2180 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 2181 uint32_t Rm; // the register with the target address 2182 switch (encoding) { 2183 case eEncodingT1: 2184 Rm = Bits32(opcode, 6, 3); 2185 if (InITBlock() && !LastInITBlock()) 2186 return false; 2187 break; 2188 case eEncodingA1: 2189 Rm = Bits32(opcode, 3, 0); 2190 break; 2191 default: 2192 return false; 2193 } 2194 bool success = false; 2195 addr_t target = ReadCoreReg(Rm, &success); 2196 if (!success) 2197 return false; 2198 2199 std::optional<RegisterInfo> dwarf_reg = 2200 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 2201 context.SetRegister(*dwarf_reg); 2202 if (!BXWritePC(context, target)) 2203 return false; 2204 } 2205 return true; 2206} 2207 2208// Branch and Exchange Jazelle attempts to change to Jazelle state. If the 2209// attempt fails, it branches to an address and instruction set specified by a 2210// register as though it were a BX instruction. 2211// 2212// TODO: Emulate Jazelle architecture? 2213// We currently assume that switching to Jazelle state fails, thus 2214// treating BXJ as a BX operation. 2215bool EmulateInstructionARM::EmulateBXJRm(const uint32_t opcode, 2216 const ARMEncoding encoding) { 2217#if 0 2218 // ARM pseudo code... 2219 if (ConditionPassed()) 2220 { 2221 EncodingSpecificOperations(); 2222 if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then 2223 BXWritePC(R[m]); 2224 else 2225 if JazelleAcceptsExecution() then 2226 SwitchToJazelleExecution(); 2227 else 2228 SUBARCHITECTURE_DEFINED handler call; 2229 } 2230#endif 2231 2232 if (ConditionPassed(opcode)) { 2233 EmulateInstruction::Context context; 2234 context.type = EmulateInstruction::eContextAbsoluteBranchRegister; 2235 uint32_t Rm; // the register with the target address 2236 switch (encoding) { 2237 case eEncodingT1: 2238 Rm = Bits32(opcode, 19, 16); 2239 if (BadReg(Rm)) 2240 return false; 2241 if (InITBlock() && !LastInITBlock()) 2242 return false; 2243 break; 2244 case eEncodingA1: 2245 Rm = Bits32(opcode, 3, 0); 2246 if (Rm == 15) 2247 return false; 2248 break; 2249 default: 2250 return false; 2251 } 2252 bool success = false; 2253 addr_t target = ReadCoreReg(Rm, &success); 2254 if (!success) 2255 return false; 2256 2257 std::optional<RegisterInfo> dwarf_reg = 2258 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 2259 context.SetRegister(*dwarf_reg); 2260 if (!BXWritePC(context, target)) 2261 return false; 2262 } 2263 return true; 2264} 2265 2266// Set r7 to point to some ip offset. 2267// SUB (immediate) 2268bool EmulateInstructionARM::EmulateSUBR7IPImm(const uint32_t opcode, 2269 const ARMEncoding encoding) { 2270#if 0 2271 // ARM pseudo code... 2272 if (ConditionPassed()) 2273 { 2274 EncodingSpecificOperations(); 2275 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 2276 if d == 15 then // Can only occur for ARM encoding 2277 ALUWritePC(result); // setflags is always FALSE here 2278 else 2279 R[d] = result; 2280 if setflags then 2281 APSR.N = result<31>; 2282 APSR.Z = IsZeroBit(result); 2283 APSR.C = carry; 2284 APSR.V = overflow; 2285 } 2286#endif 2287 2288 if (ConditionPassed(opcode)) { 2289 bool success = false; 2290 const addr_t ip = ReadCoreReg(12, &success); 2291 if (!success) 2292 return false; 2293 uint32_t imm32; 2294 switch (encoding) { 2295 case eEncodingA1: 2296 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2297 break; 2298 default: 2299 return false; 2300 } 2301 addr_t ip_offset = imm32; 2302 addr_t addr = ip - ip_offset; // the adjusted ip value 2303 2304 EmulateInstruction::Context context; 2305 context.type = EmulateInstruction::eContextRegisterPlusOffset; 2306 std::optional<RegisterInfo> dwarf_reg = 2307 GetRegisterInfo(eRegisterKindDWARF, dwarf_r12); 2308 context.SetRegisterPlusOffset(*dwarf_reg, -ip_offset); 2309 2310 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r7, addr)) 2311 return false; 2312 } 2313 return true; 2314} 2315 2316// Set ip to point to some stack offset. 2317// SUB (SP minus immediate) 2318bool EmulateInstructionARM::EmulateSUBIPSPImm(const uint32_t opcode, 2319 const ARMEncoding encoding) { 2320#if 0 2321 // ARM pseudo code... 2322 if (ConditionPassed()) 2323 { 2324 EncodingSpecificOperations(); 2325 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 2326 if d == 15 then // Can only occur for ARM encoding 2327 ALUWritePC(result); // setflags is always FALSE here 2328 else 2329 R[d] = result; 2330 if setflags then 2331 APSR.N = result<31>; 2332 APSR.Z = IsZeroBit(result); 2333 APSR.C = carry; 2334 APSR.V = overflow; 2335 } 2336#endif 2337 2338 if (ConditionPassed(opcode)) { 2339 bool success = false; 2340 const addr_t sp = ReadCoreReg(SP_REG, &success); 2341 if (!success) 2342 return false; 2343 uint32_t imm32; 2344 switch (encoding) { 2345 case eEncodingA1: 2346 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2347 break; 2348 default: 2349 return false; 2350 } 2351 addr_t sp_offset = imm32; 2352 addr_t addr = sp - sp_offset; // the adjusted stack pointer value 2353 2354 EmulateInstruction::Context context; 2355 context.type = EmulateInstruction::eContextRegisterPlusOffset; 2356 std::optional<RegisterInfo> dwarf_reg = 2357 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP); 2358 context.SetRegisterPlusOffset(*dwarf_reg, -sp_offset); 2359 2360 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r12, addr)) 2361 return false; 2362 } 2363 return true; 2364} 2365 2366// This instruction subtracts an immediate value from the SP value, and writes 2367// the result to the destination register. 2368// 2369// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local 2370// storage. 2371bool EmulateInstructionARM::EmulateSUBSPImm(const uint32_t opcode, 2372 const ARMEncoding encoding) { 2373#if 0 2374 // ARM pseudo code... 2375 if (ConditionPassed()) 2376 { 2377 EncodingSpecificOperations(); 2378 (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1'); 2379 if d == 15 then // Can only occur for ARM encoding 2380 ALUWritePC(result); // setflags is always FALSE here 2381 else 2382 R[d] = result; 2383 if setflags then 2384 APSR.N = result<31>; 2385 APSR.Z = IsZeroBit(result); 2386 APSR.C = carry; 2387 APSR.V = overflow; 2388 } 2389#endif 2390 2391 bool success = false; 2392 if (ConditionPassed(opcode)) { 2393 const addr_t sp = ReadCoreReg(SP_REG, &success); 2394 if (!success) 2395 return false; 2396 2397 uint32_t Rd; 2398 bool setflags; 2399 uint32_t imm32; 2400 switch (encoding) { 2401 case eEncodingT1: 2402 Rd = 13; 2403 setflags = false; 2404 imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) 2405 break; 2406 case eEncodingT2: 2407 Rd = Bits32(opcode, 11, 8); 2408 setflags = BitIsSet(opcode, 20); 2409 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 2410 if (Rd == 15 && setflags) 2411 return EmulateCMPImm(opcode, eEncodingT2); 2412 if (Rd == 15 && !setflags) 2413 return false; 2414 break; 2415 case eEncodingT3: 2416 Rd = Bits32(opcode, 11, 8); 2417 setflags = false; 2418 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 2419 if (Rd == 15) 2420 return false; 2421 break; 2422 case eEncodingA1: 2423 Rd = Bits32(opcode, 15, 12); 2424 setflags = BitIsSet(opcode, 20); 2425 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 2426 2427 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 2428 // instructions; 2429 if (Rd == 15 && setflags) 2430 return EmulateSUBSPcLrEtc(opcode, encoding); 2431 break; 2432 default: 2433 return false; 2434 } 2435 AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1); 2436 2437 EmulateInstruction::Context context; 2438 if (Rd == 13) { 2439 uint64_t imm64 = imm32; // Need to expand it to 64 bits before attempting 2440 // to negate it, or the wrong 2441 // value gets passed down to context.SetImmediateSigned. 2442 context.type = EmulateInstruction::eContextAdjustStackPointer; 2443 context.SetImmediateSigned(-imm64); // the stack pointer offset 2444 } else { 2445 context.type = EmulateInstruction::eContextImmediate; 2446 context.SetNoArgs(); 2447 } 2448 2449 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 2450 res.carry_out, res.overflow)) 2451 return false; 2452 } 2453 return true; 2454} 2455 2456// A store operation to the stack that also updates the SP. 2457bool EmulateInstructionARM::EmulateSTRRtSP(const uint32_t opcode, 2458 const ARMEncoding encoding) { 2459#if 0 2460 // ARM pseudo code... 2461 if (ConditionPassed()) 2462 { 2463 EncodingSpecificOperations(); 2464 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 2465 address = if index then offset_addr else R[n]; 2466 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 2467 if wback then R[n] = offset_addr; 2468 } 2469#endif 2470 2471 bool success = false; 2472 if (ConditionPassed(opcode)) { 2473 const uint32_t addr_byte_size = GetAddressByteSize(); 2474 const addr_t sp = ReadCoreReg(SP_REG, &success); 2475 if (!success) 2476 return false; 2477 uint32_t Rt; // the source register 2478 uint32_t imm12; 2479 uint32_t 2480 Rn; // This function assumes Rn is the SP, but we should verify that. 2481 2482 bool index; 2483 bool add; 2484 bool wback; 2485 switch (encoding) { 2486 case eEncodingA1: 2487 Rt = Bits32(opcode, 15, 12); 2488 imm12 = Bits32(opcode, 11, 0); 2489 Rn = Bits32(opcode, 19, 16); 2490 2491 if (Rn != 13) // 13 is the SP reg on ARM. Verify that Rn == SP. 2492 return false; 2493 2494 index = BitIsSet(opcode, 24); 2495 add = BitIsSet(opcode, 23); 2496 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 2497 2498 if (wback && ((Rn == 15) || (Rn == Rt))) 2499 return false; 2500 break; 2501 default: 2502 return false; 2503 } 2504 addr_t offset_addr; 2505 if (add) 2506 offset_addr = sp + imm12; 2507 else 2508 offset_addr = sp - imm12; 2509 2510 addr_t addr; 2511 if (index) 2512 addr = offset_addr; 2513 else 2514 addr = sp; 2515 2516 EmulateInstruction::Context context; 2517 context.type = EmulateInstruction::eContextPushRegisterOnStack; 2518 std::optional<RegisterInfo> sp_reg = 2519 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 2520 std::optional<RegisterInfo> dwarf_reg = 2521 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rt); 2522 2523 context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp); 2524 if (Rt != 15) { 2525 uint32_t reg_value = ReadCoreReg(Rt, &success); 2526 if (!success) 2527 return false; 2528 if (!MemUWrite(context, addr, reg_value, addr_byte_size)) 2529 return false; 2530 } else { 2531 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2532 if (!success) 2533 return false; 2534 if (!MemUWrite(context, addr, pc, addr_byte_size)) 2535 return false; 2536 } 2537 2538 if (wback) { 2539 context.type = EmulateInstruction::eContextAdjustStackPointer; 2540 context.SetImmediateSigned(addr - sp); 2541 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2542 LLDB_REGNUM_GENERIC_SP, offset_addr)) 2543 return false; 2544 } 2545 } 2546 return true; 2547} 2548 2549// Vector Push stores multiple extension registers to the stack. It also 2550// updates SP to point to the start of the stored data. 2551bool EmulateInstructionARM::EmulateVPUSH(const uint32_t opcode, 2552 const ARMEncoding encoding) { 2553#if 0 2554 // ARM pseudo code... 2555 if (ConditionPassed()) 2556 { 2557 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 2558 address = SP - imm32; 2559 SP = SP - imm32; 2560 if single_regs then 2561 for r = 0 to regs-1 2562 MemA[address,4] = S[d+r]; address = address+4; 2563 else 2564 for r = 0 to regs-1 2565 // Store as two word-aligned words in the correct order for 2566 // current endianness. 2567 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 2568 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 2569 address = address+8; 2570 } 2571#endif 2572 2573 bool success = false; 2574 if (ConditionPassed(opcode)) { 2575 const uint32_t addr_byte_size = GetAddressByteSize(); 2576 const addr_t sp = ReadCoreReg(SP_REG, &success); 2577 if (!success) 2578 return false; 2579 bool single_regs; 2580 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 2581 uint32_t imm32; // stack offset 2582 uint32_t regs; // number of registers 2583 switch (encoding) { 2584 case eEncodingT1: 2585 case eEncodingA1: 2586 single_regs = false; 2587 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 2588 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2589 // If UInt(imm8) is odd, see "FSTMX". 2590 regs = Bits32(opcode, 7, 0) / 2; 2591 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2592 if (regs == 0 || regs > 16 || (d + regs) > 32) 2593 return false; 2594 break; 2595 case eEncodingT2: 2596 case eEncodingA2: 2597 single_regs = true; 2598 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 2599 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2600 regs = Bits32(opcode, 7, 0); 2601 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2602 if (regs == 0 || regs > 16 || (d + regs) > 32) 2603 return false; 2604 break; 2605 default: 2606 return false; 2607 } 2608 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 2609 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 2610 addr_t sp_offset = imm32; 2611 addr_t addr = sp - sp_offset; 2612 uint32_t i; 2613 2614 EmulateInstruction::Context context; 2615 context.type = EmulateInstruction::eContextPushRegisterOnStack; 2616 2617 std::optional<RegisterInfo> sp_reg = 2618 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 2619 for (i = 0; i < regs; ++i) { 2620 std::optional<RegisterInfo> dwarf_reg = 2621 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i); 2622 context.SetRegisterToRegisterPlusOffset(*dwarf_reg, *sp_reg, addr - sp); 2623 // uint64_t to accommodate 64-bit registers. 2624 uint64_t reg_value = ReadRegisterUnsigned(*dwarf_reg, 0, &success); 2625 if (!success) 2626 return false; 2627 if (!MemAWrite(context, addr, reg_value, reg_byte_size)) 2628 return false; 2629 addr += reg_byte_size; 2630 } 2631 2632 context.type = EmulateInstruction::eContextAdjustStackPointer; 2633 context.SetImmediateSigned(-sp_offset); 2634 2635 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2636 LLDB_REGNUM_GENERIC_SP, sp - sp_offset)) 2637 return false; 2638 } 2639 return true; 2640} 2641 2642// Vector Pop loads multiple extension registers from the stack. It also 2643// updates SP to point just above the loaded data. 2644bool EmulateInstructionARM::EmulateVPOP(const uint32_t opcode, 2645 const ARMEncoding encoding) { 2646#if 0 2647 // ARM pseudo code... 2648 if (ConditionPassed()) 2649 { 2650 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13); 2651 address = SP; 2652 SP = SP + imm32; 2653 if single_regs then 2654 for r = 0 to regs-1 2655 S[d+r] = MemA[address,4]; address = address+4; 2656 else 2657 for r = 0 to regs-1 2658 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 2659 // Combine the word-aligned words in the correct order for 2660 // current endianness. 2661 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 2662 } 2663#endif 2664 2665 bool success = false; 2666 if (ConditionPassed(opcode)) { 2667 const uint32_t addr_byte_size = GetAddressByteSize(); 2668 const addr_t sp = ReadCoreReg(SP_REG, &success); 2669 if (!success) 2670 return false; 2671 bool single_regs; 2672 uint32_t d; // UInt(D:Vd) or UInt(Vd:D) starting register 2673 uint32_t imm32; // stack offset 2674 uint32_t regs; // number of registers 2675 switch (encoding) { 2676 case eEncodingT1: 2677 case eEncodingA1: 2678 single_regs = false; 2679 d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12); 2680 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2681 // If UInt(imm8) is odd, see "FLDMX". 2682 regs = Bits32(opcode, 7, 0) / 2; 2683 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2684 if (regs == 0 || regs > 16 || (d + regs) > 32) 2685 return false; 2686 break; 2687 case eEncodingT2: 2688 case eEncodingA2: 2689 single_regs = true; 2690 d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22); 2691 imm32 = Bits32(opcode, 7, 0) * addr_byte_size; 2692 regs = Bits32(opcode, 7, 0); 2693 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 2694 if (regs == 0 || regs > 16 || (d + regs) > 32) 2695 return false; 2696 break; 2697 default: 2698 return false; 2699 } 2700 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 2701 uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2; 2702 addr_t sp_offset = imm32; 2703 addr_t addr = sp; 2704 uint32_t i; 2705 uint64_t data; // uint64_t to accommodate 64-bit registers. 2706 2707 EmulateInstruction::Context context; 2708 context.type = EmulateInstruction::eContextPopRegisterOffStack; 2709 2710 for (i = 0; i < regs; ++i) { 2711 std::optional<RegisterInfo> dwarf_reg = 2712 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + i); 2713 context.SetAddress(addr); 2714 data = MemARead(context, addr, reg_byte_size, 0, &success); 2715 if (!success) 2716 return false; 2717 if (!WriteRegisterUnsigned(context, *dwarf_reg, data)) 2718 return false; 2719 addr += reg_byte_size; 2720 } 2721 2722 context.type = EmulateInstruction::eContextAdjustStackPointer; 2723 context.SetImmediateSigned(sp_offset); 2724 2725 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2726 LLDB_REGNUM_GENERIC_SP, sp + sp_offset)) 2727 return false; 2728 } 2729 return true; 2730} 2731 2732// SVC (previously SWI) 2733bool EmulateInstructionARM::EmulateSVC(const uint32_t opcode, 2734 const ARMEncoding encoding) { 2735#if 0 2736 // ARM pseudo code... 2737 if (ConditionPassed()) 2738 { 2739 EncodingSpecificOperations(); 2740 CallSupervisor(); 2741 } 2742#endif 2743 2744 bool success = false; 2745 2746 if (ConditionPassed(opcode)) { 2747 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2748 addr_t lr; // next instruction address 2749 if (!success) 2750 return false; 2751 uint32_t imm32; // the immediate constant 2752 uint32_t mode; // ARM or Thumb mode 2753 switch (encoding) { 2754 case eEncodingT1: 2755 lr = (pc + 2) | 1u; // return address 2756 imm32 = Bits32(opcode, 7, 0); 2757 mode = eModeThumb; 2758 break; 2759 case eEncodingA1: 2760 lr = pc + 4; // return address 2761 imm32 = Bits32(opcode, 23, 0); 2762 mode = eModeARM; 2763 break; 2764 default: 2765 return false; 2766 } 2767 2768 EmulateInstruction::Context context; 2769 context.type = EmulateInstruction::eContextSupervisorCall; 2770 context.SetISAAndImmediate(mode, imm32); 2771 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 2772 LLDB_REGNUM_GENERIC_RA, lr)) 2773 return false; 2774 } 2775 return true; 2776} 2777 2778// If Then makes up to four following instructions (the IT block) conditional. 2779bool EmulateInstructionARM::EmulateIT(const uint32_t opcode, 2780 const ARMEncoding encoding) { 2781#if 0 2782 // ARM pseudo code... 2783 EncodingSpecificOperations(); 2784 ITSTATE.IT<7:0> = firstcond:mask; 2785#endif 2786 2787 m_it_session.InitIT(Bits32(opcode, 7, 0)); 2788 return true; 2789} 2790 2791bool EmulateInstructionARM::EmulateNop(const uint32_t opcode, 2792 const ARMEncoding encoding) { 2793 // NOP, nothing to do... 2794 return true; 2795} 2796 2797// Branch causes a branch to a target address. 2798bool EmulateInstructionARM::EmulateB(const uint32_t opcode, 2799 const ARMEncoding encoding) { 2800#if 0 2801 // ARM pseudo code... 2802 if (ConditionPassed()) 2803 { 2804 EncodingSpecificOperations(); 2805 BranchWritePC(PC + imm32); 2806 } 2807#endif 2808 2809 bool success = false; 2810 2811 if (ConditionPassed(opcode)) { 2812 EmulateInstruction::Context context; 2813 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2814 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2815 if (!success) 2816 return false; 2817 addr_t target; // target address 2818 int32_t imm32; // PC-relative offset 2819 switch (encoding) { 2820 case eEncodingT1: 2821 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2822 imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1); 2823 target = pc + imm32; 2824 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2825 break; 2826 case eEncodingT2: 2827 imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1); 2828 target = pc + imm32; 2829 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2830 break; 2831 case eEncodingT3: 2832 // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). 2833 { 2834 if (Bits32(opcode, 25, 23) == 7) 2835 return false; // See Branches and miscellaneous control on page 2836 // A6-235. 2837 2838 uint32_t S = Bit32(opcode, 26); 2839 uint32_t imm6 = Bits32(opcode, 21, 16); 2840 uint32_t J1 = Bit32(opcode, 13); 2841 uint32_t J2 = Bit32(opcode, 11); 2842 uint32_t imm11 = Bits32(opcode, 10, 0); 2843 uint32_t imm21 = 2844 (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1); 2845 imm32 = llvm::SignExtend32<21>(imm21); 2846 target = pc + imm32; 2847 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2848 break; 2849 } 2850 case eEncodingT4: { 2851 uint32_t S = Bit32(opcode, 26); 2852 uint32_t imm10 = Bits32(opcode, 25, 16); 2853 uint32_t J1 = Bit32(opcode, 13); 2854 uint32_t J2 = Bit32(opcode, 11); 2855 uint32_t imm11 = Bits32(opcode, 10, 0); 2856 uint32_t I1 = !(J1 ^ S); 2857 uint32_t I2 = !(J2 ^ S); 2858 uint32_t imm25 = 2859 (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1); 2860 imm32 = llvm::SignExtend32<25>(imm25); 2861 target = pc + imm32; 2862 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2863 break; 2864 } 2865 case eEncodingA1: 2866 imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2); 2867 target = pc + imm32; 2868 context.SetISAAndImmediateSigned(eModeARM, 8 + imm32); 2869 break; 2870 default: 2871 return false; 2872 } 2873 if (!BranchWritePC(context, target)) 2874 return false; 2875 } 2876 return true; 2877} 2878 2879// Compare and Branch on Nonzero and Compare and Branch on Zero compare the 2880// value in a register with zero and conditionally branch forward a constant 2881// value. They do not affect the condition flags. CBNZ, CBZ 2882bool EmulateInstructionARM::EmulateCB(const uint32_t opcode, 2883 const ARMEncoding encoding) { 2884#if 0 2885 // ARM pseudo code... 2886 EncodingSpecificOperations(); 2887 if nonzero ^ IsZero(R[n]) then 2888 BranchWritePC(PC + imm32); 2889#endif 2890 2891 bool success = false; 2892 2893 // Read the register value from the operand register Rn. 2894 uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success); 2895 if (!success) 2896 return false; 2897 2898 EmulateInstruction::Context context; 2899 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2900 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2901 if (!success) 2902 return false; 2903 2904 addr_t target; // target address 2905 uint32_t imm32; // PC-relative offset to branch forward 2906 bool nonzero; 2907 switch (encoding) { 2908 case eEncodingT1: 2909 imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1; 2910 nonzero = BitIsSet(opcode, 11); 2911 target = pc + imm32; 2912 context.SetISAAndImmediateSigned(eModeThumb, 4 + imm32); 2913 break; 2914 default: 2915 return false; 2916 } 2917 if (m_ignore_conditions || (nonzero ^ (reg_val == 0))) 2918 if (!BranchWritePC(context, target)) 2919 return false; 2920 2921 return true; 2922} 2923 2924// Table Branch Byte causes a PC-relative forward branch using a table of 2925// single byte offsets. 2926// A base register provides a pointer to the table, and a second register 2927// supplies an index into the table. 2928// The branch length is twice the value of the byte returned from the table. 2929// 2930// Table Branch Halfword causes a PC-relative forward branch using a table of 2931// single halfword offsets. 2932// A base register provides a pointer to the table, and a second register 2933// supplies an index into the table. 2934// The branch length is twice the value of the halfword returned from the 2935// table. TBB, TBH 2936bool EmulateInstructionARM::EmulateTB(const uint32_t opcode, 2937 const ARMEncoding encoding) { 2938#if 0 2939 // ARM pseudo code... 2940 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 2941 if is_tbh then 2942 halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]); 2943 else 2944 halfwords = UInt(MemU[R[n]+R[m], 1]); 2945 BranchWritePC(PC + 2*halfwords); 2946#endif 2947 2948 bool success = false; 2949 2950 if (ConditionPassed(opcode)) { 2951 uint32_t Rn; // the base register which contains the address of the table of 2952 // branch lengths 2953 uint32_t Rm; // the index register which contains an integer pointing to a 2954 // byte/halfword in the table 2955 bool is_tbh; // true if table branch halfword 2956 switch (encoding) { 2957 case eEncodingT1: 2958 Rn = Bits32(opcode, 19, 16); 2959 Rm = Bits32(opcode, 3, 0); 2960 is_tbh = BitIsSet(opcode, 4); 2961 if (Rn == 13 || BadReg(Rm)) 2962 return false; 2963 if (InITBlock() && !LastInITBlock()) 2964 return false; 2965 break; 2966 default: 2967 return false; 2968 } 2969 2970 // Read the address of the table from the operand register Rn. The PC can 2971 // be used, in which case the table immediately follows this instruction. 2972 uint32_t base = ReadCoreReg(Rn, &success); 2973 if (!success) 2974 return false; 2975 2976 // the table index 2977 uint32_t index = ReadCoreReg(Rm, &success); 2978 if (!success) 2979 return false; 2980 2981 // the offsetted table address 2982 addr_t addr = base + (is_tbh ? index * 2 : index); 2983 2984 // PC-relative offset to branch forward 2985 EmulateInstruction::Context context; 2986 context.type = EmulateInstruction::eContextTableBranchReadMemory; 2987 uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; 2988 if (!success) 2989 return false; 2990 2991 const uint32_t pc = ReadCoreReg(PC_REG, &success); 2992 if (!success) 2993 return false; 2994 2995 // target address 2996 addr_t target = pc + offset; 2997 context.type = EmulateInstruction::eContextRelativeBranchImmediate; 2998 context.SetISAAndImmediateSigned(eModeThumb, 4 + offset); 2999 3000 if (!BranchWritePC(context, target)) 3001 return false; 3002 } 3003 3004 return true; 3005} 3006 3007// This instruction adds an immediate value to a register value, and writes the 3008// result to the destination register. It can optionally update the condition 3009// flags based on the result. 3010bool EmulateInstructionARM::EmulateADDImmThumb(const uint32_t opcode, 3011 const ARMEncoding encoding) { 3012#if 0 3013 if ConditionPassed() then 3014 EncodingSpecificOperations(); 3015 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 3016 R[d] = result; 3017 if setflags then 3018 APSR.N = result<31>; 3019 APSR.Z = IsZeroBit(result); 3020 APSR.C = carry; 3021 APSR.V = overflow; 3022#endif 3023 3024 bool success = false; 3025 3026 if (ConditionPassed(opcode)) { 3027 uint32_t d; 3028 uint32_t n; 3029 bool setflags; 3030 uint32_t imm32; 3031 uint32_t carry_out; 3032 3033 // EncodingSpecificOperations(); 3034 switch (encoding) { 3035 case eEncodingT1: 3036 // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = 3037 // ZeroExtend(imm3, 32); 3038 d = Bits32(opcode, 2, 0); 3039 n = Bits32(opcode, 5, 3); 3040 setflags = !InITBlock(); 3041 imm32 = Bits32(opcode, 8, 6); 3042 3043 break; 3044 3045 case eEncodingT2: 3046 // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = 3047 // ZeroExtend(imm8, 32); 3048 d = Bits32(opcode, 10, 8); 3049 n = Bits32(opcode, 10, 8); 3050 setflags = !InITBlock(); 3051 imm32 = Bits32(opcode, 7, 0); 3052 3053 break; 3054 3055 case eEncodingT3: 3056 // if Rd == '1111' && S == '1' then SEE CMN (immediate); 3057 // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = 3058 // ThumbExpandImm(i:imm3:imm8); 3059 d = Bits32(opcode, 11, 8); 3060 n = Bits32(opcode, 19, 16); 3061 setflags = BitIsSet(opcode, 20); 3062 imm32 = ThumbExpandImm_C(opcode, APSR_C, carry_out); 3063 3064 // if Rn == '1101' then SEE ADD (SP plus immediate); 3065 if (n == 13) 3066 return EmulateADDSPImm(opcode, eEncodingT3); 3067 3068 // if BadReg(d) || n == 15 then UNPREDICTABLE; 3069 if (BadReg(d) || (n == 15)) 3070 return false; 3071 3072 break; 3073 3074 case eEncodingT4: { 3075 // if Rn == '1111' then SEE ADR; 3076 // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = 3077 // ZeroExtend(i:imm3:imm8, 32); 3078 d = Bits32(opcode, 11, 8); 3079 n = Bits32(opcode, 19, 16); 3080 setflags = false; 3081 uint32_t i = Bit32(opcode, 26); 3082 uint32_t imm3 = Bits32(opcode, 14, 12); 3083 uint32_t imm8 = Bits32(opcode, 7, 0); 3084 imm32 = (i << 11) | (imm3 << 8) | imm8; 3085 3086 // if Rn == '1101' then SEE ADD (SP plus immediate); 3087 if (n == 13) 3088 return EmulateADDSPImm(opcode, eEncodingT4); 3089 3090 // if BadReg(d) then UNPREDICTABLE; 3091 if (BadReg(d)) 3092 return false; 3093 3094 break; 3095 } 3096 3097 default: 3098 return false; 3099 } 3100 3101 uint64_t Rn = 3102 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3103 if (!success) 3104 return false; 3105 3106 //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 3107 AddWithCarryResult res = AddWithCarry(Rn, imm32, 0); 3108 3109 std::optional<RegisterInfo> reg_n = 3110 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 3111 EmulateInstruction::Context context; 3112 context.type = eContextArithmetic; 3113 context.SetRegisterPlusOffset(*reg_n, imm32); 3114 3115 // R[d] = result; 3116 // if setflags then 3117 // APSR.N = result<31>; 3118 // APSR.Z = IsZeroBit(result); 3119 // APSR.C = carry; 3120 // APSR.V = overflow; 3121 if (!WriteCoreRegOptionalFlags(context, res.result, d, setflags, 3122 res.carry_out, res.overflow)) 3123 return false; 3124 } 3125 return true; 3126} 3127 3128// This instruction adds an immediate value to a register value, and writes the 3129// result to the destination register. It can optionally update the condition 3130// flags based on the result. 3131bool EmulateInstructionARM::EmulateADDImmARM(const uint32_t opcode, 3132 const ARMEncoding encoding) { 3133#if 0 3134 // ARM pseudo code... 3135 if ConditionPassed() then 3136 EncodingSpecificOperations(); 3137 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 3138 if d == 15 then 3139 ALUWritePC(result); // setflags is always FALSE here 3140 else 3141 R[d] = result; 3142 if setflags then 3143 APSR.N = result<31>; 3144 APSR.Z = IsZeroBit(result); 3145 APSR.C = carry; 3146 APSR.V = overflow; 3147#endif 3148 3149 bool success = false; 3150 3151 if (ConditionPassed(opcode)) { 3152 uint32_t Rd, Rn; 3153 uint32_t 3154 imm32; // the immediate value to be added to the value obtained from Rn 3155 bool setflags; 3156 switch (encoding) { 3157 case eEncodingA1: 3158 Rd = Bits32(opcode, 15, 12); 3159 Rn = Bits32(opcode, 19, 16); 3160 setflags = BitIsSet(opcode, 20); 3161 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 3162 break; 3163 default: 3164 return false; 3165 } 3166 3167 // Read the first operand. 3168 uint32_t val1 = ReadCoreReg(Rn, &success); 3169 if (!success) 3170 return false; 3171 3172 AddWithCarryResult res = AddWithCarry(val1, imm32, 0); 3173 3174 EmulateInstruction::Context context; 3175 if (Rd == 13) 3176 context.type = EmulateInstruction::eContextAdjustStackPointer; 3177 else if (Rd == GetFramePointerRegisterNumber()) 3178 context.type = EmulateInstruction::eContextSetFramePointer; 3179 else 3180 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3181 3182 std::optional<RegisterInfo> dwarf_reg = 3183 GetRegisterInfo(eRegisterKindDWARF, Rn); 3184 context.SetRegisterPlusOffset(*dwarf_reg, imm32); 3185 3186 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 3187 res.carry_out, res.overflow)) 3188 return false; 3189 } 3190 return true; 3191} 3192 3193// This instruction adds a register value and an optionally-shifted register 3194// value, and writes the result to the destination register. It can optionally 3195// update the condition flags based on the result. 3196bool EmulateInstructionARM::EmulateADDReg(const uint32_t opcode, 3197 const ARMEncoding encoding) { 3198#if 0 3199 // ARM pseudo code... 3200 if ConditionPassed() then 3201 EncodingSpecificOperations(); 3202 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 3203 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 3204 if d == 15 then 3205 ALUWritePC(result); // setflags is always FALSE here 3206 else 3207 R[d] = result; 3208 if setflags then 3209 APSR.N = result<31>; 3210 APSR.Z = IsZeroBit(result); 3211 APSR.C = carry; 3212 APSR.V = overflow; 3213#endif 3214 3215 bool success = false; 3216 3217 if (ConditionPassed(opcode)) { 3218 uint32_t Rd, Rn, Rm; 3219 ARM_ShifterType shift_t; 3220 uint32_t shift_n; // the shift applied to the value read from Rm 3221 bool setflags; 3222 switch (encoding) { 3223 case eEncodingT1: 3224 Rd = Bits32(opcode, 2, 0); 3225 Rn = Bits32(opcode, 5, 3); 3226 Rm = Bits32(opcode, 8, 6); 3227 setflags = !InITBlock(); 3228 shift_t = SRType_LSL; 3229 shift_n = 0; 3230 break; 3231 case eEncodingT2: 3232 Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 3233 Rm = Bits32(opcode, 6, 3); 3234 setflags = false; 3235 shift_t = SRType_LSL; 3236 shift_n = 0; 3237 if (Rn == 15 && Rm == 15) 3238 return false; 3239 if (Rd == 15 && InITBlock() && !LastInITBlock()) 3240 return false; 3241 break; 3242 case eEncodingA1: 3243 Rd = Bits32(opcode, 15, 12); 3244 Rn = Bits32(opcode, 19, 16); 3245 Rm = Bits32(opcode, 3, 0); 3246 setflags = BitIsSet(opcode, 20); 3247 shift_n = DecodeImmShiftARM(opcode, shift_t); 3248 break; 3249 default: 3250 return false; 3251 } 3252 3253 // Read the first operand. 3254 uint32_t val1 = ReadCoreReg(Rn, &success); 3255 if (!success) 3256 return false; 3257 3258 // Read the second operand. 3259 uint32_t val2 = ReadCoreReg(Rm, &success); 3260 if (!success) 3261 return false; 3262 3263 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 3264 if (!success) 3265 return false; 3266 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 3267 3268 EmulateInstruction::Context context; 3269 context.type = eContextArithmetic; 3270 std::optional<RegisterInfo> op1_reg = 3271 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn); 3272 std::optional<RegisterInfo> op2_reg = 3273 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rm); 3274 context.SetRegisterRegisterOperands(*op1_reg, *op2_reg); 3275 3276 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 3277 res.carry_out, res.overflow)) 3278 return false; 3279 } 3280 return true; 3281} 3282 3283// Compare Negative (immediate) adds a register value and an immediate value. 3284// It updates the condition flags based on the result, and discards the result. 3285bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode, 3286 const ARMEncoding encoding) { 3287#if 0 3288 // ARM pseudo code... 3289 if ConditionPassed() then 3290 EncodingSpecificOperations(); 3291 (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 3292 APSR.N = result<31>; 3293 APSR.Z = IsZeroBit(result); 3294 APSR.C = carry; 3295 APSR.V = overflow; 3296#endif 3297 3298 bool success = false; 3299 3300 uint32_t Rn; // the first operand 3301 uint32_t imm32; // the immediate value to be compared with 3302 switch (encoding) { 3303 case eEncodingT1: 3304 Rn = Bits32(opcode, 19, 16); 3305 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 3306 if (Rn == 15) 3307 return false; 3308 break; 3309 case eEncodingA1: 3310 Rn = Bits32(opcode, 19, 16); 3311 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 3312 break; 3313 default: 3314 return false; 3315 } 3316 // Read the register value from the operand register Rn. 3317 uint32_t reg_val = ReadCoreReg(Rn, &success); 3318 if (!success) 3319 return false; 3320 3321 AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0); 3322 3323 EmulateInstruction::Context context; 3324 context.type = EmulateInstruction::eContextImmediate; 3325 context.SetNoArgs(); 3326 return WriteFlags(context, res.result, res.carry_out, res.overflow); 3327} 3328 3329// Compare Negative (register) adds a register value and an optionally-shifted 3330// register value. It updates the condition flags based on the result, and 3331// discards the result. 3332bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode, 3333 const ARMEncoding encoding) { 3334#if 0 3335 // ARM pseudo code... 3336 if ConditionPassed() then 3337 EncodingSpecificOperations(); 3338 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 3339 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 3340 APSR.N = result<31>; 3341 APSR.Z = IsZeroBit(result); 3342 APSR.C = carry; 3343 APSR.V = overflow; 3344#endif 3345 3346 bool success = false; 3347 3348 uint32_t Rn; // the first operand 3349 uint32_t Rm; // the second operand 3350 ARM_ShifterType shift_t; 3351 uint32_t shift_n; // the shift applied to the value read from Rm 3352 switch (encoding) { 3353 case eEncodingT1: 3354 Rn = Bits32(opcode, 2, 0); 3355 Rm = Bits32(opcode, 5, 3); 3356 shift_t = SRType_LSL; 3357 shift_n = 0; 3358 break; 3359 case eEncodingT2: 3360 Rn = Bits32(opcode, 19, 16); 3361 Rm = Bits32(opcode, 3, 0); 3362 shift_n = DecodeImmShiftThumb(opcode, shift_t); 3363 // if n == 15 || BadReg(m) then UNPREDICTABLE; 3364 if (Rn == 15 || BadReg(Rm)) 3365 return false; 3366 break; 3367 case eEncodingA1: 3368 Rn = Bits32(opcode, 19, 16); 3369 Rm = Bits32(opcode, 3, 0); 3370 shift_n = DecodeImmShiftARM(opcode, shift_t); 3371 break; 3372 default: 3373 return false; 3374 } 3375 // Read the register value from register Rn. 3376 uint32_t val1 = ReadCoreReg(Rn, &success); 3377 if (!success) 3378 return false; 3379 3380 // Read the register value from register Rm. 3381 uint32_t val2 = ReadCoreReg(Rm, &success); 3382 if (!success) 3383 return false; 3384 3385 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 3386 if (!success) 3387 return false; 3388 AddWithCarryResult res = AddWithCarry(val1, shifted, 0); 3389 3390 EmulateInstruction::Context context; 3391 context.type = EmulateInstruction::eContextImmediate; 3392 context.SetNoArgs(); 3393 return WriteFlags(context, res.result, res.carry_out, res.overflow); 3394} 3395 3396// Compare (immediate) subtracts an immediate value from a register value. It 3397// updates the condition flags based on the result, and discards the result. 3398bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode, 3399 const ARMEncoding encoding) { 3400#if 0 3401 // ARM pseudo code... 3402 if ConditionPassed() then 3403 EncodingSpecificOperations(); 3404 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 3405 APSR.N = result<31>; 3406 APSR.Z = IsZeroBit(result); 3407 APSR.C = carry; 3408 APSR.V = overflow; 3409#endif 3410 3411 bool success = false; 3412 3413 uint32_t Rn; // the first operand 3414 uint32_t imm32; // the immediate value to be compared with 3415 switch (encoding) { 3416 case eEncodingT1: 3417 Rn = Bits32(opcode, 10, 8); 3418 imm32 = Bits32(opcode, 7, 0); 3419 break; 3420 case eEncodingT2: 3421 Rn = Bits32(opcode, 19, 16); 3422 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 3423 if (Rn == 15) 3424 return false; 3425 break; 3426 case eEncodingA1: 3427 Rn = Bits32(opcode, 19, 16); 3428 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 3429 break; 3430 default: 3431 return false; 3432 } 3433 // Read the register value from the operand register Rn. 3434 uint32_t reg_val = ReadCoreReg(Rn, &success); 3435 if (!success) 3436 return false; 3437 3438 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 3439 3440 EmulateInstruction::Context context; 3441 context.type = EmulateInstruction::eContextImmediate; 3442 context.SetNoArgs(); 3443 return WriteFlags(context, res.result, res.carry_out, res.overflow); 3444} 3445 3446// Compare (register) subtracts an optionally-shifted register value from a 3447// register value. It updates the condition flags based on the result, and 3448// discards the result. 3449bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode, 3450 const ARMEncoding encoding) { 3451#if 0 3452 // ARM pseudo code... 3453 if ConditionPassed() then 3454 EncodingSpecificOperations(); 3455 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 3456 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 3457 APSR.N = result<31>; 3458 APSR.Z = IsZeroBit(result); 3459 APSR.C = carry; 3460 APSR.V = overflow; 3461#endif 3462 3463 bool success = false; 3464 3465 uint32_t Rn; // the first operand 3466 uint32_t Rm; // the second operand 3467 ARM_ShifterType shift_t; 3468 uint32_t shift_n; // the shift applied to the value read from Rm 3469 switch (encoding) { 3470 case eEncodingT1: 3471 Rn = Bits32(opcode, 2, 0); 3472 Rm = Bits32(opcode, 5, 3); 3473 shift_t = SRType_LSL; 3474 shift_n = 0; 3475 break; 3476 case eEncodingT2: 3477 Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0); 3478 Rm = Bits32(opcode, 6, 3); 3479 shift_t = SRType_LSL; 3480 shift_n = 0; 3481 if (Rn < 8 && Rm < 8) 3482 return false; 3483 if (Rn == 15 || Rm == 15) 3484 return false; 3485 break; 3486 case eEncodingT3: 3487 Rn = Bits32(opcode, 19, 16); 3488 Rm = Bits32(opcode, 3, 0); 3489 shift_n = DecodeImmShiftThumb(opcode, shift_t); 3490 if (Rn == 15 || BadReg(Rm)) 3491 return false; 3492 break; 3493 case eEncodingA1: 3494 Rn = Bits32(opcode, 19, 16); 3495 Rm = Bits32(opcode, 3, 0); 3496 shift_n = DecodeImmShiftARM(opcode, shift_t); 3497 break; 3498 default: 3499 return false; 3500 } 3501 // Read the register value from register Rn. 3502 uint32_t val1 = ReadCoreReg(Rn, &success); 3503 if (!success) 3504 return false; 3505 3506 // Read the register value from register Rm. 3507 uint32_t val2 = ReadCoreReg(Rm, &success); 3508 if (!success) 3509 return false; 3510 3511 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 3512 if (!success) 3513 return false; 3514 AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1); 3515 3516 EmulateInstruction::Context context; 3517 context.type = EmulateInstruction::eContextImmediate; 3518 context.SetNoArgs(); 3519 return WriteFlags(context, res.result, res.carry_out, res.overflow); 3520} 3521 3522// Arithmetic Shift Right (immediate) shifts a register value right by an 3523// immediate number of bits, shifting in copies of its sign bit, and writes the 3524// result to the destination register. It can optionally update the condition 3525// flags based on the result. 3526bool EmulateInstructionARM::EmulateASRImm(const uint32_t opcode, 3527 const ARMEncoding encoding) { 3528#if 0 3529 // ARM pseudo code... 3530 if ConditionPassed() then 3531 EncodingSpecificOperations(); 3532 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 3533 if d == 15 then // Can only occur for ARM encoding 3534 ALUWritePC(result); // setflags is always FALSE here 3535 else 3536 R[d] = result; 3537 if setflags then 3538 APSR.N = result<31>; 3539 APSR.Z = IsZeroBit(result); 3540 APSR.C = carry; 3541 // APSR.V unchanged 3542#endif 3543 3544 return EmulateShiftImm(opcode, encoding, SRType_ASR); 3545} 3546 3547// Arithmetic Shift Right (register) shifts a register value right by a 3548// variable number of bits, shifting in copies of its sign bit, and writes the 3549// result to the destination register. The variable number of bits is read from 3550// the bottom byte of a register. It can optionally update the condition flags 3551// based on the result. 3552bool EmulateInstructionARM::EmulateASRReg(const uint32_t opcode, 3553 const ARMEncoding encoding) { 3554#if 0 3555 // ARM pseudo code... 3556 if ConditionPassed() then 3557 EncodingSpecificOperations(); 3558 shift_n = UInt(R[m]<7:0>); 3559 (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C); 3560 R[d] = result; 3561 if setflags then 3562 APSR.N = result<31>; 3563 APSR.Z = IsZeroBit(result); 3564 APSR.C = carry; 3565 // APSR.V unchanged 3566#endif 3567 3568 return EmulateShiftReg(opcode, encoding, SRType_ASR); 3569} 3570 3571// Logical Shift Left (immediate) shifts a register value left by an immediate 3572// number of bits, shifting in zeros, and writes the result to the destination 3573// register. It can optionally update the condition flags based on the result. 3574bool EmulateInstructionARM::EmulateLSLImm(const uint32_t opcode, 3575 const ARMEncoding encoding) { 3576#if 0 3577 // ARM pseudo code... 3578 if ConditionPassed() then 3579 EncodingSpecificOperations(); 3580 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 3581 if d == 15 then // Can only occur for ARM encoding 3582 ALUWritePC(result); // setflags is always FALSE here 3583 else 3584 R[d] = result; 3585 if setflags then 3586 APSR.N = result<31>; 3587 APSR.Z = IsZeroBit(result); 3588 APSR.C = carry; 3589 // APSR.V unchanged 3590#endif 3591 3592 return EmulateShiftImm(opcode, encoding, SRType_LSL); 3593} 3594 3595// Logical Shift Left (register) shifts a register value left by a variable 3596// number of bits, shifting in zeros, and writes the result to the destination 3597// register. The variable number of bits is read from the bottom byte of a 3598// register. It can optionally update the condition flags based on the result. 3599bool EmulateInstructionARM::EmulateLSLReg(const uint32_t opcode, 3600 const ARMEncoding encoding) { 3601#if 0 3602 // ARM pseudo code... 3603 if ConditionPassed() then 3604 EncodingSpecificOperations(); 3605 shift_n = UInt(R[m]<7:0>); 3606 (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C); 3607 R[d] = result; 3608 if setflags then 3609 APSR.N = result<31>; 3610 APSR.Z = IsZeroBit(result); 3611 APSR.C = carry; 3612 // APSR.V unchanged 3613#endif 3614 3615 return EmulateShiftReg(opcode, encoding, SRType_LSL); 3616} 3617 3618// Logical Shift Right (immediate) shifts a register value right by an 3619// immediate number of bits, shifting in zeros, and writes the result to the 3620// destination register. It can optionally update the condition flags based on 3621// the result. 3622bool EmulateInstructionARM::EmulateLSRImm(const uint32_t opcode, 3623 const ARMEncoding encoding) { 3624#if 0 3625 // ARM pseudo code... 3626 if ConditionPassed() then 3627 EncodingSpecificOperations(); 3628 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 3629 if d == 15 then // Can only occur for ARM encoding 3630 ALUWritePC(result); // setflags is always FALSE here 3631 else 3632 R[d] = result; 3633 if setflags then 3634 APSR.N = result<31>; 3635 APSR.Z = IsZeroBit(result); 3636 APSR.C = carry; 3637 // APSR.V unchanged 3638#endif 3639 3640 return EmulateShiftImm(opcode, encoding, SRType_LSR); 3641} 3642 3643// Logical Shift Right (register) shifts a register value right by a variable 3644// number of bits, shifting in zeros, and writes the result to the destination 3645// register. The variable number of bits is read from the bottom byte of a 3646// register. It can optionally update the condition flags based on the result. 3647bool EmulateInstructionARM::EmulateLSRReg(const uint32_t opcode, 3648 const ARMEncoding encoding) { 3649#if 0 3650 // ARM pseudo code... 3651 if ConditionPassed() then 3652 EncodingSpecificOperations(); 3653 shift_n = UInt(R[m]<7:0>); 3654 (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C); 3655 R[d] = result; 3656 if setflags then 3657 APSR.N = result<31>; 3658 APSR.Z = IsZeroBit(result); 3659 APSR.C = carry; 3660 // APSR.V unchanged 3661#endif 3662 3663 return EmulateShiftReg(opcode, encoding, SRType_LSR); 3664} 3665 3666// Rotate Right (immediate) provides the value of the contents of a register 3667// rotated by a constant value. The bits that are rotated off the right end are 3668// inserted into the vacated bit positions on the left. It can optionally 3669// update the condition flags based on the result. 3670bool EmulateInstructionARM::EmulateRORImm(const uint32_t opcode, 3671 const ARMEncoding encoding) { 3672#if 0 3673 // ARM pseudo code... 3674 if ConditionPassed() then 3675 EncodingSpecificOperations(); 3676 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 3677 if d == 15 then // Can only occur for ARM encoding 3678 ALUWritePC(result); // setflags is always FALSE here 3679 else 3680 R[d] = result; 3681 if setflags then 3682 APSR.N = result<31>; 3683 APSR.Z = IsZeroBit(result); 3684 APSR.C = carry; 3685 // APSR.V unchanged 3686#endif 3687 3688 return EmulateShiftImm(opcode, encoding, SRType_ROR); 3689} 3690 3691// Rotate Right (register) provides the value of the contents of a register 3692// rotated by a variable number of bits. The bits that are rotated off the 3693// right end are inserted into the vacated bit positions on the left. The 3694// variable number of bits is read from the bottom byte of a register. It can 3695// optionally update the condition flags based on the result. 3696bool EmulateInstructionARM::EmulateRORReg(const uint32_t opcode, 3697 const ARMEncoding encoding) { 3698#if 0 3699 // ARM pseudo code... 3700 if ConditionPassed() then 3701 EncodingSpecificOperations(); 3702 shift_n = UInt(R[m]<7:0>); 3703 (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C); 3704 R[d] = result; 3705 if setflags then 3706 APSR.N = result<31>; 3707 APSR.Z = IsZeroBit(result); 3708 APSR.C = carry; 3709 // APSR.V unchanged 3710#endif 3711 3712 return EmulateShiftReg(opcode, encoding, SRType_ROR); 3713} 3714 3715// Rotate Right with Extend provides the value of the contents of a register 3716// shifted right by one place, with the carry flag shifted into bit [31]. 3717// 3718// RRX can optionally update the condition flags based on the result. 3719// In that case, bit [0] is shifted into the carry flag. 3720bool EmulateInstructionARM::EmulateRRX(const uint32_t opcode, 3721 const ARMEncoding encoding) { 3722#if 0 3723 // ARM pseudo code... 3724 if ConditionPassed() then 3725 EncodingSpecificOperations(); 3726 (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C); 3727 if d == 15 then // Can only occur for ARM encoding 3728 ALUWritePC(result); // setflags is always FALSE here 3729 else 3730 R[d] = result; 3731 if setflags then 3732 APSR.N = result<31>; 3733 APSR.Z = IsZeroBit(result); 3734 APSR.C = carry; 3735 // APSR.V unchanged 3736#endif 3737 3738 return EmulateShiftImm(opcode, encoding, SRType_RRX); 3739} 3740 3741bool EmulateInstructionARM::EmulateShiftImm(const uint32_t opcode, 3742 const ARMEncoding encoding, 3743 ARM_ShifterType shift_type) { 3744 // assert(shift_type == SRType_ASR 3745 // || shift_type == SRType_LSL 3746 // || shift_type == SRType_LSR 3747 // || shift_type == SRType_ROR 3748 // || shift_type == SRType_RRX); 3749 3750 bool success = false; 3751 3752 if (ConditionPassed(opcode)) { 3753 uint32_t Rd; // the destination register 3754 uint32_t Rm; // the first operand register 3755 uint32_t imm5; // encoding for the shift amount 3756 uint32_t carry; // the carry bit after the shift operation 3757 bool setflags; 3758 3759 // Special case handling! 3760 // A8.6.139 ROR (immediate) -- Encoding T1 3761 ARMEncoding use_encoding = encoding; 3762 if (shift_type == SRType_ROR && use_encoding == eEncodingT1) { 3763 // Morph the T1 encoding from the ARM Architecture Manual into T2 3764 // encoding to have the same decoding of bit fields as the other Thumb2 3765 // shift operations. 3766 use_encoding = eEncodingT2; 3767 } 3768 3769 switch (use_encoding) { 3770 case eEncodingT1: 3771 Rd = Bits32(opcode, 2, 0); 3772 Rm = Bits32(opcode, 5, 3); 3773 setflags = !InITBlock(); 3774 imm5 = Bits32(opcode, 10, 6); 3775 break; 3776 case eEncodingT2: 3777 // A8.6.141 RRX 3778 // There's no imm form of RRX instructions. 3779 if (shift_type == SRType_RRX) 3780 return false; 3781 3782 Rd = Bits32(opcode, 11, 8); 3783 Rm = Bits32(opcode, 3, 0); 3784 setflags = BitIsSet(opcode, 20); 3785 imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6); 3786 if (BadReg(Rd) || BadReg(Rm)) 3787 return false; 3788 break; 3789 case eEncodingA1: 3790 Rd = Bits32(opcode, 15, 12); 3791 Rm = Bits32(opcode, 3, 0); 3792 setflags = BitIsSet(opcode, 20); 3793 imm5 = Bits32(opcode, 11, 7); 3794 break; 3795 default: 3796 return false; 3797 } 3798 3799 // A8.6.139 ROR (immediate) 3800 if (shift_type == SRType_ROR && imm5 == 0) 3801 shift_type = SRType_RRX; 3802 3803 // Get the first operand. 3804 uint32_t value = ReadCoreReg(Rm, &success); 3805 if (!success) 3806 return false; 3807 3808 // Decode the shift amount if not RRX. 3809 uint32_t amt = 3810 (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5)); 3811 3812 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success); 3813 if (!success) 3814 return false; 3815 3816 // The context specifies that an immediate is to be moved into Rd. 3817 EmulateInstruction::Context context; 3818 context.type = EmulateInstruction::eContextImmediate; 3819 context.SetNoArgs(); 3820 3821 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3822 return false; 3823 } 3824 return true; 3825} 3826 3827bool EmulateInstructionARM::EmulateShiftReg(const uint32_t opcode, 3828 const ARMEncoding encoding, 3829 ARM_ShifterType shift_type) { 3830 // assert(shift_type == SRType_ASR 3831 // || shift_type == SRType_LSL 3832 // || shift_type == SRType_LSR 3833 // || shift_type == SRType_ROR); 3834 3835 bool success = false; 3836 3837 if (ConditionPassed(opcode)) { 3838 uint32_t Rd; // the destination register 3839 uint32_t Rn; // the first operand register 3840 uint32_t 3841 Rm; // the register whose bottom byte contains the amount to shift by 3842 uint32_t carry; // the carry bit after the shift operation 3843 bool setflags; 3844 switch (encoding) { 3845 case eEncodingT1: 3846 Rd = Bits32(opcode, 2, 0); 3847 Rn = Rd; 3848 Rm = Bits32(opcode, 5, 3); 3849 setflags = !InITBlock(); 3850 break; 3851 case eEncodingT2: 3852 Rd = Bits32(opcode, 11, 8); 3853 Rn = Bits32(opcode, 19, 16); 3854 Rm = Bits32(opcode, 3, 0); 3855 setflags = BitIsSet(opcode, 20); 3856 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 3857 return false; 3858 break; 3859 case eEncodingA1: 3860 Rd = Bits32(opcode, 15, 12); 3861 Rn = Bits32(opcode, 3, 0); 3862 Rm = Bits32(opcode, 11, 8); 3863 setflags = BitIsSet(opcode, 20); 3864 if (Rd == 15 || Rn == 15 || Rm == 15) 3865 return false; 3866 break; 3867 default: 3868 return false; 3869 } 3870 3871 // Get the first operand. 3872 uint32_t value = ReadCoreReg(Rn, &success); 3873 if (!success) 3874 return false; 3875 // Get the Rm register content. 3876 uint32_t val = ReadCoreReg(Rm, &success); 3877 if (!success) 3878 return false; 3879 3880 // Get the shift amount. 3881 uint32_t amt = Bits32(val, 7, 0); 3882 3883 uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success); 3884 if (!success) 3885 return false; 3886 3887 // The context specifies that an immediate is to be moved into Rd. 3888 EmulateInstruction::Context context; 3889 context.type = EmulateInstruction::eContextImmediate; 3890 context.SetNoArgs(); 3891 3892 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 3893 return false; 3894 } 3895 return true; 3896} 3897 3898// LDM loads multiple registers from consecutive memory locations, using an 3899// address from a base register. Optionally the address just above the highest 3900// of those locations can be written back to the base register. 3901bool EmulateInstructionARM::EmulateLDM(const uint32_t opcode, 3902 const ARMEncoding encoding) { 3903#if 0 3904 // ARM pseudo code... 3905 if ConditionPassed() 3906 EncodingSpecificOperations(); NullCheckIfThumbEE (n); 3907 address = R[n]; 3908 3909 for i = 0 to 14 3910 if registers<i> == '1' then 3911 R[i] = MemA[address, 4]; address = address + 4; 3912 if registers<15> == '1' then 3913 LoadWritePC (MemA[address, 4]); 3914 3915 if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers); 3916 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 3917 3918#endif 3919 3920 bool success = false; 3921 if (ConditionPassed(opcode)) { 3922 uint32_t n; 3923 uint32_t registers = 0; 3924 bool wback; 3925 const uint32_t addr_byte_size = GetAddressByteSize(); 3926 switch (encoding) { 3927 case eEncodingT1: 3928 // n = UInt(Rn); registers = '00000000':register_list; wback = 3929 // (registers<n> == '0'); 3930 n = Bits32(opcode, 10, 8); 3931 registers = Bits32(opcode, 7, 0); 3932 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 3933 wback = BitIsClear(registers, n); 3934 // if BitCount(registers) < 1 then UNPREDICTABLE; 3935 if (BitCount(registers) < 1) 3936 return false; 3937 break; 3938 case eEncodingT2: 3939 // if W == '1' && Rn == '1101' then SEE POP; 3940 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 3941 n = Bits32(opcode, 19, 16); 3942 registers = Bits32(opcode, 15, 0); 3943 registers = registers & 0xdfff; // Make sure bit 13 is zero. 3944 wback = BitIsSet(opcode, 21); 3945 3946 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then 3947 // UNPREDICTABLE; 3948 if ((n == 15) || (BitCount(registers) < 2) || 3949 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15))) 3950 return false; 3951 3952 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then 3953 // UNPREDICTABLE; 3954 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 3955 return false; 3956 3957 // if wback && registers<n> == '1' then UNPREDICTABLE; 3958 if (wback && BitIsSet(registers, n)) 3959 return false; 3960 break; 3961 3962 case eEncodingA1: 3963 n = Bits32(opcode, 19, 16); 3964 registers = Bits32(opcode, 15, 0); 3965 wback = BitIsSet(opcode, 21); 3966 if ((n == 15) || (BitCount(registers) < 1)) 3967 return false; 3968 break; 3969 default: 3970 return false; 3971 } 3972 3973 int32_t offset = 0; 3974 const addr_t base_address = 3975 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 3976 if (!success) 3977 return false; 3978 3979 EmulateInstruction::Context context; 3980 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3981 std::optional<RegisterInfo> dwarf_reg = 3982 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 3983 context.SetRegisterPlusOffset(*dwarf_reg, offset); 3984 3985 for (int i = 0; i < 14; ++i) { 3986 if (BitIsSet(registers, i)) { 3987 context.type = EmulateInstruction::eContextRegisterPlusOffset; 3988 context.SetRegisterPlusOffset(*dwarf_reg, offset); 3989 if (wback && (n == 13)) // Pop Instruction 3990 { 3991 context.type = EmulateInstruction::eContextPopRegisterOffStack; 3992 context.SetAddress(base_address + offset); 3993 } 3994 3995 // R[i] = MemA [address, 4]; address = address + 4; 3996 uint32_t data = MemARead(context, base_address + offset, addr_byte_size, 3997 0, &success); 3998 if (!success) 3999 return false; 4000 4001 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, 4002 data)) 4003 return false; 4004 4005 offset += addr_byte_size; 4006 } 4007 } 4008 4009 if (BitIsSet(registers, 15)) { 4010 // LoadWritePC (MemA [address, 4]); 4011 context.type = EmulateInstruction::eContextRegisterPlusOffset; 4012 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4013 uint32_t data = 4014 MemARead(context, base_address + offset, addr_byte_size, 0, &success); 4015 if (!success) 4016 return false; 4017 // In ARMv5T and above, this is an interworking branch. 4018 if (!LoadWritePC(context, data)) 4019 return false; 4020 } 4021 4022 if (wback && BitIsClear(registers, n)) { 4023 // R[n] = R[n] + 4 * BitCount (registers) 4024 int32_t offset = addr_byte_size * BitCount(registers); 4025 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4026 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4027 4028 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4029 base_address + offset)) 4030 return false; 4031 } 4032 if (wback && BitIsSet(registers, n)) 4033 // R[n] bits(32) UNKNOWN; 4034 return WriteBits32Unknown(n); 4035 } 4036 return true; 4037} 4038 4039// LDMDA loads multiple registers from consecutive memory locations using an 4040// address from a base register. 4041// The consecutive memory locations end at this address and the address just 4042// below the lowest of those locations can optionally be written back to the 4043// base register. 4044bool EmulateInstructionARM::EmulateLDMDA(const uint32_t opcode, 4045 const ARMEncoding encoding) { 4046#if 0 4047 // ARM pseudo code... 4048 if ConditionPassed() then 4049 EncodingSpecificOperations(); 4050 address = R[n] - 4*BitCount(registers) + 4; 4051 4052 for i = 0 to 14 4053 if registers<i> == '1' then 4054 R[i] = MemA[address,4]; address = address + 4; 4055 4056 if registers<15> == '1' then 4057 LoadWritePC(MemA[address,4]); 4058 4059 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 4060 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 4061#endif 4062 4063 bool success = false; 4064 4065 if (ConditionPassed(opcode)) { 4066 uint32_t n; 4067 uint32_t registers = 0; 4068 bool wback; 4069 const uint32_t addr_byte_size = GetAddressByteSize(); 4070 4071 // EncodingSpecificOperations(); 4072 switch (encoding) { 4073 case eEncodingA1: 4074 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4075 n = Bits32(opcode, 19, 16); 4076 registers = Bits32(opcode, 15, 0); 4077 wback = BitIsSet(opcode, 21); 4078 4079 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4080 if ((n == 15) || (BitCount(registers) < 1)) 4081 return false; 4082 4083 break; 4084 4085 default: 4086 return false; 4087 } 4088 // address = R[n] - 4*BitCount(registers) + 4; 4089 4090 int32_t offset = 0; 4091 addr_t Rn = ReadCoreReg(n, &success); 4092 4093 if (!success) 4094 return false; 4095 4096 addr_t address = 4097 Rn - (addr_byte_size * BitCount(registers)) + addr_byte_size; 4098 4099 EmulateInstruction::Context context; 4100 context.type = EmulateInstruction::eContextRegisterPlusOffset; 4101 std::optional<RegisterInfo> dwarf_reg = 4102 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4103 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4104 4105 // for i = 0 to 14 4106 for (int i = 0; i < 14; ++i) { 4107 // if registers<i> == '1' then 4108 if (BitIsSet(registers, i)) { 4109 // R[i] = MemA[address,4]; address = address + 4; 4110 context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset)); 4111 uint32_t data = 4112 MemARead(context, address + offset, addr_byte_size, 0, &success); 4113 if (!success) 4114 return false; 4115 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, 4116 data)) 4117 return false; 4118 offset += addr_byte_size; 4119 } 4120 } 4121 4122 // if registers<15> == '1' then 4123 // LoadWritePC(MemA[address,4]); 4124 if (BitIsSet(registers, 15)) { 4125 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4126 uint32_t data = 4127 MemARead(context, address + offset, addr_byte_size, 0, &success); 4128 if (!success) 4129 return false; 4130 // In ARMv5T and above, this is an interworking branch. 4131 if (!LoadWritePC(context, data)) 4132 return false; 4133 } 4134 4135 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 4136 if (wback && BitIsClear(registers, n)) { 4137 4138 offset = (addr_byte_size * BitCount(registers)) * -1; 4139 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4140 context.SetImmediateSigned(offset); 4141 addr_t addr = Rn + offset; 4142 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4143 addr)) 4144 return false; 4145 } 4146 4147 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 4148 if (wback && BitIsSet(registers, n)) 4149 return WriteBits32Unknown(n); 4150 } 4151 return true; 4152} 4153 4154// LDMDB loads multiple registers from consecutive memory locations using an 4155// address from a base register. The 4156// consecutive memory locations end just below this address, and the address of 4157// the lowest of those locations can be optionally written back to the base 4158// register. 4159bool EmulateInstructionARM::EmulateLDMDB(const uint32_t opcode, 4160 const ARMEncoding encoding) { 4161#if 0 4162 // ARM pseudo code... 4163 if ConditionPassed() then 4164 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4165 address = R[n] - 4*BitCount(registers); 4166 4167 for i = 0 to 14 4168 if registers<i> == '1' then 4169 R[i] = MemA[address,4]; address = address + 4; 4170 if registers<15> == '1' then 4171 LoadWritePC(MemA[address,4]); 4172 4173 if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 4174 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1 4175#endif 4176 4177 bool success = false; 4178 4179 if (ConditionPassed(opcode)) { 4180 uint32_t n; 4181 uint32_t registers = 0; 4182 bool wback; 4183 const uint32_t addr_byte_size = GetAddressByteSize(); 4184 switch (encoding) { 4185 case eEncodingT1: 4186 // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 4187 n = Bits32(opcode, 19, 16); 4188 registers = Bits32(opcode, 15, 0); 4189 registers = registers & 0xdfff; // Make sure bit 13 is a zero. 4190 wback = BitIsSet(opcode, 21); 4191 4192 // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then 4193 // UNPREDICTABLE; 4194 if ((n == 15) || (BitCount(registers) < 2) || 4195 (BitIsSet(opcode, 14) && BitIsSet(opcode, 15))) 4196 return false; 4197 4198 // if registers<15> == '1' && InITBlock() && !LastInITBlock() then 4199 // UNPREDICTABLE; 4200 if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock()) 4201 return false; 4202 4203 // if wback && registers<n> == '1' then UNPREDICTABLE; 4204 if (wback && BitIsSet(registers, n)) 4205 return false; 4206 4207 break; 4208 4209 case eEncodingA1: 4210 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4211 n = Bits32(opcode, 19, 16); 4212 registers = Bits32(opcode, 15, 0); 4213 wback = BitIsSet(opcode, 21); 4214 4215 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4216 if ((n == 15) || (BitCount(registers) < 1)) 4217 return false; 4218 4219 break; 4220 4221 default: 4222 return false; 4223 } 4224 4225 // address = R[n] - 4*BitCount(registers); 4226 4227 int32_t offset = 0; 4228 addr_t Rn = 4229 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4230 4231 if (!success) 4232 return false; 4233 4234 addr_t address = Rn - (addr_byte_size * BitCount(registers)); 4235 EmulateInstruction::Context context; 4236 context.type = EmulateInstruction::eContextRegisterPlusOffset; 4237 std::optional<RegisterInfo> dwarf_reg = 4238 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4239 context.SetRegisterPlusOffset(*dwarf_reg, Rn - address); 4240 4241 for (int i = 0; i < 14; ++i) { 4242 if (BitIsSet(registers, i)) { 4243 // R[i] = MemA[address,4]; address = address + 4; 4244 context.SetRegisterPlusOffset(*dwarf_reg, Rn - (address + offset)); 4245 uint32_t data = 4246 MemARead(context, address + offset, addr_byte_size, 0, &success); 4247 if (!success) 4248 return false; 4249 4250 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, 4251 data)) 4252 return false; 4253 4254 offset += addr_byte_size; 4255 } 4256 } 4257 4258 // if registers<15> == '1' then 4259 // LoadWritePC(MemA[address,4]); 4260 if (BitIsSet(registers, 15)) { 4261 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4262 uint32_t data = 4263 MemARead(context, address + offset, addr_byte_size, 0, &success); 4264 if (!success) 4265 return false; 4266 // In ARMv5T and above, this is an interworking branch. 4267 if (!LoadWritePC(context, data)) 4268 return false; 4269 } 4270 4271 // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 4272 if (wback && BitIsClear(registers, n)) { 4273 4274 offset = (addr_byte_size * BitCount(registers)) * -1; 4275 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4276 context.SetImmediateSigned(offset); 4277 addr_t addr = Rn + offset; 4278 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4279 addr)) 4280 return false; 4281 } 4282 4283 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only 4284 // possible for encoding A1 4285 if (wback && BitIsSet(registers, n)) 4286 return WriteBits32Unknown(n); 4287 } 4288 return true; 4289} 4290 4291// LDMIB loads multiple registers from consecutive memory locations using an 4292// address from a base register. The 4293// consecutive memory locations start just above this address, and thea ddress 4294// of the last of those locations can optinoally be written back to the base 4295// register. 4296bool EmulateInstructionARM::EmulateLDMIB(const uint32_t opcode, 4297 const ARMEncoding encoding) { 4298#if 0 4299 if ConditionPassed() then 4300 EncodingSpecificOperations(); 4301 address = R[n] + 4; 4302 4303 for i = 0 to 14 4304 if registers<i> == '1' then 4305 R[i] = MemA[address,4]; address = address + 4; 4306 if registers<15> == '1' then 4307 LoadWritePC(MemA[address,4]); 4308 4309 if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 4310 if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; 4311#endif 4312 4313 bool success = false; 4314 4315 if (ConditionPassed(opcode)) { 4316 uint32_t n; 4317 uint32_t registers = 0; 4318 bool wback; 4319 const uint32_t addr_byte_size = GetAddressByteSize(); 4320 switch (encoding) { 4321 case eEncodingA1: 4322 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4323 n = Bits32(opcode, 19, 16); 4324 registers = Bits32(opcode, 15, 0); 4325 wback = BitIsSet(opcode, 21); 4326 4327 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4328 if ((n == 15) || (BitCount(registers) < 1)) 4329 return false; 4330 4331 break; 4332 default: 4333 return false; 4334 } 4335 // address = R[n] + 4; 4336 4337 int32_t offset = 0; 4338 addr_t Rn = 4339 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4340 4341 if (!success) 4342 return false; 4343 4344 addr_t address = Rn + addr_byte_size; 4345 4346 EmulateInstruction::Context context; 4347 context.type = EmulateInstruction::eContextRegisterPlusOffset; 4348 std::optional<RegisterInfo> dwarf_reg = 4349 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4350 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4351 4352 for (int i = 0; i < 14; ++i) { 4353 if (BitIsSet(registers, i)) { 4354 // R[i] = MemA[address,4]; address = address + 4; 4355 4356 context.SetRegisterPlusOffset(*dwarf_reg, offset + addr_byte_size); 4357 uint32_t data = 4358 MemARead(context, address + offset, addr_byte_size, 0, &success); 4359 if (!success) 4360 return false; 4361 4362 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, 4363 data)) 4364 return false; 4365 4366 offset += addr_byte_size; 4367 } 4368 } 4369 4370 // if registers<15> == '1' then 4371 // LoadWritePC(MemA[address,4]); 4372 if (BitIsSet(registers, 15)) { 4373 context.SetRegisterPlusOffset(*dwarf_reg, offset); 4374 uint32_t data = 4375 MemARead(context, address + offset, addr_byte_size, 0, &success); 4376 if (!success) 4377 return false; 4378 // In ARMv5T and above, this is an interworking branch. 4379 if (!LoadWritePC(context, data)) 4380 return false; 4381 } 4382 4383 // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 4384 if (wback && BitIsClear(registers, n)) { 4385 4386 offset = addr_byte_size * BitCount(registers); 4387 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4388 context.SetImmediateSigned(offset); 4389 addr_t addr = Rn + offset; 4390 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4391 addr)) 4392 return false; 4393 } 4394 4395 // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only 4396 // possible for encoding A1 4397 if (wback && BitIsSet(registers, n)) 4398 return WriteBits32Unknown(n); 4399 } 4400 return true; 4401} 4402 4403// Load Register (immediate) calculates an address from a base register value 4404// and an immediate offset, loads a word from memory, and writes to a register. 4405// LDR (immediate, Thumb) 4406bool EmulateInstructionARM::EmulateLDRRtRnImm(const uint32_t opcode, 4407 const ARMEncoding encoding) { 4408#if 0 4409 // ARM pseudo code... 4410 if (ConditionPassed()) 4411 { 4412 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 4413 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 4414 address = if index then offset_addr else R[n]; 4415 data = MemU[address,4]; 4416 if wback then R[n] = offset_addr; 4417 if t == 15 then 4418 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 4419 elsif UnalignedSupport() || address<1:0> = '00' then 4420 R[t] = data; 4421 else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7 4422 } 4423#endif 4424 4425 bool success = false; 4426 4427 if (ConditionPassed(opcode)) { 4428 uint32_t Rt; // the destination register 4429 uint32_t Rn; // the base register 4430 uint32_t imm32; // the immediate offset used to form the address 4431 addr_t offset_addr; // the offset address 4432 addr_t address; // the calculated address 4433 uint32_t data; // the literal data value from memory load 4434 bool add, index, wback; 4435 switch (encoding) { 4436 case eEncodingT1: 4437 Rt = Bits32(opcode, 2, 0); 4438 Rn = Bits32(opcode, 5, 3); 4439 imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32); 4440 // index = TRUE; add = TRUE; wback = FALSE 4441 add = true; 4442 index = true; 4443 wback = false; 4444 4445 break; 4446 4447 case eEncodingT2: 4448 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 4449 Rt = Bits32(opcode, 10, 8); 4450 Rn = 13; 4451 imm32 = Bits32(opcode, 7, 0) << 2; 4452 4453 // index = TRUE; add = TRUE; wback = FALSE; 4454 index = true; 4455 add = true; 4456 wback = false; 4457 4458 break; 4459 4460 case eEncodingT3: 4461 // if Rn == '1111' then SEE LDR (literal); 4462 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 4463 Rt = Bits32(opcode, 15, 12); 4464 Rn = Bits32(opcode, 19, 16); 4465 imm32 = Bits32(opcode, 11, 0); 4466 4467 // index = TRUE; add = TRUE; wback = FALSE; 4468 index = true; 4469 add = true; 4470 wback = false; 4471 4472 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 4473 if ((Rt == 15) && InITBlock() && !LastInITBlock()) 4474 return false; 4475 4476 break; 4477 4478 case eEncodingT4: 4479 // if Rn == '1111' then SEE LDR (literal); 4480 // if P == '1' && U == '1' && W == '0' then SEE LDRT; 4481 // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == 4482 // '00000100' then SEE POP; 4483 // if P == '0' && W == '0' then UNDEFINED; 4484 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) 4485 return false; 4486 4487 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 4488 Rt = Bits32(opcode, 15, 12); 4489 Rn = Bits32(opcode, 19, 16); 4490 imm32 = Bits32(opcode, 7, 0); 4491 4492 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 4493 index = BitIsSet(opcode, 10); 4494 add = BitIsSet(opcode, 9); 4495 wback = BitIsSet(opcode, 8); 4496 4497 // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) 4498 // then UNPREDICTABLE; 4499 if ((wback && (Rn == Rt)) || 4500 ((Rt == 15) && InITBlock() && !LastInITBlock())) 4501 return false; 4502 4503 break; 4504 4505 default: 4506 return false; 4507 } 4508 uint32_t base = ReadCoreReg(Rn, &success); 4509 if (!success) 4510 return false; 4511 if (add) 4512 offset_addr = base + imm32; 4513 else 4514 offset_addr = base - imm32; 4515 4516 address = (index ? offset_addr : base); 4517 4518 std::optional<RegisterInfo> base_reg = 4519 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + Rn); 4520 if (wback) { 4521 EmulateInstruction::Context ctx; 4522 if (Rn == 13) { 4523 ctx.type = eContextAdjustStackPointer; 4524 ctx.SetImmediateSigned((int32_t)(offset_addr - base)); 4525 } else if (Rn == GetFramePointerRegisterNumber()) { 4526 ctx.type = eContextSetFramePointer; 4527 ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base)); 4528 } else { 4529 ctx.type = EmulateInstruction::eContextAdjustBaseRegister; 4530 ctx.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base)); 4531 } 4532 4533 if (!WriteRegisterUnsigned(ctx, eRegisterKindDWARF, dwarf_r0 + Rn, 4534 offset_addr)) 4535 return false; 4536 } 4537 4538 // Prepare to write to the Rt register. 4539 EmulateInstruction::Context context; 4540 context.type = EmulateInstruction::eContextRegisterLoad; 4541 context.SetRegisterPlusOffset(*base_reg, (int32_t)(offset_addr - base)); 4542 4543 // Read memory from the address. 4544 data = MemURead(context, address, 4, 0, &success); 4545 if (!success) 4546 return false; 4547 4548 if (Rt == 15) { 4549 if (Bits32(address, 1, 0) == 0) { 4550 if (!LoadWritePC(context, data)) 4551 return false; 4552 } else 4553 return false; 4554 } else if (UnalignedSupport() || Bits32(address, 1, 0) == 0) { 4555 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + Rt, 4556 data)) 4557 return false; 4558 } else 4559 WriteBits32Unknown(Rt); 4560 } 4561 return true; 4562} 4563 4564// STM (Store Multiple Increment After) stores multiple registers to consecutive 4565// memory locations using an address 4566// from a base register. The consecutive memory locations start at this 4567// address, and the address just above the last of those locations can 4568// optionally be written back to the base register. 4569bool EmulateInstructionARM::EmulateSTM(const uint32_t opcode, 4570 const ARMEncoding encoding) { 4571#if 0 4572 if ConditionPassed() then 4573 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4574 address = R[n]; 4575 4576 for i = 0 to 14 4577 if registers<i> == '1' then 4578 if i == n && wback && i != LowestSetBit(registers) then 4579 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1 4580 else 4581 MemA[address,4] = R[i]; 4582 address = address + 4; 4583 4584 if registers<15> == '1' then // Only possible for encoding A1 4585 MemA[address,4] = PCStoreValue(); 4586 if wback then R[n] = R[n] + 4*BitCount(registers); 4587#endif 4588 4589 bool success = false; 4590 4591 if (ConditionPassed(opcode)) { 4592 uint32_t n; 4593 uint32_t registers = 0; 4594 bool wback; 4595 const uint32_t addr_byte_size = GetAddressByteSize(); 4596 4597 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4598 switch (encoding) { 4599 case eEncodingT1: 4600 // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE; 4601 n = Bits32(opcode, 10, 8); 4602 registers = Bits32(opcode, 7, 0); 4603 registers = registers & 0x00ff; // Make sure the top 8 bits are zeros. 4604 wback = true; 4605 4606 // if BitCount(registers) < 1 then UNPREDICTABLE; 4607 if (BitCount(registers) < 1) 4608 return false; 4609 4610 break; 4611 4612 case eEncodingT2: 4613 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 4614 n = Bits32(opcode, 19, 16); 4615 registers = Bits32(opcode, 15, 0); 4616 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 4617 wback = BitIsSet(opcode, 21); 4618 4619 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 4620 if ((n == 15) || (BitCount(registers) < 2)) 4621 return false; 4622 4623 // if wback && registers<n> == '1' then UNPREDICTABLE; 4624 if (wback && BitIsSet(registers, n)) 4625 return false; 4626 4627 break; 4628 4629 case eEncodingA1: 4630 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4631 n = Bits32(opcode, 19, 16); 4632 registers = Bits32(opcode, 15, 0); 4633 wback = BitIsSet(opcode, 21); 4634 4635 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4636 if ((n == 15) || (BitCount(registers) < 1)) 4637 return false; 4638 4639 break; 4640 4641 default: 4642 return false; 4643 } 4644 4645 // address = R[n]; 4646 int32_t offset = 0; 4647 const addr_t address = 4648 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4649 if (!success) 4650 return false; 4651 4652 EmulateInstruction::Context context; 4653 context.type = EmulateInstruction::eContextRegisterStore; 4654 std::optional<RegisterInfo> base_reg = 4655 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4656 4657 // for i = 0 to 14 4658 uint32_t lowest_set_bit = 14; 4659 for (uint32_t i = 0; i < 14; ++i) { 4660 // if registers<i> == '1' then 4661 if (BitIsSet(registers, i)) { 4662 if (i < lowest_set_bit) 4663 lowest_set_bit = i; 4664 // if i == n && wback && i != LowestSetBit(registers) then 4665 if ((i == n) && wback && (i != lowest_set_bit)) 4666 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings 4667 // T1 and A1 4668 WriteBits32UnknownToMemory(address + offset); 4669 else { 4670 // MemA[address,4] = R[i]; 4671 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, 4672 0, &success); 4673 if (!success) 4674 return false; 4675 4676 std::optional<RegisterInfo> data_reg = 4677 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); 4678 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset); 4679 if (!MemAWrite(context, address + offset, data, addr_byte_size)) 4680 return false; 4681 } 4682 4683 // address = address + 4; 4684 offset += addr_byte_size; 4685 } 4686 } 4687 4688 // if registers<15> == '1' then // Only possible for encoding A1 4689 // MemA[address,4] = PCStoreValue(); 4690 if (BitIsSet(registers, 15)) { 4691 std::optional<RegisterInfo> pc_reg = 4692 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 4693 context.SetRegisterPlusOffset(*pc_reg, 8); 4694 const uint32_t pc = ReadCoreReg(PC_REG, &success); 4695 if (!success) 4696 return false; 4697 4698 if (!MemAWrite(context, address + offset, pc, addr_byte_size)) 4699 return false; 4700 } 4701 4702 // if wback then R[n] = R[n] + 4*BitCount(registers); 4703 if (wback) { 4704 offset = addr_byte_size * BitCount(registers); 4705 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4706 context.SetImmediateSigned(offset); 4707 addr_t data = address + offset; 4708 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4709 data)) 4710 return false; 4711 } 4712 } 4713 return true; 4714} 4715 4716// STMDA (Store Multiple Decrement After) stores multiple registers to 4717// consecutive memory locations using an address from a base register. The 4718// consecutive memory locations end at this address, and the address just below 4719// the lowest of those locations can optionally be written back to the base 4720// register. 4721bool EmulateInstructionARM::EmulateSTMDA(const uint32_t opcode, 4722 const ARMEncoding encoding) { 4723#if 0 4724 if ConditionPassed() then 4725 EncodingSpecificOperations(); 4726 address = R[n] - 4*BitCount(registers) + 4; 4727 4728 for i = 0 to 14 4729 if registers<i> == '1' then 4730 if i == n && wback && i != LowestSetBit(registers) then 4731 MemA[address,4] = bits(32) UNKNOWN; 4732 else 4733 MemA[address,4] = R[i]; 4734 address = address + 4; 4735 4736 if registers<15> == '1' then 4737 MemA[address,4] = PCStoreValue(); 4738 4739 if wback then R[n] = R[n] - 4*BitCount(registers); 4740#endif 4741 4742 bool success = false; 4743 4744 if (ConditionPassed(opcode)) { 4745 uint32_t n; 4746 uint32_t registers = 0; 4747 bool wback; 4748 const uint32_t addr_byte_size = GetAddressByteSize(); 4749 4750 // EncodingSpecificOperations(); 4751 switch (encoding) { 4752 case eEncodingA1: 4753 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4754 n = Bits32(opcode, 19, 16); 4755 registers = Bits32(opcode, 15, 0); 4756 wback = BitIsSet(opcode, 21); 4757 4758 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4759 if ((n == 15) || (BitCount(registers) < 1)) 4760 return false; 4761 break; 4762 default: 4763 return false; 4764 } 4765 4766 // address = R[n] - 4*BitCount(registers) + 4; 4767 int32_t offset = 0; 4768 addr_t Rn = ReadCoreReg(n, &success); 4769 if (!success) 4770 return false; 4771 4772 addr_t address = Rn - (addr_byte_size * BitCount(registers)) + 4; 4773 4774 EmulateInstruction::Context context; 4775 context.type = EmulateInstruction::eContextRegisterStore; 4776 std::optional<RegisterInfo> base_reg = 4777 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4778 4779 // for i = 0 to 14 4780 uint32_t lowest_bit_set = 14; 4781 for (uint32_t i = 0; i < 14; ++i) { 4782 // if registers<i> == '1' then 4783 if (BitIsSet(registers, i)) { 4784 if (i < lowest_bit_set) 4785 lowest_bit_set = i; 4786 // if i == n && wback && i != LowestSetBit(registers) then 4787 if ((i == n) && wback && (i != lowest_bit_set)) 4788 // MemA[address,4] = bits(32) UNKNOWN; 4789 WriteBits32UnknownToMemory(address + offset); 4790 else { 4791 // MemA[address,4] = R[i]; 4792 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, 4793 0, &success); 4794 if (!success) 4795 return false; 4796 4797 std::optional<RegisterInfo> data_reg = 4798 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); 4799 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 4800 Rn - (address + offset)); 4801 if (!MemAWrite(context, address + offset, data, addr_byte_size)) 4802 return false; 4803 } 4804 4805 // address = address + 4; 4806 offset += addr_byte_size; 4807 } 4808 } 4809 4810 // if registers<15> == '1' then 4811 // MemA[address,4] = PCStoreValue(); 4812 if (BitIsSet(registers, 15)) { 4813 std::optional<RegisterInfo> pc_reg = 4814 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 4815 context.SetRegisterPlusOffset(*pc_reg, 8); 4816 const uint32_t pc = ReadCoreReg(PC_REG, &success); 4817 if (!success) 4818 return false; 4819 4820 if (!MemAWrite(context, address + offset, pc, addr_byte_size)) 4821 return false; 4822 } 4823 4824 // if wback then R[n] = R[n] - 4*BitCount(registers); 4825 if (wback) { 4826 offset = (addr_byte_size * BitCount(registers)) * -1; 4827 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4828 context.SetImmediateSigned(offset); 4829 addr_t data = Rn + offset; 4830 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4831 data)) 4832 return false; 4833 } 4834 } 4835 return true; 4836} 4837 4838// STMDB (Store Multiple Decrement Before) stores multiple registers to 4839// consecutive memory locations using an address from a base register. The 4840// consecutive memory locations end just below this address, and the address of 4841// the first of those locations can optionally be written back to the base 4842// register. 4843bool EmulateInstructionARM::EmulateSTMDB(const uint32_t opcode, 4844 const ARMEncoding encoding) { 4845#if 0 4846 if ConditionPassed() then 4847 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4848 address = R[n] - 4*BitCount(registers); 4849 4850 for i = 0 to 14 4851 if registers<i> == '1' then 4852 if i == n && wback && i != LowestSetBit(registers) then 4853 MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1 4854 else 4855 MemA[address,4] = R[i]; 4856 address = address + 4; 4857 4858 if registers<15> == '1' then // Only possible for encoding A1 4859 MemA[address,4] = PCStoreValue(); 4860 4861 if wback then R[n] = R[n] - 4*BitCount(registers); 4862#endif 4863 4864 bool success = false; 4865 4866 if (ConditionPassed(opcode)) { 4867 uint32_t n; 4868 uint32_t registers = 0; 4869 bool wback; 4870 const uint32_t addr_byte_size = GetAddressByteSize(); 4871 4872 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 4873 switch (encoding) { 4874 case eEncodingT1: 4875 // if W == '1' && Rn == '1101' then SEE PUSH; 4876 if ((BitIsSet(opcode, 21)) && (Bits32(opcode, 19, 16) == 13)) { 4877 // See PUSH 4878 } 4879 // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 4880 n = Bits32(opcode, 19, 16); 4881 registers = Bits32(opcode, 15, 0); 4882 registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros. 4883 wback = BitIsSet(opcode, 21); 4884 // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE; 4885 if ((n == 15) || BitCount(registers) < 2) 4886 return false; 4887 // if wback && registers<n> == '1' then UNPREDICTABLE; 4888 if (wback && BitIsSet(registers, n)) 4889 return false; 4890 break; 4891 4892 case eEncodingA1: 4893 // if W == '1' && Rn == '1101' && BitCount(register_list) >= 2 then SEE 4894 // PUSH; 4895 if (BitIsSet(opcode, 21) && (Bits32(opcode, 19, 16) == 13) && 4896 BitCount(Bits32(opcode, 15, 0)) >= 2) { 4897 // See Push 4898 } 4899 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 4900 n = Bits32(opcode, 19, 16); 4901 registers = Bits32(opcode, 15, 0); 4902 wback = BitIsSet(opcode, 21); 4903 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 4904 if ((n == 15) || BitCount(registers) < 1) 4905 return false; 4906 break; 4907 4908 default: 4909 return false; 4910 } 4911 4912 // address = R[n] - 4*BitCount(registers); 4913 4914 int32_t offset = 0; 4915 addr_t Rn = 4916 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 4917 if (!success) 4918 return false; 4919 4920 addr_t address = Rn - (addr_byte_size * BitCount(registers)); 4921 4922 EmulateInstruction::Context context; 4923 context.type = EmulateInstruction::eContextRegisterStore; 4924 std::optional<RegisterInfo> base_reg = 4925 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 4926 4927 // for i = 0 to 14 4928 uint32_t lowest_set_bit = 14; 4929 for (uint32_t i = 0; i < 14; ++i) { 4930 // if registers<i> == '1' then 4931 if (BitIsSet(registers, i)) { 4932 if (i < lowest_set_bit) 4933 lowest_set_bit = i; 4934 // if i == n && wback && i != LowestSetBit(registers) then 4935 if ((i == n) && wback && (i != lowest_set_bit)) 4936 // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding 4937 // A1 4938 WriteBits32UnknownToMemory(address + offset); 4939 else { 4940 // MemA[address,4] = R[i]; 4941 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, 4942 0, &success); 4943 if (!success) 4944 return false; 4945 4946 std::optional<RegisterInfo> data_reg = 4947 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); 4948 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 4949 Rn - (address + offset)); 4950 if (!MemAWrite(context, address + offset, data, addr_byte_size)) 4951 return false; 4952 } 4953 4954 // address = address + 4; 4955 offset += addr_byte_size; 4956 } 4957 } 4958 4959 // if registers<15> == '1' then // Only possible for encoding A1 4960 // MemA[address,4] = PCStoreValue(); 4961 if (BitIsSet(registers, 15)) { 4962 std::optional<RegisterInfo> pc_reg = 4963 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 4964 context.SetRegisterPlusOffset(*pc_reg, 8); 4965 const uint32_t pc = ReadCoreReg(PC_REG, &success); 4966 if (!success) 4967 return false; 4968 4969 if (!MemAWrite(context, address + offset, pc, addr_byte_size)) 4970 return false; 4971 } 4972 4973 // if wback then R[n] = R[n] - 4*BitCount(registers); 4974 if (wback) { 4975 offset = (addr_byte_size * BitCount(registers)) * -1; 4976 context.type = EmulateInstruction::eContextAdjustBaseRegister; 4977 context.SetImmediateSigned(offset); 4978 addr_t data = Rn + offset; 4979 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 4980 data)) 4981 return false; 4982 } 4983 } 4984 return true; 4985} 4986 4987// STMIB (Store Multiple Increment Before) stores multiple registers to 4988// consecutive memory locations using an address from a base register. The 4989// consecutive memory locations start just above this address, and the address 4990// of the last of those locations can optionally be written back to the base 4991// register. 4992bool EmulateInstructionARM::EmulateSTMIB(const uint32_t opcode, 4993 const ARMEncoding encoding) { 4994#if 0 4995 if ConditionPassed() then 4996 EncodingSpecificOperations(); 4997 address = R[n] + 4; 4998 4999 for i = 0 to 14 5000 if registers<i> == '1' then 5001 if i == n && wback && i != LowestSetBit(registers) then 5002 MemA[address,4] = bits(32) UNKNOWN; 5003 else 5004 MemA[address,4] = R[i]; 5005 address = address + 4; 5006 5007 if registers<15> == '1' then 5008 MemA[address,4] = PCStoreValue(); 5009 5010 if wback then R[n] = R[n] + 4*BitCount(registers); 5011#endif 5012 5013 bool success = false; 5014 5015 if (ConditionPassed(opcode)) { 5016 uint32_t n; 5017 uint32_t registers = 0; 5018 bool wback; 5019 const uint32_t addr_byte_size = GetAddressByteSize(); 5020 5021 // EncodingSpecificOperations(); 5022 switch (encoding) { 5023 case eEncodingA1: 5024 // n = UInt(Rn); registers = register_list; wback = (W == '1'); 5025 n = Bits32(opcode, 19, 16); 5026 registers = Bits32(opcode, 15, 0); 5027 wback = BitIsSet(opcode, 21); 5028 5029 // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE; 5030 if ((n == 15) && (BitCount(registers) < 1)) 5031 return false; 5032 break; 5033 default: 5034 return false; 5035 } 5036 // address = R[n] + 4; 5037 5038 int32_t offset = 0; 5039 addr_t Rn = ReadCoreReg(n, &success); 5040 if (!success) 5041 return false; 5042 5043 addr_t address = Rn + addr_byte_size; 5044 5045 EmulateInstruction::Context context; 5046 context.type = EmulateInstruction::eContextRegisterStore; 5047 std::optional<RegisterInfo> base_reg = 5048 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 5049 5050 uint32_t lowest_set_bit = 14; 5051 // for i = 0 to 14 5052 for (uint32_t i = 0; i < 14; ++i) { 5053 // if registers<i> == '1' then 5054 if (BitIsSet(registers, i)) { 5055 if (i < lowest_set_bit) 5056 lowest_set_bit = i; 5057 // if i == n && wback && i != LowestSetBit(registers) then 5058 if ((i == n) && wback && (i != lowest_set_bit)) 5059 // MemA[address,4] = bits(32) UNKNOWN; 5060 WriteBits32UnknownToMemory(address + offset); 5061 // else 5062 else { 5063 // MemA[address,4] = R[i]; 5064 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + i, 5065 0, &success); 5066 if (!success) 5067 return false; 5068 5069 std::optional<RegisterInfo> data_reg = 5070 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + i); 5071 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 5072 offset + addr_byte_size); 5073 if (!MemAWrite(context, address + offset, data, addr_byte_size)) 5074 return false; 5075 } 5076 5077 // address = address + 4; 5078 offset += addr_byte_size; 5079 } 5080 } 5081 5082 // if registers<15> == '1' then 5083 // MemA[address,4] = PCStoreValue(); 5084 if (BitIsSet(registers, 15)) { 5085 std::optional<RegisterInfo> pc_reg = 5086 GetRegisterInfo(eRegisterKindDWARF, dwarf_pc); 5087 context.SetRegisterPlusOffset(*pc_reg, 8); 5088 const uint32_t pc = ReadCoreReg(PC_REG, &success); 5089 if (!success) 5090 return false; 5091 5092 if (!MemAWrite(context, address + offset, pc, addr_byte_size)) 5093 return false; 5094 } 5095 5096 // if wback then R[n] = R[n] + 4*BitCount(registers); 5097 if (wback) { 5098 offset = addr_byte_size * BitCount(registers); 5099 context.type = EmulateInstruction::eContextAdjustBaseRegister; 5100 context.SetImmediateSigned(offset); 5101 addr_t data = Rn + offset; 5102 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 5103 data)) 5104 return false; 5105 } 5106 } 5107 return true; 5108} 5109 5110// STR (store immediate) calculates an address from a base register value and an 5111// immediate offset, and stores a word 5112// from a register to memory. It can use offset, post-indexed, or pre-indexed 5113// addressing. 5114bool EmulateInstructionARM::EmulateSTRThumb(const uint32_t opcode, 5115 const ARMEncoding encoding) { 5116#if 0 5117 if ConditionPassed() then 5118 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5119 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5120 address = if index then offset_addr else R[n]; 5121 if UnalignedSupport() || address<1:0> == '00' then 5122 MemU[address,4] = R[t]; 5123 else // Can only occur before ARMv7 5124 MemU[address,4] = bits(32) UNKNOWN; 5125 if wback then R[n] = offset_addr; 5126#endif 5127 5128 bool success = false; 5129 5130 if (ConditionPassed(opcode)) { 5131 const uint32_t addr_byte_size = GetAddressByteSize(); 5132 5133 uint32_t t; 5134 uint32_t n; 5135 uint32_t imm32; 5136 bool index; 5137 bool add; 5138 bool wback; 5139 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 5140 switch (encoding) { 5141 case eEncodingT1: 5142 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32); 5143 t = Bits32(opcode, 2, 0); 5144 n = Bits32(opcode, 5, 3); 5145 imm32 = Bits32(opcode, 10, 6) << 2; 5146 5147 // index = TRUE; add = TRUE; wback = FALSE; 5148 index = true; 5149 add = false; 5150 wback = false; 5151 break; 5152 5153 case eEncodingT2: 5154 // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32); 5155 t = Bits32(opcode, 10, 8); 5156 n = 13; 5157 imm32 = Bits32(opcode, 7, 0) << 2; 5158 5159 // index = TRUE; add = TRUE; wback = FALSE; 5160 index = true; 5161 add = true; 5162 wback = false; 5163 break; 5164 5165 case eEncodingT3: 5166 // if Rn == '1111' then UNDEFINED; 5167 if (Bits32(opcode, 19, 16) == 15) 5168 return false; 5169 5170 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5171 t = Bits32(opcode, 15, 12); 5172 n = Bits32(opcode, 19, 16); 5173 imm32 = Bits32(opcode, 11, 0); 5174 5175 // index = TRUE; add = TRUE; wback = FALSE; 5176 index = true; 5177 add = true; 5178 wback = false; 5179 5180 // if t == 15 then UNPREDICTABLE; 5181 if (t == 15) 5182 return false; 5183 break; 5184 5185 case eEncodingT4: 5186 // if P == '1' && U == '1' && W == '0' then SEE STRT; 5187 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == 5188 // '00000100' then SEE PUSH; 5189 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 5190 if ((Bits32(opcode, 19, 16) == 15) || 5191 (BitIsClear(opcode, 10) && BitIsClear(opcode, 8))) 5192 return false; 5193 5194 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 5195 t = Bits32(opcode, 15, 12); 5196 n = Bits32(opcode, 19, 16); 5197 imm32 = Bits32(opcode, 7, 0); 5198 5199 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 5200 index = BitIsSet(opcode, 10); 5201 add = BitIsSet(opcode, 9); 5202 wback = BitIsSet(opcode, 8); 5203 5204 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 5205 if ((t == 15) || (wback && (n == t))) 5206 return false; 5207 break; 5208 5209 default: 5210 return false; 5211 } 5212 5213 addr_t offset_addr; 5214 addr_t address; 5215 5216 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5217 uint32_t base_address = ReadCoreReg(n, &success); 5218 if (!success) 5219 return false; 5220 5221 if (add) 5222 offset_addr = base_address + imm32; 5223 else 5224 offset_addr = base_address - imm32; 5225 5226 // address = if index then offset_addr else R[n]; 5227 if (index) 5228 address = offset_addr; 5229 else 5230 address = base_address; 5231 5232 EmulateInstruction::Context context; 5233 if (n == 13) 5234 context.type = eContextPushRegisterOnStack; 5235 else 5236 context.type = eContextRegisterStore; 5237 5238 std::optional<RegisterInfo> base_reg = 5239 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 5240 5241 // if UnalignedSupport() || address<1:0> == '00' then 5242 if (UnalignedSupport() || 5243 (BitIsClear(address, 1) && BitIsClear(address, 0))) { 5244 // MemU[address,4] = R[t]; 5245 uint32_t data = 5246 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 5247 if (!success) 5248 return false; 5249 5250 std::optional<RegisterInfo> data_reg = 5251 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 5252 int32_t offset = address - base_address; 5253 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, offset); 5254 if (!MemUWrite(context, address, data, addr_byte_size)) 5255 return false; 5256 } else { 5257 // MemU[address,4] = bits(32) UNKNOWN; 5258 WriteBits32UnknownToMemory(address); 5259 } 5260 5261 // if wback then R[n] = offset_addr; 5262 if (wback) { 5263 if (n == 13) 5264 context.type = eContextAdjustStackPointer; 5265 else 5266 context.type = eContextAdjustBaseRegister; 5267 context.SetAddress(offset_addr); 5268 5269 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 5270 offset_addr)) 5271 return false; 5272 } 5273 } 5274 return true; 5275} 5276 5277// STR (Store Register) calculates an address from a base register value and an 5278// offset register value, stores a 5279// word from a register to memory. The offset register value can optionally 5280// be shifted. 5281bool EmulateInstructionARM::EmulateSTRRegister(const uint32_t opcode, 5282 const ARMEncoding encoding) { 5283#if 0 5284 if ConditionPassed() then 5285 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5286 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5287 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5288 address = if index then offset_addr else R[n]; 5289 if t == 15 then // Only possible for encoding A1 5290 data = PCStoreValue(); 5291 else 5292 data = R[t]; 5293 if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then 5294 MemU[address,4] = data; 5295 else // Can only occur before ARMv7 5296 MemU[address,4] = bits(32) UNKNOWN; 5297 if wback then R[n] = offset_addr; 5298#endif 5299 5300 bool success = false; 5301 5302 if (ConditionPassed(opcode)) { 5303 const uint32_t addr_byte_size = GetAddressByteSize(); 5304 5305 uint32_t t; 5306 uint32_t n; 5307 uint32_t m; 5308 ARM_ShifterType shift_t; 5309 uint32_t shift_n; 5310 bool index; 5311 bool add; 5312 bool wback; 5313 5314 // EncodingSpecificOperations (); NullCheckIfThumbEE(n); 5315 switch (encoding) { 5316 case eEncodingT1: 5317 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation 5318 // in ThumbEE"; 5319 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5320 t = Bits32(opcode, 2, 0); 5321 n = Bits32(opcode, 5, 3); 5322 m = Bits32(opcode, 8, 6); 5323 5324 // index = TRUE; add = TRUE; wback = FALSE; 5325 index = true; 5326 add = true; 5327 wback = false; 5328 5329 // (shift_t, shift_n) = (SRType_LSL, 0); 5330 shift_t = SRType_LSL; 5331 shift_n = 0; 5332 break; 5333 5334 case eEncodingT2: 5335 // if Rn == '1111' then UNDEFINED; 5336 if (Bits32(opcode, 19, 16) == 15) 5337 return false; 5338 5339 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5340 t = Bits32(opcode, 15, 12); 5341 n = Bits32(opcode, 19, 16); 5342 m = Bits32(opcode, 3, 0); 5343 5344 // index = TRUE; add = TRUE; wback = FALSE; 5345 index = true; 5346 add = true; 5347 wback = false; 5348 5349 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5350 shift_t = SRType_LSL; 5351 shift_n = Bits32(opcode, 5, 4); 5352 5353 // if t == 15 || BadReg(m) then UNPREDICTABLE; 5354 if ((t == 15) || (BadReg(m))) 5355 return false; 5356 break; 5357 5358 case eEncodingA1: { 5359 // if P == '0' && W == '1' then SEE STRT; 5360 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5361 t = Bits32(opcode, 15, 12); 5362 n = Bits32(opcode, 19, 16); 5363 m = Bits32(opcode, 3, 0); 5364 5365 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 5366 // (W == '1'); 5367 index = BitIsSet(opcode, 24); 5368 add = BitIsSet(opcode, 23); 5369 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 5370 5371 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 5372 uint32_t typ = Bits32(opcode, 6, 5); 5373 uint32_t imm5 = Bits32(opcode, 11, 7); 5374 shift_n = DecodeImmShift(typ, imm5, shift_t); 5375 5376 // if m == 15 then UNPREDICTABLE; 5377 if (m == 15) 5378 return false; 5379 5380 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5381 if (wback && ((n == 15) || (n == t))) 5382 return false; 5383 5384 break; 5385 } 5386 default: 5387 return false; 5388 } 5389 5390 addr_t offset_addr; 5391 addr_t address; 5392 int32_t offset = 0; 5393 5394 addr_t base_address = 5395 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5396 if (!success) 5397 return false; 5398 5399 uint32_t Rm_data = 5400 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 5401 if (!success) 5402 return false; 5403 5404 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 5405 offset = Shift(Rm_data, shift_t, shift_n, APSR_C, &success); 5406 if (!success) 5407 return false; 5408 5409 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5410 if (add) 5411 offset_addr = base_address + offset; 5412 else 5413 offset_addr = base_address - offset; 5414 5415 // address = if index then offset_addr else R[n]; 5416 if (index) 5417 address = offset_addr; 5418 else 5419 address = base_address; 5420 5421 uint32_t data; 5422 // if t == 15 then // Only possible for encoding A1 5423 if (t == 15) 5424 // data = PCStoreValue(); 5425 data = ReadCoreReg(PC_REG, &success); 5426 else 5427 // data = R[t]; 5428 data = 5429 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 5430 5431 if (!success) 5432 return false; 5433 5434 EmulateInstruction::Context context; 5435 context.type = eContextRegisterStore; 5436 5437 // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == 5438 // InstrSet_ARM then 5439 if (UnalignedSupport() || 5440 (BitIsClear(address, 1) && BitIsClear(address, 0)) || 5441 CurrentInstrSet() == eModeARM) { 5442 // MemU[address,4] = data; 5443 5444 std::optional<RegisterInfo> base_reg = 5445 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 5446 std::optional<RegisterInfo> data_reg = 5447 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 5448 5449 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 5450 address - base_address); 5451 if (!MemUWrite(context, address, data, addr_byte_size)) 5452 return false; 5453 5454 } else 5455 // MemU[address,4] = bits(32) UNKNOWN; 5456 WriteBits32UnknownToMemory(address); 5457 5458 // if wback then R[n] = offset_addr; 5459 if (wback) { 5460 context.type = eContextRegisterLoad; 5461 context.SetAddress(offset_addr); 5462 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 5463 offset_addr)) 5464 return false; 5465 } 5466 } 5467 return true; 5468} 5469 5470bool EmulateInstructionARM::EmulateSTRBThumb(const uint32_t opcode, 5471 const ARMEncoding encoding) { 5472#if 0 5473 if ConditionPassed() then 5474 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5475 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5476 address = if index then offset_addr else R[n]; 5477 MemU[address,1] = R[t]<7:0>; 5478 if wback then R[n] = offset_addr; 5479#endif 5480 5481 bool success = false; 5482 5483 if (ConditionPassed(opcode)) { 5484 uint32_t t; 5485 uint32_t n; 5486 uint32_t imm32; 5487 bool index; 5488 bool add; 5489 bool wback; 5490 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5491 switch (encoding) { 5492 case eEncodingT1: 5493 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 5494 t = Bits32(opcode, 2, 0); 5495 n = Bits32(opcode, 5, 3); 5496 imm32 = Bits32(opcode, 10, 6); 5497 5498 // index = TRUE; add = TRUE; wback = FALSE; 5499 index = true; 5500 add = true; 5501 wback = false; 5502 break; 5503 5504 case eEncodingT2: 5505 // if Rn == '1111' then UNDEFINED; 5506 if (Bits32(opcode, 19, 16) == 15) 5507 return false; 5508 5509 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 5510 t = Bits32(opcode, 15, 12); 5511 n = Bits32(opcode, 19, 16); 5512 imm32 = Bits32(opcode, 11, 0); 5513 5514 // index = TRUE; add = TRUE; wback = FALSE; 5515 index = true; 5516 add = true; 5517 wback = false; 5518 5519 // if BadReg(t) then UNPREDICTABLE; 5520 if (BadReg(t)) 5521 return false; 5522 break; 5523 5524 case eEncodingT3: 5525 // if P == '1' && U == '1' && W == '0' then SEE STRBT; 5526 // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 5527 if (Bits32(opcode, 19, 16) == 15) 5528 return false; 5529 5530 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 5531 t = Bits32(opcode, 15, 12); 5532 n = Bits32(opcode, 19, 16); 5533 imm32 = Bits32(opcode, 7, 0); 5534 5535 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 5536 index = BitIsSet(opcode, 10); 5537 add = BitIsSet(opcode, 9); 5538 wback = BitIsSet(opcode, 8); 5539 5540 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE 5541 if ((BadReg(t)) || (wback && (n == t))) 5542 return false; 5543 break; 5544 5545 default: 5546 return false; 5547 } 5548 5549 addr_t offset_addr; 5550 addr_t address; 5551 addr_t base_address = 5552 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 5553 if (!success) 5554 return false; 5555 5556 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 5557 if (add) 5558 offset_addr = base_address + imm32; 5559 else 5560 offset_addr = base_address - imm32; 5561 5562 // address = if index then offset_addr else R[n]; 5563 if (index) 5564 address = offset_addr; 5565 else 5566 address = base_address; 5567 5568 // MemU[address,1] = R[t]<7:0> 5569 std::optional<RegisterInfo> base_reg = 5570 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 5571 std::optional<RegisterInfo> data_reg = 5572 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 5573 5574 EmulateInstruction::Context context; 5575 context.type = eContextRegisterStore; 5576 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 5577 address - base_address); 5578 5579 uint32_t data = 5580 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 5581 if (!success) 5582 return false; 5583 5584 data = Bits32(data, 7, 0); 5585 5586 if (!MemUWrite(context, address, data, 1)) 5587 return false; 5588 5589 // if wback then R[n] = offset_addr; 5590 if (wback) { 5591 context.type = eContextRegisterLoad; 5592 context.SetAddress(offset_addr); 5593 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 5594 offset_addr)) 5595 return false; 5596 } 5597 } 5598 5599 return true; 5600} 5601 5602// STRH (register) calculates an address from a base register value and an 5603// offset register value, and stores a 5604// halfword from a register to memory. The offset register value can be 5605// shifted left by 0, 1, 2, or 3 bits. 5606bool EmulateInstructionARM::EmulateSTRHRegister(const uint32_t opcode, 5607 const ARMEncoding encoding) { 5608#if 0 5609 if ConditionPassed() then 5610 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5611 offset = Shift(R[m], shift_t, shift_n, APSR.C); 5612 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5613 address = if index then offset_addr else R[n]; 5614 if UnalignedSupport() || address<0> == '0' then 5615 MemU[address,2] = R[t]<15:0>; 5616 else // Can only occur before ARMv7 5617 MemU[address,2] = bits(16) UNKNOWN; 5618 if wback then R[n] = offset_addr; 5619#endif 5620 5621 bool success = false; 5622 5623 if (ConditionPassed(opcode)) { 5624 uint32_t t; 5625 uint32_t n; 5626 uint32_t m; 5627 bool index; 5628 bool add; 5629 bool wback; 5630 ARM_ShifterType shift_t; 5631 uint32_t shift_n; 5632 5633 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 5634 switch (encoding) { 5635 case eEncodingT1: 5636 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation 5637 // in ThumbEE"; 5638 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5639 t = Bits32(opcode, 2, 0); 5640 n = Bits32(opcode, 5, 3); 5641 m = Bits32(opcode, 8, 6); 5642 5643 // index = TRUE; add = TRUE; wback = FALSE; 5644 index = true; 5645 add = true; 5646 wback = false; 5647 5648 // (shift_t, shift_n) = (SRType_LSL, 0); 5649 shift_t = SRType_LSL; 5650 shift_n = 0; 5651 5652 break; 5653 5654 case eEncodingT2: 5655 // if Rn == '1111' then UNDEFINED; 5656 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5657 t = Bits32(opcode, 15, 12); 5658 n = Bits32(opcode, 19, 16); 5659 m = Bits32(opcode, 3, 0); 5660 if (n == 15) 5661 return false; 5662 5663 // index = TRUE; add = TRUE; wback = FALSE; 5664 index = true; 5665 add = true; 5666 wback = false; 5667 5668 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 5669 shift_t = SRType_LSL; 5670 shift_n = Bits32(opcode, 5, 4); 5671 5672 // if BadReg(t) || BadReg(m) then UNPREDICTABLE; 5673 if (BadReg(t) || BadReg(m)) 5674 return false; 5675 5676 break; 5677 5678 case eEncodingA1: 5679 // if P == '0' && W == '1' then SEE STRHT; 5680 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 5681 t = Bits32(opcode, 15, 12); 5682 n = Bits32(opcode, 19, 16); 5683 m = Bits32(opcode, 3, 0); 5684 5685 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 5686 // (W == '1'); 5687 index = BitIsSet(opcode, 24); 5688 add = BitIsSet(opcode, 23); 5689 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 5690 5691 // (shift_t, shift_n) = (SRType_LSL, 0); 5692 shift_t = SRType_LSL; 5693 shift_n = 0; 5694 5695 // if t == 15 || m == 15 then UNPREDICTABLE; 5696 if ((t == 15) || (m == 15)) 5697 return false; 5698 5699 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 5700 if (wback && ((n == 15) || (n == t))) 5701 return false; 5702 5703 break; 5704 5705 default: 5706 return false; 5707 } 5708 5709 uint32_t Rm = ReadCoreReg(m, &success); 5710 if (!success) 5711 return false; 5712 5713 uint32_t Rn = ReadCoreReg(n, &success); 5714 if (!success) 5715 return false; 5716 5717 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 5718 uint32_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); 5719 if (!success) 5720 return false; 5721 5722 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 5723 addr_t offset_addr; 5724 if (add) 5725 offset_addr = Rn + offset; 5726 else 5727 offset_addr = Rn - offset; 5728 5729 // address = if index then offset_addr else R[n]; 5730 addr_t address; 5731 if (index) 5732 address = offset_addr; 5733 else 5734 address = Rn; 5735 5736 EmulateInstruction::Context context; 5737 context.type = eContextRegisterStore; 5738 5739 // if UnalignedSupport() || address<0> == '0' then 5740 if (UnalignedSupport() || BitIsClear(address, 0)) { 5741 // MemU[address,2] = R[t]<15:0>; 5742 uint32_t Rt = ReadCoreReg(t, &success); 5743 if (!success) 5744 return false; 5745 5746 EmulateInstruction::Context context; 5747 context.type = eContextRegisterStore; 5748 std::optional<RegisterInfo> base_reg = 5749 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 5750 std::optional<RegisterInfo> offset_reg = 5751 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 5752 std::optional<RegisterInfo> data_reg = 5753 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 5754 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg, 5755 *data_reg); 5756 5757 if (!MemUWrite(context, address, Bits32(Rt, 15, 0), 2)) 5758 return false; 5759 } else // Can only occur before ARMv7 5760 { 5761 // MemU[address,2] = bits(16) UNKNOWN; 5762 } 5763 5764 // if wback then R[n] = offset_addr; 5765 if (wback) { 5766 context.type = eContextAdjustBaseRegister; 5767 context.SetAddress(offset_addr); 5768 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 5769 offset_addr)) 5770 return false; 5771 } 5772 } 5773 5774 return true; 5775} 5776 5777// Add with Carry (immediate) adds an immediate value and the carry flag value 5778// to a register value, and writes the result to the destination register. It 5779// can optionally update the condition flags based on the result. 5780bool EmulateInstructionARM::EmulateADCImm(const uint32_t opcode, 5781 const ARMEncoding encoding) { 5782#if 0 5783 // ARM pseudo code... 5784 if ConditionPassed() then 5785 EncodingSpecificOperations(); 5786 (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C); 5787 if d == 15 then // Can only occur for ARM encoding 5788 ALUWritePC(result); // setflags is always FALSE here 5789 else 5790 R[d] = result; 5791 if setflags then 5792 APSR.N = result<31>; 5793 APSR.Z = IsZeroBit(result); 5794 APSR.C = carry; 5795 APSR.V = overflow; 5796#endif 5797 5798 bool success = false; 5799 5800 if (ConditionPassed(opcode)) { 5801 uint32_t Rd, Rn; 5802 uint32_t 5803 imm32; // the immediate value to be added to the value obtained from Rn 5804 bool setflags; 5805 switch (encoding) { 5806 case eEncodingT1: 5807 Rd = Bits32(opcode, 11, 8); 5808 Rn = Bits32(opcode, 19, 16); 5809 setflags = BitIsSet(opcode, 20); 5810 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 5811 if (BadReg(Rd) || BadReg(Rn)) 5812 return false; 5813 break; 5814 case eEncodingA1: 5815 Rd = Bits32(opcode, 15, 12); 5816 Rn = Bits32(opcode, 19, 16); 5817 setflags = BitIsSet(opcode, 20); 5818 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5819 5820 if (Rd == 15 && setflags) 5821 return EmulateSUBSPcLrEtc(opcode, encoding); 5822 break; 5823 default: 5824 return false; 5825 } 5826 5827 // Read the first operand. 5828 int32_t val1 = ReadCoreReg(Rn, &success); 5829 if (!success) 5830 return false; 5831 5832 AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C); 5833 5834 EmulateInstruction::Context context; 5835 context.type = EmulateInstruction::eContextImmediate; 5836 context.SetNoArgs(); 5837 5838 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 5839 res.carry_out, res.overflow)) 5840 return false; 5841 } 5842 return true; 5843} 5844 5845// Add with Carry (register) adds a register value, the carry flag value, and 5846// an optionally-shifted register value, and writes the result to the 5847// destination register. It can optionally update the condition flags based on 5848// the result. 5849bool EmulateInstructionARM::EmulateADCReg(const uint32_t opcode, 5850 const ARMEncoding encoding) { 5851#if 0 5852 // ARM pseudo code... 5853 if ConditionPassed() then 5854 EncodingSpecificOperations(); 5855 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 5856 (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C); 5857 if d == 15 then // Can only occur for ARM encoding 5858 ALUWritePC(result); // setflags is always FALSE here 5859 else 5860 R[d] = result; 5861 if setflags then 5862 APSR.N = result<31>; 5863 APSR.Z = IsZeroBit(result); 5864 APSR.C = carry; 5865 APSR.V = overflow; 5866#endif 5867 5868 bool success = false; 5869 5870 if (ConditionPassed(opcode)) { 5871 uint32_t Rd, Rn, Rm; 5872 ARM_ShifterType shift_t; 5873 uint32_t shift_n; // the shift applied to the value read from Rm 5874 bool setflags; 5875 switch (encoding) { 5876 case eEncodingT1: 5877 Rd = Rn = Bits32(opcode, 2, 0); 5878 Rm = Bits32(opcode, 5, 3); 5879 setflags = !InITBlock(); 5880 shift_t = SRType_LSL; 5881 shift_n = 0; 5882 break; 5883 case eEncodingT2: 5884 Rd = Bits32(opcode, 11, 8); 5885 Rn = Bits32(opcode, 19, 16); 5886 Rm = Bits32(opcode, 3, 0); 5887 setflags = BitIsSet(opcode, 20); 5888 shift_n = DecodeImmShiftThumb(opcode, shift_t); 5889 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 5890 return false; 5891 break; 5892 case eEncodingA1: 5893 Rd = Bits32(opcode, 15, 12); 5894 Rn = Bits32(opcode, 19, 16); 5895 Rm = Bits32(opcode, 3, 0); 5896 setflags = BitIsSet(opcode, 20); 5897 shift_n = DecodeImmShiftARM(opcode, shift_t); 5898 5899 if (Rd == 15 && setflags) 5900 return EmulateSUBSPcLrEtc(opcode, encoding); 5901 break; 5902 default: 5903 return false; 5904 } 5905 5906 // Read the first operand. 5907 int32_t val1 = ReadCoreReg(Rn, &success); 5908 if (!success) 5909 return false; 5910 5911 // Read the second operand. 5912 int32_t val2 = ReadCoreReg(Rm, &success); 5913 if (!success) 5914 return false; 5915 5916 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 5917 if (!success) 5918 return false; 5919 AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C); 5920 5921 EmulateInstruction::Context context; 5922 context.type = EmulateInstruction::eContextImmediate; 5923 context.SetNoArgs(); 5924 5925 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 5926 res.carry_out, res.overflow)) 5927 return false; 5928 } 5929 return true; 5930} 5931 5932// This instruction adds an immediate value to the PC value to form a PC- 5933// relative address, and writes the result to the destination register. 5934bool EmulateInstructionARM::EmulateADR(const uint32_t opcode, 5935 const ARMEncoding encoding) { 5936#if 0 5937 // ARM pseudo code... 5938 if ConditionPassed() then 5939 EncodingSpecificOperations(); 5940 result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32); 5941 if d == 15 then // Can only occur for ARM encodings 5942 ALUWritePC(result); 5943 else 5944 R[d] = result; 5945#endif 5946 5947 bool success = false; 5948 5949 if (ConditionPassed(opcode)) { 5950 uint32_t Rd; 5951 uint32_t imm32; // the immediate value to be added/subtracted to/from the PC 5952 bool add; 5953 switch (encoding) { 5954 case eEncodingT1: 5955 Rd = Bits32(opcode, 10, 8); 5956 imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32) 5957 add = true; 5958 break; 5959 case eEncodingT2: 5960 case eEncodingT3: 5961 Rd = Bits32(opcode, 11, 8); 5962 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 5963 add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB 5964 if (BadReg(Rd)) 5965 return false; 5966 break; 5967 case eEncodingA1: 5968 case eEncodingA2: 5969 Rd = Bits32(opcode, 15, 12); 5970 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 5971 add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB 5972 break; 5973 default: 5974 return false; 5975 } 5976 5977 // Read the PC value. 5978 uint32_t pc = ReadCoreReg(PC_REG, &success); 5979 if (!success) 5980 return false; 5981 5982 uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32); 5983 5984 EmulateInstruction::Context context; 5985 context.type = EmulateInstruction::eContextImmediate; 5986 context.SetNoArgs(); 5987 5988 if (!WriteCoreReg(context, result, Rd)) 5989 return false; 5990 } 5991 return true; 5992} 5993 5994// This instruction performs a bitwise AND of a register value and an immediate 5995// value, and writes the result to the destination register. It can optionally 5996// update the condition flags based on the result. 5997bool EmulateInstructionARM::EmulateANDImm(const uint32_t opcode, 5998 const ARMEncoding encoding) { 5999#if 0 6000 // ARM pseudo code... 6001 if ConditionPassed() then 6002 EncodingSpecificOperations(); 6003 result = R[n] AND imm32; 6004 if d == 15 then // Can only occur for ARM encoding 6005 ALUWritePC(result); // setflags is always FALSE here 6006 else 6007 R[d] = result; 6008 if setflags then 6009 APSR.N = result<31>; 6010 APSR.Z = IsZeroBit(result); 6011 APSR.C = carry; 6012 // APSR.V unchanged 6013#endif 6014 6015 bool success = false; 6016 6017 if (ConditionPassed(opcode)) { 6018 uint32_t Rd, Rn; 6019 uint32_t 6020 imm32; // the immediate value to be ANDed to the value obtained from Rn 6021 bool setflags; 6022 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 6023 switch (encoding) { 6024 case eEncodingT1: 6025 Rd = Bits32(opcode, 11, 8); 6026 Rn = Bits32(opcode, 19, 16); 6027 setflags = BitIsSet(opcode, 20); 6028 imm32 = ThumbExpandImm_C( 6029 opcode, APSR_C, 6030 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 6031 // if Rd == '1111' && S == '1' then SEE TST (immediate); 6032 if (Rd == 15 && setflags) 6033 return EmulateTSTImm(opcode, eEncodingT1); 6034 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 6035 return false; 6036 break; 6037 case eEncodingA1: 6038 Rd = Bits32(opcode, 15, 12); 6039 Rn = Bits32(opcode, 19, 16); 6040 setflags = BitIsSet(opcode, 20); 6041 imm32 = 6042 ARMExpandImm_C(opcode, APSR_C, 6043 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 6044 6045 if (Rd == 15 && setflags) 6046 return EmulateSUBSPcLrEtc(opcode, encoding); 6047 break; 6048 default: 6049 return false; 6050 } 6051 6052 // Read the first operand. 6053 uint32_t val1 = ReadCoreReg(Rn, &success); 6054 if (!success) 6055 return false; 6056 6057 uint32_t result = val1 & imm32; 6058 6059 EmulateInstruction::Context context; 6060 context.type = EmulateInstruction::eContextImmediate; 6061 context.SetNoArgs(); 6062 6063 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 6064 return false; 6065 } 6066 return true; 6067} 6068 6069// This instruction performs a bitwise AND of a register value and an 6070// optionally-shifted register value, and writes the result to the destination 6071// register. It can optionally update the condition flags based on the result. 6072bool EmulateInstructionARM::EmulateANDReg(const uint32_t opcode, 6073 const ARMEncoding encoding) { 6074#if 0 6075 // ARM pseudo code... 6076 if ConditionPassed() then 6077 EncodingSpecificOperations(); 6078 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 6079 result = R[n] AND shifted; 6080 if d == 15 then // Can only occur for ARM encoding 6081 ALUWritePC(result); // setflags is always FALSE here 6082 else 6083 R[d] = result; 6084 if setflags then 6085 APSR.N = result<31>; 6086 APSR.Z = IsZeroBit(result); 6087 APSR.C = carry; 6088 // APSR.V unchanged 6089#endif 6090 6091 bool success = false; 6092 6093 if (ConditionPassed(opcode)) { 6094 uint32_t Rd, Rn, Rm; 6095 ARM_ShifterType shift_t; 6096 uint32_t shift_n; // the shift applied to the value read from Rm 6097 bool setflags; 6098 uint32_t carry; 6099 switch (encoding) { 6100 case eEncodingT1: 6101 Rd = Rn = Bits32(opcode, 2, 0); 6102 Rm = Bits32(opcode, 5, 3); 6103 setflags = !InITBlock(); 6104 shift_t = SRType_LSL; 6105 shift_n = 0; 6106 break; 6107 case eEncodingT2: 6108 Rd = Bits32(opcode, 11, 8); 6109 Rn = Bits32(opcode, 19, 16); 6110 Rm = Bits32(opcode, 3, 0); 6111 setflags = BitIsSet(opcode, 20); 6112 shift_n = DecodeImmShiftThumb(opcode, shift_t); 6113 // if Rd == '1111' && S == '1' then SEE TST (register); 6114 if (Rd == 15 && setflags) 6115 return EmulateTSTReg(opcode, eEncodingT2); 6116 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 6117 return false; 6118 break; 6119 case eEncodingA1: 6120 Rd = Bits32(opcode, 15, 12); 6121 Rn = Bits32(opcode, 19, 16); 6122 Rm = Bits32(opcode, 3, 0); 6123 setflags = BitIsSet(opcode, 20); 6124 shift_n = DecodeImmShiftARM(opcode, shift_t); 6125 6126 if (Rd == 15 && setflags) 6127 return EmulateSUBSPcLrEtc(opcode, encoding); 6128 break; 6129 default: 6130 return false; 6131 } 6132 6133 // Read the first operand. 6134 uint32_t val1 = ReadCoreReg(Rn, &success); 6135 if (!success) 6136 return false; 6137 6138 // Read the second operand. 6139 uint32_t val2 = ReadCoreReg(Rm, &success); 6140 if (!success) 6141 return false; 6142 6143 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 6144 if (!success) 6145 return false; 6146 uint32_t result = val1 & shifted; 6147 6148 EmulateInstruction::Context context; 6149 context.type = EmulateInstruction::eContextImmediate; 6150 context.SetNoArgs(); 6151 6152 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 6153 return false; 6154 } 6155 return true; 6156} 6157 6158// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and 6159// the complement of an immediate value, and writes the result to the 6160// destination register. It can optionally update the condition flags based on 6161// the result. 6162bool EmulateInstructionARM::EmulateBICImm(const uint32_t opcode, 6163 const ARMEncoding encoding) { 6164#if 0 6165 // ARM pseudo code... 6166 if ConditionPassed() then 6167 EncodingSpecificOperations(); 6168 result = R[n] AND NOT(imm32); 6169 if d == 15 then // Can only occur for ARM encoding 6170 ALUWritePC(result); // setflags is always FALSE here 6171 else 6172 R[d] = result; 6173 if setflags then 6174 APSR.N = result<31>; 6175 APSR.Z = IsZeroBit(result); 6176 APSR.C = carry; 6177 // APSR.V unchanged 6178#endif 6179 6180 bool success = false; 6181 6182 if (ConditionPassed(opcode)) { 6183 uint32_t Rd, Rn; 6184 uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to 6185 // the value obtained from Rn 6186 bool setflags; 6187 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 6188 switch (encoding) { 6189 case eEncodingT1: 6190 Rd = Bits32(opcode, 11, 8); 6191 Rn = Bits32(opcode, 19, 16); 6192 setflags = BitIsSet(opcode, 20); 6193 imm32 = ThumbExpandImm_C( 6194 opcode, APSR_C, 6195 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 6196 if (BadReg(Rd) || BadReg(Rn)) 6197 return false; 6198 break; 6199 case eEncodingA1: 6200 Rd = Bits32(opcode, 15, 12); 6201 Rn = Bits32(opcode, 19, 16); 6202 setflags = BitIsSet(opcode, 20); 6203 imm32 = 6204 ARMExpandImm_C(opcode, APSR_C, 6205 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 6206 6207 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 6208 // instructions; 6209 if (Rd == 15 && setflags) 6210 return EmulateSUBSPcLrEtc(opcode, encoding); 6211 break; 6212 default: 6213 return false; 6214 } 6215 6216 // Read the first operand. 6217 uint32_t val1 = ReadCoreReg(Rn, &success); 6218 if (!success) 6219 return false; 6220 6221 uint32_t result = val1 & ~imm32; 6222 6223 EmulateInstruction::Context context; 6224 context.type = EmulateInstruction::eContextImmediate; 6225 context.SetNoArgs(); 6226 6227 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 6228 return false; 6229 } 6230 return true; 6231} 6232 6233// Bitwise Bit Clear (register) performs a bitwise AND of a register value and 6234// the complement of an optionally-shifted register value, and writes the 6235// result to the destination register. It can optionally update the condition 6236// flags based on the result. 6237bool EmulateInstructionARM::EmulateBICReg(const uint32_t opcode, 6238 const ARMEncoding encoding) { 6239#if 0 6240 // ARM pseudo code... 6241 if ConditionPassed() then 6242 EncodingSpecificOperations(); 6243 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 6244 result = R[n] AND NOT(shifted); 6245 if d == 15 then // Can only occur for ARM encoding 6246 ALUWritePC(result); // setflags is always FALSE here 6247 else 6248 R[d] = result; 6249 if setflags then 6250 APSR.N = result<31>; 6251 APSR.Z = IsZeroBit(result); 6252 APSR.C = carry; 6253 // APSR.V unchanged 6254#endif 6255 6256 bool success = false; 6257 6258 if (ConditionPassed(opcode)) { 6259 uint32_t Rd, Rn, Rm; 6260 ARM_ShifterType shift_t; 6261 uint32_t shift_n; // the shift applied to the value read from Rm 6262 bool setflags; 6263 uint32_t carry; 6264 switch (encoding) { 6265 case eEncodingT1: 6266 Rd = Rn = Bits32(opcode, 2, 0); 6267 Rm = Bits32(opcode, 5, 3); 6268 setflags = !InITBlock(); 6269 shift_t = SRType_LSL; 6270 shift_n = 0; 6271 break; 6272 case eEncodingT2: 6273 Rd = Bits32(opcode, 11, 8); 6274 Rn = Bits32(opcode, 19, 16); 6275 Rm = Bits32(opcode, 3, 0); 6276 setflags = BitIsSet(opcode, 20); 6277 shift_n = DecodeImmShiftThumb(opcode, shift_t); 6278 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 6279 return false; 6280 break; 6281 case eEncodingA1: 6282 Rd = Bits32(opcode, 15, 12); 6283 Rn = Bits32(opcode, 19, 16); 6284 Rm = Bits32(opcode, 3, 0); 6285 setflags = BitIsSet(opcode, 20); 6286 shift_n = DecodeImmShiftARM(opcode, shift_t); 6287 6288 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 6289 // instructions; 6290 if (Rd == 15 && setflags) 6291 return EmulateSUBSPcLrEtc(opcode, encoding); 6292 break; 6293 default: 6294 return false; 6295 } 6296 6297 // Read the first operand. 6298 uint32_t val1 = ReadCoreReg(Rn, &success); 6299 if (!success) 6300 return false; 6301 6302 // Read the second operand. 6303 uint32_t val2 = ReadCoreReg(Rm, &success); 6304 if (!success) 6305 return false; 6306 6307 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 6308 if (!success) 6309 return false; 6310 uint32_t result = val1 & ~shifted; 6311 6312 EmulateInstruction::Context context; 6313 context.type = EmulateInstruction::eContextImmediate; 6314 context.SetNoArgs(); 6315 6316 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 6317 return false; 6318 } 6319 return true; 6320} 6321 6322// LDR (immediate, ARM) calculates an address from a base register value and an 6323// immediate offset, loads a word 6324// from memory, and writes it to a register. It can use offset, post-indexed, 6325// or pre-indexed addressing. 6326bool EmulateInstructionARM::EmulateLDRImmediateARM(const uint32_t opcode, 6327 const ARMEncoding encoding) { 6328#if 0 6329 if ConditionPassed() then 6330 EncodingSpecificOperations(); 6331 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6332 address = if index then offset_addr else R[n]; 6333 data = MemU[address,4]; 6334 if wback then R[n] = offset_addr; 6335 if t == 15 then 6336 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6337 elsif UnalignedSupport() || address<1:0> = '00' then 6338 R[t] = data; 6339 else // Can only apply before ARMv7 6340 R[t] = ROR(data, 8*UInt(address<1:0>)); 6341#endif 6342 6343 bool success = false; 6344 6345 if (ConditionPassed(opcode)) { 6346 const uint32_t addr_byte_size = GetAddressByteSize(); 6347 6348 uint32_t t; 6349 uint32_t n; 6350 uint32_t imm32; 6351 bool index; 6352 bool add; 6353 bool wback; 6354 6355 switch (encoding) { 6356 case eEncodingA1: 6357 // if Rn == '1111' then SEE LDR (literal); 6358 // if P == '0' && W == '1' then SEE LDRT; 6359 // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == 6360 // '000000000100' then SEE POP; 6361 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6362 t = Bits32(opcode, 15, 12); 6363 n = Bits32(opcode, 19, 16); 6364 imm32 = Bits32(opcode, 11, 0); 6365 6366 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 6367 // (W == '1'); 6368 index = BitIsSet(opcode, 24); 6369 add = BitIsSet(opcode, 23); 6370 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 6371 6372 // if wback && n == t then UNPREDICTABLE; 6373 if (wback && (n == t)) 6374 return false; 6375 6376 break; 6377 6378 default: 6379 return false; 6380 } 6381 6382 addr_t address; 6383 addr_t offset_addr; 6384 addr_t base_address = ReadCoreReg(n, &success); 6385 if (!success) 6386 return false; 6387 6388 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6389 if (add) 6390 offset_addr = base_address + imm32; 6391 else 6392 offset_addr = base_address - imm32; 6393 6394 // address = if index then offset_addr else R[n]; 6395 if (index) 6396 address = offset_addr; 6397 else 6398 address = base_address; 6399 6400 // data = MemU[address,4]; 6401 6402 std::optional<RegisterInfo> base_reg = 6403 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 6404 EmulateInstruction::Context context; 6405 context.type = eContextRegisterLoad; 6406 context.SetRegisterPlusOffset(*base_reg, address - base_address); 6407 6408 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success); 6409 if (!success) 6410 return false; 6411 6412 // if wback then R[n] = offset_addr; 6413 if (wback) { 6414 context.type = eContextAdjustBaseRegister; 6415 context.SetAddress(offset_addr); 6416 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 6417 offset_addr)) 6418 return false; 6419 } 6420 6421 // if t == 15 then 6422 if (t == 15) { 6423 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6424 if (BitIsClear(address, 1) && BitIsClear(address, 0)) { 6425 // LoadWritePC (data); 6426 context.type = eContextRegisterLoad; 6427 context.SetRegisterPlusOffset(*base_reg, address - base_address); 6428 LoadWritePC(context, data); 6429 } else 6430 return false; 6431 } 6432 // elsif UnalignedSupport() || address<1:0> = '00' then 6433 else if (UnalignedSupport() || 6434 (BitIsClear(address, 1) && BitIsClear(address, 0))) { 6435 // R[t] = data; 6436 context.type = eContextRegisterLoad; 6437 context.SetRegisterPlusOffset(*base_reg, address - base_address); 6438 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 6439 data)) 6440 return false; 6441 } 6442 // else // Can only apply before ARMv7 6443 else { 6444 // R[t] = ROR(data, 8*UInt(address<1:0>)); 6445 data = ROR(data, Bits32(address, 1, 0), &success); 6446 if (!success) 6447 return false; 6448 context.type = eContextRegisterLoad; 6449 context.SetImmediate(data); 6450 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 6451 data)) 6452 return false; 6453 } 6454 } 6455 return true; 6456} 6457 6458// LDR (register) calculates an address from a base register value and an offset 6459// register value, loads a word 6460// from memory, and writes it to a register. The offset register value can 6461// optionally be shifted. 6462bool EmulateInstructionARM::EmulateLDRRegister(const uint32_t opcode, 6463 const ARMEncoding encoding) { 6464#if 0 6465 if ConditionPassed() then 6466 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6467 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6468 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6469 address = if index then offset_addr else R[n]; 6470 data = MemU[address,4]; 6471 if wback then R[n] = offset_addr; 6472 if t == 15 then 6473 if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6474 elsif UnalignedSupport() || address<1:0> = '00' then 6475 R[t] = data; 6476 else // Can only apply before ARMv7 6477 if CurrentInstrSet() == InstrSet_ARM then 6478 R[t] = ROR(data, 8*UInt(address<1:0>)); 6479 else 6480 R[t] = bits(32) UNKNOWN; 6481#endif 6482 6483 bool success = false; 6484 6485 if (ConditionPassed(opcode)) { 6486 const uint32_t addr_byte_size = GetAddressByteSize(); 6487 6488 uint32_t t; 6489 uint32_t n; 6490 uint32_t m; 6491 bool index; 6492 bool add; 6493 bool wback; 6494 ARM_ShifterType shift_t; 6495 uint32_t shift_n; 6496 6497 switch (encoding) { 6498 case eEncodingT1: 6499 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation 6500 // in ThumbEE"; 6501 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6502 t = Bits32(opcode, 2, 0); 6503 n = Bits32(opcode, 5, 3); 6504 m = Bits32(opcode, 8, 6); 6505 6506 // index = TRUE; add = TRUE; wback = FALSE; 6507 index = true; 6508 add = true; 6509 wback = false; 6510 6511 // (shift_t, shift_n) = (SRType_LSL, 0); 6512 shift_t = SRType_LSL; 6513 shift_n = 0; 6514 6515 break; 6516 6517 case eEncodingT2: 6518 // if Rn == '1111' then SEE LDR (literal); 6519 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6520 t = Bits32(opcode, 15, 12); 6521 n = Bits32(opcode, 19, 16); 6522 m = Bits32(opcode, 3, 0); 6523 6524 // index = TRUE; add = TRUE; wback = FALSE; 6525 index = true; 6526 add = true; 6527 wback = false; 6528 6529 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6530 shift_t = SRType_LSL; 6531 shift_n = Bits32(opcode, 5, 4); 6532 6533 // if BadReg(m) then UNPREDICTABLE; 6534 if (BadReg(m)) 6535 return false; 6536 6537 // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 6538 if ((t == 15) && InITBlock() && !LastInITBlock()) 6539 return false; 6540 6541 break; 6542 6543 case eEncodingA1: { 6544 // if P == '0' && W == '1' then SEE LDRT; 6545 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6546 t = Bits32(opcode, 15, 12); 6547 n = Bits32(opcode, 19, 16); 6548 m = Bits32(opcode, 3, 0); 6549 6550 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 6551 // (W == '1'); 6552 index = BitIsSet(opcode, 24); 6553 add = BitIsSet(opcode, 23); 6554 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 6555 6556 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 6557 uint32_t type = Bits32(opcode, 6, 5); 6558 uint32_t imm5 = Bits32(opcode, 11, 7); 6559 shift_n = DecodeImmShift(type, imm5, shift_t); 6560 6561 // if m == 15 then UNPREDICTABLE; 6562 if (m == 15) 6563 return false; 6564 6565 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6566 if (wback && ((n == 15) || (n == t))) 6567 return false; 6568 } break; 6569 6570 default: 6571 return false; 6572 } 6573 6574 uint32_t Rm = 6575 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 6576 if (!success) 6577 return false; 6578 6579 uint32_t Rn = 6580 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6581 if (!success) 6582 return false; 6583 6584 addr_t offset_addr; 6585 addr_t address; 6586 6587 // offset = Shift(R[m], shift_t, shift_n, APSR.C); -- Note "The APSR is 6588 // an application level alias for the CPSR". 6589 addr_t offset = 6590 Shift(Rm, shift_t, shift_n, Bit32(m_opcode_cpsr, APSR_C), &success); 6591 if (!success) 6592 return false; 6593 6594 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6595 if (add) 6596 offset_addr = Rn + offset; 6597 else 6598 offset_addr = Rn - offset; 6599 6600 // address = if index then offset_addr else R[n]; 6601 if (index) 6602 address = offset_addr; 6603 else 6604 address = Rn; 6605 6606 // data = MemU[address,4]; 6607 std::optional<RegisterInfo> base_reg = 6608 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 6609 EmulateInstruction::Context context; 6610 context.type = eContextRegisterLoad; 6611 context.SetRegisterPlusOffset(*base_reg, address - Rn); 6612 6613 uint64_t data = MemURead(context, address, addr_byte_size, 0, &success); 6614 if (!success) 6615 return false; 6616 6617 // if wback then R[n] = offset_addr; 6618 if (wback) { 6619 context.type = eContextAdjustBaseRegister; 6620 context.SetAddress(offset_addr); 6621 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 6622 offset_addr)) 6623 return false; 6624 } 6625 6626 // if t == 15 then 6627 if (t == 15) { 6628 // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 6629 if (BitIsClear(address, 1) && BitIsClear(address, 0)) { 6630 context.type = eContextRegisterLoad; 6631 context.SetRegisterPlusOffset(*base_reg, address - Rn); 6632 LoadWritePC(context, data); 6633 } else 6634 return false; 6635 } 6636 // elsif UnalignedSupport() || address<1:0> = '00' then 6637 else if (UnalignedSupport() || 6638 (BitIsClear(address, 1) && BitIsClear(address, 0))) { 6639 // R[t] = data; 6640 context.type = eContextRegisterLoad; 6641 context.SetRegisterPlusOffset(*base_reg, address - Rn); 6642 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 6643 data)) 6644 return false; 6645 } else // Can only apply before ARMv7 6646 { 6647 // if CurrentInstrSet() == InstrSet_ARM then 6648 if (CurrentInstrSet() == eModeARM) { 6649 // R[t] = ROR(data, 8*UInt(address<1:0>)); 6650 data = ROR(data, Bits32(address, 1, 0), &success); 6651 if (!success) 6652 return false; 6653 context.type = eContextRegisterLoad; 6654 context.SetImmediate(data); 6655 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 6656 data)) 6657 return false; 6658 } else { 6659 // R[t] = bits(32) UNKNOWN; 6660 WriteBits32Unknown(t); 6661 } 6662 } 6663 } 6664 return true; 6665} 6666 6667// LDRB (immediate, Thumb) 6668bool EmulateInstructionARM::EmulateLDRBImmediate(const uint32_t opcode, 6669 const ARMEncoding encoding) { 6670#if 0 6671 if ConditionPassed() then 6672 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6673 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6674 address = if index then offset_addr else R[n]; 6675 R[t] = ZeroExtend(MemU[address,1], 32); 6676 if wback then R[n] = offset_addr; 6677#endif 6678 6679 bool success = false; 6680 6681 if (ConditionPassed(opcode)) { 6682 uint32_t t; 6683 uint32_t n; 6684 uint32_t imm32; 6685 bool index; 6686 bool add; 6687 bool wback; 6688 6689 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6690 switch (encoding) { 6691 case eEncodingT1: 6692 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 6693 t = Bits32(opcode, 2, 0); 6694 n = Bits32(opcode, 5, 3); 6695 imm32 = Bits32(opcode, 10, 6); 6696 6697 // index = TRUE; add = TRUE; wback = FALSE; 6698 index = true; 6699 add = true; 6700 wback = false; 6701 6702 break; 6703 6704 case eEncodingT2: 6705 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 6706 t = Bits32(opcode, 15, 12); 6707 n = Bits32(opcode, 19, 16); 6708 imm32 = Bits32(opcode, 11, 0); 6709 6710 // index = TRUE; add = TRUE; wback = FALSE; 6711 index = true; 6712 add = true; 6713 wback = false; 6714 6715 // if Rt == '1111' then SEE PLD; 6716 if (t == 15) 6717 return false; // PLD is not implemented yet 6718 6719 // if Rn == '1111' then SEE LDRB (literal); 6720 if (n == 15) 6721 return EmulateLDRBLiteral(opcode, eEncodingT1); 6722 6723 // if t == 13 then UNPREDICTABLE; 6724 if (t == 13) 6725 return false; 6726 6727 break; 6728 6729 case eEncodingT3: 6730 // if P == '1' && U == '1' && W == '0' then SEE LDRBT; 6731 // if P == '0' && W == '0' then UNDEFINED; 6732 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) 6733 return false; 6734 6735 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 6736 t = Bits32(opcode, 15, 12); 6737 n = Bits32(opcode, 19, 16); 6738 imm32 = Bits32(opcode, 7, 0); 6739 6740 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 6741 index = BitIsSet(opcode, 10); 6742 add = BitIsSet(opcode, 9); 6743 wback = BitIsSet(opcode, 8); 6744 6745 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; 6746 if (t == 15) 6747 return false; // PLD is not implemented yet 6748 6749 // if Rn == '1111' then SEE LDRB (literal); 6750 if (n == 15) 6751 return EmulateLDRBLiteral(opcode, eEncodingT1); 6752 6753 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 6754 if (BadReg(t) || (wback && (n == t))) 6755 return false; 6756 6757 break; 6758 6759 default: 6760 return false; 6761 } 6762 6763 uint32_t Rn = 6764 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 6765 if (!success) 6766 return false; 6767 6768 addr_t address; 6769 addr_t offset_addr; 6770 6771 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 6772 if (add) 6773 offset_addr = Rn + imm32; 6774 else 6775 offset_addr = Rn - imm32; 6776 6777 // address = if index then offset_addr else R[n]; 6778 if (index) 6779 address = offset_addr; 6780 else 6781 address = Rn; 6782 6783 // R[t] = ZeroExtend(MemU[address,1], 32); 6784 std::optional<RegisterInfo> base_reg = 6785 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 6786 std::optional<RegisterInfo> data_reg = 6787 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 6788 6789 EmulateInstruction::Context context; 6790 context.type = eContextRegisterLoad; 6791 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 6792 6793 uint64_t data = MemURead(context, address, 1, 0, &success); 6794 if (!success) 6795 return false; 6796 6797 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6798 return false; 6799 6800 // if wback then R[n] = offset_addr; 6801 if (wback) { 6802 context.type = eContextAdjustBaseRegister; 6803 context.SetAddress(offset_addr); 6804 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 6805 offset_addr)) 6806 return false; 6807 } 6808 } 6809 return true; 6810} 6811 6812// LDRB (literal) calculates an address from the PC value and an immediate 6813// offset, loads a byte from memory, 6814// zero-extends it to form a 32-bit word and writes it to a register. 6815bool EmulateInstructionARM::EmulateLDRBLiteral(const uint32_t opcode, 6816 const ARMEncoding encoding) { 6817#if 0 6818 if ConditionPassed() then 6819 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 6820 base = Align(PC,4); 6821 address = if add then (base + imm32) else (base - imm32); 6822 R[t] = ZeroExtend(MemU[address,1], 32); 6823#endif 6824 6825 bool success = false; 6826 6827 if (ConditionPassed(opcode)) { 6828 uint32_t t; 6829 uint32_t imm32; 6830 bool add; 6831 switch (encoding) { 6832 case eEncodingT1: 6833 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6834 t = Bits32(opcode, 15, 12); 6835 imm32 = Bits32(opcode, 11, 0); 6836 add = BitIsSet(opcode, 23); 6837 6838 // if Rt == '1111' then SEE PLD; 6839 if (t == 15) 6840 return false; // PLD is not implemented yet 6841 6842 // if t == 13 then UNPREDICTABLE; 6843 if (t == 13) 6844 return false; 6845 6846 break; 6847 6848 case eEncodingA1: 6849 // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 6850 t = Bits32(opcode, 15, 12); 6851 imm32 = Bits32(opcode, 11, 0); 6852 add = BitIsSet(opcode, 23); 6853 6854 // if t == 15 then UNPREDICTABLE; 6855 if (t == 15) 6856 return false; 6857 break; 6858 6859 default: 6860 return false; 6861 } 6862 6863 // base = Align(PC,4); 6864 uint32_t pc_val = ReadCoreReg(PC_REG, &success); 6865 if (!success) 6866 return false; 6867 6868 uint32_t base = AlignPC(pc_val); 6869 6870 addr_t address; 6871 // address = if add then (base + imm32) else (base - imm32); 6872 if (add) 6873 address = base + imm32; 6874 else 6875 address = base - imm32; 6876 6877 // R[t] = ZeroExtend(MemU[address,1], 32); 6878 EmulateInstruction::Context context; 6879 context.type = eContextRelativeBranchImmediate; 6880 context.SetImmediate(address - base); 6881 6882 uint64_t data = MemURead(context, address, 1, 0, &success); 6883 if (!success) 6884 return false; 6885 6886 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) 6887 return false; 6888 } 6889 return true; 6890} 6891 6892// LDRB (register) calculates an address from a base register value and an 6893// offset rigister value, loads a byte from memory, zero-extends it to form a 6894// 32-bit word, and writes it to a register. The offset register value can 6895// optionally be shifted. 6896bool EmulateInstructionARM::EmulateLDRBRegister(const uint32_t opcode, 6897 const ARMEncoding encoding) { 6898#if 0 6899 if ConditionPassed() then 6900 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6901 offset = Shift(R[m], shift_t, shift_n, APSR.C); 6902 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 6903 address = if index then offset_addr else R[n]; 6904 R[t] = ZeroExtend(MemU[address,1],32); 6905 if wback then R[n] = offset_addr; 6906#endif 6907 6908 bool success = false; 6909 6910 if (ConditionPassed(opcode)) { 6911 uint32_t t; 6912 uint32_t n; 6913 uint32_t m; 6914 bool index; 6915 bool add; 6916 bool wback; 6917 ARM_ShifterType shift_t; 6918 uint32_t shift_n; 6919 6920 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 6921 switch (encoding) { 6922 case eEncodingT1: 6923 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6924 t = Bits32(opcode, 2, 0); 6925 n = Bits32(opcode, 5, 3); 6926 m = Bits32(opcode, 8, 6); 6927 6928 // index = TRUE; add = TRUE; wback = FALSE; 6929 index = true; 6930 add = true; 6931 wback = false; 6932 6933 // (shift_t, shift_n) = (SRType_LSL, 0); 6934 shift_t = SRType_LSL; 6935 shift_n = 0; 6936 break; 6937 6938 case eEncodingT2: 6939 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6940 t = Bits32(opcode, 15, 12); 6941 n = Bits32(opcode, 19, 16); 6942 m = Bits32(opcode, 3, 0); 6943 6944 // index = TRUE; add = TRUE; wback = FALSE; 6945 index = true; 6946 add = true; 6947 wback = false; 6948 6949 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 6950 shift_t = SRType_LSL; 6951 shift_n = Bits32(opcode, 5, 4); 6952 6953 // if Rt == '1111' then SEE PLD; 6954 if (t == 15) 6955 return false; // PLD is not implemented yet 6956 6957 // if Rn == '1111' then SEE LDRB (literal); 6958 if (n == 15) 6959 return EmulateLDRBLiteral(opcode, eEncodingT1); 6960 6961 // if t == 13 || BadReg(m) then UNPREDICTABLE; 6962 if ((t == 13) || BadReg(m)) 6963 return false; 6964 break; 6965 6966 case eEncodingA1: { 6967 // if P == '0' && W == '1' then SEE LDRBT; 6968 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 6969 t = Bits32(opcode, 15, 12); 6970 n = Bits32(opcode, 19, 16); 6971 m = Bits32(opcode, 3, 0); 6972 6973 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 6974 // (W == '1'); 6975 index = BitIsSet(opcode, 24); 6976 add = BitIsSet(opcode, 23); 6977 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 6978 6979 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 6980 uint32_t type = Bits32(opcode, 6, 5); 6981 uint32_t imm5 = Bits32(opcode, 11, 7); 6982 shift_n = DecodeImmShift(type, imm5, shift_t); 6983 6984 // if t == 15 || m == 15 then UNPREDICTABLE; 6985 if ((t == 15) || (m == 15)) 6986 return false; 6987 6988 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 6989 if (wback && ((n == 15) || (n == t))) 6990 return false; 6991 } break; 6992 6993 default: 6994 return false; 6995 } 6996 6997 addr_t offset_addr; 6998 addr_t address; 6999 7000 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7001 uint32_t Rm = 7002 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7003 if (!success) 7004 return false; 7005 7006 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); 7007 if (!success) 7008 return false; 7009 7010 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7011 uint32_t Rn = 7012 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7013 if (!success) 7014 return false; 7015 7016 if (add) 7017 offset_addr = Rn + offset; 7018 else 7019 offset_addr = Rn - offset; 7020 7021 // address = if index then offset_addr else R[n]; 7022 if (index) 7023 address = offset_addr; 7024 else 7025 address = Rn; 7026 7027 // R[t] = ZeroExtend(MemU[address,1],32); 7028 std::optional<RegisterInfo> base_reg = 7029 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 7030 7031 EmulateInstruction::Context context; 7032 context.type = eContextRegisterLoad; 7033 context.SetRegisterPlusOffset(*base_reg, address - Rn); 7034 7035 uint64_t data = MemURead(context, address, 1, 0, &success); 7036 if (!success) 7037 return false; 7038 7039 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) 7040 return false; 7041 7042 // if wback then R[n] = offset_addr; 7043 if (wback) { 7044 context.type = eContextAdjustBaseRegister; 7045 context.SetAddress(offset_addr); 7046 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 7047 offset_addr)) 7048 return false; 7049 } 7050 } 7051 return true; 7052} 7053 7054// LDRH (immediate, Thumb) calculates an address from a base register value and 7055// an immediate offset, loads a 7056// halfword from memory, zero-extends it to form a 32-bit word, and writes it 7057// to a register. It can use offset, post-indexed, or pre-indexed addressing. 7058bool EmulateInstructionARM::EmulateLDRHImmediate(const uint32_t opcode, 7059 const ARMEncoding encoding) { 7060#if 0 7061 if ConditionPassed() then 7062 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7063 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7064 address = if index then offset_addr else R[n]; 7065 data = MemU[address,2]; 7066 if wback then R[n] = offset_addr; 7067 if UnalignedSupport() || address<0> = '0' then 7068 R[t] = ZeroExtend(data, 32); 7069 else // Can only apply before ARMv7 7070 R[t] = bits(32) UNKNOWN; 7071#endif 7072 7073 bool success = false; 7074 7075 if (ConditionPassed(opcode)) { 7076 uint32_t t; 7077 uint32_t n; 7078 uint32_t imm32; 7079 bool index; 7080 bool add; 7081 bool wback; 7082 7083 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7084 switch (encoding) { 7085 case eEncodingT1: 7086 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32); 7087 t = Bits32(opcode, 2, 0); 7088 n = Bits32(opcode, 5, 3); 7089 imm32 = Bits32(opcode, 10, 6) << 1; 7090 7091 // index = TRUE; add = TRUE; wback = FALSE; 7092 index = true; 7093 add = true; 7094 wback = false; 7095 7096 break; 7097 7098 case eEncodingT2: 7099 // if Rt == '1111' then SEE "Unallocated memory hints"; 7100 // if Rn == '1111' then SEE LDRH (literal); 7101 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7102 t = Bits32(opcode, 15, 12); 7103 n = Bits32(opcode, 19, 16); 7104 imm32 = Bits32(opcode, 11, 0); 7105 7106 // index = TRUE; add = TRUE; wback = FALSE; 7107 index = true; 7108 add = true; 7109 wback = false; 7110 7111 // if t == 13 then UNPREDICTABLE; 7112 if (t == 13) 7113 return false; 7114 break; 7115 7116 case eEncodingT3: 7117 // if Rn == '1111' then SEE LDRH (literal); 7118 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE 7119 // "Unallocated memory hints"; 7120 // if P == '1' && U == '1' && W == '0' then SEE LDRHT; 7121 // if P == '0' && W == '0' then UNDEFINED; 7122 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) 7123 return false; 7124 7125 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7126 t = Bits32(opcode, 15, 12); 7127 n = Bits32(opcode, 19, 16); 7128 imm32 = Bits32(opcode, 7, 0); 7129 7130 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7131 index = BitIsSet(opcode, 10); 7132 add = BitIsSet(opcode, 9); 7133 wback = BitIsSet(opcode, 8); 7134 7135 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7136 if (BadReg(t) || (wback && (n == t))) 7137 return false; 7138 break; 7139 7140 default: 7141 return false; 7142 } 7143 7144 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7145 uint32_t Rn = 7146 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7147 if (!success) 7148 return false; 7149 7150 addr_t offset_addr; 7151 addr_t address; 7152 7153 if (add) 7154 offset_addr = Rn + imm32; 7155 else 7156 offset_addr = Rn - imm32; 7157 7158 // address = if index then offset_addr else R[n]; 7159 if (index) 7160 address = offset_addr; 7161 else 7162 address = Rn; 7163 7164 // data = MemU[address,2]; 7165 std::optional<RegisterInfo> base_reg = 7166 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 7167 7168 EmulateInstruction::Context context; 7169 context.type = eContextRegisterLoad; 7170 context.SetRegisterPlusOffset(*base_reg, address - Rn); 7171 7172 uint64_t data = MemURead(context, address, 2, 0, &success); 7173 if (!success) 7174 return false; 7175 7176 // if wback then R[n] = offset_addr; 7177 if (wback) { 7178 context.type = eContextAdjustBaseRegister; 7179 context.SetAddress(offset_addr); 7180 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 7181 offset_addr)) 7182 return false; 7183 } 7184 7185 // if UnalignedSupport() || address<0> = '0' then 7186 if (UnalignedSupport() || BitIsClear(address, 0)) { 7187 // R[t] = ZeroExtend(data, 32); 7188 context.type = eContextRegisterLoad; 7189 context.SetRegisterPlusOffset(*base_reg, address - Rn); 7190 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7191 data)) 7192 return false; 7193 } else // Can only apply before ARMv7 7194 { 7195 // R[t] = bits(32) UNKNOWN; 7196 WriteBits32Unknown(t); 7197 } 7198 } 7199 return true; 7200} 7201 7202// LDRH (literal) calculates an address from the PC value and an immediate 7203// offset, loads a halfword from memory, 7204// zero-extends it to form a 32-bit word, and writes it to a register. 7205bool EmulateInstructionARM::EmulateLDRHLiteral(const uint32_t opcode, 7206 const ARMEncoding encoding) { 7207#if 0 7208 if ConditionPassed() then 7209 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7210 base = Align(PC,4); 7211 address = if add then (base + imm32) else (base - imm32); 7212 data = MemU[address,2]; 7213 if UnalignedSupport() || address<0> = '0' then 7214 R[t] = ZeroExtend(data, 32); 7215 else // Can only apply before ARMv7 7216 R[t] = bits(32) UNKNOWN; 7217#endif 7218 7219 bool success = false; 7220 7221 if (ConditionPassed(opcode)) { 7222 uint32_t t; 7223 uint32_t imm32; 7224 bool add; 7225 7226 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7227 switch (encoding) { 7228 case eEncodingT1: 7229 // if Rt == '1111' then SEE "Unallocated memory hints"; 7230 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 7231 t = Bits32(opcode, 15, 12); 7232 imm32 = Bits32(opcode, 11, 0); 7233 add = BitIsSet(opcode, 23); 7234 7235 // if t == 13 then UNPREDICTABLE; 7236 if (t == 13) 7237 return false; 7238 7239 break; 7240 7241 case eEncodingA1: { 7242 uint32_t imm4H = Bits32(opcode, 11, 8); 7243 uint32_t imm4L = Bits32(opcode, 3, 0); 7244 7245 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 7246 t = Bits32(opcode, 15, 12); 7247 imm32 = (imm4H << 4) | imm4L; 7248 add = BitIsSet(opcode, 23); 7249 7250 // if t == 15 then UNPREDICTABLE; 7251 if (t == 15) 7252 return false; 7253 break; 7254 } 7255 7256 default: 7257 return false; 7258 } 7259 7260 // base = Align(PC,4); 7261 uint64_t pc_value = ReadCoreReg(PC_REG, &success); 7262 if (!success) 7263 return false; 7264 7265 addr_t base = AlignPC(pc_value); 7266 addr_t address; 7267 7268 // address = if add then (base + imm32) else (base - imm32); 7269 if (add) 7270 address = base + imm32; 7271 else 7272 address = base - imm32; 7273 7274 // data = MemU[address,2]; 7275 std::optional<RegisterInfo> base_reg = 7276 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 7277 7278 EmulateInstruction::Context context; 7279 context.type = eContextRegisterLoad; 7280 context.SetRegisterPlusOffset(*base_reg, address - base); 7281 7282 uint64_t data = MemURead(context, address, 2, 0, &success); 7283 if (!success) 7284 return false; 7285 7286 // if UnalignedSupport() || address<0> = '0' then 7287 if (UnalignedSupport() || BitIsClear(address, 0)) { 7288 // R[t] = ZeroExtend(data, 32); 7289 context.type = eContextRegisterLoad; 7290 context.SetRegisterPlusOffset(*base_reg, address - base); 7291 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7292 data)) 7293 return false; 7294 7295 } else // Can only apply before ARMv7 7296 { 7297 // R[t] = bits(32) UNKNOWN; 7298 WriteBits32Unknown(t); 7299 } 7300 } 7301 return true; 7302} 7303 7304// LDRH (literal) calculates an address from a base register value and an offset 7305// register value, loads a halfword 7306// from memory, zero-extends it to form a 32-bit word, and writes it to a 7307// register. The offset register value can be shifted left by 0, 1, 2, or 3 7308// bits. 7309bool EmulateInstructionARM::EmulateLDRHRegister(const uint32_t opcode, 7310 const ARMEncoding encoding) { 7311#if 0 7312 if ConditionPassed() then 7313 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7314 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7315 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7316 address = if index then offset_addr else R[n]; 7317 data = MemU[address,2]; 7318 if wback then R[n] = offset_addr; 7319 if UnalignedSupport() || address<0> = '0' then 7320 R[t] = ZeroExtend(data, 32); 7321 else // Can only apply before ARMv7 7322 R[t] = bits(32) UNKNOWN; 7323#endif 7324 7325 bool success = false; 7326 7327 if (ConditionPassed(opcode)) { 7328 uint32_t t; 7329 uint32_t n; 7330 uint32_t m; 7331 bool index; 7332 bool add; 7333 bool wback; 7334 ARM_ShifterType shift_t; 7335 uint32_t shift_n; 7336 7337 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7338 switch (encoding) { 7339 case eEncodingT1: 7340 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation 7341 // in ThumbEE"; 7342 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7343 t = Bits32(opcode, 2, 0); 7344 n = Bits32(opcode, 5, 3); 7345 m = Bits32(opcode, 8, 6); 7346 7347 // index = TRUE; add = TRUE; wback = FALSE; 7348 index = true; 7349 add = true; 7350 wback = false; 7351 7352 // (shift_t, shift_n) = (SRType_LSL, 0); 7353 shift_t = SRType_LSL; 7354 shift_n = 0; 7355 7356 break; 7357 7358 case eEncodingT2: 7359 // if Rn == '1111' then SEE LDRH (literal); 7360 // if Rt == '1111' then SEE "Unallocated memory hints"; 7361 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7362 t = Bits32(opcode, 15, 12); 7363 n = Bits32(opcode, 19, 16); 7364 m = Bits32(opcode, 3, 0); 7365 7366 // index = TRUE; add = TRUE; wback = FALSE; 7367 index = true; 7368 add = true; 7369 wback = false; 7370 7371 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7372 shift_t = SRType_LSL; 7373 shift_n = Bits32(opcode, 5, 4); 7374 7375 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7376 if ((t == 13) || BadReg(m)) 7377 return false; 7378 break; 7379 7380 case eEncodingA1: 7381 // if P == '0' && W == '1' then SEE LDRHT; 7382 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7383 t = Bits32(opcode, 15, 12); 7384 n = Bits32(opcode, 19, 16); 7385 m = Bits32(opcode, 3, 0); 7386 7387 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 7388 // (W == '1'); 7389 index = BitIsSet(opcode, 24); 7390 add = BitIsSet(opcode, 23); 7391 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 7392 7393 // (shift_t, shift_n) = (SRType_LSL, 0); 7394 shift_t = SRType_LSL; 7395 shift_n = 0; 7396 7397 // if t == 15 || m == 15 then UNPREDICTABLE; 7398 if ((t == 15) || (m == 15)) 7399 return false; 7400 7401 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7402 if (wback && ((n == 15) || (n == t))) 7403 return false; 7404 7405 break; 7406 7407 default: 7408 return false; 7409 } 7410 7411 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7412 7413 uint64_t Rm = 7414 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7415 if (!success) 7416 return false; 7417 7418 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); 7419 if (!success) 7420 return false; 7421 7422 addr_t offset_addr; 7423 addr_t address; 7424 7425 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7426 uint64_t Rn = 7427 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7428 if (!success) 7429 return false; 7430 7431 if (add) 7432 offset_addr = Rn + offset; 7433 else 7434 offset_addr = Rn - offset; 7435 7436 // address = if index then offset_addr else R[n]; 7437 if (index) 7438 address = offset_addr; 7439 else 7440 address = Rn; 7441 7442 // data = MemU[address,2]; 7443 std::optional<RegisterInfo> base_reg = 7444 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 7445 std::optional<RegisterInfo> offset_reg = 7446 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 7447 7448 EmulateInstruction::Context context; 7449 context.type = eContextRegisterLoad; 7450 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); 7451 uint64_t data = MemURead(context, address, 2, 0, &success); 7452 if (!success) 7453 return false; 7454 7455 // if wback then R[n] = offset_addr; 7456 if (wback) { 7457 context.type = eContextAdjustBaseRegister; 7458 context.SetAddress(offset_addr); 7459 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 7460 offset_addr)) 7461 return false; 7462 } 7463 7464 // if UnalignedSupport() || address<0> = '0' then 7465 if (UnalignedSupport() || BitIsClear(address, 0)) { 7466 // R[t] = ZeroExtend(data, 32); 7467 context.type = eContextRegisterLoad; 7468 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); 7469 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7470 data)) 7471 return false; 7472 } else // Can only apply before ARMv7 7473 { 7474 // R[t] = bits(32) UNKNOWN; 7475 WriteBits32Unknown(t); 7476 } 7477 } 7478 return true; 7479} 7480 7481// LDRSB (immediate) calculates an address from a base register value and an 7482// immediate offset, loads a byte from 7483// memory, sign-extends it to form a 32-bit word, and writes it to a register. 7484// It can use offset, post-indexed, or pre-indexed addressing. 7485bool EmulateInstructionARM::EmulateLDRSBImmediate(const uint32_t opcode, 7486 const ARMEncoding encoding) { 7487#if 0 7488 if ConditionPassed() then 7489 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7490 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7491 address = if index then offset_addr else R[n]; 7492 R[t] = SignExtend(MemU[address,1], 32); 7493 if wback then R[n] = offset_addr; 7494#endif 7495 7496 bool success = false; 7497 7498 if (ConditionPassed(opcode)) { 7499 uint32_t t; 7500 uint32_t n; 7501 uint32_t imm32; 7502 bool index; 7503 bool add; 7504 bool wback; 7505 7506 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7507 switch (encoding) { 7508 case eEncodingT1: 7509 // if Rt == '1111' then SEE PLI; 7510 // if Rn == '1111' then SEE LDRSB (literal); 7511 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7512 t = Bits32(opcode, 15, 12); 7513 n = Bits32(opcode, 19, 16); 7514 imm32 = Bits32(opcode, 11, 0); 7515 7516 // index = TRUE; add = TRUE; wback = FALSE; 7517 index = true; 7518 add = true; 7519 wback = false; 7520 7521 // if t == 13 then UNPREDICTABLE; 7522 if (t == 13) 7523 return false; 7524 7525 break; 7526 7527 case eEncodingT2: 7528 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI; 7529 // if Rn == '1111' then SEE LDRSB (literal); 7530 // if P == '1' && U == '1' && W == '0' then SEE LDRSBT; 7531 // if P == '0' && W == '0' then UNDEFINED; 7532 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) 7533 return false; 7534 7535 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7536 t = Bits32(opcode, 15, 12); 7537 n = Bits32(opcode, 19, 16); 7538 imm32 = Bits32(opcode, 7, 0); 7539 7540 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7541 index = BitIsSet(opcode, 10); 7542 add = BitIsSet(opcode, 9); 7543 wback = BitIsSet(opcode, 8); 7544 7545 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7546 if (((t == 13) || 7547 ((t == 15) && (BitIsClear(opcode, 10) || BitIsSet(opcode, 9) || 7548 BitIsSet(opcode, 8)))) || 7549 (wback && (n == t))) 7550 return false; 7551 7552 break; 7553 7554 case eEncodingA1: { 7555 // if Rn == '1111' then SEE LDRSB (literal); 7556 // if P == '0' && W == '1' then SEE LDRSBT; 7557 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 7558 t = Bits32(opcode, 15, 12); 7559 n = Bits32(opcode, 19, 16); 7560 7561 uint32_t imm4H = Bits32(opcode, 11, 8); 7562 uint32_t imm4L = Bits32(opcode, 3, 0); 7563 imm32 = (imm4H << 4) | imm4L; 7564 7565 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 7566 // (W == '1'); 7567 index = BitIsSet(opcode, 24); 7568 add = BitIsSet(opcode, 23); 7569 wback = (BitIsClear(opcode, 24) || BitIsSet(opcode, 21)); 7570 7571 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 7572 if ((t == 15) || (wback && (n == t))) 7573 return false; 7574 7575 break; 7576 } 7577 7578 default: 7579 return false; 7580 } 7581 7582 uint64_t Rn = ReadCoreReg(n, &success); 7583 if (!success) 7584 return false; 7585 7586 addr_t offset_addr; 7587 addr_t address; 7588 7589 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7590 if (add) 7591 offset_addr = Rn + imm32; 7592 else 7593 offset_addr = Rn - imm32; 7594 7595 // address = if index then offset_addr else R[n]; 7596 if (index) 7597 address = offset_addr; 7598 else 7599 address = Rn; 7600 7601 // R[t] = SignExtend(MemU[address,1], 32); 7602 std::optional<RegisterInfo> base_reg = 7603 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 7604 7605 EmulateInstruction::Context context; 7606 context.type = eContextRegisterLoad; 7607 context.SetRegisterPlusOffset(*base_reg, address - Rn); 7608 7609 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); 7610 if (!success) 7611 return false; 7612 7613 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7614 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7615 (uint64_t)signed_data)) 7616 return false; 7617 7618 // if wback then R[n] = offset_addr; 7619 if (wback) { 7620 context.type = eContextAdjustBaseRegister; 7621 context.SetAddress(offset_addr); 7622 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 7623 offset_addr)) 7624 return false; 7625 } 7626 } 7627 7628 return true; 7629} 7630 7631// LDRSB (literal) calculates an address from the PC value and an immediate 7632// offset, loads a byte from memory, 7633// sign-extends it to form a 32-bit word, and writes tit to a register. 7634bool EmulateInstructionARM::EmulateLDRSBLiteral(const uint32_t opcode, 7635 const ARMEncoding encoding) { 7636#if 0 7637 if ConditionPassed() then 7638 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7639 base = Align(PC,4); 7640 address = if add then (base + imm32) else (base - imm32); 7641 R[t] = SignExtend(MemU[address,1], 32); 7642#endif 7643 7644 bool success = false; 7645 7646 if (ConditionPassed(opcode)) { 7647 uint32_t t; 7648 uint32_t imm32; 7649 bool add; 7650 7651 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 7652 switch (encoding) { 7653 case eEncodingT1: 7654 // if Rt == '1111' then SEE PLI; 7655 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 7656 t = Bits32(opcode, 15, 12); 7657 imm32 = Bits32(opcode, 11, 0); 7658 add = BitIsSet(opcode, 23); 7659 7660 // if t == 13 then UNPREDICTABLE; 7661 if (t == 13) 7662 return false; 7663 7664 break; 7665 7666 case eEncodingA1: { 7667 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 7668 t = Bits32(opcode, 15, 12); 7669 uint32_t imm4H = Bits32(opcode, 11, 8); 7670 uint32_t imm4L = Bits32(opcode, 3, 0); 7671 imm32 = (imm4H << 4) | imm4L; 7672 add = BitIsSet(opcode, 23); 7673 7674 // if t == 15 then UNPREDICTABLE; 7675 if (t == 15) 7676 return false; 7677 7678 break; 7679 } 7680 7681 default: 7682 return false; 7683 } 7684 7685 // base = Align(PC,4); 7686 uint64_t pc_value = ReadCoreReg(PC_REG, &success); 7687 if (!success) 7688 return false; 7689 uint64_t base = AlignPC(pc_value); 7690 7691 // address = if add then (base + imm32) else (base - imm32); 7692 addr_t address; 7693 if (add) 7694 address = base + imm32; 7695 else 7696 address = base - imm32; 7697 7698 // R[t] = SignExtend(MemU[address,1], 32); 7699 std::optional<RegisterInfo> base_reg = 7700 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 7701 7702 EmulateInstruction::Context context; 7703 context.type = eContextRegisterLoad; 7704 context.SetRegisterPlusOffset(*base_reg, address - base); 7705 7706 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); 7707 if (!success) 7708 return false; 7709 7710 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7711 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7712 (uint64_t)signed_data)) 7713 return false; 7714 } 7715 return true; 7716} 7717 7718// LDRSB (register) calculates an address from a base register value and an 7719// offset register value, loadsa byte from 7720// memory, sign-extends it to form a 32-bit word, and writes it to a register. 7721// The offset register value can be shifted left by 0, 1, 2, or 3 bits. 7722bool EmulateInstructionARM::EmulateLDRSBRegister(const uint32_t opcode, 7723 const ARMEncoding encoding) { 7724#if 0 7725 if ConditionPassed() then 7726 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7727 offset = Shift(R[m], shift_t, shift_n, APSR.C); 7728 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7729 address = if index then offset_addr else R[n]; 7730 R[t] = SignExtend(MemU[address,1], 32); 7731 if wback then R[n] = offset_addr; 7732#endif 7733 7734 bool success = false; 7735 7736 if (ConditionPassed(opcode)) { 7737 uint32_t t; 7738 uint32_t n; 7739 uint32_t m; 7740 bool index; 7741 bool add; 7742 bool wback; 7743 ARM_ShifterType shift_t; 7744 uint32_t shift_n; 7745 7746 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7747 switch (encoding) { 7748 case eEncodingT1: 7749 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7750 t = Bits32(opcode, 2, 0); 7751 n = Bits32(opcode, 5, 3); 7752 m = Bits32(opcode, 8, 6); 7753 7754 // index = TRUE; add = TRUE; wback = FALSE; 7755 index = true; 7756 add = true; 7757 wback = false; 7758 7759 // (shift_t, shift_n) = (SRType_LSL, 0); 7760 shift_t = SRType_LSL; 7761 shift_n = 0; 7762 7763 break; 7764 7765 case eEncodingT2: 7766 // if Rt == '1111' then SEE PLI; 7767 // if Rn == '1111' then SEE LDRSB (literal); 7768 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7769 t = Bits32(opcode, 15, 12); 7770 n = Bits32(opcode, 19, 16); 7771 m = Bits32(opcode, 3, 0); 7772 7773 // index = TRUE; add = TRUE; wback = FALSE; 7774 index = true; 7775 add = true; 7776 wback = false; 7777 7778 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 7779 shift_t = SRType_LSL; 7780 shift_n = Bits32(opcode, 5, 4); 7781 7782 // if t == 13 || BadReg(m) then UNPREDICTABLE; 7783 if ((t == 13) || BadReg(m)) 7784 return false; 7785 break; 7786 7787 case eEncodingA1: 7788 // if P == '0' && W == '1' then SEE LDRSBT; 7789 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 7790 t = Bits32(opcode, 15, 12); 7791 n = Bits32(opcode, 19, 16); 7792 m = Bits32(opcode, 3, 0); 7793 7794 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 7795 // (W == '1'); 7796 index = BitIsSet(opcode, 24); 7797 add = BitIsSet(opcode, 23); 7798 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 7799 7800 // (shift_t, shift_n) = (SRType_LSL, 0); 7801 shift_t = SRType_LSL; 7802 shift_n = 0; 7803 7804 // if t == 15 || m == 15 then UNPREDICTABLE; 7805 if ((t == 15) || (m == 15)) 7806 return false; 7807 7808 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 7809 if (wback && ((n == 15) || (n == t))) 7810 return false; 7811 break; 7812 7813 default: 7814 return false; 7815 } 7816 7817 uint64_t Rm = 7818 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 7819 if (!success) 7820 return false; 7821 7822 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 7823 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); 7824 if (!success) 7825 return false; 7826 7827 addr_t offset_addr; 7828 addr_t address; 7829 7830 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 7831 uint64_t Rn = 7832 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7833 if (!success) 7834 return false; 7835 7836 if (add) 7837 offset_addr = Rn + offset; 7838 else 7839 offset_addr = Rn - offset; 7840 7841 // address = if index then offset_addr else R[n]; 7842 if (index) 7843 address = offset_addr; 7844 else 7845 address = Rn; 7846 7847 // R[t] = SignExtend(MemU[address,1], 32); 7848 std::optional<RegisterInfo> base_reg = 7849 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 7850 std::optional<RegisterInfo> offset_reg = 7851 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 7852 7853 EmulateInstruction::Context context; 7854 context.type = eContextRegisterLoad; 7855 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); 7856 7857 uint64_t unsigned_data = MemURead(context, address, 1, 0, &success); 7858 if (!success) 7859 return false; 7860 7861 int64_t signed_data = llvm::SignExtend64<8>(unsigned_data); 7862 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 7863 (uint64_t)signed_data)) 7864 return false; 7865 7866 // if wback then R[n] = offset_addr; 7867 if (wback) { 7868 context.type = eContextAdjustBaseRegister; 7869 context.SetAddress(offset_addr); 7870 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 7871 offset_addr)) 7872 return false; 7873 } 7874 } 7875 return true; 7876} 7877 7878// LDRSH (immediate) calculates an address from a base register value and an 7879// immediate offset, loads a halfword from 7880// memory, sign-extends it to form a 32-bit word, and writes it to a register. 7881// It can use offset, post-indexed, or pre-indexed addressing. 7882bool EmulateInstructionARM::EmulateLDRSHImmediate(const uint32_t opcode, 7883 const ARMEncoding encoding) { 7884#if 0 7885 if ConditionPassed() then 7886 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7887 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7888 address = if index then offset_addr else R[n]; 7889 data = MemU[address,2]; 7890 if wback then R[n] = offset_addr; 7891 if UnalignedSupport() || address<0> = '0' then 7892 R[t] = SignExtend(data, 32); 7893 else // Can only apply before ARMv7 7894 R[t] = bits(32) UNKNOWN; 7895#endif 7896 7897 bool success = false; 7898 7899 if (ConditionPassed(opcode)) { 7900 uint32_t t; 7901 uint32_t n; 7902 uint32_t imm32; 7903 bool index; 7904 bool add; 7905 bool wback; 7906 7907 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 7908 switch (encoding) { 7909 case eEncodingT1: 7910 // if Rn == '1111' then SEE LDRSH (literal); 7911 // if Rt == '1111' then SEE "Unallocated memory hints"; 7912 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 7913 t = Bits32(opcode, 15, 12); 7914 n = Bits32(opcode, 19, 16); 7915 imm32 = Bits32(opcode, 11, 0); 7916 7917 // index = TRUE; add = TRUE; wback = FALSE; 7918 index = true; 7919 add = true; 7920 wback = false; 7921 7922 // if t == 13 then UNPREDICTABLE; 7923 if (t == 13) 7924 return false; 7925 7926 break; 7927 7928 case eEncodingT2: 7929 // if Rn == '1111' then SEE LDRSH (literal); 7930 // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE 7931 // "Unallocated memory hints"; 7932 // if P == '1' && U == '1' && W == '0' then SEE LDRSHT; 7933 // if P == '0' && W == '0' then UNDEFINED; 7934 if (BitIsClear(opcode, 10) && BitIsClear(opcode, 8)) 7935 return false; 7936 7937 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 7938 t = Bits32(opcode, 15, 12); 7939 n = Bits32(opcode, 19, 16); 7940 imm32 = Bits32(opcode, 7, 0); 7941 7942 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 7943 index = BitIsSet(opcode, 10); 7944 add = BitIsSet(opcode, 9); 7945 wback = BitIsSet(opcode, 8); 7946 7947 // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; 7948 if (BadReg(t) || (wback && (n == t))) 7949 return false; 7950 7951 break; 7952 7953 case eEncodingA1: { 7954 // if Rn == '1111' then SEE LDRSH (literal); 7955 // if P == '0' && W == '1' then SEE LDRSHT; 7956 // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 7957 t = Bits32(opcode, 15, 12); 7958 n = Bits32(opcode, 19, 16); 7959 uint32_t imm4H = Bits32(opcode, 11, 8); 7960 uint32_t imm4L = Bits32(opcode, 3, 0); 7961 imm32 = (imm4H << 4) | imm4L; 7962 7963 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 7964 // (W == '1'); 7965 index = BitIsSet(opcode, 24); 7966 add = BitIsSet(opcode, 23); 7967 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 7968 7969 // if t == 15 || (wback && n == t) then UNPREDICTABLE; 7970 if ((t == 15) || (wback && (n == t))) 7971 return false; 7972 7973 break; 7974 } 7975 7976 default: 7977 return false; 7978 } 7979 7980 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 7981 uint64_t Rn = 7982 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 7983 if (!success) 7984 return false; 7985 7986 addr_t offset_addr; 7987 if (add) 7988 offset_addr = Rn + imm32; 7989 else 7990 offset_addr = Rn - imm32; 7991 7992 // address = if index then offset_addr else R[n]; 7993 addr_t address; 7994 if (index) 7995 address = offset_addr; 7996 else 7997 address = Rn; 7998 7999 // data = MemU[address,2]; 8000 std::optional<RegisterInfo> base_reg = 8001 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 8002 8003 EmulateInstruction::Context context; 8004 context.type = eContextRegisterLoad; 8005 context.SetRegisterPlusOffset(*base_reg, address - Rn); 8006 8007 uint64_t data = MemURead(context, address, 2, 0, &success); 8008 if (!success) 8009 return false; 8010 8011 // if wback then R[n] = offset_addr; 8012 if (wback) { 8013 context.type = eContextAdjustBaseRegister; 8014 context.SetAddress(offset_addr); 8015 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 8016 offset_addr)) 8017 return false; 8018 } 8019 8020 // if UnalignedSupport() || address<0> = '0' then 8021 if (UnalignedSupport() || BitIsClear(address, 0)) { 8022 // R[t] = SignExtend(data, 32); 8023 int64_t signed_data = llvm::SignExtend64<16>(data); 8024 context.type = eContextRegisterLoad; 8025 context.SetRegisterPlusOffset(*base_reg, address - Rn); 8026 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 8027 (uint64_t)signed_data)) 8028 return false; 8029 } else // Can only apply before ARMv7 8030 { 8031 // R[t] = bits(32) UNKNOWN; 8032 WriteBits32Unknown(t); 8033 } 8034 } 8035 return true; 8036} 8037 8038// LDRSH (literal) calculates an address from the PC value and an immediate 8039// offset, loads a halfword from memory, 8040// sign-extends it to from a 32-bit word, and writes it to a register. 8041bool EmulateInstructionARM::EmulateLDRSHLiteral(const uint32_t opcode, 8042 const ARMEncoding encoding) { 8043#if 0 8044 if ConditionPassed() then 8045 EncodingSpecificOperations(); NullCheckIfThumbEE(15); 8046 base = Align(PC,4); 8047 address = if add then (base + imm32) else (base - imm32); 8048 data = MemU[address,2]; 8049 if UnalignedSupport() || address<0> = '0' then 8050 R[t] = SignExtend(data, 32); 8051 else // Can only apply before ARMv7 8052 R[t] = bits(32) UNKNOWN; 8053#endif 8054 8055 bool success = false; 8056 8057 if (ConditionPassed(opcode)) { 8058 uint32_t t; 8059 uint32_t imm32; 8060 bool add; 8061 8062 // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 8063 switch (encoding) { 8064 case eEncodingT1: 8065 // if Rt == '1111' then SEE "Unallocated memory hints"; 8066 // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 8067 t = Bits32(opcode, 15, 12); 8068 imm32 = Bits32(opcode, 11, 0); 8069 add = BitIsSet(opcode, 23); 8070 8071 // if t == 13 then UNPREDICTABLE; 8072 if (t == 13) 8073 return false; 8074 8075 break; 8076 8077 case eEncodingA1: { 8078 // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 8079 t = Bits32(opcode, 15, 12); 8080 uint32_t imm4H = Bits32(opcode, 11, 8); 8081 uint32_t imm4L = Bits32(opcode, 3, 0); 8082 imm32 = (imm4H << 4) | imm4L; 8083 add = BitIsSet(opcode, 23); 8084 8085 // if t == 15 then UNPREDICTABLE; 8086 if (t == 15) 8087 return false; 8088 8089 break; 8090 } 8091 default: 8092 return false; 8093 } 8094 8095 // base = Align(PC,4); 8096 uint64_t pc_value = ReadCoreReg(PC_REG, &success); 8097 if (!success) 8098 return false; 8099 8100 uint64_t base = AlignPC(pc_value); 8101 8102 addr_t address; 8103 // address = if add then (base + imm32) else (base - imm32); 8104 if (add) 8105 address = base + imm32; 8106 else 8107 address = base - imm32; 8108 8109 // data = MemU[address,2]; 8110 std::optional<RegisterInfo> base_reg = 8111 GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); 8112 8113 EmulateInstruction::Context context; 8114 context.type = eContextRegisterLoad; 8115 context.SetRegisterPlusOffset(*base_reg, imm32); 8116 8117 uint64_t data = MemURead(context, address, 2, 0, &success); 8118 if (!success) 8119 return false; 8120 8121 // if UnalignedSupport() || address<0> = '0' then 8122 if (UnalignedSupport() || BitIsClear(address, 0)) { 8123 // R[t] = SignExtend(data, 32); 8124 int64_t signed_data = llvm::SignExtend64<16>(data); 8125 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 8126 (uint64_t)signed_data)) 8127 return false; 8128 } else // Can only apply before ARMv7 8129 { 8130 // R[t] = bits(32) UNKNOWN; 8131 WriteBits32Unknown(t); 8132 } 8133 } 8134 return true; 8135} 8136 8137// LDRSH (register) calculates an address from a base register value and an 8138// offset register value, loads a halfword 8139// from memory, sign-extends it to form a 32-bit word, and writes it to a 8140// register. The offset register value can be shifted left by 0, 1, 2, or 3 8141// bits. 8142bool EmulateInstructionARM::EmulateLDRSHRegister(const uint32_t opcode, 8143 const ARMEncoding encoding) { 8144#if 0 8145 if ConditionPassed() then 8146 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 8147 offset = Shift(R[m], shift_t, shift_n, APSR.C); 8148 offset_addr = if add then (R[n] + offset) else (R[n] - offset); 8149 address = if index then offset_addr else R[n]; 8150 data = MemU[address,2]; 8151 if wback then R[n] = offset_addr; 8152 if UnalignedSupport() || address<0> = '0' then 8153 R[t] = SignExtend(data, 32); 8154 else // Can only apply before ARMv7 8155 R[t] = bits(32) UNKNOWN; 8156#endif 8157 8158 bool success = false; 8159 8160 if (ConditionPassed(opcode)) { 8161 uint32_t t; 8162 uint32_t n; 8163 uint32_t m; 8164 bool index; 8165 bool add; 8166 bool wback; 8167 ARM_ShifterType shift_t; 8168 uint32_t shift_n; 8169 8170 // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 8171 switch (encoding) { 8172 case eEncodingT1: 8173 // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation 8174 // in ThumbEE"; 8175 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 8176 t = Bits32(opcode, 2, 0); 8177 n = Bits32(opcode, 5, 3); 8178 m = Bits32(opcode, 8, 6); 8179 8180 // index = TRUE; add = TRUE; wback = FALSE; 8181 index = true; 8182 add = true; 8183 wback = false; 8184 8185 // (shift_t, shift_n) = (SRType_LSL, 0); 8186 shift_t = SRType_LSL; 8187 shift_n = 0; 8188 8189 break; 8190 8191 case eEncodingT2: 8192 // if Rn == '1111' then SEE LDRSH (literal); 8193 // if Rt == '1111' then SEE "Unallocated memory hints"; 8194 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 8195 t = Bits32(opcode, 15, 12); 8196 n = Bits32(opcode, 19, 16); 8197 m = Bits32(opcode, 3, 0); 8198 8199 // index = TRUE; add = TRUE; wback = FALSE; 8200 index = true; 8201 add = true; 8202 wback = false; 8203 8204 // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 8205 shift_t = SRType_LSL; 8206 shift_n = Bits32(opcode, 5, 4); 8207 8208 // if t == 13 || BadReg(m) then UNPREDICTABLE; 8209 if ((t == 13) || BadReg(m)) 8210 return false; 8211 8212 break; 8213 8214 case eEncodingA1: 8215 // if P == '0' && W == '1' then SEE LDRSHT; 8216 // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 8217 t = Bits32(opcode, 15, 12); 8218 n = Bits32(opcode, 19, 16); 8219 m = Bits32(opcode, 3, 0); 8220 8221 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || 8222 // (W == '1'); 8223 index = BitIsSet(opcode, 24); 8224 add = BitIsSet(opcode, 23); 8225 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 8226 8227 // (shift_t, shift_n) = (SRType_LSL, 0); 8228 shift_t = SRType_LSL; 8229 shift_n = 0; 8230 8231 // if t == 15 || m == 15 then UNPREDICTABLE; 8232 if ((t == 15) || (m == 15)) 8233 return false; 8234 8235 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 8236 if (wback && ((n == 15) || (n == t))) 8237 return false; 8238 8239 break; 8240 8241 default: 8242 return false; 8243 } 8244 8245 uint64_t Rm = 8246 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8247 if (!success) 8248 return false; 8249 8250 uint64_t Rn = 8251 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 8252 if (!success) 8253 return false; 8254 8255 // offset = Shift(R[m], shift_t, shift_n, APSR.C); 8256 addr_t offset = Shift(Rm, shift_t, shift_n, APSR_C, &success); 8257 if (!success) 8258 return false; 8259 8260 addr_t offset_addr; 8261 addr_t address; 8262 8263 // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 8264 if (add) 8265 offset_addr = Rn + offset; 8266 else 8267 offset_addr = Rn - offset; 8268 8269 // address = if index then offset_addr else R[n]; 8270 if (index) 8271 address = offset_addr; 8272 else 8273 address = Rn; 8274 8275 // data = MemU[address,2]; 8276 std::optional<RegisterInfo> base_reg = 8277 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 8278 std::optional<RegisterInfo> offset_reg = 8279 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 8280 8281 EmulateInstruction::Context context; 8282 context.type = eContextRegisterLoad; 8283 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); 8284 8285 uint64_t data = MemURead(context, address, 2, 0, &success); 8286 if (!success) 8287 return false; 8288 8289 // if wback then R[n] = offset_addr; 8290 if (wback) { 8291 context.type = eContextAdjustBaseRegister; 8292 context.SetAddress(offset_addr); 8293 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 8294 offset_addr)) 8295 return false; 8296 } 8297 8298 // if UnalignedSupport() || address<0> = '0' then 8299 if (UnalignedSupport() || BitIsClear(address, 0)) { 8300 // R[t] = SignExtend(data, 32); 8301 context.type = eContextRegisterLoad; 8302 context.SetRegisterPlusIndirectOffset(*base_reg, *offset_reg); 8303 8304 int64_t signed_data = llvm::SignExtend64<16>(data); 8305 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 8306 (uint64_t)signed_data)) 8307 return false; 8308 } else // Can only apply before ARMv7 8309 { 8310 // R[t] = bits(32) UNKNOWN; 8311 WriteBits32Unknown(t); 8312 } 8313 } 8314 return true; 8315} 8316 8317// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and 8318// writes the result to the destination 8319// register. You can specifiy a rotation by 0, 8, 16, or 24 bits before 8320// extracting the 8-bit value. 8321bool EmulateInstructionARM::EmulateSXTB(const uint32_t opcode, 8322 const ARMEncoding encoding) { 8323#if 0 8324 if ConditionPassed() then 8325 EncodingSpecificOperations(); 8326 rotated = ROR(R[m], rotation); 8327 R[d] = SignExtend(rotated<7:0>, 32); 8328#endif 8329 8330 bool success = false; 8331 8332 if (ConditionPassed(opcode)) { 8333 uint32_t d; 8334 uint32_t m; 8335 uint32_t rotation; 8336 8337 // EncodingSpecificOperations(); 8338 switch (encoding) { 8339 case eEncodingT1: 8340 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 8341 d = Bits32(opcode, 2, 0); 8342 m = Bits32(opcode, 5, 3); 8343 rotation = 0; 8344 8345 break; 8346 8347 case eEncodingT2: 8348 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8349 d = Bits32(opcode, 11, 8); 8350 m = Bits32(opcode, 3, 0); 8351 rotation = Bits32(opcode, 5, 4) << 3; 8352 8353 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 8354 if (BadReg(d) || BadReg(m)) 8355 return false; 8356 8357 break; 8358 8359 case eEncodingA1: 8360 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8361 d = Bits32(opcode, 15, 12); 8362 m = Bits32(opcode, 3, 0); 8363 rotation = Bits32(opcode, 11, 10) << 3; 8364 8365 // if d == 15 || m == 15 then UNPREDICTABLE; 8366 if ((d == 15) || (m == 15)) 8367 return false; 8368 8369 break; 8370 8371 default: 8372 return false; 8373 } 8374 8375 uint64_t Rm = 8376 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8377 if (!success) 8378 return false; 8379 8380 // rotated = ROR(R[m], rotation); 8381 uint64_t rotated = ROR(Rm, rotation, &success); 8382 if (!success) 8383 return false; 8384 8385 // R[d] = SignExtend(rotated<7:0>, 32); 8386 int64_t data = llvm::SignExtend64<8>(rotated); 8387 8388 std::optional<RegisterInfo> source_reg = 8389 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 8390 8391 EmulateInstruction::Context context; 8392 context.type = eContextRegisterLoad; 8393 context.SetRegister(*source_reg); 8394 8395 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 8396 (uint64_t)data)) 8397 return false; 8398 } 8399 return true; 8400} 8401 8402// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and 8403// writes the result to the destination 8404// register. You can specify a rotation by 0, 8, 16, or 24 bits before 8405// extracting the 16-bit value. 8406bool EmulateInstructionARM::EmulateSXTH(const uint32_t opcode, 8407 const ARMEncoding encoding) { 8408#if 0 8409 if ConditionPassed() then 8410 EncodingSpecificOperations(); 8411 rotated = ROR(R[m], rotation); 8412 R[d] = SignExtend(rotated<15:0>, 32); 8413#endif 8414 8415 bool success = false; 8416 8417 if (ConditionPassed(opcode)) { 8418 uint32_t d; 8419 uint32_t m; 8420 uint32_t rotation; 8421 8422 // EncodingSpecificOperations(); 8423 switch (encoding) { 8424 case eEncodingT1: 8425 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 8426 d = Bits32(opcode, 2, 0); 8427 m = Bits32(opcode, 5, 3); 8428 rotation = 0; 8429 8430 break; 8431 8432 case eEncodingT2: 8433 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8434 d = Bits32(opcode, 11, 8); 8435 m = Bits32(opcode, 3, 0); 8436 rotation = Bits32(opcode, 5, 4) << 3; 8437 8438 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 8439 if (BadReg(d) || BadReg(m)) 8440 return false; 8441 8442 break; 8443 8444 case eEncodingA1: 8445 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8446 d = Bits32(opcode, 15, 12); 8447 m = Bits32(opcode, 3, 0); 8448 rotation = Bits32(opcode, 11, 10) << 3; 8449 8450 // if d == 15 || m == 15 then UNPREDICTABLE; 8451 if ((d == 15) || (m == 15)) 8452 return false; 8453 8454 break; 8455 8456 default: 8457 return false; 8458 } 8459 8460 uint64_t Rm = 8461 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8462 if (!success) 8463 return false; 8464 8465 // rotated = ROR(R[m], rotation); 8466 uint64_t rotated = ROR(Rm, rotation, &success); 8467 if (!success) 8468 return false; 8469 8470 // R[d] = SignExtend(rotated<15:0>, 32); 8471 std::optional<RegisterInfo> source_reg = 8472 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 8473 8474 EmulateInstruction::Context context; 8475 context.type = eContextRegisterLoad; 8476 context.SetRegister(*source_reg); 8477 8478 int64_t data = llvm::SignExtend64<16>(rotated); 8479 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 8480 (uint64_t)data)) 8481 return false; 8482 } 8483 8484 return true; 8485} 8486 8487// UXTB extracts an 8-bit value from a register, zero-extends it to 32 bits, and 8488// writes the result to the destination 8489// register. You can specify a rotation by 0, 8, 16, or 24 bits before 8490// extracting the 8-bit value. 8491bool EmulateInstructionARM::EmulateUXTB(const uint32_t opcode, 8492 const ARMEncoding encoding) { 8493#if 0 8494 if ConditionPassed() then 8495 EncodingSpecificOperations(); 8496 rotated = ROR(R[m], rotation); 8497 R[d] = ZeroExtend(rotated<7:0>, 32); 8498#endif 8499 8500 bool success = false; 8501 8502 if (ConditionPassed(opcode)) { 8503 uint32_t d; 8504 uint32_t m; 8505 uint32_t rotation; 8506 8507 // EncodingSpecificOperations(); 8508 switch (encoding) { 8509 case eEncodingT1: 8510 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 8511 d = Bits32(opcode, 2, 0); 8512 m = Bits32(opcode, 5, 3); 8513 rotation = 0; 8514 8515 break; 8516 8517 case eEncodingT2: 8518 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8519 d = Bits32(opcode, 11, 8); 8520 m = Bits32(opcode, 3, 0); 8521 rotation = Bits32(opcode, 5, 4) << 3; 8522 8523 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 8524 if (BadReg(d) || BadReg(m)) 8525 return false; 8526 8527 break; 8528 8529 case eEncodingA1: 8530 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8531 d = Bits32(opcode, 15, 12); 8532 m = Bits32(opcode, 3, 0); 8533 rotation = Bits32(opcode, 11, 10) << 3; 8534 8535 // if d == 15 || m == 15 then UNPREDICTABLE; 8536 if ((d == 15) || (m == 15)) 8537 return false; 8538 8539 break; 8540 8541 default: 8542 return false; 8543 } 8544 8545 uint64_t Rm = 8546 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8547 if (!success) 8548 return false; 8549 8550 // rotated = ROR(R[m], rotation); 8551 uint64_t rotated = ROR(Rm, rotation, &success); 8552 if (!success) 8553 return false; 8554 8555 // R[d] = ZeroExtend(rotated<7:0>, 32); 8556 std::optional<RegisterInfo> source_reg = 8557 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 8558 8559 EmulateInstruction::Context context; 8560 context.type = eContextRegisterLoad; 8561 context.SetRegister(*source_reg); 8562 8563 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 8564 Bits32(rotated, 7, 0))) 8565 return false; 8566 } 8567 return true; 8568} 8569 8570// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and 8571// writes the result to the destination 8572// register. You can specify a rotation by 0, 8, 16, or 24 bits before 8573// extracting the 16-bit value. 8574bool EmulateInstructionARM::EmulateUXTH(const uint32_t opcode, 8575 const ARMEncoding encoding) { 8576#if 0 8577 if ConditionPassed() then 8578 EncodingSpecificOperations(); 8579 rotated = ROR(R[m], rotation); 8580 R[d] = ZeroExtend(rotated<15:0>, 32); 8581#endif 8582 8583 bool success = false; 8584 8585 if (ConditionPassed(opcode)) { 8586 uint32_t d; 8587 uint32_t m; 8588 uint32_t rotation; 8589 8590 switch (encoding) { 8591 case eEncodingT1: 8592 // d = UInt(Rd); m = UInt(Rm); rotation = 0; 8593 d = Bits32(opcode, 2, 0); 8594 m = Bits32(opcode, 5, 3); 8595 rotation = 0; 8596 8597 break; 8598 8599 case eEncodingT2: 8600 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8601 d = Bits32(opcode, 11, 8); 8602 m = Bits32(opcode, 3, 0); 8603 rotation = Bits32(opcode, 5, 4) << 3; 8604 8605 // if BadReg(d) || BadReg(m) then UNPREDICTABLE; 8606 if (BadReg(d) || BadReg(m)) 8607 return false; 8608 8609 break; 8610 8611 case eEncodingA1: 8612 // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 8613 d = Bits32(opcode, 15, 12); 8614 m = Bits32(opcode, 3, 0); 8615 rotation = Bits32(opcode, 11, 10) << 3; 8616 8617 // if d == 15 || m == 15 then UNPREDICTABLE; 8618 if ((d == 15) || (m == 15)) 8619 return false; 8620 8621 break; 8622 8623 default: 8624 return false; 8625 } 8626 8627 uint64_t Rm = 8628 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + m, 0, &success); 8629 if (!success) 8630 return false; 8631 8632 // rotated = ROR(R[m], rotation); 8633 uint64_t rotated = ROR(Rm, rotation, &success); 8634 if (!success) 8635 return false; 8636 8637 // R[d] = ZeroExtend(rotated<15:0>, 32); 8638 std::optional<RegisterInfo> source_reg = 8639 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 8640 8641 EmulateInstruction::Context context; 8642 context.type = eContextRegisterLoad; 8643 context.SetRegister(*source_reg); 8644 8645 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 8646 Bits32(rotated, 15, 0))) 8647 return false; 8648 } 8649 return true; 8650} 8651 8652// RFE (Return From Exception) loads the PC and the CPSR from the word at the 8653// specified address and the following 8654// word respectively. 8655bool EmulateInstructionARM::EmulateRFE(const uint32_t opcode, 8656 const ARMEncoding encoding) { 8657#if 0 8658 if ConditionPassed() then 8659 EncodingSpecificOperations(); 8660 if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then 8661 UNPREDICTABLE; 8662 else 8663 address = if increment then R[n] else R[n]-8; 8664 if wordhigher then address = address+4; 8665 CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 8666 BranchWritePC(MemA[address,4]); 8667 if wback then R[n] = if increment then R[n]+8 else R[n]-8; 8668#endif 8669 8670 bool success = false; 8671 8672 if (ConditionPassed(opcode)) { 8673 uint32_t n; 8674 bool wback; 8675 bool increment; 8676 bool wordhigher; 8677 8678 // EncodingSpecificOperations(); 8679 switch (encoding) { 8680 case eEncodingT1: 8681 // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = 8682 // FALSE; 8683 n = Bits32(opcode, 19, 16); 8684 wback = BitIsSet(opcode, 21); 8685 increment = false; 8686 wordhigher = false; 8687 8688 // if n == 15 then UNPREDICTABLE; 8689 if (n == 15) 8690 return false; 8691 8692 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 8693 if (InITBlock() && !LastInITBlock()) 8694 return false; 8695 8696 break; 8697 8698 case eEncodingT2: 8699 // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE; 8700 n = Bits32(opcode, 19, 16); 8701 wback = BitIsSet(opcode, 21); 8702 increment = true; 8703 wordhigher = false; 8704 8705 // if n == 15 then UNPREDICTABLE; 8706 if (n == 15) 8707 return false; 8708 8709 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 8710 if (InITBlock() && !LastInITBlock()) 8711 return false; 8712 8713 break; 8714 8715 case eEncodingA1: 8716 // n = UInt(Rn); 8717 n = Bits32(opcode, 19, 16); 8718 8719 // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U); 8720 wback = BitIsSet(opcode, 21); 8721 increment = BitIsSet(opcode, 23); 8722 wordhigher = (Bit32(opcode, 24) == Bit32(opcode, 23)); 8723 8724 // if n == 15 then UNPREDICTABLE; 8725 if (n == 15) 8726 return false; 8727 8728 break; 8729 8730 default: 8731 return false; 8732 } 8733 8734 // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE 8735 // then 8736 if (!CurrentModeIsPrivileged()) 8737 // UNPREDICTABLE; 8738 return false; 8739 else { 8740 uint64_t Rn = 8741 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + n, 0, &success); 8742 if (!success) 8743 return false; 8744 8745 addr_t address; 8746 // address = if increment then R[n] else R[n]-8; 8747 if (increment) 8748 address = Rn; 8749 else 8750 address = Rn - 8; 8751 8752 // if wordhigher then address = address+4; 8753 if (wordhigher) 8754 address = address + 4; 8755 8756 // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 8757 std::optional<RegisterInfo> base_reg = 8758 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 8759 8760 EmulateInstruction::Context context; 8761 context.type = eContextReturnFromException; 8762 context.SetRegisterPlusOffset(*base_reg, address - Rn); 8763 8764 uint64_t data = MemARead(context, address + 4, 4, 0, &success); 8765 if (!success) 8766 return false; 8767 8768 CPSRWriteByInstr(data, 15, true); 8769 8770 // BranchWritePC(MemA[address,4]); 8771 uint64_t data2 = MemARead(context, address, 4, 0, &success); 8772 if (!success) 8773 return false; 8774 8775 BranchWritePC(context, data2); 8776 8777 // if wback then R[n] = if increment then R[n]+8 else R[n]-8; 8778 if (wback) { 8779 context.type = eContextAdjustBaseRegister; 8780 if (increment) { 8781 context.SetOffset(8); 8782 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 8783 Rn + 8)) 8784 return false; 8785 } else { 8786 context.SetOffset(-8); 8787 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 8788 Rn - 8)) 8789 return false; 8790 } 8791 } // if wback 8792 } 8793 } // if ConditionPassed() 8794 return true; 8795} 8796 8797// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a 8798// register value and an immediate value, and writes the result to the 8799// destination register. It can optionally update the condition flags based on 8800// the result. 8801bool EmulateInstructionARM::EmulateEORImm(const uint32_t opcode, 8802 const ARMEncoding encoding) { 8803#if 0 8804 // ARM pseudo code... 8805 if ConditionPassed() then 8806 EncodingSpecificOperations(); 8807 result = R[n] EOR imm32; 8808 if d == 15 then // Can only occur for ARM encoding 8809 ALUWritePC(result); // setflags is always FALSE here 8810 else 8811 R[d] = result; 8812 if setflags then 8813 APSR.N = result<31>; 8814 APSR.Z = IsZeroBit(result); 8815 APSR.C = carry; 8816 // APSR.V unchanged 8817#endif 8818 8819 bool success = false; 8820 8821 if (ConditionPassed(opcode)) { 8822 uint32_t Rd, Rn; 8823 uint32_t 8824 imm32; // the immediate value to be ORed to the value obtained from Rn 8825 bool setflags; 8826 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8827 switch (encoding) { 8828 case eEncodingT1: 8829 Rd = Bits32(opcode, 11, 8); 8830 Rn = Bits32(opcode, 19, 16); 8831 setflags = BitIsSet(opcode, 20); 8832 imm32 = ThumbExpandImm_C( 8833 opcode, APSR_C, 8834 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 8835 // if Rd == '1111' && S == '1' then SEE TEQ (immediate); 8836 if (Rd == 15 && setflags) 8837 return EmulateTEQImm(opcode, eEncodingT1); 8838 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn)) 8839 return false; 8840 break; 8841 case eEncodingA1: 8842 Rd = Bits32(opcode, 15, 12); 8843 Rn = Bits32(opcode, 19, 16); 8844 setflags = BitIsSet(opcode, 20); 8845 imm32 = 8846 ARMExpandImm_C(opcode, APSR_C, 8847 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 8848 8849 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 8850 // instructions; 8851 if (Rd == 15 && setflags) 8852 return EmulateSUBSPcLrEtc(opcode, encoding); 8853 break; 8854 default: 8855 return false; 8856 } 8857 8858 // Read the first operand. 8859 uint32_t val1 = ReadCoreReg(Rn, &success); 8860 if (!success) 8861 return false; 8862 8863 uint32_t result = val1 ^ imm32; 8864 8865 EmulateInstruction::Context context; 8866 context.type = EmulateInstruction::eContextImmediate; 8867 context.SetNoArgs(); 8868 8869 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8870 return false; 8871 } 8872 return true; 8873} 8874 8875// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a 8876// register value and an optionally-shifted register value, and writes the 8877// result to the destination register. It can optionally update the condition 8878// flags based on the result. 8879bool EmulateInstructionARM::EmulateEORReg(const uint32_t opcode, 8880 const ARMEncoding encoding) { 8881#if 0 8882 // ARM pseudo code... 8883 if ConditionPassed() then 8884 EncodingSpecificOperations(); 8885 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 8886 result = R[n] EOR shifted; 8887 if d == 15 then // Can only occur for ARM encoding 8888 ALUWritePC(result); // setflags is always FALSE here 8889 else 8890 R[d] = result; 8891 if setflags then 8892 APSR.N = result<31>; 8893 APSR.Z = IsZeroBit(result); 8894 APSR.C = carry; 8895 // APSR.V unchanged 8896#endif 8897 8898 bool success = false; 8899 8900 if (ConditionPassed(opcode)) { 8901 uint32_t Rd, Rn, Rm; 8902 ARM_ShifterType shift_t; 8903 uint32_t shift_n; // the shift applied to the value read from Rm 8904 bool setflags; 8905 uint32_t carry; 8906 switch (encoding) { 8907 case eEncodingT1: 8908 Rd = Rn = Bits32(opcode, 2, 0); 8909 Rm = Bits32(opcode, 5, 3); 8910 setflags = !InITBlock(); 8911 shift_t = SRType_LSL; 8912 shift_n = 0; 8913 break; 8914 case eEncodingT2: 8915 Rd = Bits32(opcode, 11, 8); 8916 Rn = Bits32(opcode, 19, 16); 8917 Rm = Bits32(opcode, 3, 0); 8918 setflags = BitIsSet(opcode, 20); 8919 shift_n = DecodeImmShiftThumb(opcode, shift_t); 8920 // if Rd == '1111' && S == '1' then SEE TEQ (register); 8921 if (Rd == 15 && setflags) 8922 return EmulateTEQReg(opcode, eEncodingT1); 8923 if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm)) 8924 return false; 8925 break; 8926 case eEncodingA1: 8927 Rd = Bits32(opcode, 15, 12); 8928 Rn = Bits32(opcode, 19, 16); 8929 Rm = Bits32(opcode, 3, 0); 8930 setflags = BitIsSet(opcode, 20); 8931 shift_n = DecodeImmShiftARM(opcode, shift_t); 8932 8933 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 8934 // instructions; 8935 if (Rd == 15 && setflags) 8936 return EmulateSUBSPcLrEtc(opcode, encoding); 8937 break; 8938 default: 8939 return false; 8940 } 8941 8942 // Read the first operand. 8943 uint32_t val1 = ReadCoreReg(Rn, &success); 8944 if (!success) 8945 return false; 8946 8947 // Read the second operand. 8948 uint32_t val2 = ReadCoreReg(Rm, &success); 8949 if (!success) 8950 return false; 8951 8952 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 8953 if (!success) 8954 return false; 8955 uint32_t result = val1 ^ shifted; 8956 8957 EmulateInstruction::Context context; 8958 context.type = EmulateInstruction::eContextImmediate; 8959 context.SetNoArgs(); 8960 8961 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 8962 return false; 8963 } 8964 return true; 8965} 8966 8967// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value 8968// and an immediate value, and writes the result to the destination register. 8969// It can optionally update the condition flags based on the result. 8970bool EmulateInstructionARM::EmulateORRImm(const uint32_t opcode, 8971 const ARMEncoding encoding) { 8972#if 0 8973 // ARM pseudo code... 8974 if ConditionPassed() then 8975 EncodingSpecificOperations(); 8976 result = R[n] OR imm32; 8977 if d == 15 then // Can only occur for ARM encoding 8978 ALUWritePC(result); // setflags is always FALSE here 8979 else 8980 R[d] = result; 8981 if setflags then 8982 APSR.N = result<31>; 8983 APSR.Z = IsZeroBit(result); 8984 APSR.C = carry; 8985 // APSR.V unchanged 8986#endif 8987 8988 bool success = false; 8989 8990 if (ConditionPassed(opcode)) { 8991 uint32_t Rd, Rn; 8992 uint32_t 8993 imm32; // the immediate value to be ORed to the value obtained from Rn 8994 bool setflags; 8995 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 8996 switch (encoding) { 8997 case eEncodingT1: 8998 Rd = Bits32(opcode, 11, 8); 8999 Rn = Bits32(opcode, 19, 16); 9000 setflags = BitIsSet(opcode, 20); 9001 imm32 = ThumbExpandImm_C( 9002 opcode, APSR_C, 9003 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9004 // if Rn == '1111' then SEE MOV (immediate); 9005 if (Rn == 15) 9006 return EmulateMOVRdImm(opcode, eEncodingT2); 9007 if (BadReg(Rd) || Rn == 13) 9008 return false; 9009 break; 9010 case eEncodingA1: 9011 Rd = Bits32(opcode, 15, 12); 9012 Rn = Bits32(opcode, 19, 16); 9013 setflags = BitIsSet(opcode, 20); 9014 imm32 = 9015 ARMExpandImm_C(opcode, APSR_C, 9016 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9017 9018 if (Rd == 15 && setflags) 9019 return EmulateSUBSPcLrEtc(opcode, encoding); 9020 break; 9021 default: 9022 return false; 9023 } 9024 9025 // Read the first operand. 9026 uint32_t val1 = ReadCoreReg(Rn, &success); 9027 if (!success) 9028 return false; 9029 9030 uint32_t result = val1 | imm32; 9031 9032 EmulateInstruction::Context context; 9033 context.type = EmulateInstruction::eContextImmediate; 9034 context.SetNoArgs(); 9035 9036 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 9037 return false; 9038 } 9039 return true; 9040} 9041 9042// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value 9043// and an optionally-shifted register value, and writes the result to the 9044// destination register. It can optionally update the condition flags based on 9045// the result. 9046bool EmulateInstructionARM::EmulateORRReg(const uint32_t opcode, 9047 const ARMEncoding encoding) { 9048#if 0 9049 // ARM pseudo code... 9050 if ConditionPassed() then 9051 EncodingSpecificOperations(); 9052 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9053 result = R[n] OR shifted; 9054 if d == 15 then // Can only occur for ARM encoding 9055 ALUWritePC(result); // setflags is always FALSE here 9056 else 9057 R[d] = result; 9058 if setflags then 9059 APSR.N = result<31>; 9060 APSR.Z = IsZeroBit(result); 9061 APSR.C = carry; 9062 // APSR.V unchanged 9063#endif 9064 9065 bool success = false; 9066 9067 if (ConditionPassed(opcode)) { 9068 uint32_t Rd, Rn, Rm; 9069 ARM_ShifterType shift_t; 9070 uint32_t shift_n; // the shift applied to the value read from Rm 9071 bool setflags; 9072 uint32_t carry; 9073 switch (encoding) { 9074 case eEncodingT1: 9075 Rd = Rn = Bits32(opcode, 2, 0); 9076 Rm = Bits32(opcode, 5, 3); 9077 setflags = !InITBlock(); 9078 shift_t = SRType_LSL; 9079 shift_n = 0; 9080 break; 9081 case eEncodingT2: 9082 Rd = Bits32(opcode, 11, 8); 9083 Rn = Bits32(opcode, 19, 16); 9084 Rm = Bits32(opcode, 3, 0); 9085 setflags = BitIsSet(opcode, 20); 9086 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9087 // if Rn == '1111' then SEE MOV (register); 9088 if (Rn == 15) 9089 return EmulateMOVRdRm(opcode, eEncodingT3); 9090 if (BadReg(Rd) || Rn == 13 || BadReg(Rm)) 9091 return false; 9092 break; 9093 case eEncodingA1: 9094 Rd = Bits32(opcode, 15, 12); 9095 Rn = Bits32(opcode, 19, 16); 9096 Rm = Bits32(opcode, 3, 0); 9097 setflags = BitIsSet(opcode, 20); 9098 shift_n = DecodeImmShiftARM(opcode, shift_t); 9099 9100 if (Rd == 15 && setflags) 9101 return EmulateSUBSPcLrEtc(opcode, encoding); 9102 break; 9103 default: 9104 return false; 9105 } 9106 9107 // Read the first operand. 9108 uint32_t val1 = ReadCoreReg(Rn, &success); 9109 if (!success) 9110 return false; 9111 9112 // Read the second operand. 9113 uint32_t val2 = ReadCoreReg(Rm, &success); 9114 if (!success) 9115 return false; 9116 9117 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 9118 if (!success) 9119 return false; 9120 uint32_t result = val1 | shifted; 9121 9122 EmulateInstruction::Context context; 9123 context.type = EmulateInstruction::eContextImmediate; 9124 context.SetNoArgs(); 9125 9126 if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry)) 9127 return false; 9128 } 9129 return true; 9130} 9131 9132// Reverse Subtract (immediate) subtracts a register value from an immediate 9133// value, and writes the result to the destination register. It can optionally 9134// update the condition flags based on the result. 9135bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode, 9136 const ARMEncoding encoding) { 9137#if 0 9138 // ARM pseudo code... 9139 if ConditionPassed() then 9140 EncodingSpecificOperations(); 9141 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1'); 9142 if d == 15 then // Can only occur for ARM encoding 9143 ALUWritePC(result); // setflags is always FALSE here 9144 else 9145 R[d] = result; 9146 if setflags then 9147 APSR.N = result<31>; 9148 APSR.Z = IsZeroBit(result); 9149 APSR.C = carry; 9150 APSR.V = overflow; 9151#endif 9152 9153 bool success = false; 9154 9155 uint32_t Rd; // the destination register 9156 uint32_t Rn; // the first operand 9157 bool setflags; 9158 uint32_t 9159 imm32; // the immediate value to be added to the value obtained from Rn 9160 switch (encoding) { 9161 case eEncodingT1: 9162 Rd = Bits32(opcode, 2, 0); 9163 Rn = Bits32(opcode, 5, 3); 9164 setflags = !InITBlock(); 9165 imm32 = 0; 9166 break; 9167 case eEncodingT2: 9168 Rd = Bits32(opcode, 11, 8); 9169 Rn = Bits32(opcode, 19, 16); 9170 setflags = BitIsSet(opcode, 20); 9171 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 9172 if (BadReg(Rd) || BadReg(Rn)) 9173 return false; 9174 break; 9175 case eEncodingA1: 9176 Rd = Bits32(opcode, 15, 12); 9177 Rn = Bits32(opcode, 19, 16); 9178 setflags = BitIsSet(opcode, 20); 9179 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 9180 9181 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9182 // instructions; 9183 if (Rd == 15 && setflags) 9184 return EmulateSUBSPcLrEtc(opcode, encoding); 9185 break; 9186 default: 9187 return false; 9188 } 9189 // Read the register value from the operand register Rn. 9190 uint32_t reg_val = ReadCoreReg(Rn, &success); 9191 if (!success) 9192 return false; 9193 9194 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1); 9195 9196 EmulateInstruction::Context context; 9197 context.type = EmulateInstruction::eContextImmediate; 9198 context.SetNoArgs(); 9199 9200 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9201 res.carry_out, res.overflow); 9202} 9203 9204// Reverse Subtract (register) subtracts a register value from an optionally- 9205// shifted register value, and writes the result to the destination register. 9206// It can optionally update the condition flags based on the result. 9207bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode, 9208 const ARMEncoding encoding) { 9209#if 0 9210 // ARM pseudo code... 9211 if ConditionPassed() then 9212 EncodingSpecificOperations(); 9213 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9214 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1'); 9215 if d == 15 then // Can only occur for ARM encoding 9216 ALUWritePC(result); // setflags is always FALSE here 9217 else 9218 R[d] = result; 9219 if setflags then 9220 APSR.N = result<31>; 9221 APSR.Z = IsZeroBit(result); 9222 APSR.C = carry; 9223 APSR.V = overflow; 9224#endif 9225 9226 bool success = false; 9227 9228 uint32_t Rd; // the destination register 9229 uint32_t Rn; // the first operand 9230 uint32_t Rm; // the second operand 9231 bool setflags; 9232 ARM_ShifterType shift_t; 9233 uint32_t shift_n; // the shift applied to the value read from Rm 9234 switch (encoding) { 9235 case eEncodingT1: 9236 Rd = Bits32(opcode, 11, 8); 9237 Rn = Bits32(opcode, 19, 16); 9238 Rm = Bits32(opcode, 3, 0); 9239 setflags = BitIsSet(opcode, 20); 9240 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9241 // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE; 9242 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 9243 return false; 9244 break; 9245 case eEncodingA1: 9246 Rd = Bits32(opcode, 15, 12); 9247 Rn = Bits32(opcode, 19, 16); 9248 Rm = Bits32(opcode, 3, 0); 9249 setflags = BitIsSet(opcode, 20); 9250 shift_n = DecodeImmShiftARM(opcode, shift_t); 9251 9252 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9253 // instructions; 9254 if (Rd == 15 && setflags) 9255 return EmulateSUBSPcLrEtc(opcode, encoding); 9256 break; 9257 default: 9258 return false; 9259 } 9260 // Read the register value from register Rn. 9261 uint32_t val1 = ReadCoreReg(Rn, &success); 9262 if (!success) 9263 return false; 9264 9265 // Read the register value from register Rm. 9266 uint32_t val2 = ReadCoreReg(Rm, &success); 9267 if (!success) 9268 return false; 9269 9270 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 9271 if (!success) 9272 return false; 9273 AddWithCarryResult res = AddWithCarry(~val1, shifted, 1); 9274 9275 EmulateInstruction::Context context; 9276 context.type = EmulateInstruction::eContextImmediate; 9277 context.SetNoArgs(); 9278 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9279 res.carry_out, res.overflow); 9280} 9281 9282// Reverse Subtract with Carry (immediate) subtracts a register value and the 9283// value of NOT (Carry flag) from an immediate value, and writes the result to 9284// the destination register. It can optionally update the condition flags based 9285// on the result. 9286bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode, 9287 const ARMEncoding encoding) { 9288#if 0 9289 // ARM pseudo code... 9290 if ConditionPassed() then 9291 EncodingSpecificOperations(); 9292 (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C); 9293 if d == 15 then 9294 ALUWritePC(result); // setflags is always FALSE here 9295 else 9296 R[d] = result; 9297 if setflags then 9298 APSR.N = result<31>; 9299 APSR.Z = IsZeroBit(result); 9300 APSR.C = carry; 9301 APSR.V = overflow; 9302#endif 9303 9304 bool success = false; 9305 9306 uint32_t Rd; // the destination register 9307 uint32_t Rn; // the first operand 9308 bool setflags; 9309 uint32_t 9310 imm32; // the immediate value to be added to the value obtained from Rn 9311 switch (encoding) { 9312 case eEncodingA1: 9313 Rd = Bits32(opcode, 15, 12); 9314 Rn = Bits32(opcode, 19, 16); 9315 setflags = BitIsSet(opcode, 20); 9316 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 9317 9318 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9319 // instructions; 9320 if (Rd == 15 && setflags) 9321 return EmulateSUBSPcLrEtc(opcode, encoding); 9322 break; 9323 default: 9324 return false; 9325 } 9326 // Read the register value from the operand register Rn. 9327 uint32_t reg_val = ReadCoreReg(Rn, &success); 9328 if (!success) 9329 return false; 9330 9331 AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C); 9332 9333 EmulateInstruction::Context context; 9334 context.type = EmulateInstruction::eContextImmediate; 9335 context.SetNoArgs(); 9336 9337 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9338 res.carry_out, res.overflow); 9339} 9340 9341// Reverse Subtract with Carry (register) subtracts a register value and the 9342// value of NOT (Carry flag) from an optionally-shifted register value, and 9343// writes the result to the destination register. It can optionally update the 9344// condition flags based on the result. 9345bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode, 9346 const ARMEncoding encoding) { 9347#if 0 9348 // ARM pseudo code... 9349 if ConditionPassed() then 9350 EncodingSpecificOperations(); 9351 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9352 (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C); 9353 if d == 15 then 9354 ALUWritePC(result); // setflags is always FALSE here 9355 else 9356 R[d] = result; 9357 if setflags then 9358 APSR.N = result<31>; 9359 APSR.Z = IsZeroBit(result); 9360 APSR.C = carry; 9361 APSR.V = overflow; 9362#endif 9363 9364 bool success = false; 9365 9366 uint32_t Rd; // the destination register 9367 uint32_t Rn; // the first operand 9368 uint32_t Rm; // the second operand 9369 bool setflags; 9370 ARM_ShifterType shift_t; 9371 uint32_t shift_n; // the shift applied to the value read from Rm 9372 switch (encoding) { 9373 case eEncodingA1: 9374 Rd = Bits32(opcode, 15, 12); 9375 Rn = Bits32(opcode, 19, 16); 9376 Rm = Bits32(opcode, 3, 0); 9377 setflags = BitIsSet(opcode, 20); 9378 shift_n = DecodeImmShiftARM(opcode, shift_t); 9379 9380 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9381 // instructions; 9382 if (Rd == 15 && setflags) 9383 return EmulateSUBSPcLrEtc(opcode, encoding); 9384 break; 9385 default: 9386 return false; 9387 } 9388 // Read the register value from register Rn. 9389 uint32_t val1 = ReadCoreReg(Rn, &success); 9390 if (!success) 9391 return false; 9392 9393 // Read the register value from register Rm. 9394 uint32_t val2 = ReadCoreReg(Rm, &success); 9395 if (!success) 9396 return false; 9397 9398 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 9399 if (!success) 9400 return false; 9401 AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C); 9402 9403 EmulateInstruction::Context context; 9404 context.type = EmulateInstruction::eContextImmediate; 9405 context.SetNoArgs(); 9406 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9407 res.carry_out, res.overflow); 9408} 9409 9410// Subtract with Carry (immediate) subtracts an immediate value and the value 9411// of 9412// NOT (Carry flag) from a register value, and writes the result to the 9413// destination register. 9414// It can optionally update the condition flags based on the result. 9415bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode, 9416 const ARMEncoding encoding) { 9417#if 0 9418 // ARM pseudo code... 9419 if ConditionPassed() then 9420 EncodingSpecificOperations(); 9421 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C); 9422 if d == 15 then // Can only occur for ARM encoding 9423 ALUWritePC(result); // setflags is always FALSE here 9424 else 9425 R[d] = result; 9426 if setflags then 9427 APSR.N = result<31>; 9428 APSR.Z = IsZeroBit(result); 9429 APSR.C = carry; 9430 APSR.V = overflow; 9431#endif 9432 9433 bool success = false; 9434 9435 uint32_t Rd; // the destination register 9436 uint32_t Rn; // the first operand 9437 bool setflags; 9438 uint32_t 9439 imm32; // the immediate value to be added to the value obtained from Rn 9440 switch (encoding) { 9441 case eEncodingT1: 9442 Rd = Bits32(opcode, 11, 8); 9443 Rn = Bits32(opcode, 19, 16); 9444 setflags = BitIsSet(opcode, 20); 9445 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 9446 if (BadReg(Rd) || BadReg(Rn)) 9447 return false; 9448 break; 9449 case eEncodingA1: 9450 Rd = Bits32(opcode, 15, 12); 9451 Rn = Bits32(opcode, 19, 16); 9452 setflags = BitIsSet(opcode, 20); 9453 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 9454 9455 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9456 // instructions; 9457 if (Rd == 15 && setflags) 9458 return EmulateSUBSPcLrEtc(opcode, encoding); 9459 break; 9460 default: 9461 return false; 9462 } 9463 // Read the register value from the operand register Rn. 9464 uint32_t reg_val = ReadCoreReg(Rn, &success); 9465 if (!success) 9466 return false; 9467 9468 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C); 9469 9470 EmulateInstruction::Context context; 9471 context.type = EmulateInstruction::eContextImmediate; 9472 context.SetNoArgs(); 9473 9474 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9475 res.carry_out, res.overflow); 9476} 9477 9478// Subtract with Carry (register) subtracts an optionally-shifted register 9479// value and the value of 9480// NOT (Carry flag) from a register value, and writes the result to the 9481// destination register. 9482// It can optionally update the condition flags based on the result. 9483bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode, 9484 const ARMEncoding encoding) { 9485#if 0 9486 // ARM pseudo code... 9487 if ConditionPassed() then 9488 EncodingSpecificOperations(); 9489 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9490 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C); 9491 if d == 15 then // Can only occur for ARM encoding 9492 ALUWritePC(result); // setflags is always FALSE here 9493 else 9494 R[d] = result; 9495 if setflags then 9496 APSR.N = result<31>; 9497 APSR.Z = IsZeroBit(result); 9498 APSR.C = carry; 9499 APSR.V = overflow; 9500#endif 9501 9502 bool success = false; 9503 9504 uint32_t Rd; // the destination register 9505 uint32_t Rn; // the first operand 9506 uint32_t Rm; // the second operand 9507 bool setflags; 9508 ARM_ShifterType shift_t; 9509 uint32_t shift_n; // the shift applied to the value read from Rm 9510 switch (encoding) { 9511 case eEncodingT1: 9512 Rd = Rn = Bits32(opcode, 2, 0); 9513 Rm = Bits32(opcode, 5, 3); 9514 setflags = !InITBlock(); 9515 shift_t = SRType_LSL; 9516 shift_n = 0; 9517 break; 9518 case eEncodingT2: 9519 Rd = Bits32(opcode, 11, 8); 9520 Rn = Bits32(opcode, 19, 16); 9521 Rm = Bits32(opcode, 3, 0); 9522 setflags = BitIsSet(opcode, 20); 9523 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9524 if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm)) 9525 return false; 9526 break; 9527 case eEncodingA1: 9528 Rd = Bits32(opcode, 15, 12); 9529 Rn = Bits32(opcode, 19, 16); 9530 Rm = Bits32(opcode, 3, 0); 9531 setflags = BitIsSet(opcode, 20); 9532 shift_n = DecodeImmShiftARM(opcode, shift_t); 9533 9534 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9535 // instructions; 9536 if (Rd == 15 && setflags) 9537 return EmulateSUBSPcLrEtc(opcode, encoding); 9538 break; 9539 default: 9540 return false; 9541 } 9542 // Read the register value from register Rn. 9543 uint32_t val1 = ReadCoreReg(Rn, &success); 9544 if (!success) 9545 return false; 9546 9547 // Read the register value from register Rm. 9548 uint32_t val2 = ReadCoreReg(Rm, &success); 9549 if (!success) 9550 return false; 9551 9552 uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success); 9553 if (!success) 9554 return false; 9555 AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C); 9556 9557 EmulateInstruction::Context context; 9558 context.type = EmulateInstruction::eContextImmediate; 9559 context.SetNoArgs(); 9560 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9561 res.carry_out, res.overflow); 9562} 9563 9564// This instruction subtracts an immediate value from a register value, and 9565// writes the result to the destination register. It can optionally update the 9566// condition flags based on the result. 9567bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode, 9568 const ARMEncoding encoding) { 9569#if 0 9570 // ARM pseudo code... 9571 if ConditionPassed() then 9572 EncodingSpecificOperations(); 9573 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 9574 R[d] = result; 9575 if setflags then 9576 APSR.N = result<31>; 9577 APSR.Z = IsZeroBit(result); 9578 APSR.C = carry; 9579 APSR.V = overflow; 9580#endif 9581 9582 bool success = false; 9583 9584 uint32_t Rd; // the destination register 9585 uint32_t Rn; // the first operand 9586 bool setflags; 9587 uint32_t imm32; // the immediate value to be subtracted from the value 9588 // obtained from Rn 9589 switch (encoding) { 9590 case eEncodingT1: 9591 Rd = Bits32(opcode, 2, 0); 9592 Rn = Bits32(opcode, 5, 3); 9593 setflags = !InITBlock(); 9594 imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32) 9595 break; 9596 case eEncodingT2: 9597 Rd = Rn = Bits32(opcode, 10, 8); 9598 setflags = !InITBlock(); 9599 imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32) 9600 break; 9601 case eEncodingT3: 9602 Rd = Bits32(opcode, 11, 8); 9603 Rn = Bits32(opcode, 19, 16); 9604 setflags = BitIsSet(opcode, 20); 9605 imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8) 9606 9607 // if Rd == '1111' && S == '1' then SEE CMP (immediate); 9608 if (Rd == 15 && setflags) 9609 return EmulateCMPImm(opcode, eEncodingT2); 9610 9611 // if Rn == '1101' then SEE SUB (SP minus immediate); 9612 if (Rn == 13) 9613 return EmulateSUBSPImm(opcode, eEncodingT2); 9614 9615 // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE; 9616 if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15) 9617 return false; 9618 break; 9619 case eEncodingT4: 9620 Rd = Bits32(opcode, 11, 8); 9621 Rn = Bits32(opcode, 19, 16); 9622 setflags = BitIsSet(opcode, 20); 9623 imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32) 9624 9625 // if Rn == '1111' then SEE ADR; 9626 if (Rn == 15) 9627 return EmulateADR(opcode, eEncodingT2); 9628 9629 // if Rn == '1101' then SEE SUB (SP minus immediate); 9630 if (Rn == 13) 9631 return EmulateSUBSPImm(opcode, eEncodingT3); 9632 9633 if (BadReg(Rd)) 9634 return false; 9635 break; 9636 default: 9637 return false; 9638 } 9639 // Read the register value from the operand register Rn. 9640 uint32_t reg_val = ReadCoreReg(Rn, &success); 9641 if (!success) 9642 return false; 9643 9644 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 9645 9646 EmulateInstruction::Context context; 9647 context.type = EmulateInstruction::eContextImmediate; 9648 context.SetNoArgs(); 9649 9650 return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9651 res.carry_out, res.overflow); 9652} 9653 9654// This instruction subtracts an immediate value from a register value, and 9655// writes the result to the destination register. It can optionally update the 9656// condition flags based on the result. 9657bool EmulateInstructionARM::EmulateSUBImmARM(const uint32_t opcode, 9658 const ARMEncoding encoding) { 9659#if 0 9660 // ARM pseudo code... 9661 if ConditionPassed() then 9662 EncodingSpecificOperations(); 9663 (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1'); 9664 if d == 15 then 9665 ALUWritePC(result); // setflags is always FALSE here 9666 else 9667 R[d] = result; 9668 if setflags then 9669 APSR.N = result<31>; 9670 APSR.Z = IsZeroBit(result); 9671 APSR.C = carry; 9672 APSR.V = overflow; 9673#endif 9674 9675 bool success = false; 9676 9677 if (ConditionPassed(opcode)) { 9678 uint32_t Rd; // the destination register 9679 uint32_t Rn; // the first operand 9680 bool setflags; 9681 uint32_t imm32; // the immediate value to be subtracted from the value 9682 // obtained from Rn 9683 switch (encoding) { 9684 case eEncodingA1: 9685 Rd = Bits32(opcode, 15, 12); 9686 Rn = Bits32(opcode, 19, 16); 9687 setflags = BitIsSet(opcode, 20); 9688 imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12) 9689 9690 // if Rn == '1111' && S == '0' then SEE ADR; 9691 if (Rn == 15 && !setflags) 9692 return EmulateADR(opcode, eEncodingA2); 9693 9694 // if Rn == '1101' then SEE SUB (SP minus immediate); 9695 if (Rn == 13) 9696 return EmulateSUBSPImm(opcode, eEncodingA1); 9697 9698 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 9699 // instructions; 9700 if (Rd == 15 && setflags) 9701 return EmulateSUBSPcLrEtc(opcode, encoding); 9702 break; 9703 default: 9704 return false; 9705 } 9706 // Read the register value from the operand register Rn. 9707 uint32_t reg_val = ReadCoreReg(Rn, &success); 9708 if (!success) 9709 return false; 9710 9711 AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1); 9712 9713 EmulateInstruction::Context context; 9714 if (Rd == 13) 9715 context.type = EmulateInstruction::eContextAdjustStackPointer; 9716 else 9717 context.type = EmulateInstruction::eContextRegisterPlusOffset; 9718 9719 std::optional<RegisterInfo> dwarf_reg = 9720 GetRegisterInfo(eRegisterKindDWARF, Rn); 9721 int64_t imm32_signed = imm32; 9722 context.SetRegisterPlusOffset(*dwarf_reg, -imm32_signed); 9723 9724 if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, 9725 res.carry_out, res.overflow)) 9726 return false; 9727 } 9728 return true; 9729} 9730 9731// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a 9732// register value and an immediate value. It updates the condition flags based 9733// on the result, and discards the result. 9734bool EmulateInstructionARM::EmulateTEQImm(const uint32_t opcode, 9735 const ARMEncoding encoding) { 9736#if 0 9737 // ARM pseudo code... 9738 if ConditionPassed() then 9739 EncodingSpecificOperations(); 9740 result = R[n] EOR imm32; 9741 APSR.N = result<31>; 9742 APSR.Z = IsZeroBit(result); 9743 APSR.C = carry; 9744 // APSR.V unchanged 9745#endif 9746 9747 bool success = false; 9748 9749 if (ConditionPassed(opcode)) { 9750 uint32_t Rn; 9751 uint32_t 9752 imm32; // the immediate value to be ANDed to the value obtained from Rn 9753 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9754 switch (encoding) { 9755 case eEncodingT1: 9756 Rn = Bits32(opcode, 19, 16); 9757 imm32 = ThumbExpandImm_C( 9758 opcode, APSR_C, 9759 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9760 if (BadReg(Rn)) 9761 return false; 9762 break; 9763 case eEncodingA1: 9764 Rn = Bits32(opcode, 19, 16); 9765 imm32 = 9766 ARMExpandImm_C(opcode, APSR_C, 9767 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9768 break; 9769 default: 9770 return false; 9771 } 9772 9773 // Read the first operand. 9774 uint32_t val1 = ReadCoreReg(Rn, &success); 9775 if (!success) 9776 return false; 9777 9778 uint32_t result = val1 ^ imm32; 9779 9780 EmulateInstruction::Context context; 9781 context.type = EmulateInstruction::eContextImmediate; 9782 context.SetNoArgs(); 9783 9784 if (!WriteFlags(context, result, carry)) 9785 return false; 9786 } 9787 return true; 9788} 9789 9790// Test Equivalence (register) performs a bitwise exclusive OR operation on a 9791// register value and an optionally-shifted register value. It updates the 9792// condition flags based on the result, and discards the result. 9793bool EmulateInstructionARM::EmulateTEQReg(const uint32_t opcode, 9794 const ARMEncoding encoding) { 9795#if 0 9796 // ARM pseudo code... 9797 if ConditionPassed() then 9798 EncodingSpecificOperations(); 9799 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9800 result = R[n] EOR shifted; 9801 APSR.N = result<31>; 9802 APSR.Z = IsZeroBit(result); 9803 APSR.C = carry; 9804 // APSR.V unchanged 9805#endif 9806 9807 bool success = false; 9808 9809 if (ConditionPassed(opcode)) { 9810 uint32_t Rn, Rm; 9811 ARM_ShifterType shift_t; 9812 uint32_t shift_n; // the shift applied to the value read from Rm 9813 uint32_t carry; 9814 switch (encoding) { 9815 case eEncodingT1: 9816 Rn = Bits32(opcode, 19, 16); 9817 Rm = Bits32(opcode, 3, 0); 9818 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9819 if (BadReg(Rn) || BadReg(Rm)) 9820 return false; 9821 break; 9822 case eEncodingA1: 9823 Rn = Bits32(opcode, 19, 16); 9824 Rm = Bits32(opcode, 3, 0); 9825 shift_n = DecodeImmShiftARM(opcode, shift_t); 9826 break; 9827 default: 9828 return false; 9829 } 9830 9831 // Read the first operand. 9832 uint32_t val1 = ReadCoreReg(Rn, &success); 9833 if (!success) 9834 return false; 9835 9836 // Read the second operand. 9837 uint32_t val2 = ReadCoreReg(Rm, &success); 9838 if (!success) 9839 return false; 9840 9841 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 9842 if (!success) 9843 return false; 9844 uint32_t result = val1 ^ shifted; 9845 9846 EmulateInstruction::Context context; 9847 context.type = EmulateInstruction::eContextImmediate; 9848 context.SetNoArgs(); 9849 9850 if (!WriteFlags(context, result, carry)) 9851 return false; 9852 } 9853 return true; 9854} 9855 9856// Test (immediate) performs a bitwise AND operation on a register value and an 9857// immediate value. It updates the condition flags based on the result, and 9858// discards the result. 9859bool EmulateInstructionARM::EmulateTSTImm(const uint32_t opcode, 9860 const ARMEncoding encoding) { 9861#if 0 9862 // ARM pseudo code... 9863 if ConditionPassed() then 9864 EncodingSpecificOperations(); 9865 result = R[n] AND imm32; 9866 APSR.N = result<31>; 9867 APSR.Z = IsZeroBit(result); 9868 APSR.C = carry; 9869 // APSR.V unchanged 9870#endif 9871 9872 bool success = false; 9873 9874 if (ConditionPassed(opcode)) { 9875 uint32_t Rn; 9876 uint32_t 9877 imm32; // the immediate value to be ANDed to the value obtained from Rn 9878 uint32_t carry; // the carry bit after ARM/Thumb Expand operation 9879 switch (encoding) { 9880 case eEncodingT1: 9881 Rn = Bits32(opcode, 19, 16); 9882 imm32 = ThumbExpandImm_C( 9883 opcode, APSR_C, 9884 carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C) 9885 if (BadReg(Rn)) 9886 return false; 9887 break; 9888 case eEncodingA1: 9889 Rn = Bits32(opcode, 19, 16); 9890 imm32 = 9891 ARMExpandImm_C(opcode, APSR_C, 9892 carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C) 9893 break; 9894 default: 9895 return false; 9896 } 9897 9898 // Read the first operand. 9899 uint32_t val1 = ReadCoreReg(Rn, &success); 9900 if (!success) 9901 return false; 9902 9903 uint32_t result = val1 & imm32; 9904 9905 EmulateInstruction::Context context; 9906 context.type = EmulateInstruction::eContextImmediate; 9907 context.SetNoArgs(); 9908 9909 if (!WriteFlags(context, result, carry)) 9910 return false; 9911 } 9912 return true; 9913} 9914 9915// Test (register) performs a bitwise AND operation on a register value and an 9916// optionally-shifted register value. It updates the condition flags based on 9917// the result, and discards the result. 9918bool EmulateInstructionARM::EmulateTSTReg(const uint32_t opcode, 9919 const ARMEncoding encoding) { 9920#if 0 9921 // ARM pseudo code... 9922 if ConditionPassed() then 9923 EncodingSpecificOperations(); 9924 (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C); 9925 result = R[n] AND shifted; 9926 APSR.N = result<31>; 9927 APSR.Z = IsZeroBit(result); 9928 APSR.C = carry; 9929 // APSR.V unchanged 9930#endif 9931 9932 bool success = false; 9933 9934 if (ConditionPassed(opcode)) { 9935 uint32_t Rn, Rm; 9936 ARM_ShifterType shift_t; 9937 uint32_t shift_n; // the shift applied to the value read from Rm 9938 uint32_t carry; 9939 switch (encoding) { 9940 case eEncodingT1: 9941 Rn = Bits32(opcode, 2, 0); 9942 Rm = Bits32(opcode, 5, 3); 9943 shift_t = SRType_LSL; 9944 shift_n = 0; 9945 break; 9946 case eEncodingT2: 9947 Rn = Bits32(opcode, 19, 16); 9948 Rm = Bits32(opcode, 3, 0); 9949 shift_n = DecodeImmShiftThumb(opcode, shift_t); 9950 if (BadReg(Rn) || BadReg(Rm)) 9951 return false; 9952 break; 9953 case eEncodingA1: 9954 Rn = Bits32(opcode, 19, 16); 9955 Rm = Bits32(opcode, 3, 0); 9956 shift_n = DecodeImmShiftARM(opcode, shift_t); 9957 break; 9958 default: 9959 return false; 9960 } 9961 9962 // Read the first operand. 9963 uint32_t val1 = ReadCoreReg(Rn, &success); 9964 if (!success) 9965 return false; 9966 9967 // Read the second operand. 9968 uint32_t val2 = ReadCoreReg(Rm, &success); 9969 if (!success) 9970 return false; 9971 9972 uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success); 9973 if (!success) 9974 return false; 9975 uint32_t result = val1 & shifted; 9976 9977 EmulateInstruction::Context context; 9978 context.type = EmulateInstruction::eContextImmediate; 9979 context.SetNoArgs(); 9980 9981 if (!WriteFlags(context, result, carry)) 9982 return false; 9983 } 9984 return true; 9985} 9986 9987// A8.6.216 SUB (SP minus register) 9988bool EmulateInstructionARM::EmulateSUBSPReg(const uint32_t opcode, 9989 const ARMEncoding encoding) { 9990#if 0 9991 if ConditionPassed() then 9992 EncodingSpecificOperations(); 9993 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 9994 (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1'); 9995 if d == 15 then // Can only occur for ARM encoding 9996 ALUWritePC(result); // setflags is always FALSE here 9997 else 9998 R[d] = result; 9999 if setflags then 10000 APSR.N = result<31>; 10001 APSR.Z = IsZeroBit(result); 10002 APSR.C = carry; 10003 APSR.V = overflow; 10004#endif 10005 10006 bool success = false; 10007 10008 if (ConditionPassed(opcode)) { 10009 uint32_t d; 10010 uint32_t m; 10011 bool setflags; 10012 ARM_ShifterType shift_t; 10013 uint32_t shift_n; 10014 10015 switch (encoding) { 10016 case eEncodingT1: 10017 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); 10018 d = Bits32(opcode, 11, 8); 10019 m = Bits32(opcode, 3, 0); 10020 setflags = BitIsSet(opcode, 20); 10021 10022 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 10023 shift_n = DecodeImmShiftThumb(opcode, shift_t); 10024 10025 // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then 10026 // UNPREDICTABLE; 10027 if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3))) 10028 return false; 10029 10030 // if d == 15 || BadReg(m) then UNPREDICTABLE; 10031 if ((d == 15) || BadReg(m)) 10032 return false; 10033 break; 10034 10035 case eEncodingA1: 10036 // d = UInt(Rd); m = UInt(Rm); setflags = (S == '1'); 10037 d = Bits32(opcode, 15, 12); 10038 m = Bits32(opcode, 3, 0); 10039 setflags = BitIsSet(opcode, 20); 10040 10041 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 10042 // instructions; 10043 if (d == 15 && setflags) 10044 EmulateSUBSPcLrEtc(opcode, encoding); 10045 10046 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 10047 shift_n = DecodeImmShiftARM(opcode, shift_t); 10048 break; 10049 10050 default: 10051 return false; 10052 } 10053 10054 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 10055 uint32_t Rm = ReadCoreReg(m, &success); 10056 if (!success) 10057 return false; 10058 10059 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success); 10060 if (!success) 10061 return false; 10062 10063 // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), '1'); 10064 uint32_t sp_val = ReadCoreReg(SP_REG, &success); 10065 if (!success) 10066 return false; 10067 10068 AddWithCarryResult res = AddWithCarry(sp_val, ~shifted, 1); 10069 10070 EmulateInstruction::Context context; 10071 context.type = eContextArithmetic; 10072 std::optional<RegisterInfo> sp_reg = 10073 GetRegisterInfo(eRegisterKindDWARF, dwarf_sp); 10074 std::optional<RegisterInfo> dwarf_reg = 10075 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 10076 context.SetRegisterRegisterOperands(*sp_reg, *dwarf_reg); 10077 10078 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, 10079 res.carry_out, res.overflow)) 10080 return false; 10081 } 10082 return true; 10083} 10084 10085// A8.6.7 ADD (register-shifted register) 10086bool EmulateInstructionARM::EmulateADDRegShift(const uint32_t opcode, 10087 const ARMEncoding encoding) { 10088#if 0 10089 if ConditionPassed() then 10090 EncodingSpecificOperations(); 10091 shift_n = UInt(R[s]<7:0>); 10092 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 10093 (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 10094 R[d] = result; 10095 if setflags then 10096 APSR.N = result<31>; 10097 APSR.Z = IsZeroBit(result); 10098 APSR.C = carry; 10099 APSR.V = overflow; 10100#endif 10101 10102 bool success = false; 10103 10104 if (ConditionPassed(opcode)) { 10105 uint32_t d; 10106 uint32_t n; 10107 uint32_t m; 10108 uint32_t s; 10109 bool setflags; 10110 ARM_ShifterType shift_t; 10111 10112 switch (encoding) { 10113 case eEncodingA1: 10114 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs); 10115 d = Bits32(opcode, 15, 12); 10116 n = Bits32(opcode, 19, 16); 10117 m = Bits32(opcode, 3, 0); 10118 s = Bits32(opcode, 11, 8); 10119 10120 // setflags = (S == '1'); shift_t = DecodeRegShift(type); 10121 setflags = BitIsSet(opcode, 20); 10122 shift_t = DecodeRegShift(Bits32(opcode, 6, 5)); 10123 10124 // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE; 10125 if ((d == 15) || (n == 15) || (m == 15) || (s == 15)) 10126 return false; 10127 break; 10128 10129 default: 10130 return false; 10131 } 10132 10133 // shift_n = UInt(R[s]<7:0>); 10134 uint32_t Rs = ReadCoreReg(s, &success); 10135 if (!success) 10136 return false; 10137 10138 uint32_t shift_n = Bits32(Rs, 7, 0); 10139 10140 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 10141 uint32_t Rm = ReadCoreReg(m, &success); 10142 if (!success) 10143 return false; 10144 10145 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success); 10146 if (!success) 10147 return false; 10148 10149 // (result, carry, overflow) = AddWithCarry(R[n], shifted, '0'); 10150 uint32_t Rn = ReadCoreReg(n, &success); 10151 if (!success) 10152 return false; 10153 10154 AddWithCarryResult res = AddWithCarry(Rn, shifted, 0); 10155 10156 // R[d] = result; 10157 EmulateInstruction::Context context; 10158 context.type = eContextArithmetic; 10159 std::optional<RegisterInfo> reg_n = 10160 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10161 std::optional<RegisterInfo> reg_m = 10162 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 10163 10164 context.SetRegisterRegisterOperands(*reg_n, *reg_m); 10165 10166 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 10167 res.result)) 10168 return false; 10169 10170 // if setflags then 10171 // APSR.N = result<31>; 10172 // APSR.Z = IsZeroBit(result); 10173 // APSR.C = carry; 10174 // APSR.V = overflow; 10175 if (setflags) 10176 return WriteFlags(context, res.result, res.carry_out, res.overflow); 10177 } 10178 return true; 10179} 10180 10181// A8.6.213 SUB (register) 10182bool EmulateInstructionARM::EmulateSUBReg(const uint32_t opcode, 10183 const ARMEncoding encoding) { 10184#if 0 10185 if ConditionPassed() then 10186 EncodingSpecificOperations(); 10187 shifted = Shift(R[m], shift_t, shift_n, APSR.C); 10188 (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 10189 if d == 15 then // Can only occur for ARM encoding 10190 ALUWritePC(result); // setflags is always FALSE here 10191 else 10192 R[d] = result; 10193 if setflags then 10194 APSR.N = result<31>; 10195 APSR.Z = IsZeroBit(result); 10196 APSR.C = carry; 10197 APSR.V = overflow; 10198#endif 10199 10200 bool success = false; 10201 10202 if (ConditionPassed(opcode)) { 10203 uint32_t d; 10204 uint32_t n; 10205 uint32_t m; 10206 bool setflags; 10207 ARM_ShifterType shift_t; 10208 uint32_t shift_n; 10209 10210 switch (encoding) { 10211 case eEncodingT1: 10212 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock(); 10213 d = Bits32(opcode, 2, 0); 10214 n = Bits32(opcode, 5, 3); 10215 m = Bits32(opcode, 8, 6); 10216 setflags = !InITBlock(); 10217 10218 // (shift_t, shift_n) = (SRType_LSL, 0); 10219 shift_t = SRType_LSL; 10220 shift_n = 0; 10221 10222 break; 10223 10224 case eEncodingT2: 10225 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1"); 10226 d = Bits32(opcode, 11, 8); 10227 n = Bits32(opcode, 19, 16); 10228 m = Bits32(opcode, 3, 0); 10229 setflags = BitIsSet(opcode, 20); 10230 10231 // if Rd == "1111" && S == "1" then SEE CMP (register); 10232 if (d == 15 && setflags == 1) 10233 return EmulateCMPImm(opcode, eEncodingT3); 10234 10235 // if Rn == "1101" then SEE SUB (SP minus register); 10236 if (n == 13) 10237 return EmulateSUBSPReg(opcode, eEncodingT1); 10238 10239 // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); 10240 shift_n = DecodeImmShiftThumb(opcode, shift_t); 10241 10242 // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then 10243 // UNPREDICTABLE; 10244 if ((d == 13) || ((d == 15) && BitIsClear(opcode, 20)) || (n == 15) || 10245 BadReg(m)) 10246 return false; 10247 10248 break; 10249 10250 case eEncodingA1: 10251 // if Rn == '1101' then SEE SUB (SP minus register); 10252 // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); 10253 d = Bits32(opcode, 15, 12); 10254 n = Bits32(opcode, 19, 16); 10255 m = Bits32(opcode, 3, 0); 10256 setflags = BitIsSet(opcode, 20); 10257 10258 // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related 10259 // instructions; 10260 if ((d == 15) && setflags) 10261 EmulateSUBSPcLrEtc(opcode, encoding); 10262 10263 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 10264 shift_n = DecodeImmShiftARM(opcode, shift_t); 10265 10266 break; 10267 10268 default: 10269 return false; 10270 } 10271 10272 // shifted = Shift(R[m], shift_t, shift_n, APSR.C); 10273 uint32_t Rm = ReadCoreReg(m, &success); 10274 if (!success) 10275 return false; 10276 10277 uint32_t shifted = Shift(Rm, shift_t, shift_n, APSR_C, &success); 10278 if (!success) 10279 return false; 10280 10281 // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1'); 10282 uint32_t Rn = ReadCoreReg(n, &success); 10283 if (!success) 10284 return false; 10285 10286 AddWithCarryResult res = AddWithCarry(Rn, ~shifted, 1); 10287 10288 // if d == 15 then // Can only occur for ARM encoding ALUWritePC(result); 10289 // // setflags is always FALSE here else 10290 // R[d] = result; 10291 // if setflags then 10292 // APSR.N = result<31>; 10293 // APSR.Z = IsZeroBit(result); 10294 // APSR.C = carry; 10295 // APSR.V = overflow; 10296 10297 EmulateInstruction::Context context; 10298 context.type = eContextArithmetic; 10299 std::optional<RegisterInfo> reg_n = 10300 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10301 std::optional<RegisterInfo> reg_m = 10302 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 10303 context.SetRegisterRegisterOperands(*reg_n, *reg_m); 10304 10305 if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, 10306 res.carry_out, res.overflow)) 10307 return false; 10308 } 10309 return true; 10310} 10311 10312// A8.6.202 STREX 10313// Store Register Exclusive calculates an address from a base register value 10314// and an immediate offset, and stores a word from a register to memory if the 10315// executing processor has exclusive access to the memory addressed. 10316bool EmulateInstructionARM::EmulateSTREX(const uint32_t opcode, 10317 const ARMEncoding encoding) { 10318#if 0 10319 if ConditionPassed() then 10320 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10321 address = R[n] + imm32; 10322 if ExclusiveMonitorsPass(address,4) then 10323 MemA[address,4] = R[t]; 10324 R[d] = 0; 10325 else 10326 R[d] = 1; 10327#endif 10328 10329 bool success = false; 10330 10331 if (ConditionPassed(opcode)) { 10332 uint32_t d; 10333 uint32_t t; 10334 uint32_t n; 10335 uint32_t imm32; 10336 const uint32_t addr_byte_size = GetAddressByteSize(); 10337 10338 switch (encoding) { 10339 case eEncodingT1: 10340 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = 10341 // ZeroExtend(imm8:'00', 10342 // 32); 10343 d = Bits32(opcode, 11, 8); 10344 t = Bits32(opcode, 15, 12); 10345 n = Bits32(opcode, 19, 16); 10346 imm32 = Bits32(opcode, 7, 0) << 2; 10347 10348 // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE; 10349 if (BadReg(d) || BadReg(t) || (n == 15)) 10350 return false; 10351 10352 // if d == n || d == t then UNPREDICTABLE; 10353 if ((d == n) || (d == t)) 10354 return false; 10355 10356 break; 10357 10358 case eEncodingA1: 10359 // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero 10360 // offset 10361 d = Bits32(opcode, 15, 12); 10362 t = Bits32(opcode, 3, 0); 10363 n = Bits32(opcode, 19, 16); 10364 imm32 = 0; 10365 10366 // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE; 10367 if ((d == 15) || (t == 15) || (n == 15)) 10368 return false; 10369 10370 // if d == n || d == t then UNPREDICTABLE; 10371 if ((d == n) || (d == t)) 10372 return false; 10373 10374 break; 10375 10376 default: 10377 return false; 10378 } 10379 10380 // address = R[n] + imm32; 10381 uint32_t Rn = ReadCoreReg(n, &success); 10382 if (!success) 10383 return false; 10384 10385 addr_t address = Rn + imm32; 10386 10387 std::optional<RegisterInfo> base_reg = 10388 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10389 std::optional<RegisterInfo> data_reg = 10390 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 10391 EmulateInstruction::Context context; 10392 context.type = eContextRegisterStore; 10393 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, imm32); 10394 10395 // if ExclusiveMonitorsPass(address,4) then if (ExclusiveMonitorsPass 10396 // (address, addr_byte_size)) -- For now, for the sake of emulation, we 10397 // will say this 10398 // always return 10399 // true. 10400 if (true) { 10401 // MemA[address,4] = R[t]; 10402 uint32_t Rt = 10403 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_r0 + t, 0, &success); 10404 if (!success) 10405 return false; 10406 10407 if (!MemAWrite(context, address, Rt, addr_byte_size)) 10408 return false; 10409 10410 // R[d] = 0; 10411 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, 0)) 10412 return false; 10413 } 10414#if 0 // unreachable because if true 10415 else 10416 { 10417 // R[d] = 1; 10418 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1)) 10419 return false; 10420 } 10421#endif // unreachable because if true 10422 } 10423 return true; 10424} 10425 10426// A8.6.197 STRB (immediate, ARM) 10427bool EmulateInstructionARM::EmulateSTRBImmARM(const uint32_t opcode, 10428 const ARMEncoding encoding) { 10429#if 0 10430 if ConditionPassed() then 10431 EncodingSpecificOperations(); 10432 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10433 address = if index then offset_addr else R[n]; 10434 MemU[address,1] = R[t]<7:0>; 10435 if wback then R[n] = offset_addr; 10436#endif 10437 10438 bool success = false; 10439 10440 if (ConditionPassed(opcode)) { 10441 uint32_t t; 10442 uint32_t n; 10443 uint32_t imm32; 10444 bool index; 10445 bool add; 10446 bool wback; 10447 10448 switch (encoding) { 10449 case eEncodingA1: 10450 // if P == '0' && W == '1' then SEE STRBT; 10451 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 10452 t = Bits32(opcode, 15, 12); 10453 n = Bits32(opcode, 19, 16); 10454 imm32 = Bits32(opcode, 11, 0); 10455 10456 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 10457 index = BitIsSet(opcode, 24); 10458 add = BitIsSet(opcode, 23); 10459 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 10460 10461 // if t == 15 then UNPREDICTABLE; 10462 if (t == 15) 10463 return false; 10464 10465 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 10466 if (wback && ((n == 15) || (n == t))) 10467 return false; 10468 10469 break; 10470 10471 default: 10472 return false; 10473 } 10474 10475 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10476 uint32_t Rn = ReadCoreReg(n, &success); 10477 if (!success) 10478 return false; 10479 10480 addr_t offset_addr; 10481 if (add) 10482 offset_addr = Rn + imm32; 10483 else 10484 offset_addr = Rn - imm32; 10485 10486 // address = if index then offset_addr else R[n]; 10487 addr_t address; 10488 if (index) 10489 address = offset_addr; 10490 else 10491 address = Rn; 10492 10493 // MemU[address,1] = R[t]<7:0>; 10494 uint32_t Rt = ReadCoreReg(t, &success); 10495 if (!success) 10496 return false; 10497 10498 std::optional<RegisterInfo> base_reg = 10499 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10500 std::optional<RegisterInfo> data_reg = 10501 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 10502 EmulateInstruction::Context context; 10503 context.type = eContextRegisterStore; 10504 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 10505 10506 if (!MemUWrite(context, address, Bits32(Rt, 7, 0), 1)) 10507 return false; 10508 10509 // if wback then R[n] = offset_addr; 10510 if (wback) { 10511 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 10512 offset_addr)) 10513 return false; 10514 } 10515 } 10516 return true; 10517} 10518 10519// A8.6.194 STR (immediate, ARM) 10520bool EmulateInstructionARM::EmulateSTRImmARM(const uint32_t opcode, 10521 const ARMEncoding encoding) { 10522#if 0 10523 if ConditionPassed() then 10524 EncodingSpecificOperations(); 10525 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10526 address = if index then offset_addr else R[n]; 10527 MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 10528 if wback then R[n] = offset_addr; 10529#endif 10530 10531 bool success = false; 10532 10533 if (ConditionPassed(opcode)) { 10534 uint32_t t; 10535 uint32_t n; 10536 uint32_t imm32; 10537 bool index; 10538 bool add; 10539 bool wback; 10540 10541 const uint32_t addr_byte_size = GetAddressByteSize(); 10542 10543 switch (encoding) { 10544 case eEncodingA1: 10545 // if P == '0' && W == '1' then SEE STRT; 10546 // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm12 == 10547 // '000000000100' then SEE PUSH; 10548 // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 10549 t = Bits32(opcode, 15, 12); 10550 n = Bits32(opcode, 19, 16); 10551 imm32 = Bits32(opcode, 11, 0); 10552 10553 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 10554 index = BitIsSet(opcode, 24); 10555 add = BitIsSet(opcode, 23); 10556 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 10557 10558 // if wback && (n == 15 || n == t) then UNPREDICTABLE; 10559 if (wback && ((n == 15) || (n == t))) 10560 return false; 10561 10562 break; 10563 10564 default: 10565 return false; 10566 } 10567 10568 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10569 uint32_t Rn = ReadCoreReg(n, &success); 10570 if (!success) 10571 return false; 10572 10573 addr_t offset_addr; 10574 if (add) 10575 offset_addr = Rn + imm32; 10576 else 10577 offset_addr = Rn - imm32; 10578 10579 // address = if index then offset_addr else R[n]; 10580 addr_t address; 10581 if (index) 10582 address = offset_addr; 10583 else 10584 address = Rn; 10585 10586 std::optional<RegisterInfo> base_reg = 10587 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10588 std::optional<RegisterInfo> data_reg = 10589 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 10590 EmulateInstruction::Context context; 10591 context.type = eContextRegisterStore; 10592 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 10593 10594 // MemU[address,4] = if t == 15 then PCStoreValue() else R[t]; 10595 uint32_t Rt = ReadCoreReg(t, &success); 10596 if (!success) 10597 return false; 10598 10599 if (t == 15) { 10600 uint32_t pc_value = ReadCoreReg(PC_REG, &success); 10601 if (!success) 10602 return false; 10603 10604 if (!MemUWrite(context, address, pc_value, addr_byte_size)) 10605 return false; 10606 } else { 10607 if (!MemUWrite(context, address, Rt, addr_byte_size)) 10608 return false; 10609 } 10610 10611 // if wback then R[n] = offset_addr; 10612 if (wback) { 10613 context.type = eContextAdjustBaseRegister; 10614 context.SetImmediate(offset_addr); 10615 10616 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 10617 offset_addr)) 10618 return false; 10619 } 10620 } 10621 return true; 10622} 10623 10624// A8.6.66 LDRD (immediate) 10625// Load Register Dual (immediate) calculates an address from a base register 10626// value and an immediate offset, loads two words from memory, and writes them 10627// to two registers. It can use offset, post-indexed, or pre-indexed 10628// addressing. 10629bool EmulateInstructionARM::EmulateLDRDImmediate(const uint32_t opcode, 10630 const ARMEncoding encoding) { 10631#if 0 10632 if ConditionPassed() then 10633 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10634 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10635 address = if index then offset_addr else R[n]; 10636 R[t] = MemA[address,4]; 10637 R[t2] = MemA[address+4,4]; 10638 if wback then R[n] = offset_addr; 10639#endif 10640 10641 bool success = false; 10642 10643 if (ConditionPassed(opcode)) { 10644 uint32_t t; 10645 uint32_t t2; 10646 uint32_t n; 10647 uint32_t imm32; 10648 bool index; 10649 bool add; 10650 bool wback; 10651 10652 switch (encoding) { 10653 case eEncodingT1: 10654 // if P == '0' && W == '0' then SEE 'Related encodings'; 10655 // if Rn == '1111' then SEE LDRD (literal); 10656 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = 10657 // ZeroExtend(imm8:'00', 32); 10658 t = Bits32(opcode, 15, 12); 10659 t2 = Bits32(opcode, 11, 8); 10660 n = Bits32(opcode, 19, 16); 10661 imm32 = Bits32(opcode, 7, 0) << 2; 10662 10663 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 10664 index = BitIsSet(opcode, 24); 10665 add = BitIsSet(opcode, 23); 10666 wback = BitIsSet(opcode, 21); 10667 10668 // if wback && (n == t || n == t2) then UNPREDICTABLE; 10669 if (wback && ((n == t) || (n == t2))) 10670 return false; 10671 10672 // if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE; 10673 if (BadReg(t) || BadReg(t2) || (t == t2)) 10674 return false; 10675 10676 break; 10677 10678 case eEncodingA1: 10679 // if Rn == '1111' then SEE LDRD (literal); 10680 // if Rt<0> == '1' then UNPREDICTABLE; 10681 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 10682 // 32); 10683 t = Bits32(opcode, 15, 12); 10684 if (BitIsSet(t, 0)) 10685 return false; 10686 t2 = t + 1; 10687 n = Bits32(opcode, 19, 16); 10688 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0); 10689 10690 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 10691 index = BitIsSet(opcode, 24); 10692 add = BitIsSet(opcode, 23); 10693 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 10694 10695 // if P == '0' && W == '1' then UNPREDICTABLE; 10696 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) 10697 return false; 10698 10699 // if wback && (n == t || n == t2) then UNPREDICTABLE; 10700 if (wback && ((n == t) || (n == t2))) 10701 return false; 10702 10703 // if t2 == 15 then UNPREDICTABLE; 10704 if (t2 == 15) 10705 return false; 10706 10707 break; 10708 10709 default: 10710 return false; 10711 } 10712 10713 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10714 uint32_t Rn = ReadCoreReg(n, &success); 10715 if (!success) 10716 return false; 10717 10718 addr_t offset_addr; 10719 if (add) 10720 offset_addr = Rn + imm32; 10721 else 10722 offset_addr = Rn - imm32; 10723 10724 // address = if index then offset_addr else R[n]; 10725 addr_t address; 10726 if (index) 10727 address = offset_addr; 10728 else 10729 address = Rn; 10730 10731 // R[t] = MemA[address,4]; 10732 10733 EmulateInstruction::Context context; 10734 if (n == 13) 10735 context.type = eContextPopRegisterOffStack; 10736 else 10737 context.type = eContextRegisterLoad; 10738 context.SetAddress(address); 10739 10740 const uint32_t addr_byte_size = GetAddressByteSize(); 10741 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); 10742 if (!success) 10743 return false; 10744 10745 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) 10746 return false; 10747 10748 // R[t2] = MemA[address+4,4]; 10749 context.SetAddress(address + 4); 10750 data = MemARead(context, address + 4, addr_byte_size, 0, &success); 10751 if (!success) 10752 return false; 10753 10754 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2, 10755 data)) 10756 return false; 10757 10758 // if wback then R[n] = offset_addr; 10759 if (wback) { 10760 context.type = eContextAdjustBaseRegister; 10761 context.SetAddress(offset_addr); 10762 10763 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 10764 offset_addr)) 10765 return false; 10766 } 10767 } 10768 return true; 10769} 10770 10771// A8.6.68 LDRD (register) 10772// Load Register Dual (register) calculates an address from a base register 10773// value and a register offset, loads two words from memory, and writes them to 10774// two registers. It can use offset, post-indexed or pre-indexed addressing. 10775bool EmulateInstructionARM::EmulateLDRDRegister(const uint32_t opcode, 10776 const ARMEncoding encoding) { 10777#if 0 10778 if ConditionPassed() then 10779 EncodingSpecificOperations(); 10780 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10781 address = if index then offset_addr else R[n]; 10782 R[t] = MemA[address,4]; 10783 R[t2] = MemA[address+4,4]; 10784 if wback then R[n] = offset_addr; 10785#endif 10786 10787 bool success = false; 10788 10789 if (ConditionPassed(opcode)) { 10790 uint32_t t; 10791 uint32_t t2; 10792 uint32_t n; 10793 uint32_t m; 10794 bool index; 10795 bool add; 10796 bool wback; 10797 10798 switch (encoding) { 10799 case eEncodingA1: 10800 // if Rt<0> == '1' then UNPREDICTABLE; 10801 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 10802 t = Bits32(opcode, 15, 12); 10803 if (BitIsSet(t, 0)) 10804 return false; 10805 t2 = t + 1; 10806 n = Bits32(opcode, 19, 16); 10807 m = Bits32(opcode, 3, 0); 10808 10809 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 10810 index = BitIsSet(opcode, 24); 10811 add = BitIsSet(opcode, 23); 10812 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 10813 10814 // if P == '0' && W == '1' then UNPREDICTABLE; 10815 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) 10816 return false; 10817 10818 // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE; 10819 if ((t2 == 15) || (m == 15) || (m == t) || (m == t2)) 10820 return false; 10821 10822 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10823 if (wback && ((n == 15) || (n == t) || (n == t2))) 10824 return false; 10825 10826 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 10827 if ((ArchVersion() < 6) && wback && (m == n)) 10828 return false; 10829 break; 10830 10831 default: 10832 return false; 10833 } 10834 10835 uint32_t Rn = ReadCoreReg(n, &success); 10836 if (!success) 10837 return false; 10838 10839 uint32_t Rm = ReadCoreReg(m, &success); 10840 if (!success) 10841 return false; 10842 10843 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 10844 addr_t offset_addr; 10845 if (add) 10846 offset_addr = Rn + Rm; 10847 else 10848 offset_addr = Rn - Rm; 10849 10850 // address = if index then offset_addr else R[n]; 10851 addr_t address; 10852 if (index) 10853 address = offset_addr; 10854 else 10855 address = Rn; 10856 10857 EmulateInstruction::Context context; 10858 if (n == 13) 10859 context.type = eContextPopRegisterOffStack; 10860 else 10861 context.type = eContextRegisterLoad; 10862 context.SetAddress(address); 10863 10864 // R[t] = MemA[address,4]; 10865 const uint32_t addr_byte_size = GetAddressByteSize(); 10866 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); 10867 if (!success) 10868 return false; 10869 10870 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t, data)) 10871 return false; 10872 10873 // R[t2] = MemA[address+4,4]; 10874 10875 data = MemARead(context, address + 4, addr_byte_size, 0, &success); 10876 if (!success) 10877 return false; 10878 10879 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + t2, 10880 data)) 10881 return false; 10882 10883 // if wback then R[n] = offset_addr; 10884 if (wback) { 10885 context.type = eContextAdjustBaseRegister; 10886 context.SetAddress(offset_addr); 10887 10888 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 10889 offset_addr)) 10890 return false; 10891 } 10892 } 10893 return true; 10894} 10895 10896// A8.6.200 STRD (immediate) 10897// Store Register Dual (immediate) calculates an address from a base register 10898// value and an immediate offset, and stores two words from two registers to 10899// memory. It can use offset, post-indexed, or pre-indexed addressing. 10900bool EmulateInstructionARM::EmulateSTRDImm(const uint32_t opcode, 10901 const ARMEncoding encoding) { 10902#if 0 10903 if ConditionPassed() then 10904 EncodingSpecificOperations(); NullCheckIfThumbEE(n); 10905 offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10906 address = if index then offset_addr else R[n]; 10907 MemA[address,4] = R[t]; 10908 MemA[address+4,4] = R[t2]; 10909 if wback then R[n] = offset_addr; 10910#endif 10911 10912 bool success = false; 10913 10914 if (ConditionPassed(opcode)) { 10915 uint32_t t; 10916 uint32_t t2; 10917 uint32_t n; 10918 uint32_t imm32; 10919 bool index; 10920 bool add; 10921 bool wback; 10922 10923 switch (encoding) { 10924 case eEncodingT1: 10925 // if P == '0' && W == '0' then SEE 'Related encodings'; 10926 // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = 10927 // ZeroExtend(imm8:'00', 32); 10928 t = Bits32(opcode, 15, 12); 10929 t2 = Bits32(opcode, 11, 8); 10930 n = Bits32(opcode, 19, 16); 10931 imm32 = Bits32(opcode, 7, 0) << 2; 10932 10933 // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 10934 index = BitIsSet(opcode, 24); 10935 add = BitIsSet(opcode, 23); 10936 wback = BitIsSet(opcode, 21); 10937 10938 // if wback && (n == t || n == t2) then UNPREDICTABLE; 10939 if (wback && ((n == t) || (n == t2))) 10940 return false; 10941 10942 // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE; 10943 if ((n == 15) || BadReg(t) || BadReg(t2)) 10944 return false; 10945 10946 break; 10947 10948 case eEncodingA1: 10949 // if Rt<0> == '1' then UNPREDICTABLE; 10950 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 10951 // 32); 10952 t = Bits32(opcode, 15, 12); 10953 if (BitIsSet(t, 0)) 10954 return false; 10955 10956 t2 = t + 1; 10957 n = Bits32(opcode, 19, 16); 10958 imm32 = (Bits32(opcode, 11, 8) << 4) | Bits32(opcode, 3, 0); 10959 10960 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 10961 index = BitIsSet(opcode, 24); 10962 add = BitIsSet(opcode, 23); 10963 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 10964 10965 // if P == '0' && W == '1' then UNPREDICTABLE; 10966 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) 10967 return false; 10968 10969 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 10970 if (wback && ((n == 15) || (n == t) || (n == t2))) 10971 return false; 10972 10973 // if t2 == 15 then UNPREDICTABLE; 10974 if (t2 == 15) 10975 return false; 10976 10977 break; 10978 10979 default: 10980 return false; 10981 } 10982 10983 std::optional<RegisterInfo> base_reg = 10984 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 10985 10986 uint32_t Rn = ReadCoreReg(n, &success); 10987 if (!success) 10988 return false; 10989 10990 // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 10991 addr_t offset_addr; 10992 if (add) 10993 offset_addr = Rn + imm32; 10994 else 10995 offset_addr = Rn - imm32; 10996 10997 // address = if index then offset_addr else R[n]; 10998 addr_t address; 10999 if (index) 11000 address = offset_addr; 11001 else 11002 address = Rn; 11003 11004 // MemA[address,4] = R[t]; 11005 std::optional<RegisterInfo> data_reg = 11006 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 11007 11008 uint32_t data = ReadCoreReg(t, &success); 11009 if (!success) 11010 return false; 11011 11012 EmulateInstruction::Context context; 11013 if (n == 13) 11014 context.type = eContextPushRegisterOnStack; 11015 else 11016 context.type = eContextRegisterStore; 11017 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 11018 11019 const uint32_t addr_byte_size = GetAddressByteSize(); 11020 11021 if (!MemAWrite(context, address, data, addr_byte_size)) 11022 return false; 11023 11024 // MemA[address+4,4] = R[t2]; 11025 data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2); 11026 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11027 (address + 4) - Rn); 11028 11029 data = ReadCoreReg(t2, &success); 11030 if (!success) 11031 return false; 11032 11033 if (!MemAWrite(context, address + 4, data, addr_byte_size)) 11034 return false; 11035 11036 // if wback then R[n] = offset_addr; 11037 if (wback) { 11038 if (n == 13) 11039 context.type = eContextAdjustStackPointer; 11040 else 11041 context.type = eContextAdjustBaseRegister; 11042 context.SetAddress(offset_addr); 11043 11044 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 11045 offset_addr)) 11046 return false; 11047 } 11048 } 11049 return true; 11050} 11051 11052// A8.6.201 STRD (register) 11053bool EmulateInstructionARM::EmulateSTRDReg(const uint32_t opcode, 11054 const ARMEncoding encoding) { 11055#if 0 11056 if ConditionPassed() then 11057 EncodingSpecificOperations(); 11058 offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 11059 address = if index then offset_addr else R[n]; 11060 MemA[address,4] = R[t]; 11061 MemA[address+4,4] = R[t2]; 11062 if wback then R[n] = offset_addr; 11063#endif 11064 11065 bool success = false; 11066 11067 if (ConditionPassed(opcode)) { 11068 uint32_t t; 11069 uint32_t t2; 11070 uint32_t n; 11071 uint32_t m; 11072 bool index; 11073 bool add; 11074 bool wback; 11075 11076 switch (encoding) { 11077 case eEncodingA1: 11078 // if Rt<0> == '1' then UNPREDICTABLE; 11079 // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm); 11080 t = Bits32(opcode, 15, 12); 11081 if (BitIsSet(t, 0)) 11082 return false; 11083 11084 t2 = t + 1; 11085 n = Bits32(opcode, 19, 16); 11086 m = Bits32(opcode, 3, 0); 11087 11088 // index = (P == '1'); add = (U == '1'); wback = (P == '0') || (W == '1'); 11089 index = BitIsSet(opcode, 24); 11090 add = BitIsSet(opcode, 23); 11091 wback = BitIsClear(opcode, 24) || BitIsSet(opcode, 21); 11092 11093 // if P == '0' && W == '1' then UNPREDICTABLE; 11094 if (BitIsClear(opcode, 24) && BitIsSet(opcode, 21)) 11095 return false; 11096 11097 // if t2 == 15 || m == 15 then UNPREDICTABLE; 11098 if ((t2 == 15) || (m == 15)) 11099 return false; 11100 11101 // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; 11102 if (wback && ((n == 15) || (n == t) || (n == t2))) 11103 return false; 11104 11105 // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; 11106 if ((ArchVersion() < 6) && wback && (m == n)) 11107 return false; 11108 11109 break; 11110 11111 default: 11112 return false; 11113 } 11114 11115 uint32_t Rn = ReadCoreReg(n, &success); 11116 if (!success) 11117 return false; 11118 11119 uint32_t Rm = ReadCoreReg(m, &success); 11120 if (!success) 11121 return false; 11122 11123 // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]); 11124 addr_t offset_addr; 11125 if (add) 11126 offset_addr = Rn + Rm; 11127 else 11128 offset_addr = Rn - Rm; 11129 11130 // address = if index then offset_addr else R[n]; 11131 addr_t address; 11132 if (index) 11133 address = offset_addr; 11134 else 11135 address = Rn; 11136 // MemA[address,4] = R[t]; 11137 uint32_t Rt = ReadCoreReg(t, &success); 11138 if (!success) 11139 return false; 11140 11141 EmulateInstruction::Context context; 11142 if (t == 13) 11143 context.type = eContextPushRegisterOnStack; 11144 else 11145 context.type = eContextRegisterStore; 11146 11147 std::optional<RegisterInfo> base_reg = 11148 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11149 std::optional<RegisterInfo> offset_reg = 11150 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + m); 11151 std::optional<RegisterInfo> data_reg = 11152 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t); 11153 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg, 11154 *data_reg); 11155 11156 const uint32_t addr_byte_size = GetAddressByteSize(); 11157 11158 if (!MemAWrite(context, address, Rt, addr_byte_size)) 11159 return false; 11160 11161 // MemA[address+4,4] = R[t2]; 11162 uint32_t Rt2 = ReadCoreReg(t2, &success); 11163 if (!success) 11164 return false; 11165 11166 data_reg = GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + t2); 11167 11168 context.SetRegisterToRegisterPlusIndirectOffset(*base_reg, *offset_reg, 11169 *data_reg); 11170 11171 if (!MemAWrite(context, address + 4, Rt2, addr_byte_size)) 11172 return false; 11173 11174 // if wback then R[n] = offset_addr; 11175 if (wback) { 11176 context.type = eContextAdjustBaseRegister; 11177 context.SetAddress(offset_addr); 11178 11179 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 11180 offset_addr)) 11181 return false; 11182 } 11183 } 11184 return true; 11185} 11186 11187// A8.6.319 VLDM 11188// Vector Load Multiple loads multiple extension registers from consecutive 11189// memory locations using an address from an ARM core register. 11190bool EmulateInstructionARM::EmulateVLDM(const uint32_t opcode, 11191 const ARMEncoding encoding) { 11192#if 0 11193 if ConditionPassed() then 11194 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 11195 address = if add then R[n] else R[n]-imm32; 11196 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 11197 for r = 0 to regs-1 11198 if single_regs then 11199 S[d+r] = MemA[address,4]; address = address+4; 11200 else 11201 word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8; 11202 // Combine the word-aligned words in the correct order for 11203 // current endianness. 11204 D[d+r] = if BigEndian() then word1:word2 else word2:word1; 11205#endif 11206 11207 bool success = false; 11208 11209 if (ConditionPassed(opcode)) { 11210 bool single_regs; 11211 bool add; 11212 bool wback; 11213 uint32_t d; 11214 uint32_t n; 11215 uint32_t imm32; 11216 uint32_t regs; 11217 11218 switch (encoding) { 11219 case eEncodingT1: 11220 case eEncodingA1: 11221 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; 11222 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; 11223 // if P == '1' && W == '0' then SEE VLDR; 11224 // if P == U && W == '1' then UNDEFINED; 11225 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) 11226 return false; 11227 11228 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with 11229 // !), 101 (DB with !) 11230 // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); 11231 single_regs = false; 11232 add = BitIsSet(opcode, 23); 11233 wback = BitIsSet(opcode, 21); 11234 11235 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); 11236 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 11237 n = Bits32(opcode, 19, 16); 11238 imm32 = Bits32(opcode, 7, 0) << 2; 11239 11240 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FLDMX'. 11241 regs = Bits32(opcode, 7, 0) / 2; 11242 11243 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then 11244 // UNPREDICTABLE; 11245 if (n == 15 && (wback || CurrentInstrSet() != eModeARM)) 11246 return false; 11247 11248 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 11249 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 11250 return false; 11251 11252 break; 11253 11254 case eEncodingT2: 11255 case eEncodingA2: 11256 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; 11257 // if P == '0' && U == '1' && W == '1' && Rn == '1101' then SEE VPOP; 11258 // if P == '1' && W == '0' then SEE VLDR; 11259 // if P == U && W == '1' then UNDEFINED; 11260 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) 11261 return false; 11262 11263 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with 11264 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W 11265 // == '1'); d = 11266 // UInt(Vd:D); n = UInt(Rn); 11267 single_regs = true; 11268 add = BitIsSet(opcode, 23); 11269 wback = BitIsSet(opcode, 21); 11270 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); 11271 n = Bits32(opcode, 19, 16); 11272 11273 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); 11274 imm32 = Bits32(opcode, 7, 0) << 2; 11275 regs = Bits32(opcode, 7, 0); 11276 11277 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then 11278 // UNPREDICTABLE; 11279 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 11280 return false; 11281 11282 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 11283 if ((regs == 0) || ((d + regs) > 32)) 11284 return false; 11285 break; 11286 11287 default: 11288 return false; 11289 } 11290 11291 uint32_t Rn = ReadCoreReg(n, &success); 11292 if (!success) 11293 return false; 11294 11295 // address = if add then R[n] else R[n]-imm32; 11296 addr_t address; 11297 if (add) 11298 address = Rn; 11299 else 11300 address = Rn - imm32; 11301 11302 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 11303 EmulateInstruction::Context context; 11304 11305 if (wback) { 11306 uint32_t value; 11307 if (add) 11308 value = Rn + imm32; 11309 else 11310 value = Rn - imm32; 11311 11312 context.type = eContextAdjustBaseRegister; 11313 context.SetImmediateSigned(value - Rn); 11314 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 11315 value)) 11316 return false; 11317 } 11318 11319 const uint32_t addr_byte_size = GetAddressByteSize(); 11320 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 11321 11322 context.type = eContextRegisterLoad; 11323 11324 std::optional<RegisterInfo> base_reg = 11325 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11326 11327 // for r = 0 to regs-1 11328 for (uint32_t r = 0; r < regs; ++r) { 11329 if (single_regs) { 11330 // S[d+r] = MemA[address,4]; address = address+4; 11331 context.SetRegisterPlusOffset(*base_reg, address - Rn); 11332 11333 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); 11334 if (!success) 11335 return false; 11336 11337 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, 11338 start_reg + d + r, data)) 11339 return false; 11340 11341 address = address + 4; 11342 } else { 11343 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = 11344 // address+8; 11345 context.SetRegisterPlusOffset(*base_reg, address - Rn); 11346 uint32_t word1 = 11347 MemARead(context, address, addr_byte_size, 0, &success); 11348 if (!success) 11349 return false; 11350 11351 context.SetRegisterPlusOffset(*base_reg, (address + 4) - Rn); 11352 uint32_t word2 = 11353 MemARead(context, address + 4, addr_byte_size, 0, &success); 11354 if (!success) 11355 return false; 11356 11357 address = address + 8; 11358 // // Combine the word-aligned words in the correct order for current 11359 // endianness. 11360 // D[d+r] = if BigEndian() then word1:word2 else word2:word1; 11361 uint64_t data; 11362 if (GetByteOrder() == eByteOrderBig) { 11363 data = word1; 11364 data = (data << 32) | word2; 11365 } else { 11366 data = word2; 11367 data = (data << 32) | word1; 11368 } 11369 11370 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, 11371 start_reg + d + r, data)) 11372 return false; 11373 } 11374 } 11375 } 11376 return true; 11377} 11378 11379// A8.6.399 VSTM 11380// Vector Store Multiple stores multiple extension registers to consecutive 11381// memory locations using an address from an 11382// ARM core register. 11383bool EmulateInstructionARM::EmulateVSTM(const uint32_t opcode, 11384 const ARMEncoding encoding) { 11385#if 0 11386 if ConditionPassed() then 11387 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 11388 address = if add then R[n] else R[n]-imm32; 11389 if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 11390 for r = 0 to regs-1 11391 if single_regs then 11392 MemA[address,4] = S[d+r]; address = address+4; 11393 else 11394 // Store as two word-aligned words in the correct order for 11395 // current endianness. 11396 MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>; 11397 MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>; 11398 address = address+8; 11399#endif 11400 11401 bool success = false; 11402 11403 if (ConditionPassed(opcode)) { 11404 bool single_regs; 11405 bool add; 11406 bool wback; 11407 uint32_t d; 11408 uint32_t n; 11409 uint32_t imm32; 11410 uint32_t regs; 11411 11412 switch (encoding) { 11413 case eEncodingT1: 11414 case eEncodingA1: 11415 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; 11416 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; 11417 // if P == '1' && W == '0' then SEE VSTR; 11418 // if P == U && W == '1' then UNDEFINED; 11419 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) 11420 return false; 11421 11422 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with 11423 // !), 101 (DB with !) 11424 // single_regs = FALSE; add = (U == '1'); wback = (W == '1'); 11425 single_regs = false; 11426 add = BitIsSet(opcode, 23); 11427 wback = BitIsSet(opcode, 21); 11428 11429 // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:'00', 32); 11430 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 11431 n = Bits32(opcode, 19, 16); 11432 imm32 = Bits32(opcode, 7, 0) << 2; 11433 11434 // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see 'FSTMX'. 11435 regs = Bits32(opcode, 7, 0) / 2; 11436 11437 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then 11438 // UNPREDICTABLE; 11439 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 11440 return false; 11441 11442 // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE; 11443 if ((regs == 0) || (regs > 16) || ((d + regs) > 32)) 11444 return false; 11445 11446 break; 11447 11448 case eEncodingT2: 11449 case eEncodingA2: 11450 // if P == '0' && U == '0' && W == '0' then SEE 'Related encodings'; 11451 // if P == '1' && U == '0' && W == '1' && Rn == '1101' then SEE VPUSH; 11452 // if P == '1' && W == '0' then SEE VSTR; 11453 // if P == U && W == '1' then UNDEFINED; 11454 if ((Bit32(opcode, 24) == Bit32(opcode, 23)) && BitIsSet(opcode, 21)) 11455 return false; 11456 11457 // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with 11458 // !), 101 (DB with !) single_regs = TRUE; add = (U == '1'); wback = (W 11459 // == '1'); d = 11460 // UInt(Vd:D); n = UInt(Rn); 11461 single_regs = true; 11462 add = BitIsSet(opcode, 23); 11463 wback = BitIsSet(opcode, 21); 11464 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); 11465 n = Bits32(opcode, 19, 16); 11466 11467 // imm32 = ZeroExtend(imm8:'00', 32); regs = UInt(imm8); 11468 imm32 = Bits32(opcode, 7, 0) << 2; 11469 regs = Bits32(opcode, 7, 0); 11470 11471 // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then 11472 // UNPREDICTABLE; 11473 if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM))) 11474 return false; 11475 11476 // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE; 11477 if ((regs == 0) || ((d + regs) > 32)) 11478 return false; 11479 11480 break; 11481 11482 default: 11483 return false; 11484 } 11485 11486 std::optional<RegisterInfo> base_reg = 11487 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11488 11489 uint32_t Rn = ReadCoreReg(n, &success); 11490 if (!success) 11491 return false; 11492 11493 // address = if add then R[n] else R[n]-imm32; 11494 addr_t address; 11495 if (add) 11496 address = Rn; 11497 else 11498 address = Rn - imm32; 11499 11500 EmulateInstruction::Context context; 11501 // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32; 11502 if (wback) { 11503 uint32_t value; 11504 if (add) 11505 value = Rn + imm32; 11506 else 11507 value = Rn - imm32; 11508 11509 context.type = eContextAdjustBaseRegister; 11510 context.SetRegisterPlusOffset(*base_reg, value - Rn); 11511 11512 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 11513 value)) 11514 return false; 11515 } 11516 11517 const uint32_t addr_byte_size = GetAddressByteSize(); 11518 uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0; 11519 11520 context.type = eContextRegisterStore; 11521 // for r = 0 to regs-1 11522 for (uint32_t r = 0; r < regs; ++r) { 11523 11524 if (single_regs) { 11525 // MemA[address,4] = S[d+r]; address = address+4; 11526 uint32_t data = ReadRegisterUnsigned(eRegisterKindDWARF, 11527 start_reg + d + r, 0, &success); 11528 if (!success) 11529 return false; 11530 11531 std::optional<RegisterInfo> data_reg = 11532 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r); 11533 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11534 address - Rn); 11535 if (!MemAWrite(context, address, data, addr_byte_size)) 11536 return false; 11537 11538 address = address + 4; 11539 } else { 11540 // // Store as two word-aligned words in the correct order for current 11541 // endianness. MemA[address,4] = if BigEndian() then D[d+r]<63:32> else 11542 // D[d+r]<31:0>; 11543 // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else 11544 // D[d+r]<63:32>; 11545 uint64_t data = ReadRegisterUnsigned(eRegisterKindDWARF, 11546 start_reg + d + r, 0, &success); 11547 if (!success) 11548 return false; 11549 11550 std::optional<RegisterInfo> data_reg = 11551 GetRegisterInfo(eRegisterKindDWARF, start_reg + d + r); 11552 11553 if (GetByteOrder() == eByteOrderBig) { 11554 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11555 address - Rn); 11556 if (!MemAWrite(context, address, Bits64(data, 63, 32), 11557 addr_byte_size)) 11558 return false; 11559 11560 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11561 (address + 4) - Rn); 11562 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0), 11563 addr_byte_size)) 11564 return false; 11565 } else { 11566 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11567 address - Rn); 11568 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size)) 11569 return false; 11570 11571 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11572 (address + 4) - Rn); 11573 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32), 11574 addr_byte_size)) 11575 return false; 11576 } 11577 // address = address+8; 11578 address = address + 8; 11579 } 11580 } 11581 } 11582 return true; 11583} 11584 11585// A8.6.320 11586// This instruction loads a single extension register from memory, using an 11587// address from an ARM core register, with an optional offset. 11588bool EmulateInstructionARM::EmulateVLDR(const uint32_t opcode, 11589 ARMEncoding encoding) { 11590#if 0 11591 if ConditionPassed() then 11592 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 11593 base = if n == 15 then Align(PC,4) else R[n]; 11594 address = if add then (base + imm32) else (base - imm32); 11595 if single_reg then 11596 S[d] = MemA[address,4]; 11597 else 11598 word1 = MemA[address,4]; word2 = MemA[address+4,4]; 11599 // Combine the word-aligned words in the correct order for current 11600 // endianness. 11601 D[d] = if BigEndian() then word1:word2 else word2:word1; 11602#endif 11603 11604 bool success = false; 11605 11606 if (ConditionPassed(opcode)) { 11607 bool single_reg; 11608 bool add; 11609 uint32_t imm32; 11610 uint32_t d; 11611 uint32_t n; 11612 11613 switch (encoding) { 11614 case eEncodingT1: 11615 case eEncodingA1: 11616 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 11617 // 32); 11618 single_reg = false; 11619 add = BitIsSet(opcode, 23); 11620 imm32 = Bits32(opcode, 7, 0) << 2; 11621 11622 // d = UInt(D:Vd); n = UInt(Rn); 11623 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 11624 n = Bits32(opcode, 19, 16); 11625 11626 break; 11627 11628 case eEncodingT2: 11629 case eEncodingA2: 11630 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); 11631 single_reg = true; 11632 add = BitIsSet(opcode, 23); 11633 imm32 = Bits32(opcode, 7, 0) << 2; 11634 11635 // d = UInt(Vd:D); n = UInt(Rn); 11636 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); 11637 n = Bits32(opcode, 19, 16); 11638 11639 break; 11640 11641 default: 11642 return false; 11643 } 11644 std::optional<RegisterInfo> base_reg = 11645 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11646 11647 uint32_t Rn = ReadCoreReg(n, &success); 11648 if (!success) 11649 return false; 11650 11651 // base = if n == 15 then Align(PC,4) else R[n]; 11652 uint32_t base; 11653 if (n == 15) 11654 base = AlignPC(Rn); 11655 else 11656 base = Rn; 11657 11658 // address = if add then (base + imm32) else (base - imm32); 11659 addr_t address; 11660 if (add) 11661 address = base + imm32; 11662 else 11663 address = base - imm32; 11664 11665 const uint32_t addr_byte_size = GetAddressByteSize(); 11666 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 11667 11668 EmulateInstruction::Context context; 11669 context.type = eContextRegisterLoad; 11670 context.SetRegisterPlusOffset(*base_reg, address - base); 11671 11672 if (single_reg) { 11673 // S[d] = MemA[address,4]; 11674 uint32_t data = MemARead(context, address, addr_byte_size, 0, &success); 11675 if (!success) 11676 return false; 11677 11678 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d, 11679 data)) 11680 return false; 11681 } else { 11682 // word1 = MemA[address,4]; word2 = MemA[address+4,4]; 11683 uint32_t word1 = MemARead(context, address, addr_byte_size, 0, &success); 11684 if (!success) 11685 return false; 11686 11687 context.SetRegisterPlusOffset(*base_reg, (address + 4) - base); 11688 uint32_t word2 = 11689 MemARead(context, address + 4, addr_byte_size, 0, &success); 11690 if (!success) 11691 return false; 11692 // // Combine the word-aligned words in the correct order for current 11693 // endianness. 11694 // D[d] = if BigEndian() then word1:word2 else word2:word1; 11695 uint64_t data64; 11696 if (GetByteOrder() == eByteOrderBig) { 11697 data64 = word1; 11698 data64 = (data64 << 32) | word2; 11699 } else { 11700 data64 = word2; 11701 data64 = (data64 << 32) | word1; 11702 } 11703 11704 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, start_reg + d, 11705 data64)) 11706 return false; 11707 } 11708 } 11709 return true; 11710} 11711 11712// A8.6.400 VSTR 11713// This instruction stores a signle extension register to memory, using an 11714// address from an ARM core register, with an optional offset. 11715bool EmulateInstructionARM::EmulateVSTR(const uint32_t opcode, 11716 ARMEncoding encoding) { 11717#if 0 11718 if ConditionPassed() then 11719 EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n); 11720 address = if add then (R[n] + imm32) else (R[n] - imm32); 11721 if single_reg then 11722 MemA[address,4] = S[d]; 11723 else 11724 // Store as two word-aligned words in the correct order for current 11725 // endianness. 11726 MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 11727 MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 11728#endif 11729 11730 bool success = false; 11731 11732 if (ConditionPassed(opcode)) { 11733 bool single_reg; 11734 bool add; 11735 uint32_t imm32; 11736 uint32_t d; 11737 uint32_t n; 11738 11739 switch (encoding) { 11740 case eEncodingT1: 11741 case eEncodingA1: 11742 // single_reg = FALSE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 11743 // 32); 11744 single_reg = false; 11745 add = BitIsSet(opcode, 23); 11746 imm32 = Bits32(opcode, 7, 0) << 2; 11747 11748 // d = UInt(D:Vd); n = UInt(Rn); 11749 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 11750 n = Bits32(opcode, 19, 16); 11751 11752 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 11753 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 11754 return false; 11755 11756 break; 11757 11758 case eEncodingT2: 11759 case eEncodingA2: 11760 // single_reg = TRUE; add = (U == '1'); imm32 = ZeroExtend(imm8:'00', 32); 11761 single_reg = true; 11762 add = BitIsSet(opcode, 23); 11763 imm32 = Bits32(opcode, 7, 0) << 2; 11764 11765 // d = UInt(Vd:D); n = UInt(Rn); 11766 d = (Bits32(opcode, 15, 12) << 1) | Bit32(opcode, 22); 11767 n = Bits32(opcode, 19, 16); 11768 11769 // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE; 11770 if ((n == 15) && (CurrentInstrSet() != eModeARM)) 11771 return false; 11772 11773 break; 11774 11775 default: 11776 return false; 11777 } 11778 11779 uint32_t Rn = ReadCoreReg(n, &success); 11780 if (!success) 11781 return false; 11782 11783 // address = if add then (R[n] + imm32) else (R[n] - imm32); 11784 addr_t address; 11785 if (add) 11786 address = Rn + imm32; 11787 else 11788 address = Rn - imm32; 11789 11790 const uint32_t addr_byte_size = GetAddressByteSize(); 11791 uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0; 11792 11793 std::optional<RegisterInfo> base_reg = 11794 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11795 std::optional<RegisterInfo> data_reg = 11796 GetRegisterInfo(eRegisterKindDWARF, start_reg + d); 11797 EmulateInstruction::Context context; 11798 context.type = eContextRegisterStore; 11799 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 11800 11801 if (single_reg) { 11802 // MemA[address,4] = S[d]; 11803 uint32_t data = 11804 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success); 11805 if (!success) 11806 return false; 11807 11808 if (!MemAWrite(context, address, data, addr_byte_size)) 11809 return false; 11810 } else { 11811 // // Store as two word-aligned words in the correct order for current 11812 // endianness. 11813 // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>; 11814 // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>; 11815 uint64_t data = 11816 ReadRegisterUnsigned(eRegisterKindDWARF, start_reg + d, 0, &success); 11817 if (!success) 11818 return false; 11819 11820 if (GetByteOrder() == eByteOrderBig) { 11821 if (!MemAWrite(context, address, Bits64(data, 63, 32), addr_byte_size)) 11822 return false; 11823 11824 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11825 (address + 4) - Rn); 11826 if (!MemAWrite(context, address + 4, Bits64(data, 31, 0), 11827 addr_byte_size)) 11828 return false; 11829 } else { 11830 if (!MemAWrite(context, address, Bits64(data, 31, 0), addr_byte_size)) 11831 return false; 11832 11833 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 11834 (address + 4) - Rn); 11835 if (!MemAWrite(context, address + 4, Bits64(data, 63, 32), 11836 addr_byte_size)) 11837 return false; 11838 } 11839 } 11840 } 11841 return true; 11842} 11843 11844// A8.6.307 VLDI1 (multiple single elements) This instruction loads elements 11845// from memory into one, two, three or four registers, without de-interleaving. 11846// Every element of each register is loaded. 11847bool EmulateInstructionARM::EmulateVLD1Multiple(const uint32_t opcode, 11848 ARMEncoding encoding) { 11849#if 0 11850 if ConditionPassed() then 11851 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 11852 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 11853 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11854 for r = 0 to regs-1 11855 for e = 0 to elements-1 11856 Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11857 address = address + ebytes; 11858#endif 11859 11860 bool success = false; 11861 11862 if (ConditionPassed(opcode)) { 11863 uint32_t regs; 11864 uint32_t alignment; 11865 uint32_t ebytes; 11866 uint32_t esize; 11867 uint32_t elements; 11868 uint32_t d; 11869 uint32_t n; 11870 uint32_t m; 11871 bool wback; 11872 bool register_index; 11873 11874 switch (encoding) { 11875 case eEncodingT1: 11876 case eEncodingA1: { 11877 // case type of 11878 // when '0111' 11879 // regs = 1; if align<1> == '1' then UNDEFINED; 11880 // when '1010' 11881 // regs = 2; if align == '11' then UNDEFINED; 11882 // when '0110' 11883 // regs = 3; if align<1> == '1' then UNDEFINED; 11884 // when '0010' 11885 // regs = 4; 11886 // otherwise 11887 // SEE 'Related encodings'; 11888 uint32_t type = Bits32(opcode, 11, 8); 11889 uint32_t align = Bits32(opcode, 5, 4); 11890 if (type == 7) // '0111' 11891 { 11892 regs = 1; 11893 if (BitIsSet(align, 1)) 11894 return false; 11895 } else if (type == 10) // '1010' 11896 { 11897 regs = 2; 11898 if (align == 3) 11899 return false; 11900 11901 } else if (type == 6) // '0110' 11902 { 11903 regs = 3; 11904 if (BitIsSet(align, 1)) 11905 return false; 11906 } else if (type == 2) // '0010' 11907 { 11908 regs = 4; 11909 } else 11910 return false; 11911 11912 // alignment = if align == '00' then 1 else 4 << UInt(align); 11913 if (align == 0) 11914 alignment = 1; 11915 else 11916 alignment = 4 << align; 11917 11918 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 11919 ebytes = 1 << Bits32(opcode, 7, 6); 11920 esize = 8 * ebytes; 11921 elements = 8 / ebytes; 11922 11923 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 11924 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 11925 n = Bits32(opcode, 19, 15); 11926 m = Bits32(opcode, 3, 0); 11927 11928 // wback = (m != 15); register_index = (m != 15 && m != 13); 11929 wback = (m != 15); 11930 register_index = ((m != 15) && (m != 13)); 11931 11932 // if d+regs > 32 then UNPREDICTABLE; 11933 if ((d + regs) > 32) 11934 return false; 11935 } break; 11936 11937 default: 11938 return false; 11939 } 11940 11941 std::optional<RegisterInfo> base_reg = 11942 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 11943 11944 uint32_t Rn = ReadCoreReg(n, &success); 11945 if (!success) 11946 return false; 11947 11948 // address = R[n]; if (address MOD alignment) != 0 then 11949 // GenerateAlignmentException(); 11950 addr_t address = Rn; 11951 if ((address % alignment) != 0) 11952 return false; 11953 11954 EmulateInstruction::Context context; 11955 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 11956 if (wback) { 11957 uint32_t Rm = ReadCoreReg(m, &success); 11958 if (!success) 11959 return false; 11960 11961 uint32_t offset; 11962 if (register_index) 11963 offset = Rm; 11964 else 11965 offset = 8 * regs; 11966 11967 uint32_t value = Rn + offset; 11968 context.type = eContextAdjustBaseRegister; 11969 context.SetRegisterPlusOffset(*base_reg, offset); 11970 11971 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 11972 value)) 11973 return false; 11974 } 11975 11976 // for r = 0 to regs-1 11977 for (uint32_t r = 0; r < regs; ++r) { 11978 // for e = 0 to elements-1 11979 uint64_t assembled_data = 0; 11980 for (uint32_t e = 0; e < elements; ++e) { 11981 // Elem[D[d+r],e,esize] = MemU[address,ebytes]; 11982 context.type = eContextRegisterLoad; 11983 context.SetRegisterPlusOffset(*base_reg, address - Rn); 11984 uint64_t data = MemURead(context, address, ebytes, 0, &success); 11985 if (!success) 11986 return false; 11987 11988 assembled_data = 11989 (data << (e * esize)) | 11990 assembled_data; // New data goes to the left of existing data 11991 11992 // address = address + ebytes; 11993 address = address + ebytes; 11994 } 11995 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r, 11996 assembled_data)) 11997 return false; 11998 } 11999 } 12000 return true; 12001} 12002 12003// A8.6.308 VLD1 (single element to one lane) 12004// 12005bool EmulateInstructionARM::EmulateVLD1Single(const uint32_t opcode, 12006 const ARMEncoding encoding) { 12007#if 0 12008 if ConditionPassed() then 12009 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 12010 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 12011 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12012 Elem[D[d],index,esize] = MemU[address,ebytes]; 12013#endif 12014 12015 bool success = false; 12016 12017 if (ConditionPassed(opcode)) { 12018 uint32_t ebytes; 12019 uint32_t esize; 12020 uint32_t index; 12021 uint32_t alignment; 12022 uint32_t d; 12023 uint32_t n; 12024 uint32_t m; 12025 bool wback; 12026 bool register_index; 12027 12028 switch (encoding) { 12029 case eEncodingT1: 12030 case eEncodingA1: { 12031 uint32_t size = Bits32(opcode, 11, 10); 12032 uint32_t index_align = Bits32(opcode, 7, 4); 12033 // if size == '11' then SEE VLD1 (single element to all lanes); 12034 if (size == 3) 12035 return EmulateVLD1SingleAll(opcode, encoding); 12036 // case size of 12037 if (size == 0) // when '00' 12038 { 12039 // if index_align<0> != '0' then UNDEFINED; 12040 if (BitIsClear(index_align, 0)) 12041 return false; 12042 12043 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 12044 ebytes = 1; 12045 esize = 8; 12046 index = Bits32(index_align, 3, 1); 12047 alignment = 1; 12048 } else if (size == 1) // when '01' 12049 { 12050 // if index_align<1> != '0' then UNDEFINED; 12051 if (BitIsClear(index_align, 1)) 12052 return false; 12053 12054 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 12055 ebytes = 2; 12056 esize = 16; 12057 index = Bits32(index_align, 3, 2); 12058 12059 // alignment = if index_align<0> == '0' then 1 else 2; 12060 if (BitIsClear(index_align, 0)) 12061 alignment = 1; 12062 else 12063 alignment = 2; 12064 } else if (size == 2) // when '10' 12065 { 12066 // if index_align<2> != '0' then UNDEFINED; 12067 if (BitIsClear(index_align, 2)) 12068 return false; 12069 12070 // if index_align<1:0> != '00' && index_align<1:0> != '11' then 12071 // UNDEFINED; 12072 if ((Bits32(index_align, 1, 0) != 0) && 12073 (Bits32(index_align, 1, 0) != 3)) 12074 return false; 12075 12076 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 12077 ebytes = 4; 12078 esize = 32; 12079 index = Bit32(index_align, 3); 12080 12081 // alignment = if index_align<1:0> == '00' then 1 else 4; 12082 if (Bits32(index_align, 1, 0) == 0) 12083 alignment = 1; 12084 else 12085 alignment = 4; 12086 } else { 12087 return false; 12088 } 12089 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 12090 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 12091 n = Bits32(opcode, 19, 16); 12092 m = Bits32(opcode, 3, 0); 12093 12094 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 12095 // then UNPREDICTABLE; 12096 wback = (m != 15); 12097 register_index = ((m != 15) && (m != 13)); 12098 12099 if (n == 15) 12100 return false; 12101 12102 } break; 12103 12104 default: 12105 return false; 12106 } 12107 12108 uint32_t Rn = ReadCoreReg(n, &success); 12109 if (!success) 12110 return false; 12111 12112 // address = R[n]; if (address MOD alignment) != 0 then 12113 // GenerateAlignmentException(); 12114 addr_t address = Rn; 12115 if ((address % alignment) != 0) 12116 return false; 12117 12118 EmulateInstruction::Context context; 12119 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12120 if (wback) { 12121 uint32_t Rm = ReadCoreReg(m, &success); 12122 if (!success) 12123 return false; 12124 12125 uint32_t offset; 12126 if (register_index) 12127 offset = Rm; 12128 else 12129 offset = ebytes; 12130 12131 uint32_t value = Rn + offset; 12132 12133 context.type = eContextAdjustBaseRegister; 12134 std::optional<RegisterInfo> base_reg = 12135 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 12136 context.SetRegisterPlusOffset(*base_reg, offset); 12137 12138 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 12139 value)) 12140 return false; 12141 } 12142 12143 // Elem[D[d],index,esize] = MemU[address,ebytes]; 12144 uint32_t element = MemURead(context, address, esize, 0, &success); 12145 if (!success) 12146 return false; 12147 12148 element = element << (index * esize); 12149 12150 uint64_t reg_data = 12151 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 12152 if (!success) 12153 return false; 12154 12155 uint64_t all_ones = -1; 12156 uint64_t mask = all_ones 12157 << ((index + 1) * esize); // mask is all 1's to left of 12158 // where 'element' goes, & all 0's 12159 // at element & to the right of element. 12160 if (index > 0) 12161 mask = mask | Bits64(all_ones, (index * esize) - 1, 12162 0); // add 1's to the right of where 'element' goes. 12163 // now mask should be 0's where element goes & 1's everywhere else. 12164 12165 uint64_t masked_reg = 12166 reg_data & mask; // Take original reg value & zero out 'element' bits 12167 reg_data = 12168 masked_reg & element; // Put 'element' into those bits in reg_data. 12169 12170 context.type = eContextRegisterLoad; 12171 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + d, 12172 reg_data)) 12173 return false; 12174 } 12175 return true; 12176} 12177 12178// A8.6.391 VST1 (multiple single elements) Vector Store (multiple single 12179// elements) stores elements to memory from one, two, three, or four registers, 12180// without interleaving. Every element of each register is stored. 12181bool EmulateInstructionARM::EmulateVST1Multiple(const uint32_t opcode, 12182 ARMEncoding encoding) { 12183#if 0 12184 if ConditionPassed() then 12185 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 12186 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 12187 if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 12188 for r = 0 to regs-1 12189 for e = 0 to elements-1 12190 MemU[address,ebytes] = Elem[D[d+r],e,esize]; 12191 address = address + ebytes; 12192#endif 12193 12194 bool success = false; 12195 12196 if (ConditionPassed(opcode)) { 12197 uint32_t regs; 12198 uint32_t alignment; 12199 uint32_t ebytes; 12200 uint32_t esize; 12201 uint32_t elements; 12202 uint32_t d; 12203 uint32_t n; 12204 uint32_t m; 12205 bool wback; 12206 bool register_index; 12207 12208 switch (encoding) { 12209 case eEncodingT1: 12210 case eEncodingA1: { 12211 uint32_t type = Bits32(opcode, 11, 8); 12212 uint32_t align = Bits32(opcode, 5, 4); 12213 12214 // case type of 12215 if (type == 7) // when '0111' 12216 { 12217 // regs = 1; if align<1> == '1' then UNDEFINED; 12218 regs = 1; 12219 if (BitIsSet(align, 1)) 12220 return false; 12221 } else if (type == 10) // when '1010' 12222 { 12223 // regs = 2; if align == '11' then UNDEFINED; 12224 regs = 2; 12225 if (align == 3) 12226 return false; 12227 } else if (type == 6) // when '0110' 12228 { 12229 // regs = 3; if align<1> == '1' then UNDEFINED; 12230 regs = 3; 12231 if (BitIsSet(align, 1)) 12232 return false; 12233 } else if (type == 2) // when '0010' 12234 // regs = 4; 12235 regs = 4; 12236 else // otherwise 12237 // SEE 'Related encodings'; 12238 return false; 12239 12240 // alignment = if align == '00' then 1 else 4 << UInt(align); 12241 if (align == 0) 12242 alignment = 1; 12243 else 12244 alignment = 4 << align; 12245 12246 // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes; 12247 ebytes = 1 << Bits32(opcode, 7, 6); 12248 esize = 8 * ebytes; 12249 elements = 8 / ebytes; 12250 12251 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 12252 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 12253 n = Bits32(opcode, 19, 16); 12254 m = Bits32(opcode, 3, 0); 12255 12256 // wback = (m != 15); register_index = (m != 15 && m != 13); 12257 wback = (m != 15); 12258 register_index = ((m != 15) && (m != 13)); 12259 12260 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 12261 if ((d + regs) > 32) 12262 return false; 12263 12264 if (n == 15) 12265 return false; 12266 12267 } break; 12268 12269 default: 12270 return false; 12271 } 12272 12273 std::optional<RegisterInfo> base_reg = 12274 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 12275 12276 uint32_t Rn = ReadCoreReg(n, &success); 12277 if (!success) 12278 return false; 12279 12280 // address = R[n]; if (address MOD alignment) != 0 then 12281 // GenerateAlignmentException(); 12282 addr_t address = Rn; 12283 if ((address % alignment) != 0) 12284 return false; 12285 12286 EmulateInstruction::Context context; 12287 // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs); 12288 if (wback) { 12289 uint32_t Rm = ReadCoreReg(m, &success); 12290 if (!success) 12291 return false; 12292 12293 uint32_t offset; 12294 if (register_index) 12295 offset = Rm; 12296 else 12297 offset = 8 * regs; 12298 12299 context.type = eContextAdjustBaseRegister; 12300 context.SetRegisterPlusOffset(*base_reg, offset); 12301 12302 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 12303 Rn + offset)) 12304 return false; 12305 } 12306 12307 context.type = eContextRegisterStore; 12308 // for r = 0 to regs-1 12309 for (uint32_t r = 0; r < regs; ++r) { 12310 std::optional<RegisterInfo> data_reg = 12311 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d + r); 12312 uint64_t register_data = ReadRegisterUnsigned( 12313 eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success); 12314 if (!success) 12315 return false; 12316 12317 // for e = 0 to elements-1 12318 for (uint32_t e = 0; e < elements; ++e) { 12319 // MemU[address,ebytes] = Elem[D[d+r],e,esize]; 12320 uint64_t word = Bits64(register_data, ((e + 1) * esize) - 1, e * esize); 12321 12322 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, 12323 address - Rn); 12324 if (!MemUWrite(context, address, word, ebytes)) 12325 return false; 12326 12327 // address = address + ebytes; 12328 address = address + ebytes; 12329 } 12330 } 12331 } 12332 return true; 12333} 12334 12335// A8.6.392 VST1 (single element from one lane) This instruction stores one 12336// element to memory from one element of a register. 12337bool EmulateInstructionARM::EmulateVST1Single(const uint32_t opcode, 12338 ARMEncoding encoding) { 12339#if 0 12340 if ConditionPassed() then 12341 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 12342 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 12343 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12344 MemU[address,ebytes] = Elem[D[d],index,esize]; 12345#endif 12346 12347 bool success = false; 12348 12349 if (ConditionPassed(opcode)) { 12350 uint32_t ebytes; 12351 uint32_t esize; 12352 uint32_t index; 12353 uint32_t alignment; 12354 uint32_t d; 12355 uint32_t n; 12356 uint32_t m; 12357 bool wback; 12358 bool register_index; 12359 12360 switch (encoding) { 12361 case eEncodingT1: 12362 case eEncodingA1: { 12363 uint32_t size = Bits32(opcode, 11, 10); 12364 uint32_t index_align = Bits32(opcode, 7, 4); 12365 12366 // if size == '11' then UNDEFINED; 12367 if (size == 3) 12368 return false; 12369 12370 // case size of 12371 if (size == 0) // when '00' 12372 { 12373 // if index_align<0> != '0' then UNDEFINED; 12374 if (BitIsClear(index_align, 0)) 12375 return false; 12376 // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1; 12377 ebytes = 1; 12378 esize = 8; 12379 index = Bits32(index_align, 3, 1); 12380 alignment = 1; 12381 } else if (size == 1) // when '01' 12382 { 12383 // if index_align<1> != '0' then UNDEFINED; 12384 if (BitIsClear(index_align, 1)) 12385 return false; 12386 12387 // ebytes = 2; esize = 16; index = UInt(index_align<3:2>); 12388 ebytes = 2; 12389 esize = 16; 12390 index = Bits32(index_align, 3, 2); 12391 12392 // alignment = if index_align<0> == '0' then 1 else 2; 12393 if (BitIsClear(index_align, 0)) 12394 alignment = 1; 12395 else 12396 alignment = 2; 12397 } else if (size == 2) // when '10' 12398 { 12399 // if index_align<2> != '0' then UNDEFINED; 12400 if (BitIsClear(index_align, 2)) 12401 return false; 12402 12403 // if index_align<1:0> != '00' && index_align<1:0> != '11' then 12404 // UNDEFINED; 12405 if ((Bits32(index_align, 1, 0) != 0) && 12406 (Bits32(index_align, 1, 0) != 3)) 12407 return false; 12408 12409 // ebytes = 4; esize = 32; index = UInt(index_align<3>); 12410 ebytes = 4; 12411 esize = 32; 12412 index = Bit32(index_align, 3); 12413 12414 // alignment = if index_align<1:0> == '00' then 1 else 4; 12415 if (Bits32(index_align, 1, 0) == 0) 12416 alignment = 1; 12417 else 12418 alignment = 4; 12419 } else { 12420 return false; 12421 } 12422 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 12423 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 12424 n = Bits32(opcode, 19, 16); 12425 m = Bits32(opcode, 3, 0); 12426 12427 // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 12428 // then UNPREDICTABLE; 12429 wback = (m != 15); 12430 register_index = ((m != 15) && (m != 13)); 12431 12432 if (n == 15) 12433 return false; 12434 } break; 12435 12436 default: 12437 return false; 12438 } 12439 12440 std::optional<RegisterInfo> base_reg = 12441 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 12442 12443 uint32_t Rn = ReadCoreReg(n, &success); 12444 if (!success) 12445 return false; 12446 12447 // address = R[n]; if (address MOD alignment) != 0 then 12448 // GenerateAlignmentException(); 12449 addr_t address = Rn; 12450 if ((address % alignment) != 0) 12451 return false; 12452 12453 EmulateInstruction::Context context; 12454 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12455 if (wback) { 12456 uint32_t Rm = ReadCoreReg(m, &success); 12457 if (!success) 12458 return false; 12459 12460 uint32_t offset; 12461 if (register_index) 12462 offset = Rm; 12463 else 12464 offset = ebytes; 12465 12466 context.type = eContextAdjustBaseRegister; 12467 context.SetRegisterPlusOffset(*base_reg, offset); 12468 12469 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 12470 Rn + offset)) 12471 return false; 12472 } 12473 12474 // MemU[address,ebytes] = Elem[D[d],index,esize]; 12475 uint64_t register_data = 12476 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_d0 + d, 0, &success); 12477 if (!success) 12478 return false; 12479 12480 uint64_t word = 12481 Bits64(register_data, ((index + 1) * esize) - 1, index * esize); 12482 12483 std::optional<RegisterInfo> data_reg = 12484 GetRegisterInfo(eRegisterKindDWARF, dwarf_d0 + d); 12485 context.type = eContextRegisterStore; 12486 context.SetRegisterToRegisterPlusOffset(*data_reg, *base_reg, address - Rn); 12487 12488 if (!MemUWrite(context, address, word, ebytes)) 12489 return false; 12490 } 12491 return true; 12492} 12493 12494// A8.6.309 VLD1 (single element to all lanes) This instruction loads one 12495// element from memory into every element of one or two vectors. 12496bool EmulateInstructionARM::EmulateVLD1SingleAll(const uint32_t opcode, 12497 const ARMEncoding encoding) { 12498#if 0 12499 if ConditionPassed() then 12500 EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n); 12501 address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException(); 12502 if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12503 replicated_element = Replicate(MemU[address,ebytes], elements); 12504 for r = 0 to regs-1 12505 D[d+r] = replicated_element; 12506#endif 12507 12508 bool success = false; 12509 12510 if (ConditionPassed(opcode)) { 12511 uint32_t ebytes; 12512 uint32_t elements; 12513 uint32_t regs; 12514 uint32_t alignment; 12515 uint32_t d; 12516 uint32_t n; 12517 uint32_t m; 12518 bool wback; 12519 bool register_index; 12520 12521 switch (encoding) { 12522 case eEncodingT1: 12523 case eEncodingA1: { 12524 // if size == '11' || (size == '00' && a == '1') then UNDEFINED; 12525 uint32_t size = Bits32(opcode, 7, 6); 12526 if ((size == 3) || ((size == 0) && BitIsSet(opcode, 4))) 12527 return false; 12528 12529 // ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == '0' 12530 // then 1 else 2; 12531 ebytes = 1 << size; 12532 elements = 8 / ebytes; 12533 if (BitIsClear(opcode, 5)) 12534 regs = 1; 12535 else 12536 regs = 2; 12537 12538 // alignment = if a == '0' then 1 else ebytes; 12539 if (BitIsClear(opcode, 4)) 12540 alignment = 1; 12541 else 12542 alignment = ebytes; 12543 12544 // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm); 12545 d = (Bit32(opcode, 22) << 4) | Bits32(opcode, 15, 12); 12546 n = Bits32(opcode, 19, 16); 12547 m = Bits32(opcode, 3, 0); 12548 12549 // wback = (m != 15); register_index = (m != 15 && m != 13); 12550 wback = (m != 15); 12551 register_index = ((m != 15) && (m != 13)); 12552 12553 // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE; 12554 if ((d + regs) > 32) 12555 return false; 12556 12557 if (n == 15) 12558 return false; 12559 } break; 12560 12561 default: 12562 return false; 12563 } 12564 12565 uint32_t Rn = ReadCoreReg(n, &success); 12566 if (!success) 12567 return false; 12568 12569 // address = R[n]; if (address MOD alignment) != 0 then 12570 // GenerateAlignmentException(); 12571 addr_t address = Rn; 12572 if ((address % alignment) != 0) 12573 return false; 12574 12575 EmulateInstruction::Context context; 12576 // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes); 12577 if (wback) { 12578 uint32_t Rm = ReadCoreReg(m, &success); 12579 if (!success) 12580 return false; 12581 12582 uint32_t offset; 12583 if (register_index) 12584 offset = Rm; 12585 else 12586 offset = ebytes; 12587 12588 context.type = eContextAdjustBaseRegister; 12589 std::optional<RegisterInfo> base_reg = 12590 GetRegisterInfo(eRegisterKindDWARF, dwarf_r0 + n); 12591 context.SetRegisterPlusOffset(*base_reg, offset); 12592 12593 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + n, 12594 Rn + offset)) 12595 return false; 12596 } 12597 12598 // replicated_element = Replicate(MemU[address,ebytes], elements); 12599 12600 context.type = eContextRegisterLoad; 12601 uint64_t word = MemURead(context, address, ebytes, 0, &success); 12602 if (!success) 12603 return false; 12604 12605 uint64_t replicated_element = 0; 12606 uint32_t esize = ebytes * 8; 12607 for (uint32_t e = 0; e < elements; ++e) 12608 replicated_element = 12609 (replicated_element << esize) | Bits64(word, esize - 1, 0); 12610 12611 // for r = 0 to regs-1 12612 for (uint32_t r = 0; r < regs; ++r) { 12613 // D[d+r] = replicated_element; 12614 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_d0 + d + r, 12615 replicated_element)) 12616 return false; 12617 } 12618 } 12619 return true; 12620} 12621 12622// B6.2.13 SUBS PC, LR and related instructions The SUBS PC, LR, #<const? 12623// instruction provides an exception return without the use of the stack. It 12624// subtracts the immediate constant from the LR, branches to the resulting 12625// address, and also copies the SPSR to the CPSR. 12626bool EmulateInstructionARM::EmulateSUBSPcLrEtc(const uint32_t opcode, 12627 const ARMEncoding encoding) { 12628#if 0 12629 if ConditionPassed() then 12630 EncodingSpecificOperations(); 12631 if CurrentInstrSet() == InstrSet_ThumbEE then 12632 UNPREDICTABLE; 12633 operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32; 12634 case opcode of 12635 when '0000' result = R[n] AND operand2; // AND 12636 when '0001' result = R[n] EOR operand2; // EOR 12637 when '0010' (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB 12638 when '0011' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB 12639 when '0100' (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD 12640 when '0101' (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC 12641 when '0110' (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC 12642 when '0111' (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC 12643 when '1100' result = R[n] OR operand2; // ORR 12644 when '1101' result = operand2; // MOV 12645 when '1110' result = R[n] AND NOT(operand2); // BIC 12646 when '1111' result = NOT(operand2); // MVN 12647 CPSRWriteByInstr(SPSR[], '1111', TRUE); 12648 BranchWritePC(result); 12649#endif 12650 12651 bool success = false; 12652 12653 if (ConditionPassed(opcode)) { 12654 uint32_t n; 12655 uint32_t m; 12656 uint32_t imm32; 12657 bool register_form; 12658 ARM_ShifterType shift_t; 12659 uint32_t shift_n; 12660 uint32_t code; 12661 12662 switch (encoding) { 12663 case eEncodingT1: 12664 // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE n = 14; 12665 // imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = '0010'; 12666 // // = SUB 12667 n = 14; 12668 imm32 = Bits32(opcode, 7, 0); 12669 register_form = false; 12670 code = 2; 12671 12672 // if InITBlock() && !LastInITBlock() then UNPREDICTABLE; 12673 if (InITBlock() && !LastInITBlock()) 12674 return false; 12675 12676 break; 12677 12678 case eEncodingA1: 12679 // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE; 12680 n = Bits32(opcode, 19, 16); 12681 imm32 = ARMExpandImm(opcode); 12682 register_form = false; 12683 code = Bits32(opcode, 24, 21); 12684 12685 break; 12686 12687 case eEncodingA2: 12688 // n = UInt(Rn); m = UInt(Rm); register_form = TRUE; 12689 n = Bits32(opcode, 19, 16); 12690 m = Bits32(opcode, 3, 0); 12691 register_form = true; 12692 12693 // (shift_t, shift_n) = DecodeImmShift(type, imm5); 12694 shift_n = DecodeImmShiftARM(opcode, shift_t); 12695 12696 break; 12697 12698 default: 12699 return false; 12700 } 12701 12702 // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) 12703 // else imm32; 12704 uint32_t operand2; 12705 if (register_form) { 12706 uint32_t Rm = ReadCoreReg(m, &success); 12707 if (!success) 12708 return false; 12709 12710 operand2 = Shift(Rm, shift_t, shift_n, APSR_C, &success); 12711 if (!success) 12712 return false; 12713 } else { 12714 operand2 = imm32; 12715 } 12716 12717 uint32_t Rn = ReadCoreReg(n, &success); 12718 if (!success) 12719 return false; 12720 12721 AddWithCarryResult result; 12722 12723 // case opcode of 12724 switch (code) { 12725 case 0: // when '0000' 12726 // result = R[n] AND operand2; // AND 12727 result.result = Rn & operand2; 12728 break; 12729 12730 case 1: // when '0001' 12731 // result = R[n] EOR operand2; // EOR 12732 result.result = Rn ^ operand2; 12733 break; 12734 12735 case 2: // when '0010' 12736 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), '1'); // SUB 12737 result = AddWithCarry(Rn, ~(operand2), 1); 12738 break; 12739 12740 case 3: // when '0011' 12741 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, '1'); // RSB 12742 result = AddWithCarry(~(Rn), operand2, 1); 12743 break; 12744 12745 case 4: // when '0100' 12746 // (result, -, -) = AddWithCarry(R[n], operand2, '0'); // ADD 12747 result = AddWithCarry(Rn, operand2, 0); 12748 break; 12749 12750 case 5: // when '0101' 12751 // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC 12752 result = AddWithCarry(Rn, operand2, APSR_C); 12753 break; 12754 12755 case 6: // when '0110' 12756 // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC 12757 result = AddWithCarry(Rn, ~(operand2), APSR_C); 12758 break; 12759 12760 case 7: // when '0111' 12761 // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC 12762 result = AddWithCarry(~(Rn), operand2, APSR_C); 12763 break; 12764 12765 case 10: // when '1100' 12766 // result = R[n] OR operand2; // ORR 12767 result.result = Rn | operand2; 12768 break; 12769 12770 case 11: // when '1101' 12771 // result = operand2; // MOV 12772 result.result = operand2; 12773 break; 12774 12775 case 12: // when '1110' 12776 // result = R[n] AND NOT(operand2); // BIC 12777 result.result = Rn & ~(operand2); 12778 break; 12779 12780 case 15: // when '1111' 12781 // result = NOT(operand2); // MVN 12782 result.result = ~(operand2); 12783 break; 12784 12785 default: 12786 return false; 12787 } 12788 // CPSRWriteByInstr(SPSR[], '1111', TRUE); 12789 12790 // For now, in emulation mode, we don't have access to the SPSR, so we will 12791 // use the CPSR instead, and hope for the best. 12792 uint32_t spsr = 12793 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success); 12794 if (!success) 12795 return false; 12796 12797 CPSRWriteByInstr(spsr, 15, true); 12798 12799 // BranchWritePC(result); 12800 EmulateInstruction::Context context; 12801 context.type = eContextAdjustPC; 12802 context.SetImmediate(result.result); 12803 12804 BranchWritePC(context, result.result); 12805 } 12806 return true; 12807} 12808 12809EmulateInstructionARM::ARMOpcode * 12810EmulateInstructionARM::GetARMOpcodeForInstruction(const uint32_t opcode, 12811 uint32_t arm_isa) { 12812 static ARMOpcode g_arm_opcodes[] = { 12813 // Prologue instructions 12814 12815 // push register(s) 12816 {0x0fff0000, 0x092d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12817 &EmulateInstructionARM::EmulatePUSH, "push <registers>"}, 12818 {0x0fff0fff, 0x052d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, 12819 &EmulateInstructionARM::EmulatePUSH, "push <register>"}, 12820 12821 // set r7 to point to a stack offset 12822 {0x0ffff000, 0x028d7000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12823 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>"}, 12824 {0x0ffff000, 0x024c7000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12825 &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"}, 12826 // copy the stack pointer to ip 12827 {0x0fffffff, 0x01a0c00d, ARMvAll, eEncodingA1, No_VFP, eSize32, 12828 &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp"}, 12829 {0x0ffff000, 0x028dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12830 &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>"}, 12831 {0x0ffff000, 0x024dc000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12832 &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"}, 12833 12834 // adjust the stack pointer 12835 {0x0ffff000, 0x024dd000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12836 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"}, 12837 {0x0fef0010, 0x004d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12838 &EmulateInstructionARM::EmulateSUBSPReg, 12839 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"}, 12840 12841 // push one register 12842 // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH; 12843 {0x0e5f0000, 0x040d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12844 &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!"}, 12845 12846 // vector push consecutive extension register(s) 12847 {0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, 12848 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 12849 {0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, 12850 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 12851 12852 // Epilogue instructions 12853 12854 {0x0fff0000, 0x08bd0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12855 &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 12856 {0x0fff0fff, 0x049d0004, ARMvAll, eEncodingA2, No_VFP, eSize32, 12857 &EmulateInstructionARM::EmulatePOP, "pop <register>"}, 12858 {0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, 12859 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 12860 {0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, 12861 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 12862 12863 // Supervisor Call (previously Software Interrupt) 12864 {0x0f000000, 0x0f000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12865 &EmulateInstructionARM::EmulateSVC, "svc #imm24"}, 12866 12867 // Branch instructions 12868 // To resolve ambiguity, "blx <label>" should come before "b #imm24" and 12869 // "bl <label>". 12870 {0xfe000000, 0xfa000000, ARMV5_ABOVE, eEncodingA2, No_VFP, eSize32, 12871 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 12872 {0x0f000000, 0x0a000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12873 &EmulateInstructionARM::EmulateB, "b #imm24"}, 12874 {0x0f000000, 0x0b000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12875 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 12876 {0x0ffffff0, 0x012fff30, ARMV5_ABOVE, eEncodingA1, No_VFP, eSize32, 12877 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 12878 // for example, "bx lr" 12879 {0x0ffffff0, 0x012fff10, ARMvAll, eEncodingA1, No_VFP, eSize32, 12880 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 12881 // bxj 12882 {0x0ffffff0, 0x012fff20, ARMvAll, eEncodingA1, No_VFP, eSize32, 12883 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 12884 12885 // Data-processing instructions 12886 // adc (immediate) 12887 {0x0fe00000, 0x02a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12888 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"}, 12889 // adc (register) 12890 {0x0fe00010, 0x00a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12891 &EmulateInstructionARM::EmulateADCReg, 12892 "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12893 // add (immediate) 12894 {0x0fe00000, 0x02800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12895 &EmulateInstructionARM::EmulateADDImmARM, 12896 "add{s}<c> <Rd>, <Rn>, #const"}, 12897 // add (register) 12898 {0x0fe00010, 0x00800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12899 &EmulateInstructionARM::EmulateADDReg, 12900 "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12901 // add (register-shifted register) 12902 {0x0fe00090, 0x00800010, ARMvAll, eEncodingA1, No_VFP, eSize32, 12903 &EmulateInstructionARM::EmulateADDRegShift, 12904 "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"}, 12905 // adr 12906 {0x0fff0000, 0x028f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12907 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 12908 {0x0fff0000, 0x024f0000, ARMvAll, eEncodingA2, No_VFP, eSize32, 12909 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 12910 // and (immediate) 12911 {0x0fe00000, 0x02000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12912 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"}, 12913 // and (register) 12914 {0x0fe00010, 0x00000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12915 &EmulateInstructionARM::EmulateANDReg, 12916 "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12917 // bic (immediate) 12918 {0x0fe00000, 0x03c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12919 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"}, 12920 // bic (register) 12921 {0x0fe00010, 0x01c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12922 &EmulateInstructionARM::EmulateBICReg, 12923 "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12924 // eor (immediate) 12925 {0x0fe00000, 0x02200000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12926 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"}, 12927 // eor (register) 12928 {0x0fe00010, 0x00200000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12929 &EmulateInstructionARM::EmulateEORReg, 12930 "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12931 // orr (immediate) 12932 {0x0fe00000, 0x03800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12933 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"}, 12934 // orr (register) 12935 {0x0fe00010, 0x01800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12936 &EmulateInstructionARM::EmulateORRReg, 12937 "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12938 // rsb (immediate) 12939 {0x0fe00000, 0x02600000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12940 &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"}, 12941 // rsb (register) 12942 {0x0fe00010, 0x00600000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12943 &EmulateInstructionARM::EmulateRSBReg, 12944 "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12945 // rsc (immediate) 12946 {0x0fe00000, 0x02e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12947 &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"}, 12948 // rsc (register) 12949 {0x0fe00010, 0x00e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12950 &EmulateInstructionARM::EmulateRSCReg, 12951 "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12952 // sbc (immediate) 12953 {0x0fe00000, 0x02c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12954 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 12955 // sbc (register) 12956 {0x0fe00010, 0x00c00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12957 &EmulateInstructionARM::EmulateSBCReg, 12958 "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"}, 12959 // sub (immediate, ARM) 12960 {0x0fe00000, 0x02400000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12961 &EmulateInstructionARM::EmulateSUBImmARM, 12962 "sub{s}<c> <Rd>, <Rn>, #<const>"}, 12963 // sub (sp minus immediate) 12964 {0x0fef0000, 0x024d0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12965 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"}, 12966 // sub (register) 12967 {0x0fe00010, 0x00400000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12968 &EmulateInstructionARM::EmulateSUBReg, 12969 "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"}, 12970 // teq (immediate) 12971 {0x0ff0f000, 0x03300000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12972 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"}, 12973 // teq (register) 12974 {0x0ff0f010, 0x01300000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12975 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 12976 // tst (immediate) 12977 {0x0ff0f000, 0x03100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12978 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"}, 12979 // tst (register) 12980 {0x0ff0f010, 0x01100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12981 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"}, 12982 12983 // mov (immediate) 12984 {0x0fef0000, 0x03a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12985 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"}, 12986 {0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, 12987 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>"}, 12988 // mov (register) 12989 {0x0fef0ff0, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12990 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"}, 12991 // mvn (immediate) 12992 {0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12993 &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"}, 12994 // mvn (register) 12995 {0x0fef0010, 0x01e00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 12996 &EmulateInstructionARM::EmulateMVNReg, 12997 "mvn{s}<c> <Rd>, <Rm> {,<shift>}"}, 12998 // cmn (immediate) 12999 {0x0ff0f000, 0x03700000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13000 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 13001 // cmn (register) 13002 {0x0ff0f010, 0x01700000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13003 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 13004 // cmp (immediate) 13005 {0x0ff0f000, 0x03500000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13006 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"}, 13007 // cmp (register) 13008 {0x0ff0f010, 0x01500000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13009 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"}, 13010 // asr (immediate) 13011 {0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, No_VFP, eSize32, 13012 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"}, 13013 // asr (register) 13014 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, 13015 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"}, 13016 // lsl (immediate) 13017 {0x0fef0070, 0x01a00000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13018 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"}, 13019 // lsl (register) 13020 {0x0fef00f0, 0x01a00010, ARMvAll, eEncodingA1, No_VFP, eSize32, 13021 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"}, 13022 // lsr (immediate) 13023 {0x0fef0070, 0x01a00020, ARMvAll, eEncodingA1, No_VFP, eSize32, 13024 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"}, 13025 // lsr (register) 13026 {0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, No_VFP, eSize32, 13027 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"}, 13028 // rrx is a special case encoding of ror (immediate) 13029 {0x0fef0ff0, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, 13030 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"}, 13031 // ror (immediate) 13032 {0x0fef0070, 0x01a00060, ARMvAll, eEncodingA1, No_VFP, eSize32, 13033 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"}, 13034 // ror (register) 13035 {0x0fef00f0, 0x01a00070, ARMvAll, eEncodingA1, No_VFP, eSize32, 13036 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"}, 13037 // mul 13038 {0x0fe000f0, 0x00000090, ARMvAll, eEncodingA1, No_VFP, eSize32, 13039 &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>"}, 13040 13041 // subs pc, lr and related instructions 13042 {0x0e10f000, 0x0210f000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13043 &EmulateInstructionARM::EmulateSUBSPcLrEtc, 13044 "<opc>S<c> PC,#<const> | <Rn>,#<const>"}, 13045 {0x0e10f010, 0x0010f000, ARMvAll, eEncodingA2, No_VFP, eSize32, 13046 &EmulateInstructionARM::EmulateSUBSPcLrEtc, 13047 "<opc>S<c> PC,<Rn>,<Rm{,<shift>}"}, 13048 13049 // Load instructions 13050 {0x0fd00000, 0x08900000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13051 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"}, 13052 {0x0fd00000, 0x08100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13053 &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>"}, 13054 {0x0fd00000, 0x09100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13055 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"}, 13056 {0x0fd00000, 0x09900000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13057 &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>"}, 13058 {0x0e500000, 0x04100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13059 &EmulateInstructionARM::EmulateLDRImmediateARM, 13060 "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]"}, 13061 {0x0e500010, 0x06100000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13062 &EmulateInstructionARM::EmulateLDRRegister, 13063 "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}"}, 13064 {0x0e5f0000, 0x045f0000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13065 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"}, 13066 {0xfe500010, 0x06500000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13067 &EmulateInstructionARM::EmulateLDRBRegister, 13068 "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}"}, 13069 {0x0e5f00f0, 0x005f00b0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13070 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"}, 13071 {0x0e5000f0, 0x001000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13072 &EmulateInstructionARM::EmulateLDRHRegister, 13073 "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"}, 13074 {0x0e5000f0, 0x005000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13075 &EmulateInstructionARM::EmulateLDRSBImmediate, 13076 "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]"}, 13077 {0x0e5f00f0, 0x005f00d0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13078 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>"}, 13079 {0x0e5000f0, 0x001000d0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13080 &EmulateInstructionARM::EmulateLDRSBRegister, 13081 "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}"}, 13082 {0x0e5000f0, 0x005000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13083 &EmulateInstructionARM::EmulateLDRSHImmediate, 13084 "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"}, 13085 {0x0e5f00f0, 0x005f00f0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13086 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"}, 13087 {0x0e5000f0, 0x001000f0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13088 &EmulateInstructionARM::EmulateLDRSHRegister, 13089 "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"}, 13090 {0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, 13091 &EmulateInstructionARM::EmulateLDRDImmediate, 13092 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"}, 13093 {0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, 13094 &EmulateInstructionARM::EmulateLDRDRegister, 13095 "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 13096 {0x0e100f00, 0x0c100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, 13097 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 13098 {0x0e100f00, 0x0c100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, 13099 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 13100 {0x0f300f00, 0x0d100b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, 13101 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 13102 {0x0f300f00, 0x0d100a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, 13103 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 13104 {0xffb00000, 0xf4200000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, 13105 &EmulateInstructionARM::EmulateVLD1Multiple, 13106 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13107 {0xffb00300, 0xf4a00000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, 13108 &EmulateInstructionARM::EmulateVLD1Single, 13109 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13110 {0xffb00f00, 0xf4a00c00, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, 13111 &EmulateInstructionARM::EmulateVLD1SingleAll, 13112 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13113 13114 // Store instructions 13115 {0x0fd00000, 0x08800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13116 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"}, 13117 {0x0fd00000, 0x08000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13118 &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>"}, 13119 {0x0fd00000, 0x09000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13120 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"}, 13121 {0x0fd00000, 0x09800000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13122 &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>"}, 13123 {0x0e500010, 0x06000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13124 &EmulateInstructionARM::EmulateSTRRegister, 13125 "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}"}, 13126 {0x0e5000f0, 0x000000b0, ARMvAll, eEncodingA1, No_VFP, eSize32, 13127 &EmulateInstructionARM::EmulateSTRHRegister, 13128 "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}"}, 13129 {0x0ff00ff0, 0x01800f90, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13130 &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"}, 13131 {0x0e500000, 0x04400000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13132 &EmulateInstructionARM::EmulateSTRBImmARM, 13133 "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 13134 {0x0e500000, 0x04000000, ARMvAll, eEncodingA1, No_VFP, eSize32, 13135 &EmulateInstructionARM::EmulateSTRImmARM, 13136 "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"}, 13137 {0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, 13138 &EmulateInstructionARM::EmulateSTRDImm, 13139 "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"}, 13140 {0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, 13141 &EmulateInstructionARM::EmulateSTRDReg, 13142 "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"}, 13143 {0x0e100f00, 0x0c000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, 13144 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 13145 {0x0e100f00, 0x0c000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, 13146 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"}, 13147 {0x0f300f00, 0x0d000b00, ARMvAll, eEncodingA1, VFPv2_ABOVE, eSize32, 13148 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"}, 13149 {0x0f300f00, 0x0d000a00, ARMvAll, eEncodingA2, VFPv2v3, eSize32, 13150 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"}, 13151 {0xffb00000, 0xf4000000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, 13152 &EmulateInstructionARM::EmulateVST1Multiple, 13153 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13154 {0xffb00300, 0xf4800000, ARMvAll, eEncodingA1, AdvancedSIMD, eSize32, 13155 &EmulateInstructionARM::EmulateVST1Single, 13156 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13157 13158 // Other instructions 13159 {0x0fff00f0, 0x06af00f0, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13160 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}"}, 13161 {0x0fff00f0, 0x06bf0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13162 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}"}, 13163 {0x0fff00f0, 0x06ef0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13164 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}"}, 13165 {0x0fff00f0, 0x06ff0070, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13166 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}"}, 13167 {0xfe500000, 0xf8100000, ARMV6_ABOVE, eEncodingA1, No_VFP, eSize32, 13168 &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}"} 13169 13170 }; 13171 static const size_t k_num_arm_opcodes = std::size(g_arm_opcodes); 13172 13173 for (size_t i = 0; i < k_num_arm_opcodes; ++i) { 13174 if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value && 13175 (g_arm_opcodes[i].variants & arm_isa) != 0) 13176 return &g_arm_opcodes[i]; 13177 } 13178 return nullptr; 13179} 13180 13181EmulateInstructionARM::ARMOpcode * 13182EmulateInstructionARM::GetThumbOpcodeForInstruction(const uint32_t opcode, 13183 uint32_t arm_isa) { 13184 13185 static ARMOpcode g_thumb_opcodes[] = { 13186 // Prologue instructions 13187 13188 // push register(s) 13189 {0xfffffe00, 0x0000b400, ARMvAll, eEncodingT1, No_VFP, eSize16, 13190 &EmulateInstructionARM::EmulatePUSH, "push <registers>"}, 13191 {0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13192 &EmulateInstructionARM::EmulatePUSH, "push.w <registers>"}, 13193 {0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13194 &EmulateInstructionARM::EmulatePUSH, "push.w <register>"}, 13195 13196 // set r7 to point to a stack offset 13197 {0xffffff00, 0x0000af00, ARMvAll, eEncodingT1, No_VFP, eSize16, 13198 &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm"}, 13199 // copy the stack pointer to r7 13200 {0xffffffff, 0x0000466f, ARMvAll, eEncodingT1, No_VFP, eSize16, 13201 &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp"}, 13202 // move from high register to low register (comes after "mov r7, sp" to 13203 // resolve ambiguity) 13204 {0xffffffc0, 0x00004640, ARMvAll, eEncodingT1, No_VFP, eSize16, 13205 &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15"}, 13206 13207 // PC-relative load into register (see also EmulateADDSPRm) 13208 {0xfffff800, 0x00004800, ARMvAll, eEncodingT1, No_VFP, eSize16, 13209 &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"}, 13210 13211 // adjust the stack pointer 13212 {0xffffff87, 0x00004485, ARMvAll, eEncodingT2, No_VFP, eSize16, 13213 &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"}, 13214 {0xffffff80, 0x0000b080, ARMvAll, eEncodingT1, No_VFP, eSize16, 13215 &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"}, 13216 {0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13217 &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"}, 13218 {0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13219 &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"}, 13220 {0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13221 &EmulateInstructionARM::EmulateSUBSPReg, 13222 "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}"}, 13223 13224 // vector push consecutive extension register(s) 13225 {0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13226 &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"}, 13227 {0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13228 &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"}, 13229 13230 // Epilogue instructions 13231 13232 {0xfffff800, 0x0000a800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13233 &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"}, 13234 {0xffffff80, 0x0000b000, ARMvAll, eEncodingT2, No_VFP, eSize16, 13235 &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"}, 13236 {0xfffffe00, 0x0000bc00, ARMvAll, eEncodingT1, No_VFP, eSize16, 13237 &EmulateInstructionARM::EmulatePOP, "pop <registers>"}, 13238 {0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13239 &EmulateInstructionARM::EmulatePOP, "pop.w <registers>"}, 13240 {0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13241 &EmulateInstructionARM::EmulatePOP, "pop.w <register>"}, 13242 {0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13243 &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"}, 13244 {0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13245 &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"}, 13246 13247 // Supervisor Call (previously Software Interrupt) 13248 {0xffffff00, 0x0000df00, ARMvAll, eEncodingT1, No_VFP, eSize16, 13249 &EmulateInstructionARM::EmulateSVC, "svc #imm8"}, 13250 13251 // If Then makes up to four following instructions conditional. 13252 // The next 5 opcode _must_ come before the if then instruction 13253 {0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, 13254 &EmulateInstructionARM::EmulateNop, "nop"}, 13255 {0xffffffff, 0x0000bf10, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, 13256 &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"}, 13257 {0xffffffff, 0x0000bf20, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, 13258 &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"}, 13259 {0xffffffff, 0x0000bf30, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, 13260 &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"}, 13261 {0xffffffff, 0x0000bf40, ARMV7_ABOVE, eEncodingT1, No_VFP, eSize16, 13262 &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"}, 13263 {0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, 13264 &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"}, 13265 13266 // Branch instructions 13267 // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8". 13268 {0xfffff000, 0x0000d000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13269 &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"}, 13270 {0xfffff800, 0x0000e000, ARMvAll, eEncodingT2, No_VFP, eSize16, 13271 &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"}, 13272 {0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13273 &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"}, 13274 {0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, 13275 &EmulateInstructionARM::EmulateB, 13276 "b<c>.w #imm8 (outside or last in IT)"}, 13277 // J1 == J2 == 1 13278 {0xf800d000, 0xf000d000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize32, 13279 &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"}, 13280 // J1 == J2 == 1 13281 {0xf800d001, 0xf000c000, ARMV5_ABOVE, eEncodingT2, No_VFP, eSize32, 13282 &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"}, 13283 {0xffffff87, 0x00004780, ARMV5_ABOVE, eEncodingT1, No_VFP, eSize16, 13284 &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"}, 13285 // for example, "bx lr" 13286 {0xffffff87, 0x00004700, ARMvAll, eEncodingT1, No_VFP, eSize32, 13287 &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"}, 13288 // bxj 13289 {0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE, eEncodingT1, No_VFP, eSize32, 13290 &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"}, 13291 // compare and branch 13292 {0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, 13293 &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"}, 13294 // table branch byte 13295 {0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13296 &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"}, 13297 // table branch halfword 13298 {0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13299 &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"}, 13300 13301 // Data-processing instructions 13302 // adc (immediate) 13303 {0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13304 &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"}, 13305 // adc (register) 13306 {0xffffffc0, 0x00004140, ARMvAll, eEncodingT1, No_VFP, eSize16, 13307 &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"}, 13308 {0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13309 &EmulateInstructionARM::EmulateADCReg, 13310 "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13311 // add (register) 13312 {0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, No_VFP, eSize16, 13313 &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"}, 13314 // Make sure "add sp, <Rm>" comes before this instruction, so there's no 13315 // ambiguity decoding the two. 13316 {0xffffff00, 0x00004400, ARMvAll, eEncodingT2, No_VFP, eSize16, 13317 &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"}, 13318 // adr 13319 {0xfffff800, 0x0000a000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13320 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 13321 {0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13322 &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"}, 13323 {0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13324 &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"}, 13325 // and (immediate) 13326 {0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13327 &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"}, 13328 // and (register) 13329 {0xffffffc0, 0x00004000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13330 &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"}, 13331 {0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13332 &EmulateInstructionARM::EmulateANDReg, 13333 "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13334 // bic (immediate) 13335 {0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13336 &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"}, 13337 // bic (register) 13338 {0xffffffc0, 0x00004380, ARMvAll, eEncodingT1, No_VFP, eSize16, 13339 &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"}, 13340 {0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13341 &EmulateInstructionARM::EmulateBICReg, 13342 "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13343 // eor (immediate) 13344 {0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13345 &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"}, 13346 // eor (register) 13347 {0xffffffc0, 0x00004040, ARMvAll, eEncodingT1, No_VFP, eSize16, 13348 &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"}, 13349 {0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13350 &EmulateInstructionARM::EmulateEORReg, 13351 "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13352 // orr (immediate) 13353 {0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13354 &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"}, 13355 // orr (register) 13356 {0xffffffc0, 0x00004300, ARMvAll, eEncodingT1, No_VFP, eSize16, 13357 &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"}, 13358 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13359 &EmulateInstructionARM::EmulateORRReg, 13360 "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13361 // rsb (immediate) 13362 {0xffffffc0, 0x00004240, ARMvAll, eEncodingT1, No_VFP, eSize16, 13363 &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"}, 13364 {0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13365 &EmulateInstructionARM::EmulateRSBImm, 13366 "rsb{s}<c>.w <Rd>, <Rn>, #<const>"}, 13367 // rsb (register) 13368 {0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13369 &EmulateInstructionARM::EmulateRSBReg, 13370 "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13371 // sbc (immediate) 13372 {0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13373 &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"}, 13374 // sbc (register) 13375 {0xffffffc0, 0x00004180, ARMvAll, eEncodingT1, No_VFP, eSize16, 13376 &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"}, 13377 {0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13378 &EmulateInstructionARM::EmulateSBCReg, 13379 "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"}, 13380 // add (immediate, Thumb) 13381 {0xfffffe00, 0x00001c00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13382 &EmulateInstructionARM::EmulateADDImmThumb, 13383 "adds|add<c> <Rd>,<Rn>,#<imm3>"}, 13384 {0xfffff800, 0x00003000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, 13385 &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>"}, 13386 {0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13387 &EmulateInstructionARM::EmulateADDImmThumb, 13388 "add{s}<c>.w <Rd>,<Rn>,#<const>"}, 13389 {0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, 13390 &EmulateInstructionARM::EmulateADDImmThumb, 13391 "addw<c> <Rd>,<Rn>,#<imm12>"}, 13392 // sub (immediate, Thumb) 13393 {0xfffffe00, 0x00001e00, ARMvAll, eEncodingT1, No_VFP, eSize16, 13394 &EmulateInstructionARM::EmulateSUBImmThumb, 13395 "subs|sub<c> <Rd>, <Rn> #imm3"}, 13396 {0xfffff800, 0x00003800, ARMvAll, eEncodingT2, No_VFP, eSize16, 13397 &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"}, 13398 {0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13399 &EmulateInstructionARM::EmulateSUBImmThumb, 13400 "sub{s}<c>.w <Rd>, <Rn>, #<const>"}, 13401 {0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, 13402 &EmulateInstructionARM::EmulateSUBImmThumb, 13403 "subw<c> <Rd>, <Rn>, #imm12"}, 13404 // sub (sp minus immediate) 13405 {0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13406 &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"}, 13407 {0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13408 &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"}, 13409 // sub (register) 13410 {0xfffffe00, 0x00001a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13411 &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"}, 13412 {0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13413 &EmulateInstructionARM::EmulateSUBReg, 13414 "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"}, 13415 // teq (immediate) 13416 {0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13417 &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"}, 13418 // teq (register) 13419 {0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13420 &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"}, 13421 // tst (immediate) 13422 {0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13423 &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"}, 13424 // tst (register) 13425 {0xffffffc0, 0x00004200, ARMvAll, eEncodingT1, No_VFP, eSize16, 13426 &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"}, 13427 {0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13428 &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"}, 13429 13430 // move from high register to high register 13431 {0xffffff00, 0x00004600, ARMvAll, eEncodingT1, No_VFP, eSize16, 13432 &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"}, 13433 // move from low register to low register 13434 {0xffffffc0, 0x00000000, ARMvAll, eEncodingT2, No_VFP, eSize16, 13435 &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"}, 13436 // mov{s}<c>.w <Rd>, <Rm> 13437 {0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13438 &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"}, 13439 // move immediate 13440 {0xfffff800, 0x00002000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13441 &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"}, 13442 {0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13443 &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"}, 13444 {0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13445 &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"}, 13446 // mvn (immediate) 13447 {0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13448 &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"}, 13449 // mvn (register) 13450 {0xffffffc0, 0x000043c0, ARMvAll, eEncodingT1, No_VFP, eSize16, 13451 &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"}, 13452 {0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13453 &EmulateInstructionARM::EmulateMVNReg, 13454 "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"}, 13455 // cmn (immediate) 13456 {0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13457 &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"}, 13458 // cmn (register) 13459 {0xffffffc0, 0x000042c0, ARMvAll, eEncodingT1, No_VFP, eSize16, 13460 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"}, 13461 {0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13462 &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"}, 13463 // cmp (immediate) 13464 {0xfffff800, 0x00002800, ARMvAll, eEncodingT1, No_VFP, eSize16, 13465 &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"}, 13466 {0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13467 &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"}, 13468 // cmp (register) (Rn and Rm both from r0-r7) 13469 {0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, 13470 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 13471 // cmp (register) (Rn and Rm not both from r0-r7) 13472 {0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, 13473 &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"}, 13474 {0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16, 13475 &EmulateInstructionARM::EmulateCMPReg, 13476 "cmp<c>.w <Rn>, <Rm> {, <shift>}"}, 13477 // asr (immediate) 13478 {0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13479 &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"}, 13480 {0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13481 &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"}, 13482 // asr (register) 13483 {0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, No_VFP, eSize16, 13484 &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"}, 13485 {0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13486 &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 13487 // lsl (immediate) 13488 {0xfffff800, 0x00000000, ARMvAll, eEncodingT1, No_VFP, eSize16, 13489 &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"}, 13490 {0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13491 &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"}, 13492 // lsl (register) 13493 {0xffffffc0, 0x00004080, ARMvAll, eEncodingT1, No_VFP, eSize16, 13494 &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"}, 13495 {0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13496 &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"}, 13497 // lsr (immediate) 13498 {0xfffff800, 0x00000800, ARMvAll, eEncodingT1, No_VFP, eSize16, 13499 &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"}, 13500 {0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13501 &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"}, 13502 // lsr (register) 13503 {0xffffffc0, 0x000040c0, ARMvAll, eEncodingT1, No_VFP, eSize16, 13504 &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"}, 13505 {0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13506 &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"}, 13507 // rrx is a special case encoding of ror (immediate) 13508 {0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13509 &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"}, 13510 // ror (immediate) 13511 {0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13512 &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"}, 13513 // ror (register) 13514 {0xffffffc0, 0x000041c0, ARMvAll, eEncodingT1, No_VFP, eSize16, 13515 &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"}, 13516 {0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13517 &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"}, 13518 // mul 13519 {0xffffffc0, 0x00004340, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13520 &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>"}, 13521 // mul 13522 {0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13523 &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>"}, 13524 13525 // subs pc, lr and related instructions 13526 {0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13527 &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>"}, 13528 13529 // RFE instructions *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE 13530 // LDM.. Instructions in this table; 13531 // otherwise the wrong instructions will be selected. 13532 13533 {0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13534 &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}"}, 13535 {0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13536 &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}"}, 13537 13538 // Load instructions 13539 {0xfffff800, 0x0000c800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13540 &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>"}, 13541 {0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13542 &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>"}, 13543 {0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13544 &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>"}, 13545 {0xfffff800, 0x00006800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13546 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"}, 13547 {0xfffff800, 0x00009800, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, 13548 &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"}, 13549 {0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13550 &EmulateInstructionARM::EmulateLDRRtRnImm, 13551 "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"}, 13552 {0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, 13553 &EmulateInstructionARM::EmulateLDRRtRnImm, 13554 "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"}, 13555 // Thumb2 PC-relative load into register 13556 {0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13557 &EmulateInstructionARM::EmulateLDRRtPCRelative, 13558 "ldr<c>.w <Rt>, [PC, +/-#imm}]"}, 13559 {0xfffffe00, 0x00005800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13560 &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]"}, 13561 {0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13562 &EmulateInstructionARM::EmulateLDRRegister, 13563 "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]"}, 13564 {0xfffff800, 0x00007800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13565 &EmulateInstructionARM::EmulateLDRBImmediate, 13566 "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]"}, 13567 {0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13568 &EmulateInstructionARM::EmulateLDRBImmediate, 13569 "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]"}, 13570 {0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13571 &EmulateInstructionARM::EmulateLDRBImmediate, 13572 "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}"}, 13573 {0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13574 &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]"}, 13575 {0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, 13576 &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]"}, 13577 {0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13578 &EmulateInstructionARM::EmulateLDRBRegister, 13579 "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"}, 13580 {0xfffff800, 0x00008800, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13581 &EmulateInstructionARM::EmulateLDRHImmediate, 13582 "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"}, 13583 {0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13584 &EmulateInstructionARM::EmulateLDRHImmediate, 13585 "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]"}, 13586 {0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13587 &EmulateInstructionARM::EmulateLDRHImmediate, 13588 "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"}, 13589 {0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13590 &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>"}, 13591 {0xfffffe00, 0x00005a00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13592 &EmulateInstructionARM::EmulateLDRHRegister, 13593 "ldrh<c> <Rt>, [<Rn>,<Rm>]"}, 13594 {0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13595 &EmulateInstructionARM::EmulateLDRHRegister, 13596 "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"}, 13597 {0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13598 &EmulateInstructionARM::EmulateLDRSBImmediate, 13599 "ldrsb<c> <Rt>,[<Rn>,#<imm12>]"}, 13600 {0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13601 &EmulateInstructionARM::EmulateLDRSBImmediate, 13602 "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]"}, 13603 {0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13604 &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>"}, 13605 {0xfffffe00, 0x00005600, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13606 &EmulateInstructionARM::EmulateLDRSBRegister, 13607 "ldrsb<c> <Rt>,[<Rn>,<Rm>]"}, 13608 {0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13609 &EmulateInstructionARM::EmulateLDRSBRegister, 13610 "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"}, 13611 {0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13612 &EmulateInstructionARM::EmulateLDRSHImmediate, 13613 "ldrsh<c> <Rt>,[<Rn>,#<imm12>]"}, 13614 {0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13615 &EmulateInstructionARM::EmulateLDRSHImmediate, 13616 "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]"}, 13617 {0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13618 &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>"}, 13619 {0xfffffe00, 0x00005e00, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13620 &EmulateInstructionARM::EmulateLDRSHRegister, 13621 "ldrsh<c> <Rt>,[<Rn>,<Rm>]"}, 13622 {0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13623 &EmulateInstructionARM::EmulateLDRSHRegister, 13624 "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"}, 13625 {0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13626 &EmulateInstructionARM::EmulateLDRDImmediate, 13627 "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"}, 13628 {0xfe100f00, 0xec100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, 13629 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 13630 {0xfe100f00, 0xec100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, 13631 &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"}, 13632 {0xffe00f00, 0xed100b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, 13633 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 13634 {0xff300f00, 0xed100a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, 13635 &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"}, 13636 {0xffb00000, 0xf9200000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, 13637 &EmulateInstructionARM::EmulateVLD1Multiple, 13638 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 13639 {0xffb00300, 0xf9a00000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, 13640 &EmulateInstructionARM::EmulateVLD1Single, 13641 "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"}, 13642 {0xffb00f00, 0xf9a00c00, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, 13643 &EmulateInstructionARM::EmulateVLD1SingleAll, 13644 "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13645 13646 // Store instructions 13647 {0xfffff800, 0x0000c000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13648 &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>"}, 13649 {0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13650 &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>"}, 13651 {0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13652 &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>"}, 13653 {0xfffff800, 0x00006000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13654 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]"}, 13655 {0xfffff800, 0x00009000, ARMV4T_ABOVE, eEncodingT2, No_VFP, eSize16, 13656 &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]"}, 13657 {0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13658 &EmulateInstructionARM::EmulateSTRThumb, 13659 "str<c>.w <Rt>, [<Rn>,#<imm12>]"}, 13660 {0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, 13661 &EmulateInstructionARM::EmulateSTRThumb, 13662 "str<c> <Rt>, [<Rn>,#+/-<imm8>]"}, 13663 {0xfffffe00, 0x00005000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13664 &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]"}, 13665 {0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13666 &EmulateInstructionARM::EmulateSTRRegister, 13667 "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]"}, 13668 {0xfffff800, 0x00007000, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13669 &EmulateInstructionARM::EmulateSTRBThumb, 13670 "strb<c> <Rt>, [<Rn>, #<imm5>]"}, 13671 {0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13672 &EmulateInstructionARM::EmulateSTRBThumb, 13673 "strb<c>.w <Rt>, [<Rn>, #<imm12>]"}, 13674 {0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, 13675 &EmulateInstructionARM::EmulateSTRBThumb, 13676 "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}"}, 13677 {0xfffffe00, 0x00005200, ARMV4T_ABOVE, eEncodingT1, No_VFP, eSize16, 13678 &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]"}, 13679 {0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13680 &EmulateInstructionARM::EmulateSTRHRegister, 13681 "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]"}, 13682 {0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13683 &EmulateInstructionARM::EmulateSTREX, 13684 "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]"}, 13685 {0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, 13686 &EmulateInstructionARM::EmulateSTRDImm, 13687 "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"}, 13688 {0xfe100f00, 0xec000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, 13689 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 13690 {0xfea00f00, 0xec000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, 13691 &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"}, 13692 {0xff300f00, 0xed000b00, ARMvAll, eEncodingT1, VFPv2_ABOVE, eSize32, 13693 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"}, 13694 {0xff300f00, 0xed000a00, ARMvAll, eEncodingT2, VFPv2v3, eSize32, 13695 &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"}, 13696 {0xffb00000, 0xf9000000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, 13697 &EmulateInstructionARM::EmulateVST1Multiple, 13698 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13699 {0xffb00300, 0xf9800000, ARMvAll, eEncodingT1, AdvancedSIMD, eSize32, 13700 &EmulateInstructionARM::EmulateVST1Single, 13701 "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 13702 13703 // Other instructions 13704 {0xffffffc0, 0x0000b240, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, 13705 &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>"}, 13706 {0xfffff080, 0xfa4ff080, ARMV6_ABOVE, eEncodingT2, No_VFP, eSize32, 13707 &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}"}, 13708 {0xffffffc0, 0x0000b200, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, 13709 &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>"}, 13710 {0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13711 &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}"}, 13712 {0xffffffc0, 0x0000b2c0, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, 13713 &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>"}, 13714 {0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13715 &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}"}, 13716 {0xffffffc0, 0x0000b280, ARMV6_ABOVE, eEncodingT1, No_VFP, eSize16, 13717 &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>"}, 13718 {0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, 13719 &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}"}, 13720 }; 13721 13722 const size_t k_num_thumb_opcodes = std::size(g_thumb_opcodes); 13723 for (size_t i = 0; i < k_num_thumb_opcodes; ++i) { 13724 if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value && 13725 (g_thumb_opcodes[i].variants & arm_isa) != 0) 13726 return &g_thumb_opcodes[i]; 13727 } 13728 return nullptr; 13729} 13730 13731bool EmulateInstructionARM::SetArchitecture(const ArchSpec &arch) { 13732 m_arch = arch; 13733 m_arm_isa = 0; 13734 llvm::StringRef arch_cstr = arch.GetArchitectureName(); 13735 if (arch_cstr.equals_insensitive("armv4t")) 13736 m_arm_isa = ARMv4T; 13737 else if (arch_cstr.equals_insensitive("armv5tej")) 13738 m_arm_isa = ARMv5TEJ; 13739 else if (arch_cstr.equals_insensitive("armv5te")) 13740 m_arm_isa = ARMv5TE; 13741 else if (arch_cstr.equals_insensitive("armv5t")) 13742 m_arm_isa = ARMv5T; 13743 else if (arch_cstr.equals_insensitive("armv6k")) 13744 m_arm_isa = ARMv6K; 13745 else if (arch_cstr.equals_insensitive("armv6t2")) 13746 m_arm_isa = ARMv6T2; 13747 else if (arch_cstr.equals_insensitive("armv7s")) 13748 m_arm_isa = ARMv7S; 13749 else if (arch_cstr.equals_insensitive("arm")) 13750 m_arm_isa = ARMvAll; 13751 else if (arch_cstr.equals_insensitive("thumb")) 13752 m_arm_isa = ARMvAll; 13753 else if (arch_cstr.starts_with_insensitive("armv4")) 13754 m_arm_isa = ARMv4; 13755 else if (arch_cstr.starts_with_insensitive("armv6")) 13756 m_arm_isa = ARMv6; 13757 else if (arch_cstr.starts_with_insensitive("armv7")) 13758 m_arm_isa = ARMv7; 13759 else if (arch_cstr.starts_with_insensitive("armv8")) 13760 m_arm_isa = ARMv8; 13761 return m_arm_isa != 0; 13762} 13763 13764bool EmulateInstructionARM::SetInstruction(const Opcode &insn_opcode, 13765 const Address &inst_addr, 13766 Target *target) { 13767 if (EmulateInstruction::SetInstruction(insn_opcode, inst_addr, target)) { 13768 if (m_arch.GetTriple().getArch() == llvm::Triple::thumb || 13769 m_arch.IsAlwaysThumbInstructions()) 13770 m_opcode_mode = eModeThumb; 13771 else { 13772 AddressClass addr_class = inst_addr.GetAddressClass(); 13773 13774 if ((addr_class == AddressClass::eCode) || 13775 (addr_class == AddressClass::eUnknown)) 13776 m_opcode_mode = eModeARM; 13777 else if (addr_class == AddressClass::eCodeAlternateISA) 13778 m_opcode_mode = eModeThumb; 13779 else 13780 return false; 13781 } 13782 if (m_opcode_mode == eModeThumb || m_arch.IsAlwaysThumbInstructions()) 13783 m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T; 13784 else 13785 m_opcode_cpsr = CPSR_MODE_USR; 13786 return true; 13787 } 13788 return false; 13789} 13790 13791bool EmulateInstructionARM::ReadInstruction() { 13792 bool success = false; 13793 m_opcode_cpsr = ReadRegisterUnsigned(eRegisterKindGeneric, 13794 LLDB_REGNUM_GENERIC_FLAGS, 0, &success); 13795 if (success) { 13796 addr_t pc = 13797 ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 13798 LLDB_INVALID_ADDRESS, &success); 13799 if (success) { 13800 Context read_inst_context; 13801 read_inst_context.type = eContextReadOpcode; 13802 read_inst_context.SetNoArgs(); 13803 13804 if ((m_opcode_cpsr & MASK_CPSR_T) || m_arch.IsAlwaysThumbInstructions()) { 13805 m_opcode_mode = eModeThumb; 13806 uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success); 13807 13808 if (success) { 13809 if ((thumb_opcode & 0xe000) != 0xe000 || 13810 ((thumb_opcode & 0x1800u) == 0)) { 13811 m_opcode.SetOpcode16(thumb_opcode, GetByteOrder()); 13812 } else { 13813 m_opcode.SetOpcode32( 13814 (thumb_opcode << 16) | 13815 MemARead(read_inst_context, pc + 2, 2, 0, &success), 13816 GetByteOrder()); 13817 } 13818 } 13819 } else { 13820 m_opcode_mode = eModeARM; 13821 m_opcode.SetOpcode32(MemARead(read_inst_context, pc, 4, 0, &success), 13822 GetByteOrder()); 13823 } 13824 13825 if (!m_ignore_conditions) { 13826 // If we are not ignoreing the conditions then init the it session from 13827 // the current value of cpsr. 13828 uint32_t it = (Bits32(m_opcode_cpsr, 15, 10) << 2) | 13829 Bits32(m_opcode_cpsr, 26, 25); 13830 if (it != 0) 13831 m_it_session.InitIT(it); 13832 } 13833 } 13834 } 13835 if (!success) { 13836 m_opcode_mode = eModeInvalid; 13837 m_addr = LLDB_INVALID_ADDRESS; 13838 } 13839 return success; 13840} 13841 13842uint32_t EmulateInstructionARM::ArchVersion() { return m_arm_isa; } 13843 13844bool EmulateInstructionARM::ConditionPassed(const uint32_t opcode) { 13845 // If we are ignoring conditions, then always return true. this allows us to 13846 // iterate over disassembly code and still emulate an instruction even if we 13847 // don't have all the right bits set in the CPSR register... 13848 if (m_ignore_conditions) 13849 return true; 13850 13851 const uint32_t cond = CurrentCond(opcode); 13852 if (cond == UINT32_MAX) 13853 return false; 13854 13855 bool result = false; 13856 switch (UnsignedBits(cond, 3, 1)) { 13857 case 0: 13858 if (m_opcode_cpsr == 0) 13859 result = true; 13860 else 13861 result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; 13862 break; 13863 case 1: 13864 if (m_opcode_cpsr == 0) 13865 result = true; 13866 else 13867 result = (m_opcode_cpsr & MASK_CPSR_C) != 0; 13868 break; 13869 case 2: 13870 if (m_opcode_cpsr == 0) 13871 result = true; 13872 else 13873 result = (m_opcode_cpsr & MASK_CPSR_N) != 0; 13874 break; 13875 case 3: 13876 if (m_opcode_cpsr == 0) 13877 result = true; 13878 else 13879 result = (m_opcode_cpsr & MASK_CPSR_V) != 0; 13880 break; 13881 case 4: 13882 if (m_opcode_cpsr == 0) 13883 result = true; 13884 else 13885 result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && 13886 ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 13887 break; 13888 case 5: 13889 if (m_opcode_cpsr == 0) 13890 result = true; 13891 else { 13892 bool n = (m_opcode_cpsr & MASK_CPSR_N); 13893 bool v = (m_opcode_cpsr & MASK_CPSR_V); 13894 result = n == v; 13895 } 13896 break; 13897 case 6: 13898 if (m_opcode_cpsr == 0) 13899 result = true; 13900 else { 13901 bool n = (m_opcode_cpsr & MASK_CPSR_N); 13902 bool v = (m_opcode_cpsr & MASK_CPSR_V); 13903 result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 13904 } 13905 break; 13906 case 7: 13907 // Always execute (cond == 0b1110, or the special 0b1111 which gives 13908 // opcodes different meanings, but always means execution happens. 13909 return true; 13910 } 13911 13912 if (cond & 1) 13913 result = !result; 13914 return result; 13915} 13916 13917uint32_t EmulateInstructionARM::CurrentCond(const uint32_t opcode) { 13918 switch (m_opcode_mode) { 13919 case eModeInvalid: 13920 break; 13921 13922 case eModeARM: 13923 return UnsignedBits(opcode, 31, 28); 13924 13925 case eModeThumb: 13926 // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit 13927 // 'cond' field of the encoding. 13928 { 13929 const uint32_t byte_size = m_opcode.GetByteSize(); 13930 if (byte_size == 2) { 13931 if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 8) != 0x0f) 13932 return Bits32(opcode, 11, 8); 13933 } else if (byte_size == 4) { 13934 if (Bits32(opcode, 31, 27) == 0x1e && Bits32(opcode, 15, 14) == 0x02 && 13935 Bits32(opcode, 12, 12) == 0x00 && Bits32(opcode, 25, 22) <= 0x0d) { 13936 return Bits32(opcode, 25, 22); 13937 } 13938 } else 13939 // We have an invalid thumb instruction, let's bail out. 13940 break; 13941 13942 return m_it_session.GetCond(); 13943 } 13944 } 13945 return UINT32_MAX; // Return invalid value 13946} 13947 13948bool EmulateInstructionARM::InITBlock() { 13949 return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock(); 13950} 13951 13952bool EmulateInstructionARM::LastInITBlock() { 13953 return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock(); 13954} 13955 13956bool EmulateInstructionARM::BadMode(uint32_t mode) { 13957 13958 switch (mode) { 13959 case 16: 13960 return false; // '10000' 13961 case 17: 13962 return false; // '10001' 13963 case 18: 13964 return false; // '10010' 13965 case 19: 13966 return false; // '10011' 13967 case 22: 13968 return false; // '10110' 13969 case 23: 13970 return false; // '10111' 13971 case 27: 13972 return false; // '11011' 13973 case 31: 13974 return false; // '11111' 13975 default: 13976 return true; 13977 } 13978 return true; 13979} 13980 13981bool EmulateInstructionARM::CurrentModeIsPrivileged() { 13982 uint32_t mode = Bits32(m_opcode_cpsr, 4, 0); 13983 13984 if (BadMode(mode)) 13985 return false; 13986 13987 if (mode == 16) 13988 return false; 13989 13990 return true; 13991} 13992 13993void EmulateInstructionARM::CPSRWriteByInstr(uint32_t value, uint32_t bytemask, 13994 bool affect_execstate) { 13995 bool privileged = CurrentModeIsPrivileged(); 13996 13997 uint32_t tmp_cpsr = Bits32(m_opcode_cpsr, 23, 20) << 20; 13998 13999 if (BitIsSet(bytemask, 3)) { 14000 tmp_cpsr = tmp_cpsr | (Bits32(value, 31, 27) << 27); 14001 if (affect_execstate) 14002 tmp_cpsr = tmp_cpsr | (Bits32(value, 26, 24) << 24); 14003 } 14004 14005 if (BitIsSet(bytemask, 2)) { 14006 tmp_cpsr = tmp_cpsr | (Bits32(value, 19, 16) << 16); 14007 } 14008 14009 if (BitIsSet(bytemask, 1)) { 14010 if (affect_execstate) 14011 tmp_cpsr = tmp_cpsr | (Bits32(value, 15, 10) << 10); 14012 tmp_cpsr = tmp_cpsr | (Bit32(value, 9) << 9); 14013 if (privileged) 14014 tmp_cpsr = tmp_cpsr | (Bit32(value, 8) << 8); 14015 } 14016 14017 if (BitIsSet(bytemask, 0)) { 14018 if (privileged) 14019 tmp_cpsr = tmp_cpsr | (Bits32(value, 7, 6) << 6); 14020 if (affect_execstate) 14021 tmp_cpsr = tmp_cpsr | (Bit32(value, 5) << 5); 14022 if (privileged) 14023 tmp_cpsr = tmp_cpsr | Bits32(value, 4, 0); 14024 } 14025 14026 m_opcode_cpsr = tmp_cpsr; 14027} 14028 14029bool EmulateInstructionARM::BranchWritePC(const Context &context, 14030 uint32_t addr) { 14031 addr_t target; 14032 14033 // Check the current instruction set. 14034 if (CurrentInstrSet() == eModeARM) 14035 target = addr & 0xfffffffc; 14036 else 14037 target = addr & 0xfffffffe; 14038 14039 return WriteRegisterUnsigned(context, eRegisterKindGeneric, 14040 LLDB_REGNUM_GENERIC_PC, target); 14041} 14042 14043// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by 14044// inspecting addr. 14045bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) { 14046 addr_t target; 14047 // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE, 14048 // we want to record it and issue a WriteRegister callback so the clients can 14049 // track the mode changes accordingly. 14050 bool cpsr_changed = false; 14051 14052 if (BitIsSet(addr, 0)) { 14053 if (CurrentInstrSet() != eModeThumb) { 14054 SelectInstrSet(eModeThumb); 14055 cpsr_changed = true; 14056 } 14057 target = addr & 0xfffffffe; 14058 context.SetISA(eModeThumb); 14059 } else if (BitIsClear(addr, 1)) { 14060 if (CurrentInstrSet() != eModeARM) { 14061 SelectInstrSet(eModeARM); 14062 cpsr_changed = true; 14063 } 14064 target = addr & 0xfffffffc; 14065 context.SetISA(eModeARM); 14066 } else 14067 return false; // address<1:0> == '10' => UNPREDICTABLE 14068 14069 if (cpsr_changed) { 14070 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 14071 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 14072 return false; 14073 } 14074 return WriteRegisterUnsigned(context, eRegisterKindGeneric, 14075 LLDB_REGNUM_GENERIC_PC, target); 14076} 14077 14078// Dispatches to either BXWritePC or BranchWritePC based on architecture 14079// versions. 14080bool EmulateInstructionARM::LoadWritePC(Context &context, uint32_t addr) { 14081 if (ArchVersion() >= ARMv5T) 14082 return BXWritePC(context, addr); 14083 else 14084 return BranchWritePC((const Context)context, addr); 14085} 14086 14087// Dispatches to either BXWritePC or BranchWritePC based on architecture 14088// versions and current instruction set. 14089bool EmulateInstructionARM::ALUWritePC(Context &context, uint32_t addr) { 14090 if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM) 14091 return BXWritePC(context, addr); 14092 else 14093 return BranchWritePC((const Context)context, addr); 14094} 14095 14096EmulateInstructionARM::Mode EmulateInstructionARM::CurrentInstrSet() { 14097 return m_opcode_mode; 14098} 14099 14100// Set the 'T' bit of our CPSR. The m_opcode_mode gets updated when the next 14101// ReadInstruction() is performed. This function has a side effect of updating 14102// the m_new_inst_cpsr member variable if necessary. 14103bool EmulateInstructionARM::SelectInstrSet(Mode arm_or_thumb) { 14104 m_new_inst_cpsr = m_opcode_cpsr; 14105 switch (arm_or_thumb) { 14106 default: 14107 return false; 14108 case eModeARM: 14109 // Clear the T bit. 14110 m_new_inst_cpsr &= ~MASK_CPSR_T; 14111 break; 14112 case eModeThumb: 14113 // Set the T bit. 14114 m_new_inst_cpsr |= MASK_CPSR_T; 14115 break; 14116 } 14117 return true; 14118} 14119 14120// This function returns TRUE if the processor currently provides support for 14121// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7, 14122// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6. 14123bool EmulateInstructionARM::UnalignedSupport() { 14124 return (ArchVersion() >= ARMv7); 14125} 14126 14127// The main addition and subtraction instructions can produce status 14128// information about both unsigned carry and signed overflow conditions. This 14129// status information can be used to synthesize multi-word additions and 14130// subtractions. 14131EmulateInstructionARM::AddWithCarryResult 14132EmulateInstructionARM::AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in) { 14133 uint32_t result; 14134 uint8_t carry_out; 14135 uint8_t overflow; 14136 14137 uint64_t unsigned_sum = x + y + carry_in; 14138 int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in; 14139 14140 result = UnsignedBits(unsigned_sum, 31, 0); 14141 // carry_out = (result == unsigned_sum ? 0 : 1); 14142 overflow = ((int32_t)result == signed_sum ? 0 : 1); 14143 14144 if (carry_in) 14145 carry_out = ((int32_t)x >= (int32_t)(~y)) ? 1 : 0; 14146 else 14147 carry_out = ((int32_t)x > (int32_t)y) ? 1 : 0; 14148 14149 AddWithCarryResult res = {result, carry_out, overflow}; 14150 return res; 14151} 14152 14153uint32_t EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success) { 14154 lldb::RegisterKind reg_kind; 14155 uint32_t reg_num; 14156 switch (num) { 14157 case SP_REG: 14158 reg_kind = eRegisterKindGeneric; 14159 reg_num = LLDB_REGNUM_GENERIC_SP; 14160 break; 14161 case LR_REG: 14162 reg_kind = eRegisterKindGeneric; 14163 reg_num = LLDB_REGNUM_GENERIC_RA; 14164 break; 14165 case PC_REG: 14166 reg_kind = eRegisterKindGeneric; 14167 reg_num = LLDB_REGNUM_GENERIC_PC; 14168 break; 14169 default: 14170 if (num < SP_REG) { 14171 reg_kind = eRegisterKindDWARF; 14172 reg_num = dwarf_r0 + num; 14173 } else { 14174 // assert(0 && "Invalid register number"); 14175 *success = false; 14176 return UINT32_MAX; 14177 } 14178 break; 14179 } 14180 14181 // Read our register. 14182 uint32_t val = ReadRegisterUnsigned(reg_kind, reg_num, 0, success); 14183 14184 // When executing an ARM instruction , PC reads as the address of the current 14185 // instruction plus 8. When executing a Thumb instruction , PC reads as the 14186 // address of the current instruction plus 4. 14187 if (num == 15) { 14188 if (CurrentInstrSet() == eModeARM) 14189 val += 8; 14190 else 14191 val += 4; 14192 } 14193 14194 return val; 14195} 14196 14197// Write the result to the ARM core register Rd, and optionally update the 14198// condition flags based on the result. 14199// 14200// This helper method tries to encapsulate the following pseudocode from the 14201// ARM Architecture Reference Manual: 14202// 14203// if d == 15 then // Can only occur for encoding A1 14204// ALUWritePC(result); // setflags is always FALSE here 14205// else 14206// R[d] = result; 14207// if setflags then 14208// APSR.N = result<31>; 14209// APSR.Z = IsZeroBit(result); 14210// APSR.C = carry; 14211// // APSR.V unchanged 14212// 14213// In the above case, the API client does not pass in the overflow arg, which 14214// defaults to ~0u. 14215bool EmulateInstructionARM::WriteCoreRegOptionalFlags( 14216 Context &context, const uint32_t result, const uint32_t Rd, bool setflags, 14217 const uint32_t carry, const uint32_t overflow) { 14218 if (Rd == 15) { 14219 if (!ALUWritePC(context, result)) 14220 return false; 14221 } else { 14222 lldb::RegisterKind reg_kind; 14223 uint32_t reg_num; 14224 switch (Rd) { 14225 case SP_REG: 14226 reg_kind = eRegisterKindGeneric; 14227 reg_num = LLDB_REGNUM_GENERIC_SP; 14228 break; 14229 case LR_REG: 14230 reg_kind = eRegisterKindGeneric; 14231 reg_num = LLDB_REGNUM_GENERIC_RA; 14232 break; 14233 default: 14234 reg_kind = eRegisterKindDWARF; 14235 reg_num = dwarf_r0 + Rd; 14236 } 14237 if (!WriteRegisterUnsigned(context, reg_kind, reg_num, result)) 14238 return false; 14239 if (setflags) 14240 return WriteFlags(context, result, carry, overflow); 14241 } 14242 return true; 14243} 14244 14245// This helper method tries to encapsulate the following pseudocode from the 14246// ARM Architecture Reference Manual: 14247// 14248// APSR.N = result<31>; 14249// APSR.Z = IsZeroBit(result); 14250// APSR.C = carry; 14251// APSR.V = overflow 14252// 14253// Default arguments can be specified for carry and overflow parameters, which 14254// means not to update the respective flags. 14255bool EmulateInstructionARM::WriteFlags(Context &context, const uint32_t result, 14256 const uint32_t carry, 14257 const uint32_t overflow) { 14258 m_new_inst_cpsr = m_opcode_cpsr; 14259 SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS)); 14260 SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0); 14261 if (carry != ~0u) 14262 SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry); 14263 if (overflow != ~0u) 14264 SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow); 14265 if (m_new_inst_cpsr != m_opcode_cpsr) { 14266 if (!WriteRegisterUnsigned(context, eRegisterKindGeneric, 14267 LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr)) 14268 return false; 14269 } 14270 return true; 14271} 14272 14273bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) { 14274 ARMOpcode *opcode_data = nullptr; 14275 14276 if (m_opcode_mode == eModeThumb) 14277 opcode_data = 14278 GetThumbOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa); 14279 else if (m_opcode_mode == eModeARM) 14280 opcode_data = GetARMOpcodeForInstruction(m_opcode.GetOpcode32(), m_arm_isa); 14281 14282 const bool auto_advance_pc = 14283 evaluate_options & eEmulateInstructionOptionAutoAdvancePC; 14284 m_ignore_conditions = 14285 evaluate_options & eEmulateInstructionOptionIgnoreConditions; 14286 14287 bool success = false; 14288 if (m_opcode_cpsr == 0 || !m_ignore_conditions) { 14289 m_opcode_cpsr = 14290 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success); 14291 } 14292 14293 // Only return false if we are unable to read the CPSR if we care about 14294 // conditions 14295 if (!success && !m_ignore_conditions) 14296 return false; 14297 14298 uint32_t orig_pc_value = 0; 14299 if (auto_advance_pc) { 14300 orig_pc_value = 14301 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success); 14302 if (!success) 14303 return false; 14304 } 14305 14306 // Call the Emulate... function if we managed to decode the opcode. 14307 if (opcode_data) { 14308 success = (this->*opcode_data->callback)(m_opcode.GetOpcode32(), 14309 opcode_data->encoding); 14310 if (!success) 14311 return false; 14312 } 14313 14314 // Advance the ITSTATE bits to their values for the next instruction if we 14315 // haven't just executed an IT instruction what initialized it. 14316 if (m_opcode_mode == eModeThumb && m_it_session.InITBlock() && 14317 (opcode_data == nullptr || 14318 opcode_data->callback != &EmulateInstructionARM::EmulateIT)) 14319 m_it_session.ITAdvance(); 14320 14321 if (auto_advance_pc) { 14322 uint32_t after_pc_value = 14323 ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_pc, 0, &success); 14324 if (!success) 14325 return false; 14326 14327 if (after_pc_value == orig_pc_value) { 14328 after_pc_value += m_opcode.GetByteSize(); 14329 14330 EmulateInstruction::Context context; 14331 context.type = eContextAdvancePC; 14332 context.SetNoArgs(); 14333 if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc, 14334 after_pc_value)) 14335 return false; 14336 } 14337 } 14338 return true; 14339} 14340 14341EmulateInstruction::InstructionCondition 14342EmulateInstructionARM::GetInstructionCondition() { 14343 const uint32_t cond = CurrentCond(m_opcode.GetOpcode32()); 14344 if (cond == 0xe || cond == 0xf || cond == UINT32_MAX) 14345 return EmulateInstruction::UnconditionalCondition; 14346 return cond; 14347} 14348 14349bool EmulateInstructionARM::TestEmulation(Stream &out_stream, ArchSpec &arch, 14350 OptionValueDictionary *test_data) { 14351 if (!test_data) { 14352 out_stream.Printf("TestEmulation: Missing test data.\n"); 14353 return false; 14354 } 14355 14356 static constexpr llvm::StringLiteral opcode_key("opcode"); 14357 static constexpr llvm::StringLiteral before_key("before_state"); 14358 static constexpr llvm::StringLiteral after_key("after_state"); 14359 14360 OptionValueSP value_sp = test_data->GetValueForKey(opcode_key); 14361 14362 uint32_t test_opcode; 14363 if ((value_sp.get() == nullptr) || 14364 (value_sp->GetType() != OptionValue::eTypeUInt64)) { 14365 out_stream.Printf("TestEmulation: Error reading opcode from test file.\n"); 14366 return false; 14367 } 14368 test_opcode = value_sp->GetValueAs<uint64_t>().value_or(0); 14369 14370 if (arch.GetTriple().getArch() == llvm::Triple::thumb || 14371 arch.IsAlwaysThumbInstructions()) { 14372 m_opcode_mode = eModeThumb; 14373 if (test_opcode < 0x10000) 14374 m_opcode.SetOpcode16(test_opcode, endian::InlHostByteOrder()); 14375 else 14376 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder()); 14377 } else if (arch.GetTriple().getArch() == llvm::Triple::arm) { 14378 m_opcode_mode = eModeARM; 14379 m_opcode.SetOpcode32(test_opcode, endian::InlHostByteOrder()); 14380 } else { 14381 out_stream.Printf("TestEmulation: Invalid arch.\n"); 14382 return false; 14383 } 14384 14385 EmulationStateARM before_state; 14386 EmulationStateARM after_state; 14387 14388 value_sp = test_data->GetValueForKey(before_key); 14389 if ((value_sp.get() == nullptr) || 14390 (value_sp->GetType() != OptionValue::eTypeDictionary)) { 14391 out_stream.Printf("TestEmulation: Failed to find 'before' state.\n"); 14392 return false; 14393 } 14394 14395 OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary(); 14396 if (!before_state.LoadStateFromDictionary(state_dictionary)) { 14397 out_stream.Printf("TestEmulation: Failed loading 'before' state.\n"); 14398 return false; 14399 } 14400 14401 value_sp = test_data->GetValueForKey(after_key); 14402 if ((value_sp.get() == nullptr) || 14403 (value_sp->GetType() != OptionValue::eTypeDictionary)) { 14404 out_stream.Printf("TestEmulation: Failed to find 'after' state.\n"); 14405 return false; 14406 } 14407 14408 state_dictionary = value_sp->GetAsDictionary(); 14409 if (!after_state.LoadStateFromDictionary(state_dictionary)) { 14410 out_stream.Printf("TestEmulation: Failed loading 'after' state.\n"); 14411 return false; 14412 } 14413 14414 SetBaton((void *)&before_state); 14415 SetCallbacks(&EmulationStateARM::ReadPseudoMemory, 14416 &EmulationStateARM::WritePseudoMemory, 14417 &EmulationStateARM::ReadPseudoRegister, 14418 &EmulationStateARM::WritePseudoRegister); 14419 14420 bool success = EvaluateInstruction(eEmulateInstructionOptionAutoAdvancePC); 14421 if (!success) { 14422 out_stream.Printf("TestEmulation: EvaluateInstruction() failed.\n"); 14423 return false; 14424 } 14425 14426 success = before_state.CompareState(after_state, out_stream); 14427 if (!success) 14428 out_stream.Printf("TestEmulation: State after emulation does not match " 14429 "'after' state.\n"); 14430 14431 return success; 14432} 14433// 14434// 14435// const char * 14436// EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num) 14437//{ 14438// if (reg_kind == eRegisterKindGeneric) 14439// { 14440// switch (reg_num) 14441// { 14442// case LLDB_REGNUM_GENERIC_PC: return "pc"; 14443// case LLDB_REGNUM_GENERIC_SP: return "sp"; 14444// case LLDB_REGNUM_GENERIC_FP: return "fp"; 14445// case LLDB_REGNUM_GENERIC_RA: return "lr"; 14446// case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr"; 14447// default: return NULL; 14448// } 14449// } 14450// else if (reg_kind == eRegisterKindDWARF) 14451// { 14452// return GetARMDWARFRegisterName (reg_num); 14453// } 14454// return NULL; 14455//} 14456// 14457bool EmulateInstructionARM::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) { 14458 unwind_plan.Clear(); 14459 unwind_plan.SetRegisterKind(eRegisterKindDWARF); 14460 14461 UnwindPlan::RowSP row(new UnwindPlan::Row); 14462 14463 // Our previous Call Frame Address is the stack pointer 14464 row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_sp, 0); 14465 14466 unwind_plan.AppendRow(row); 14467 unwind_plan.SetSourceName("EmulateInstructionARM"); 14468 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); 14469 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes); 14470 unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo); 14471 unwind_plan.SetReturnAddressRegister(dwarf_lr); 14472 return true; 14473} 14474