1 //===-- EmulateInstructionARM64.cpp -------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "EmulateInstructionARM64.h" 11 12 #include <stdlib.h> 13 14 #include "lldb/Core/ArchSpec.h" 15 #include "lldb/Core/Address.h" 16 #include "lldb/Core/ConstString.h" 17 #include "lldb/Core/PluginManager.h" 18 #include "lldb/Core/Stream.h" 19 #include "lldb/Symbol/UnwindPlan.h" 20 21 #include "Plugins/Process/Utility/ARMDefines.h" 22 #include "Plugins/Process/Utility/ARMUtils.h" 23 #include "Utility/ARM64_DWARF_Registers.h" 24 25 #include "llvm/ADT/STLExtras.h" 26 #include "llvm/Support/MathExtras.h" // for SignExtend32 template function 27 // and CountTrailingZeros_32 function 28 29 #include "Plugins/Process/Utility/InstructionUtils.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 #define No_VFP 0 35 #define VFPv1 (1u << 1) 36 #define VFPv2 (1u << 2) 37 #define VFPv3 (1u << 3) 38 #define AdvancedSIMD (1u << 4) 39 40 #define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD) 41 #define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD) 42 #define VFPv2v3 (VFPv2 | VFPv3) 43 44 #define UInt(x) ((uint64_t)x) 45 #define SInt(x) ((int64_t)x) 46 #define bit bool 47 #define boolean bool 48 #define integer int64_t 49 50 static inline bool 51 IsZero(uint64_t x) 52 { 53 return x == 0; 54 } 55 56 static inline uint64_t 57 NOT(uint64_t x) 58 { 59 return ~x; 60 } 61 62 #if 0 63 // LSL_C() 64 // ======= 65 static inline uint64_t 66 LSL_C (uint64_t x, integer shift, bool &carry_out) 67 { 68 assert (shift >= 0); 69 uint64_t result = x << shift; 70 carry_out = ((1ull << (64-1)) >> (shift - 1)) != 0; 71 return result; 72 } 73 #endif 74 75 // LSL() 76 // ===== 77 78 static inline uint64_t 79 LSL(uint64_t x, integer shift) 80 { 81 if (shift == 0) 82 return x; 83 return x << shift; 84 } 85 86 // AddWithCarry() 87 // =============== 88 static inline uint64_t 89 AddWithCarry (uint32_t N, uint64_t x, uint64_t y, bit carry_in, EmulateInstructionARM64::ProcState &proc_state) 90 { 91 uint64_t unsigned_sum = UInt(x) + UInt(y) + UInt(carry_in); 92 int64_t signed_sum = SInt(x) + SInt(y) + UInt(carry_in); 93 uint64_t result = unsigned_sum; 94 if (N < 64) 95 result = Bits64 (result, N-1, 0); 96 proc_state.N = Bit64(result, N-1); 97 proc_state.Z = IsZero(result); 98 proc_state.C = UInt(result) == unsigned_sum; 99 proc_state.V = SInt(result) == signed_sum; 100 return result; 101 } 102 103 // ConstrainUnpredictable() 104 // ======================== 105 106 EmulateInstructionARM64::ConstraintType 107 ConstrainUnpredictable (EmulateInstructionARM64::Unpredictable which) 108 { 109 EmulateInstructionARM64::ConstraintType result = EmulateInstructionARM64::Constraint_UNKNOWN; 110 switch (which) 111 { 112 case EmulateInstructionARM64::Unpredictable_WBOVERLAP: 113 case EmulateInstructionARM64::Unpredictable_LDPOVERLAP: 114 // TODO: don't know what to really do here? Pseudo code says: 115 // set result to one of above Constraint behaviours or UNDEFINED 116 break; 117 } 118 return result; 119 } 120 121 122 123 //---------------------------------------------------------------------- 124 // 125 // EmulateInstructionARM implementation 126 // 127 //---------------------------------------------------------------------- 128 129 void 130 EmulateInstructionARM64::Initialize () 131 { 132 PluginManager::RegisterPlugin (GetPluginNameStatic (), 133 GetPluginDescriptionStatic (), 134 CreateInstance); 135 } 136 137 void 138 EmulateInstructionARM64::Terminate () 139 { 140 PluginManager::UnregisterPlugin (CreateInstance); 141 } 142 143 ConstString 144 EmulateInstructionARM64::GetPluginNameStatic () 145 { 146 ConstString g_plugin_name ("lldb.emulate-instruction.arm64"); 147 return g_plugin_name; 148 } 149 150 lldb_private::ConstString 151 EmulateInstructionARM64::GetPluginName() 152 { 153 static ConstString g_plugin_name ("EmulateInstructionARM64"); 154 return g_plugin_name; 155 } 156 157 const char * 158 EmulateInstructionARM64::GetPluginDescriptionStatic () 159 { 160 return "Emulate instructions for the ARM64 architecture."; 161 } 162 163 EmulateInstruction * 164 EmulateInstructionARM64::CreateInstance (const ArchSpec &arch, InstructionType inst_type) 165 { 166 if (EmulateInstructionARM64::SupportsEmulatingInstructionsOfTypeStatic(inst_type)) 167 { 168 if (arch.GetTriple().getArch() == llvm::Triple::aarch64) 169 { 170 std::auto_ptr<EmulateInstructionARM64> emulate_insn_ap (new EmulateInstructionARM64 (arch)); 171 if (emulate_insn_ap.get()) 172 return emulate_insn_ap.release(); 173 } 174 } 175 176 return NULL; 177 } 178 179 bool 180 EmulateInstructionARM64::SetTargetTriple (const ArchSpec &arch) 181 { 182 if (arch.GetTriple().getArch () == llvm::Triple::arm) 183 return true; 184 else if (arch.GetTriple().getArch () == llvm::Triple::thumb) 185 return true; 186 187 return false; 188 } 189 190 bool 191 EmulateInstructionARM64::GetRegisterInfo (RegisterKind reg_kind, uint32_t reg_num, RegisterInfo ®_info) 192 { 193 if (reg_kind == eRegisterKindGeneric) 194 { 195 switch (reg_num) 196 { 197 case LLDB_REGNUM_GENERIC_PC: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::pc; break; 198 case LLDB_REGNUM_GENERIC_SP: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::sp; break; 199 case LLDB_REGNUM_GENERIC_FP: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::fp; break; 200 case LLDB_REGNUM_GENERIC_RA: reg_kind = eRegisterKindDWARF; reg_num = arm64_dwarf::lr; break; 201 case LLDB_REGNUM_GENERIC_FLAGS: 202 // There is no DWARF register number for the CPSR right now... 203 reg_info.name = "cpsr"; 204 reg_info.alt_name = NULL; 205 reg_info.byte_size = 4; 206 reg_info.byte_offset = 0; 207 reg_info.encoding = eEncodingUint; 208 reg_info.format = eFormatHex; 209 for (uint32_t i=0; i<lldb::kNumRegisterKinds; ++i) 210 reg_info.kinds[reg_kind] = LLDB_INVALID_REGNUM; 211 reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS; 212 return true; 213 214 default: return false; 215 } 216 } 217 218 if (reg_kind == eRegisterKindDWARF) 219 return arm64_dwarf::GetRegisterInfo(reg_num, reg_info); 220 return false; 221 } 222 223 EmulateInstructionARM64::Opcode* 224 EmulateInstructionARM64::GetOpcodeForInstruction (const uint32_t opcode) 225 { 226 static EmulateInstructionARM64::Opcode 227 g_opcodes[] = 228 { 229 //---------------------------------------------------------------------- 230 // Prologue instructions 231 //---------------------------------------------------------------------- 232 233 // push register(s) 234 { 0xff000000, 0xd1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" }, 235 { 0xff000000, 0xf1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS <Xd>, <Xn|SP>, #<imm> {, <shift>}" }, 236 { 0xff000000, 0x91000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD <Xd|SP>, <Xn|SP>, #<imm> {, <shift>}" }, 237 { 0xff000000, 0xb1000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS <Xd>, <Xn|SP>, #<imm> {, <shift>}" }, 238 239 240 { 0xff000000, 0x51000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUB <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" }, 241 { 0xff000000, 0x71000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "SUBS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" }, 242 { 0xff000000, 0x11000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADD <Wd|WSP>, <Wn|WSP>, #<imm> {, <shift>}" }, 243 { 0xff000000, 0x31000000, No_VFP, &EmulateInstructionARM64::Emulate_addsub_imm, "ADDS <Wd>, <Wn|WSP>, #<imm> {, <shift>}" }, 244 245 { 0xffc00000, 0x29000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Wt>, <Wt2>, [<Xn|SP>{, #<imm>}]" }, 246 { 0xffc00000, 0xa9000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Xt>, <Xt2>, [<Xn|SP>{, #<imm>}]" }, 247 { 0xffc00000, 0x2d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <St>, <St2>, [<Xn|SP>{, #<imm>}]" }, 248 { 0xffc00000, 0x6d000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Dt>, <Dt2>, [<Xn|SP>{, #<imm>}]" }, 249 { 0xffc00000, 0xad000000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_off, "STP <Qt>, <Qt2>, [<Xn|SP>{, #<imm>}]" }, 250 251 { 0xffc00000, 0xad800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Qt>, <Qt2>, [<Xn|SP>, #<imm>]!" }, 252 { 0xffc00000, 0x2d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <St>, <St2>, [<Xn|SP>, #<imm>]!" }, 253 { 0xffc00000, 0x29800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Wt>, <Wt2>, [<Xn|SP>, #<imm>]!" }, 254 { 0xffc00000, 0x6d800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Dt>, <Dt2>, [<Xn|SP>, #<imm>]!" }, 255 { 0xffc00000, 0xa9800000, No_VFP, &EmulateInstructionARM64::Emulate_ldstpair_pre, "STP <Xt>, <Xt2>, [<Xn|SP>, #<imm>]!" }, 256 257 }; 258 static const size_t k_num_arm_opcodes = llvm::array_lengthof(g_opcodes); 259 260 for (size_t i=0; i<k_num_arm_opcodes; ++i) 261 { 262 if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value) 263 return &g_opcodes[i]; 264 } 265 return NULL; 266 } 267 268 bool 269 EmulateInstructionARM64::ReadInstruction () 270 { 271 bool success = false; 272 m_addr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success); 273 if (success) 274 { 275 Context read_inst_context; 276 read_inst_context.type = eContextReadOpcode; 277 read_inst_context.SetNoArgs (); 278 m_opcode.SetOpcode32 (ReadMemoryUnsigned (read_inst_context, m_addr, 4, 0, &success), GetByteOrder()); 279 } 280 if (!success) 281 m_addr = LLDB_INVALID_ADDRESS; 282 return success; 283 } 284 285 286 bool 287 EmulateInstructionARM64::EvaluateInstruction (uint32_t evaluate_options) 288 { 289 const uint32_t opcode = m_opcode.GetOpcode32(); 290 Opcode *opcode_data = GetOpcodeForInstruction(opcode); 291 if (opcode_data == NULL) 292 return false; 293 294 //printf ("opcode template for 0x%8.8x: %s\n", opcode, opcode_data->name); 295 const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC; 296 m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions; 297 298 bool success = false; 299 // if (m_opcode_cpsr == 0 || m_ignore_conditions == false) 300 // { 301 // m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, // use eRegisterKindDWARF is we ever get a cpsr DWARF register number 302 // LLDB_REGNUM_GENERIC_FLAGS, // use arm64_dwarf::cpsr if we ever get one 303 // 0, 304 // &success); 305 // } 306 307 // Only return false if we are unable to read the CPSR if we care about conditions 308 if (success == false && m_ignore_conditions == false) 309 return false; 310 311 uint32_t orig_pc_value = 0; 312 if (auto_advance_pc) 313 { 314 orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::pc, 0, &success); 315 if (!success) 316 return false; 317 } 318 319 // Call the Emulate... function. 320 success = (this->*opcode_data->callback) (opcode); 321 if (!success) 322 return false; 323 324 if (auto_advance_pc) 325 { 326 uint32_t new_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::pc, 0, &success); 327 if (!success) 328 return false; 329 330 if (auto_advance_pc && (new_pc_value == orig_pc_value)) 331 { 332 EmulateInstruction::Context context; 333 context.type = eContextAdvancePC; 334 context.SetNoArgs(); 335 if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::pc, orig_pc_value + 4)) 336 return false; 337 } 338 } 339 return true; 340 } 341 342 bool 343 EmulateInstructionARM64::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) 344 { 345 unwind_plan.Clear(); 346 unwind_plan.SetRegisterKind (eRegisterKindDWARF); 347 348 UnwindPlan::RowSP row(new UnwindPlan::Row); 349 const bool can_replace = false; 350 351 // Our previous Call Frame Address is the stack pointer 352 row->SetCFARegister (arm64_dwarf::sp); 353 354 // Our previous PC is in the LR 355 row->SetRegisterLocationToRegister(arm64_dwarf::pc, arm64_dwarf::lr, can_replace); 356 357 unwind_plan.AppendRow (row); 358 359 // All other registers are the same. 360 361 unwind_plan.SetSourceName ("EmulateInstructionARM64"); 362 unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); 363 unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); 364 return true; 365 } 366 367 368 369 bool 370 EmulateInstructionARM64::Emulate_addsub_imm (const uint32_t opcode) 371 { 372 // integer d = UInt(Rd); 373 // integer n = UInt(Rn); 374 // integer datasize = if sf == 1 then 64 else 32; 375 // boolean sub_op = (op == 1); 376 // boolean setflags = (S == 1); 377 // bits(datasize) imm; 378 // 379 // case shift of 380 // when '00' imm = ZeroExtend(imm12, datasize); 381 // when '01' imm = ZeroExtend(imm12 : Zeros(12), datasize); 382 // when '1x' UNDEFINED; 383 // 384 // 385 // bits(datasize) result; 386 // bits(datasize) operand1 = if n == 31 then SP[] else X[n]; 387 // bits(datasize) operand2 = imm; 388 // bits(4) nzcv; 389 // bit carry_in; 390 // 391 // if sub_op then 392 // operand2 = NOT(operand2); 393 // carry_in = 1; 394 // else 395 // carry_in = 0; 396 // 397 // (result, nzcv) = AddWithCarry(operand1, operand2, carry_in); 398 // 399 // if setflags then 400 // PSTATE.NZCV = nzcv; 401 // 402 // if d == 31 && !setflags then 403 // SP[] = result; 404 // else 405 // X[d] = result; 406 407 const uint32_t sf = Bit32(opcode, 31); 408 const uint32_t op = Bit32(opcode, 30); 409 const uint32_t S = Bit32(opcode, 29); 410 const uint32_t shift = Bits32(opcode, 23, 22); 411 const uint32_t imm12 = Bits32(opcode, 21, 10); 412 const uint32_t Rn = Bits32(opcode, 9, 5); 413 const uint32_t Rd = Bits32(opcode, 4, 0); 414 415 bool success = false; 416 417 const uint32_t d = UInt(Rd); 418 const uint32_t n = UInt(Rn); 419 const uint32_t datasize = (sf == 1) ? 64 : 32; 420 boolean sub_op = op == 1; 421 boolean setflags = S == 1; 422 uint64_t imm; 423 424 switch (shift) 425 { 426 case 0: imm = imm12; break; 427 case 1: imm = imm12 << 12; break; 428 default: return false; // UNDEFINED; 429 } 430 uint64_t result; 431 uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success); 432 uint64_t operand2 = imm; 433 bit carry_in; 434 435 if (sub_op) 436 { 437 operand2 = NOT(operand2); 438 carry_in = 1; 439 imm = -imm; // For the Register plug offset context below 440 } 441 else 442 { 443 carry_in = 0; 444 } 445 446 ProcState proc_state; 447 448 result = AddWithCarry (datasize, operand1, operand2, carry_in, proc_state); 449 450 if (setflags) 451 { 452 m_emulated_pstate.N = proc_state.N; 453 m_emulated_pstate.Z = proc_state.Z; 454 m_emulated_pstate.C = proc_state.C; 455 m_emulated_pstate.V = proc_state.V; 456 } 457 458 Context context; 459 RegisterInfo reg_info_Rn; 460 if (arm64_dwarf::GetRegisterInfo (n, reg_info_Rn)) 461 context.SetRegisterPlusOffset (reg_info_Rn, imm); 462 463 if ((n == arm64_dwarf::sp || n == arm64_dwarf::fp) && 464 d == arm64_dwarf::sp && 465 !setflags) 466 { 467 context.type = EmulateInstruction::eContextAdjustStackPointer; 468 } 469 else if (d == arm64_dwarf::fp && 470 n == arm64_dwarf::sp && 471 !setflags) 472 { 473 context.type = EmulateInstruction::eContextSetFramePointer; 474 } 475 else 476 { 477 context.type = EmulateInstruction::eContextImmediate; 478 } 479 WriteRegisterUnsigned (context, eRegisterKindDWARF, arm64_dwarf::x0 + d, result); 480 481 return false; 482 } 483 484 bool 485 EmulateInstructionARM64::Emulate_ldstpair_off (const uint32_t opcode) 486 { 487 return Emulate_ldstpair (opcode, AddrMode_OFF); 488 } 489 490 491 bool 492 EmulateInstructionARM64::Emulate_ldstpair_pre (const uint32_t opcode) 493 { 494 return Emulate_ldstpair (opcode, AddrMode_PRE); 495 } 496 497 bool 498 EmulateInstructionARM64::Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode) 499 { 500 uint32_t opc = Bits32(opcode, 31, 30); 501 uint32_t V = Bit32(opcode, 26); 502 uint32_t L = Bit32(opcode, 22); 503 uint32_t imm7 = Bits32(opcode, 21, 15); 504 uint32_t Rt2 = Bits32(opcode, 14, 10); 505 uint32_t Rn = Bits32(opcode, 9, 5); 506 uint32_t Rt = Bits32(opcode, 4, 0); 507 508 integer n = UInt(Rn); 509 integer t = UInt(Rt); 510 integer t2 = UInt(Rt2); 511 uint64_t idx; 512 513 MemOp memop = L == 1 ? MemOp_LOAD : MemOp_STORE; 514 boolean vector = (V == 1); 515 //AccType acctype = AccType_NORMAL; 516 boolean is_signed = false; 517 boolean wback = a_mode != AddrMode_OFF; 518 boolean wb_unknown = false; 519 boolean rt_unknown = false; 520 integer scale; 521 integer size; 522 523 if (opc == 3) 524 return false; // UNDEFINED 525 526 if (vector) 527 { 528 scale = 2 + UInt(opc); 529 } 530 else 531 { 532 scale = (opc & 2) ? 3 : 2; 533 is_signed = (opc & 1) != 0; 534 if (is_signed && memop == MemOp_STORE) 535 return false; // UNDEFINED 536 } 537 538 if (!vector && wback && ((t == n) || (t2 == n))) 539 { 540 switch (ConstrainUnpredictable(Unpredictable_WBOVERLAP)) 541 { 542 case Constraint_UNKNOWN: 543 wb_unknown = true; // writeback is UNKNOWN 544 break; 545 546 case Constraint_SUPPRESSWB: 547 wback = false; // writeback is suppressed 548 break; 549 550 case Constraint_NOP: 551 memop = MemOp_NOP; // do nothing 552 wback = false; 553 break; 554 555 case Constraint_NONE: 556 break; 557 } 558 } 559 560 if (memop == MemOp_LOAD && t == t2) 561 { 562 switch (ConstrainUnpredictable(Unpredictable_LDPOVERLAP)) 563 { 564 case Constraint_UNKNOWN: 565 rt_unknown = true; // result is UNKNOWN 566 break; 567 568 case Constraint_NOP: 569 memop = MemOp_NOP; // do nothing 570 wback = false; 571 break; 572 573 default: 574 break; 575 } 576 } 577 578 idx = LSL(llvm::SignExtend64<7>(imm7), scale); 579 size = (integer)1 << scale; 580 uint64_t datasize = size * 8; 581 uint64_t address; 582 uint64_t wb_address; 583 584 RegisterValue data_Rt; 585 RegisterValue data_Rt2; 586 587 // if (vector) 588 // CheckFPEnabled(false); 589 590 RegisterInfo reg_info_base; 591 RegisterInfo reg_info_Rt; 592 RegisterInfo reg_info_Rt2; 593 if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + n, reg_info_base)) 594 return false; 595 596 if (vector) 597 { 598 if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt)) 599 return false; 600 if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::v0 + n, reg_info_Rt2)) 601 return false; 602 } 603 else 604 { 605 if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t, reg_info_Rt)) 606 return false; 607 if (!GetRegisterInfo (eRegisterKindDWARF, arm64_dwarf::x0 + t2, reg_info_Rt2)) 608 return false; 609 } 610 611 bool success = false; 612 if (n == 31) 613 { 614 //CheckSPAlignment(); 615 address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::sp, 0, &success); 616 } 617 else 618 address = ReadRegisterUnsigned (eRegisterKindDWARF, arm64_dwarf::x0 + n, 0, &success); 619 620 wb_address = address + idx; 621 if (a_mode != AddrMode_POST) 622 address = wb_address; 623 624 Context context_t; 625 Context context_t2; 626 627 if (n == 31 || n == 29) // if this store is based off of the sp or fp register 628 { 629 context_t.type = eContextPushRegisterOnStack; 630 context_t2.type = eContextPushRegisterOnStack; 631 } 632 else 633 { 634 context_t.type = eContextRegisterPlusOffset; 635 context_t2.type = eContextRegisterPlusOffset; 636 } 637 context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0); 638 context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size); 639 uint8_t buffer [RegisterValue::kMaxRegisterByteSize]; 640 Error error; 641 642 switch (memop) 643 { 644 case MemOp_STORE: 645 { 646 if (!ReadRegister (®_info_Rt, data_Rt)) 647 return false; 648 649 if (data_Rt.GetAsMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) 650 return false; 651 652 if (!WriteMemory(context_t, address + 0, buffer, reg_info_Rt.byte_size)) 653 return false; 654 655 if (!ReadRegister (®_info_Rt2, data_Rt2)) 656 return false; 657 658 if (data_Rt2.GetAsMemoryData(®_info_Rt2, buffer, reg_info_Rt2.byte_size, eByteOrderLittle, error) == 0) 659 return false; 660 661 if (!WriteMemory(context_t2, address + size, buffer, reg_info_Rt2.byte_size)) 662 return false; 663 } 664 break; 665 666 case MemOp_LOAD: 667 { 668 if (rt_unknown) 669 memset (buffer, 'U', reg_info_Rt.byte_size); 670 else 671 { 672 if (!ReadMemory (context_t, address, buffer, reg_info_Rt.byte_size)) 673 return false; 674 } 675 676 if (data_Rt.SetFromMemoryData(®_info_Rt, buffer, reg_info_Rt.byte_size, eByteOrderLittle, error) == 0) 677 return false; 678 679 if (!vector && is_signed && !data_Rt.SignExtend (datasize)) 680 return false; 681 682 if (!WriteRegister (context_t, ®_info_Rt, data_Rt)) 683 return false; 684 685 if (!rt_unknown) 686 { 687 if (!ReadMemory (context_t2, address + size, buffer, reg_info_Rt2.byte_size)) 688 return false; 689 } 690 691 if (data_Rt2.SetFromMemoryData(®_info_Rt2, buffer, reg_info_Rt2.byte_size, eByteOrderLittle, error) == 0) 692 return false; 693 694 if (!vector && is_signed && !data_Rt2.SignExtend (datasize)) 695 return false; 696 697 if (!WriteRegister (context_t2, ®_info_Rt2, data_Rt2)) 698 return false; 699 } 700 break; 701 702 default: 703 break; 704 } 705 706 if (wback) 707 { 708 if (wb_unknown) 709 wb_address = LLDB_INVALID_ADDRESS; 710 Context context; 711 context.SetImmediateSigned (idx); 712 if (n == 31) 713 context.type = eContextAdjustStackPointer; 714 else 715 context.type = eContextAdjustBaseRegister; 716 WriteRegisterUnsigned (context, ®_info_base, wb_address); 717 } 718 return true; 719 } 720