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