1 //===-- DNBArchImpl.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 //  Created by Greg Clayton on 6/25/07.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #if defined (__arm__)
15 
16 #include "MacOSX/arm/DNBArchImpl.h"
17 #include "MacOSX/MachProcess.h"
18 #include "MacOSX/MachThread.h"
19 #include "DNBBreakpoint.h"
20 #include "DNBLog.h"
21 #include "DNBRegisterInfo.h"
22 #include "DNB.h"
23 #include "ARM_GCC_Registers.h"
24 #include "ARM_DWARF_Registers.h"
25 
26 #include <sys/sysctl.h>
27 
28 // BCR address match type
29 #define BCR_M_IMVA_MATCH        ((uint32_t)(0u << 21))
30 #define BCR_M_CONTEXT_ID_MATCH  ((uint32_t)(1u << 21))
31 #define BCR_M_IMVA_MISMATCH     ((uint32_t)(2u << 21))
32 #define BCR_M_RESERVED          ((uint32_t)(3u << 21))
33 
34 // Link a BVR/BCR or WVR/WCR pair to another
35 #define E_ENABLE_LINKING        ((uint32_t)(1u << 20))
36 
37 // Byte Address Select
38 #define BAS_IMVA_PLUS_0         ((uint32_t)(1u << 5))
39 #define BAS_IMVA_PLUS_1         ((uint32_t)(1u << 6))
40 #define BAS_IMVA_PLUS_2         ((uint32_t)(1u << 7))
41 #define BAS_IMVA_PLUS_3         ((uint32_t)(1u << 8))
42 #define BAS_IMVA_0_1            ((uint32_t)(3u << 5))
43 #define BAS_IMVA_2_3            ((uint32_t)(3u << 7))
44 #define BAS_IMVA_ALL            ((uint32_t)(0xfu << 5))
45 
46 // Break only in priveleged or user mode
47 #define S_RSVD                  ((uint32_t)(0u << 1))
48 #define S_PRIV                  ((uint32_t)(1u << 1))
49 #define S_USER                  ((uint32_t)(2u << 1))
50 #define S_PRIV_USER             ((S_PRIV) | (S_USER))
51 
52 #define BCR_ENABLE              ((uint32_t)(1u))
53 #define WCR_ENABLE              ((uint32_t)(1u))
54 
55 // Watchpoint load/store
56 #define WCR_LOAD                ((uint32_t)(1u << 3))
57 #define WCR_STORE               ((uint32_t)(1u << 4))
58 
59 //#define DNB_ARCH_MACH_ARM_DEBUG_SW_STEP 1
60 
61 static const uint8_t g_arm_breakpoint_opcode[] = { 0xFE, 0xDE, 0xFF, 0xE7 };
62 static const uint8_t g_thumb_breakpooint_opcode[] = { 0xFE, 0xDE };
63 
64 // ARM constants used during decoding
65 #define REG_RD          0
66 #define LDM_REGLIST     1
67 #define PC_REG          15
68 #define PC_REGLIST_BIT  0x8000
69 
70 // ARM conditions
71 #define COND_EQ     0x0
72 #define COND_NE     0x1
73 #define COND_CS     0x2
74 #define COND_HS     0x2
75 #define COND_CC     0x3
76 #define COND_LO     0x3
77 #define COND_MI     0x4
78 #define COND_PL     0x5
79 #define COND_VS     0x6
80 #define COND_VC     0x7
81 #define COND_HI     0x8
82 #define COND_LS     0x9
83 #define COND_GE     0xA
84 #define COND_LT     0xB
85 #define COND_GT     0xC
86 #define COND_LE     0xD
87 #define COND_AL     0xE
88 #define COND_UNCOND 0xF
89 
90 #define MASK_CPSR_T (1u << 5)
91 #define MASK_CPSR_J (1u << 24)
92 
93 #define MNEMONIC_STRING_SIZE 32
94 #define OPERAND_STRING_SIZE 128
95 
96 const uint8_t * const
97 DNBArchMachARM::SoftwareBreakpointOpcode (nub_size_t byte_size)
98 {
99     switch (byte_size)
100     {
101     case 2: return g_thumb_breakpooint_opcode;
102     case 4: return g_arm_breakpoint_opcode;
103     }
104     return NULL;
105 }
106 
107 uint32_t
108 DNBArchMachARM::GetCPUType()
109 {
110     return CPU_TYPE_ARM;
111 }
112 
113 uint64_t
114 DNBArchMachARM::GetPC(uint64_t failValue)
115 {
116     // Get program counter
117     if (GetGPRState(false) == KERN_SUCCESS)
118         return m_state.context.gpr.__pc;
119     return failValue;
120 }
121 
122 kern_return_t
123 DNBArchMachARM::SetPC(uint64_t value)
124 {
125     // Get program counter
126     kern_return_t err = GetGPRState(false);
127     if (err == KERN_SUCCESS)
128     {
129         m_state.context.gpr.__pc = value;
130         err = SetGPRState();
131     }
132     return err == KERN_SUCCESS;
133 }
134 
135 uint64_t
136 DNBArchMachARM::GetSP(uint64_t failValue)
137 {
138     // Get stack pointer
139     if (GetGPRState(false) == KERN_SUCCESS)
140         return m_state.context.gpr.__sp;
141     return failValue;
142 }
143 
144 kern_return_t
145 DNBArchMachARM::GetGPRState(bool force)
146 {
147     int set = e_regSetGPR;
148     // Check if we have valid cached registers
149     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
150         return KERN_SUCCESS;
151 
152     // Read the registers from our thread
153     mach_msg_type_number_t count = ARM_THREAD_STATE_COUNT;
154     kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count);
155     uint32_t *r = &m_state.context.gpr.__r[0];
156     DNBLogThreadedIf(LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x regs r0=%8.8x r1=%8.8x r2=%8.8x r3=%8.8x r4=%8.8x r5=%8.8x r6=%8.8x r7=%8.8x r8=%8.8x r9=%8.8x r10=%8.8x r11=%8.8x s12=%8.8x sp=%8.8x lr=%8.8x pc=%8.8x cpsr=%8.8x", m_thread->ThreadID(), ARM_THREAD_STATE, ARM_THREAD_STATE_COUNT, kret,
157      r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9], r[10], r[11], r[12], r[13], r[14], r[15], r[16]);
158     m_state.SetError(set, Read, kret);
159     return kret;
160 }
161 
162 kern_return_t
163 DNBArchMachARM::GetVFPState(bool force)
164 {
165     int set = e_regSetVFP;
166     // Check if we have valid cached registers
167     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
168         return KERN_SUCCESS;
169 
170     // Read the registers from our thread
171     mach_msg_type_number_t count = ARM_VFP_STATE_COUNT;
172     kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, &count);
173     m_state.SetError(set, Read, kret);
174     return kret;
175 }
176 
177 kern_return_t
178 DNBArchMachARM::GetEXCState(bool force)
179 {
180     int set = e_regSetEXC;
181     // Check if we have valid cached registers
182     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
183         return KERN_SUCCESS;
184 
185     // Read the registers from our thread
186     mach_msg_type_number_t count = ARM_EXCEPTION_STATE_COUNT;
187     kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count);
188     m_state.SetError(set, Read, kret);
189     return kret;
190 }
191 
192 static void
193 DumpDBGState(const arm_debug_state_t& dbg)
194 {
195     uint32_t i = 0;
196     for (i=0; i<16; i++)
197         DNBLogThreadedIf(LOG_STEP, "BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }",
198             i, i, dbg.__bvr[i], dbg.__bcr[i],
199             i, i, dbg.__wvr[i], dbg.__wcr[i]);
200 }
201 
202 kern_return_t
203 DNBArchMachARM::GetDBGState(bool force)
204 {
205     int set = e_regSetDBG;
206 
207     // Check if we have valid cached registers
208     if (!force && m_state.GetError(set, Read) == KERN_SUCCESS)
209         return KERN_SUCCESS;
210 
211     // Read the registers from our thread
212     mach_msg_type_number_t count = ARM_DEBUG_STATE_COUNT;
213     kern_return_t kret = ::thread_get_state(m_thread->ThreadID(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, &count);
214     m_state.SetError(set, Read, kret);
215     return kret;
216 }
217 
218 kern_return_t
219 DNBArchMachARM::SetGPRState()
220 {
221     int set = e_regSetGPR;
222     kern_return_t kret = ::thread_set_state(m_thread->ThreadID(), ARM_THREAD_STATE, (thread_state_t)&m_state.context.gpr, ARM_THREAD_STATE_COUNT);
223     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
224     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
225     return kret;                                // Return the error code
226 }
227 
228 kern_return_t
229 DNBArchMachARM::SetVFPState()
230 {
231     int set = e_regSetVFP;
232     kern_return_t kret = ::thread_set_state (m_thread->ThreadID(), ARM_VFP_STATE, (thread_state_t)&m_state.context.vfp, ARM_VFP_STATE_COUNT);
233     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
234     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
235     return kret;                                // Return the error code
236 }
237 
238 kern_return_t
239 DNBArchMachARM::SetEXCState()
240 {
241     int set = e_regSetEXC;
242     kern_return_t kret = ::thread_set_state (m_thread->ThreadID(), ARM_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, ARM_EXCEPTION_STATE_COUNT);
243     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
244     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
245     return kret;                                // Return the error code
246 }
247 
248 kern_return_t
249 DNBArchMachARM::SetDBGState()
250 {
251     int set = e_regSetDBG;
252     kern_return_t kret = ::thread_set_state (m_thread->ThreadID(), ARM_DEBUG_STATE, (thread_state_t)&m_state.dbg, ARM_DEBUG_STATE_COUNT);
253     m_state.SetError(set, Write, kret);         // Set the current write error for this register set
254     m_state.InvalidateRegisterSetState(set);    // Invalidate the current register state in case registers are read back differently
255     return kret;                                // Return the error code
256 }
257 
258 void
259 DNBArchMachARM::ThreadWillResume()
260 {
261     // Do we need to step this thread? If so, let the mach thread tell us so.
262     if (m_thread->IsStepping())
263     {
264         bool step_handled = false;
265         // This is the primary thread, let the arch do anything it needs
266         if (NumSupportedHardwareBreakpoints() > 0)
267         {
268 #if defined (DNB_ARCH_MACH_ARM_DEBUG_SW_STEP)
269             bool half_step = m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS;
270 #endif
271             step_handled = EnableHardwareSingleStep(true) == KERN_SUCCESS;
272 #if defined (DNB_ARCH_MACH_ARM_DEBUG_SW_STEP)
273             if (!half_step)
274                 step_handled = false;
275 #endif
276         }
277 
278         if (!step_handled)
279         {
280             SetSingleStepSoftwareBreakpoints();
281         }
282     }
283 }
284 
285 bool
286 DNBArchMachARM::ThreadDidStop()
287 {
288     bool success = true;
289 
290     m_state.InvalidateRegisterSetState (e_regSetALL);
291 
292     // Are we stepping a single instruction?
293     if (GetGPRState(true) == KERN_SUCCESS)
294     {
295         // We are single stepping, was this the primary thread?
296         if (m_thread->IsStepping())
297         {
298 #if defined (DNB_ARCH_MACH_ARM_DEBUG_SW_STEP)
299             success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
300             // Hardware single step must work if we are going to test software
301             // single step functionality
302             assert(success);
303             if (m_hw_single_chained_step_addr == INVALID_NUB_ADDRESS && m_sw_single_step_next_pc != INVALID_NUB_ADDRESS)
304             {
305                 uint32_t sw_step_next_pc = m_sw_single_step_next_pc & 0xFFFFFFFEu;
306                 bool sw_step_next_pc_is_thumb = (m_sw_single_step_next_pc & 1) != 0;
307                 bool actual_next_pc_is_thumb = (m_state.context.gpr.__cpsr & 0x20) != 0;
308                 if (m_state.context.gpr.__pc != sw_step_next_pc)
309                 {
310                     DNBLogError("curr pc = 0x%8.8x - calculated single step target PC was incorrect: 0x%8.8x != 0x%8.8x", m_state.context.gpr.__pc, sw_step_next_pc, m_state.context.gpr.__pc);
311                     exit(1);
312                 }
313                 if (actual_next_pc_is_thumb != sw_step_next_pc_is_thumb)
314                 {
315                     DNBLogError("curr pc = 0x%8.8x - calculated single step calculated mode mismatch: sw single mode = %s != %s",
316                                 m_state.context.gpr.__pc,
317                                 actual_next_pc_is_thumb ? "Thumb" : "ARM",
318                                 sw_step_next_pc_is_thumb ? "Thumb" : "ARM");
319                     exit(1);
320                 }
321                 m_sw_single_step_next_pc = INVALID_NUB_ADDRESS;
322             }
323 #else
324             // Are we software single stepping?
325             if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id) || m_sw_single_step_itblock_break_count)
326             {
327                 // Remove any software single stepping breakpoints that we have set
328 
329                 // Do we have a normal software single step breakpoint?
330                 if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id))
331                 {
332                     DNBLogThreadedIf(LOG_STEP, "%s: removing software single step breakpoint (breakID=%d)", __FUNCTION__, m_sw_single_step_break_id);
333                     success = m_thread->Process()->DisableBreakpoint(m_sw_single_step_break_id, true);
334                     m_sw_single_step_break_id = INVALID_NUB_BREAK_ID;
335                 }
336 
337                 // Do we have any Thumb IT breakpoints?
338                 if (m_sw_single_step_itblock_break_count > 0)
339                 {
340                     // See if we hit one of our Thumb IT breakpoints?
341                     DNBBreakpoint *step_bp = m_thread->Process()->Breakpoints().FindByAddress(m_state.context.gpr.__pc);
342 
343                     if (step_bp)
344                     {
345                         // We did hit our breakpoint, tell the breakpoint it was
346                         // hit so that it can run its callback routine and fixup
347                         // the PC.
348                         DNBLogThreadedIf(LOG_STEP, "%s: IT software single step breakpoint hit (breakID=%u)", __FUNCTION__, step_bp->GetID());
349                         step_bp->BreakpointHit(m_thread->Process()->ProcessID(), m_thread->ThreadID());
350                     }
351 
352                     // Remove all Thumb IT breakpoints
353                     for (int i = 0; i < m_sw_single_step_itblock_break_count; i++)
354                     {
355                         if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i]))
356                         {
357                             DNBLogThreadedIf(LOG_STEP, "%s: removing IT software single step breakpoint (breakID=%d)", __FUNCTION__, m_sw_single_step_itblock_break_id[i]);
358                             success = m_thread->Process()->DisableBreakpoint(m_sw_single_step_itblock_break_id[i], true);
359                             m_sw_single_step_itblock_break_id[i] = INVALID_NUB_BREAK_ID;
360                         }
361                     }
362                     m_sw_single_step_itblock_break_count = 0;
363 
364                     // Decode instructions up to the current PC to ensure the internal decoder state is valid for the IT block
365                     // The decoder has to decode each instruction in the IT block even if it is not executed so that
366                     // the fields are correctly updated
367                     DecodeITBlockInstructions(m_state.context.gpr.__pc);
368                 }
369 
370             }
371             else
372                 success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
373 #endif
374         }
375         else
376         {
377             // The MachThread will automatically restore the suspend count
378             // in ThreadDidStop(), so we don't need to do anything here if
379             // we weren't the primary thread the last time
380         }
381     }
382     return success;
383 }
384 
385 bool
386 DNBArchMachARM::StepNotComplete ()
387 {
388     if (m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS)
389     {
390         kern_return_t kret = KERN_INVALID_ARGUMENT;
391         kret = GetGPRState(false);
392         if (kret == KERN_SUCCESS)
393         {
394             if (m_state.context.gpr.__pc == m_hw_single_chained_step_addr)
395             {
396                 DNBLogThreadedIf(LOG_STEP, "Need to step some more at 0x%8.8x", m_hw_single_chained_step_addr);
397                 return true;
398             }
399         }
400     }
401 
402     m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS;
403     return false;
404 }
405 
406 
407 void
408 DNBArchMachARM::DecodeITBlockInstructions(nub_addr_t curr_pc)
409 
410 {
411     uint16_t opcode16;
412     uint32_t opcode32;
413     nub_addr_t next_pc_in_itblock;
414     nub_addr_t pc_in_itblock = m_last_decode_pc;
415 
416     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: last_decode_pc=0x%8.8x", __FUNCTION__, m_last_decode_pc);
417 
418     // Decode IT block instruction from the instruction following the m_last_decoded_instruction at
419     // PC m_last_decode_pc upto and including the instruction at curr_pc
420     if (m_thread->Process()->Task().ReadMemory(pc_in_itblock, 2, &opcode16) == 2)
421     {
422         opcode32 = opcode16;
423         pc_in_itblock += 2;
424         // Check for 32 bit thumb opcode and read the upper 16 bits if needed
425         if (((opcode32 & 0xE000) == 0xE000) && opcode32 & 0x1800)
426         {
427             // Adjust 'next_pc_in_itblock' to point to the default next Thumb instruction for
428             // a 32 bit Thumb opcode
429             // Read bits 31:16 of a 32 bit Thumb opcode
430             if (m_thread->Process()->Task().ReadMemory(pc_in_itblock, 2, &opcode16) == 2)
431             {
432                 pc_in_itblock += 2;
433                 // 32 bit thumb opcode
434                 opcode32 = (opcode32 << 16) | opcode16;
435             }
436             else
437             {
438                 DNBLogError("%s: Unable to read opcode bits 31:16 for a 32 bit thumb opcode at pc=0x%8.8lx", __FUNCTION__, pc_in_itblock);
439             }
440         }
441     }
442     else
443     {
444         DNBLogError("%s: Error reading 16-bit Thumb instruction at pc=0x%8.8x", __FUNCTION__, pc_in_itblock);
445     }
446 
447     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: pc_in_itblock=0x%8.8x, curr_pc=0x%8.8x", __FUNCTION__, pc_in_itblock, curr_pc);
448 
449     next_pc_in_itblock = pc_in_itblock;
450     while (next_pc_in_itblock <= curr_pc)
451     {
452         arm_error_t decodeError;
453 
454         m_last_decode_pc = pc_in_itblock;
455         decodeError = DecodeInstructionUsingDisassembler(pc_in_itblock, m_state.context.gpr.__cpsr, &m_last_decode_arm, &m_last_decode_thumb, &next_pc_in_itblock);
456 
457         pc_in_itblock = next_pc_in_itblock;
458         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: next_pc_in_itblock=0x%8.8x", __FUNCTION__, next_pc_in_itblock);
459     }
460 }
461 
462 
463 // Set the single step bit in the processor status register.
464 kern_return_t
465 DNBArchMachARM::EnableHardwareSingleStep (bool enable)
466 {
467     DNBError err;
468     DNBLogThreadedIf(LOG_STEP, "%s( enable = %d )", __FUNCTION__, enable);
469 
470     err = GetGPRState(false);
471 
472     if (err.Fail())
473     {
474         err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__);
475         return err.Error();
476     }
477 
478     err = GetDBGState(false);
479 
480     if (err.Fail())
481     {
482         err.LogThreaded("%s: failed to read the DBG registers", __FUNCTION__);
483         return err.Error();
484     }
485 
486     const uint32_t i = 0;
487     if (enable)
488     {
489         m_hw_single_chained_step_addr = INVALID_NUB_ADDRESS;
490 
491         // Save our previous state
492         m_dbg_save = m_state.dbg;
493         // Set a breakpoint that will stop when the PC doesn't match the current one!
494         m_state.dbg.__bvr[i] = m_state.context.gpr.__pc & 0xFFFFFFFCu;      // Set the current PC as the breakpoint address
495         m_state.dbg.__bcr[i] = BCR_M_IMVA_MISMATCH |    // Stop on address mismatch
496                                S_USER |                 // Stop only in user mode
497                                BCR_ENABLE;              // Enable this breakpoint
498         if (m_state.context.gpr.__cpsr & 0x20)
499         {
500             // Thumb breakpoint
501             if (m_state.context.gpr.__pc & 2)
502                 m_state.dbg.__bcr[i] |= BAS_IMVA_2_3;
503             else
504                 m_state.dbg.__bcr[i] |= BAS_IMVA_0_1;
505 
506             uint16_t opcode;
507             if (sizeof(opcode) == m_thread->Process()->Task().ReadMemory(m_state.context.gpr.__pc, sizeof(opcode), &opcode))
508             {
509                 if (((opcode & 0xE000) == 0xE000) && opcode & 0x1800)
510                 {
511                     // 32 bit thumb opcode...
512                     if (m_state.context.gpr.__pc & 2)
513                     {
514                         // We can't take care of a 32 bit thumb instruction single step
515                         // with just IVA mismatching. We will need to chain an extra
516                         // hardware single step in order to complete this single step...
517                         m_hw_single_chained_step_addr = m_state.context.gpr.__pc + 2;
518                     }
519                     else
520                     {
521                         // Extend the number of bits to ignore for the mismatch
522                         m_state.dbg.__bcr[i] |= BAS_IMVA_ALL;
523                     }
524                 }
525             }
526         }
527         else
528         {
529             // ARM breakpoint
530             m_state.dbg.__bcr[i] |= BAS_IMVA_ALL; // Stop when any address bits change
531         }
532 
533         DNBLogThreadedIf(LOG_STEP, "%s: BVR%u=0x%8.8x  BCR%u=0x%8.8x", __FUNCTION__, i, m_state.dbg.__bvr[i], i, m_state.dbg.__bcr[i]);
534 
535         for (uint32_t j=i+1; j<16; ++j)
536         {
537             // Disable all others
538             m_state.dbg.__bvr[j] = 0;
539             m_state.dbg.__bcr[j] = 0;
540         }
541     }
542     else
543     {
544         // Just restore the state we had before we did single stepping
545         m_state.dbg = m_dbg_save;
546     }
547 
548     return SetDBGState();
549 }
550 
551 // return 1 if bit "BIT" is set in "value"
552 static inline uint32_t bit(uint32_t value, uint32_t bit)
553 {
554     return (value >> bit) & 1u;
555 }
556 
557 // return the bitfield "value[msbit:lsbit]".
558 static inline uint32_t bits(uint32_t value, uint32_t msbit, uint32_t lsbit)
559 {
560     assert(msbit >= lsbit);
561     uint32_t shift_left = sizeof(value) * 8 - 1 - msbit;
562     value <<= shift_left;           // shift anything above the msbit off of the unsigned edge
563     value >>= shift_left + lsbit;   // shift it back again down to the lsbit (including undoing any shift from above)
564     return value;                   // return our result
565 }
566 
567 bool
568 DNBArchMachARM::ConditionPassed(uint8_t condition, uint32_t cpsr)
569 {
570     uint32_t cpsr_n = bit(cpsr, 31); // Negative condition code flag
571     uint32_t cpsr_z = bit(cpsr, 30); // Zero condition code flag
572     uint32_t cpsr_c = bit(cpsr, 29); // Carry condition code flag
573     uint32_t cpsr_v = bit(cpsr, 28); // Overflow condition code flag
574 
575     switch (condition) {
576         case COND_EQ: // (0x0)
577             if (cpsr_z == 1) return true;
578             break;
579         case COND_NE: // (0x1)
580             if (cpsr_z == 0) return true;
581             break;
582         case COND_CS: // (0x2)
583             if (cpsr_c == 1) return true;
584             break;
585         case COND_CC: // (0x3)
586             if (cpsr_c == 0) return true;
587             break;
588         case COND_MI: // (0x4)
589             if (cpsr_n == 1) return true;
590             break;
591         case COND_PL: // (0x5)
592             if (cpsr_n == 0) return true;
593             break;
594         case COND_VS: // (0x6)
595             if (cpsr_v == 1) return true;
596             break;
597         case COND_VC: // (0x7)
598             if (cpsr_v == 0) return true;
599             break;
600         case COND_HI: // (0x8)
601             if ((cpsr_c == 1) && (cpsr_z == 0)) return true;
602             break;
603         case COND_LS: // (0x9)
604             if ((cpsr_c == 0) || (cpsr_z == 1)) return true;
605             break;
606         case COND_GE: // (0xA)
607             if (cpsr_n == cpsr_v) return true;
608             break;
609         case COND_LT: // (0xB)
610             if (cpsr_n != cpsr_v) return true;
611             break;
612         case COND_GT: // (0xC)
613             if ((cpsr_z == 0) && (cpsr_n == cpsr_v)) return true;
614             break;
615         case COND_LE: // (0xD)
616             if ((cpsr_z == 1) || (cpsr_n != cpsr_v)) return true;
617             break;
618         default:
619             return true;
620             break;
621     }
622 
623     return false;
624 }
625 
626 bool
627 DNBArchMachARM::ComputeNextPC(nub_addr_t currentPC, arm_decoded_instruction_t decodedInstruction, bool currentPCIsThumb, nub_addr_t *targetPC)
628 {
629     nub_addr_t myTargetPC, addressWherePCLives;
630     pid_t mypid;
631 
632     uint32_t cpsr_c = bit(m_state.context.gpr.__cpsr, 29); // Carry condition code flag
633 
634     uint32_t firstOperand=0, secondOperand=0, shiftAmount=0, secondOperandAfterShift=0, immediateValue=0;
635     uint32_t halfwords=0, baseAddress=0, immediateOffset=0, addressOffsetFromRegister=0, addressOffsetFromRegisterAfterShift;
636     uint32_t baseAddressIndex=INVALID_NUB_HW_INDEX;
637     uint32_t firstOperandIndex=INVALID_NUB_HW_INDEX;
638     uint32_t secondOperandIndex=INVALID_NUB_HW_INDEX;
639     uint32_t addressOffsetFromRegisterIndex=INVALID_NUB_HW_INDEX;
640     uint32_t shiftRegisterIndex=INVALID_NUB_HW_INDEX;
641     uint16_t registerList16, registerList16NoPC;
642     uint8_t registerList8;
643     uint32_t numRegistersToLoad=0;
644 
645     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: instruction->code=%d", __FUNCTION__, decodedInstruction.instruction->code);
646 
647     // Get the following in this switch statement:
648     //   - firstOperand, secondOperand, immediateValue, shiftAmount: For arithmetic, logical and move instructions
649     //   - baseAddress, immediateOffset, shiftAmount: For LDR
650     //   - numRegistersToLoad: For LDM and POP instructions
651     switch (decodedInstruction.instruction->code)
652     {
653             // Arithmetic operations that can change the PC
654         case ARM_INST_ADC:
655         case ARM_INST_ADCS:
656         case ARM_INST_ADD:
657         case ARM_INST_ADDS:
658         case ARM_INST_AND:
659         case ARM_INST_ANDS:
660         case ARM_INST_ASR:
661         case ARM_INST_ASRS:
662         case ARM_INST_BIC:
663         case ARM_INST_BICS:
664         case ARM_INST_EOR:
665         case ARM_INST_EORS:
666         case ARM_INST_ORR:
667         case ARM_INST_ORRS:
668         case ARM_INST_RSB:
669         case ARM_INST_RSBS:
670         case ARM_INST_RSC:
671         case ARM_INST_RSCS:
672         case ARM_INST_SBC:
673         case ARM_INST_SBCS:
674         case ARM_INST_SUB:
675         case ARM_INST_SUBS:
676             switch (decodedInstruction.addressMode)
677             {
678                 case ARM_ADDR_DATA_IMM:
679                     if (decodedInstruction.numOperands != 3)
680                     {
681                         DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
682                         return false;
683                     }
684 
685                     if (decodedInstruction.op[0].value != PC_REG)
686                     {
687                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
688                         return false;
689                     }
690 
691                     // Get firstOperand register value (at index=1)
692                     firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
693                     firstOperand = m_state.context.gpr.__r[firstOperandIndex];
694 
695                     // Get immediateValue (at index=2)
696                     immediateValue = decodedInstruction.op[2].value;
697 
698                     break;
699 
700                 case ARM_ADDR_DATA_REG:
701                     if (decodedInstruction.numOperands != 3)
702                     {
703                         DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
704                         return false;
705                     }
706 
707                     if (decodedInstruction.op[0].value != PC_REG)
708                     {
709                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
710                         return false;
711                     }
712 
713                     // Get firstOperand register value (at index=1)
714                     firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
715                     firstOperand = m_state.context.gpr.__r[firstOperandIndex];
716 
717                     // Get secondOperand register value (at index=2)
718                     secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
719                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
720 
721                     break;
722 
723                 case ARM_ADDR_DATA_SCALED_IMM:
724                     if (decodedInstruction.numOperands != 4)
725                     {
726                         DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
727                         return false;
728                     }
729 
730                     if (decodedInstruction.op[0].value != PC_REG)
731                     {
732                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
733                         return false;
734                     }
735 
736                     // Get firstOperand register value (at index=1)
737                     firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
738                     firstOperand = m_state.context.gpr.__r[firstOperandIndex];
739 
740                     // Get secondOperand register value (at index=2)
741                     secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
742                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
743 
744                     // Get shiftAmount as immediate value (at index=3)
745                     shiftAmount = decodedInstruction.op[3].value;
746 
747                     break;
748 
749 
750                 case ARM_ADDR_DATA_SCALED_REG:
751                     if (decodedInstruction.numOperands != 4)
752                     {
753                         DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
754                         return false;
755                     }
756 
757                     if (decodedInstruction.op[0].value != PC_REG)
758                     {
759                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
760                         return false;
761                     }
762 
763                     // Get firstOperand register value (at index=1)
764                     firstOperandIndex = decodedInstruction.op[1].value; // first operand register index
765                     firstOperand = m_state.context.gpr.__r[firstOperandIndex];
766 
767                     // Get secondOperand register value (at index=2)
768                     secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
769                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
770 
771                     // Get shiftAmount from register (at index=3)
772                     shiftRegisterIndex = decodedInstruction.op[3].value; // second operand register index
773                     shiftAmount = m_state.context.gpr.__r[shiftRegisterIndex];
774 
775                     break;
776 
777                 case THUMB_ADDR_HR_HR:
778                     if (decodedInstruction.numOperands != 2)
779                     {
780                         DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
781                         return false;
782                     }
783 
784                     if (decodedInstruction.op[0].value != PC_REG)
785                     {
786                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
787                         return false;
788                     }
789 
790                     // Get firstOperand register value (at index=0)
791                     firstOperandIndex = decodedInstruction.op[0].value; // first operand register index
792                     firstOperand = m_state.context.gpr.__r[firstOperandIndex];
793 
794                     // Get secondOperand register value (at index=1)
795                     secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
796                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
797 
798                     break;
799 
800                 default:
801                     break;
802             }
803             break;
804 
805             // Logical shifts and move operations that can change the PC
806         case ARM_INST_LSL:
807         case ARM_INST_LSLS:
808         case ARM_INST_LSR:
809         case ARM_INST_LSRS:
810         case ARM_INST_MOV:
811         case ARM_INST_MOVS:
812         case ARM_INST_MVN:
813         case ARM_INST_MVNS:
814         case ARM_INST_ROR:
815         case ARM_INST_RORS:
816         case ARM_INST_RRX:
817         case ARM_INST_RRXS:
818             // In these cases, the firstOperand is always 0, as if it does not exist
819             switch (decodedInstruction.addressMode)
820             {
821                 case ARM_ADDR_DATA_IMM:
822                     if (decodedInstruction.numOperands != 2)
823                     {
824                         DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
825                         return false;
826                     }
827 
828                     if (decodedInstruction.op[0].value != PC_REG)
829                     {
830                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
831                         return false;
832                     }
833 
834                     // Get immediateValue (at index=1)
835                     immediateValue = decodedInstruction.op[1].value;
836 
837                     break;
838 
839                 case ARM_ADDR_DATA_REG:
840                     if (decodedInstruction.numOperands != 2)
841                     {
842                         DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
843                         return false;
844                     }
845 
846                     if (decodedInstruction.op[0].value != PC_REG)
847                     {
848                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
849                         return false;
850                     }
851 
852                     // Get secondOperand register value (at index=1)
853                     secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
854                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
855 
856                     break;
857 
858                 case ARM_ADDR_DATA_SCALED_IMM:
859                     if (decodedInstruction.numOperands != 3)
860                     {
861                         DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
862                         return false;
863                     }
864 
865                     if (decodedInstruction.op[0].value != PC_REG)
866                     {
867                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
868                         return false;
869                     }
870 
871                     // Get secondOperand register value (at index=1)
872                     secondOperandIndex = decodedInstruction.op[2].value; // second operand register index
873                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
874 
875                     // Get shiftAmount as immediate value (at index=2)
876                     shiftAmount = decodedInstruction.op[2].value;
877 
878                     break;
879 
880 
881                 case ARM_ADDR_DATA_SCALED_REG:
882                     if (decodedInstruction.numOperands != 3)
883                     {
884                         DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
885                         return false;
886                     }
887 
888                     if (decodedInstruction.op[0].value != PC_REG)
889                     {
890                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
891                         return false;
892                     }
893 
894                     // Get secondOperand register value (at index=1)
895                     secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
896                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
897 
898                     // Get shiftAmount from register (at index=2)
899                     shiftRegisterIndex = decodedInstruction.op[2].value; // second operand register index
900                     shiftAmount = m_state.context.gpr.__r[shiftRegisterIndex];
901 
902                     break;
903 
904                 case THUMB_ADDR_HR_HR:
905                     if (decodedInstruction.numOperands != 2)
906                     {
907                         DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
908                         return false;
909                     }
910 
911                     if (decodedInstruction.op[0].value != PC_REG)
912                     {
913                         DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
914                         return false;
915                     }
916 
917                     // Get secondOperand register value (at index=1)
918                     secondOperandIndex = decodedInstruction.op[1].value; // second operand register index
919                     secondOperand = m_state.context.gpr.__r[secondOperandIndex];
920 
921                     break;
922 
923                 default:
924                     break;
925             }
926 
927             break;
928 
929             // Simple branches, used to hop around within a routine
930         case ARM_INST_B:
931             *targetPC = decodedInstruction.targetPC; // Known targetPC
932             return true;
933             break;
934 
935             // Branch-and-link, used to call ARM subroutines
936         case ARM_INST_BL:
937             *targetPC = decodedInstruction.targetPC; // Known targetPC
938             return true;
939             break;
940 
941             // Branch-and-link with exchange, used to call opposite-mode subroutines
942         case ARM_INST_BLX:
943             if ((decodedInstruction.addressMode == ARM_ADDR_BRANCH_IMM) ||
944                 (decodedInstruction.addressMode == THUMB_ADDR_UNCOND))
945             {
946                 *targetPC = decodedInstruction.targetPC; // Known targetPC
947                 return true;
948             }
949             else    // addressMode == ARM_ADDR_BRANCH_REG
950             {
951                 // Unknown target unless we're branching to the PC itself,
952                 //  although this may not work properly with BLX
953                 if (decodedInstruction.op[REG_RD].value == PC_REG)
954                 {
955                     // this should (almost) never happen
956                     *targetPC = decodedInstruction.targetPC; // Known targetPC
957                     return true;
958                 }
959 
960                 // Get the branch address and return
961                 if (decodedInstruction.numOperands != 1)
962                 {
963                     DNBLogError("Expected 1 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
964                     return false;
965                 }
966 
967                 // Get branch address in register (at index=0)
968                 *targetPC = m_state.context.gpr.__r[decodedInstruction.op[0].value];
969                 return true;
970             }
971             break;
972 
973             // Branch with exchange, used to hop to opposite-mode code
974             // Branch to Jazelle code, used to execute Java; included here since it
975             //  acts just like BX unless the Jazelle unit is active and JPC is
976             //  already loaded into it.
977         case ARM_INST_BX:
978         case ARM_INST_BXJ:
979             // Unknown target unless we're branching to the PC itself,
980             //  although this can never switch to Thumb mode and is
981             //  therefore pretty much useless
982             if (decodedInstruction.op[REG_RD].value == PC_REG)
983             {
984                 // this should (almost) never happen
985                 *targetPC = decodedInstruction.targetPC; // Known targetPC
986                 return true;
987             }
988 
989             // Get the branch address and return
990             if (decodedInstruction.numOperands != 1)
991             {
992                 DNBLogError("Expected 1 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
993                 return false;
994             }
995 
996             // Get branch address in register (at index=0)
997             *targetPC = m_state.context.gpr.__r[decodedInstruction.op[0].value];
998             return true;
999             break;
1000 
1001             // Compare and branch on zero/non-zero (Thumb-16 only)
1002             // Unusual condition check built into the instruction
1003         case ARM_INST_CBZ:
1004         case ARM_INST_CBNZ:
1005             // Branch address is known at compile time
1006             // Get the branch address and return
1007             if (decodedInstruction.numOperands != 2)
1008             {
1009                 DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1010                 return false;
1011             }
1012 
1013             // Get branch address as an immediate value (at index=1)
1014             *targetPC = decodedInstruction.op[1].value;
1015             return true;
1016             break;
1017 
1018             // Load register can be used to load PC, usually with a function pointer
1019         case ARM_INST_LDR:
1020             if (decodedInstruction.op[REG_RD].value != PC_REG)
1021             {
1022                 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
1023                 return false;
1024             }
1025             switch (decodedInstruction.addressMode)
1026             {
1027                 case ARM_ADDR_LSWUB_IMM:
1028                 case ARM_ADDR_LSWUB_IMM_PRE:
1029                 case ARM_ADDR_LSWUB_IMM_POST:
1030                     if (decodedInstruction.numOperands != 3)
1031                     {
1032                         DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1033                         return false;
1034                     }
1035 
1036                     // Get baseAddress from register (at index=1)
1037                     baseAddressIndex = decodedInstruction.op[1].value;
1038                     baseAddress = m_state.context.gpr.__r[baseAddressIndex];
1039 
1040                     // Get immediateOffset (at index=2)
1041                     immediateOffset = decodedInstruction.op[2].value;
1042                     break;
1043 
1044                 case ARM_ADDR_LSWUB_REG:
1045                 case ARM_ADDR_LSWUB_REG_PRE:
1046                 case ARM_ADDR_LSWUB_REG_POST:
1047                     if (decodedInstruction.numOperands != 3)
1048                     {
1049                         DNBLogError("Expected 3 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1050                         return false;
1051                     }
1052 
1053                     // Get baseAddress from register (at index=1)
1054                     baseAddressIndex = decodedInstruction.op[1].value;
1055                     baseAddress = m_state.context.gpr.__r[baseAddressIndex];
1056 
1057                     // Get immediateOffset from register (at index=2)
1058                     addressOffsetFromRegisterIndex = decodedInstruction.op[2].value;
1059                     addressOffsetFromRegister = m_state.context.gpr.__r[addressOffsetFromRegisterIndex];
1060 
1061                     break;
1062 
1063                 case ARM_ADDR_LSWUB_SCALED:
1064                 case ARM_ADDR_LSWUB_SCALED_PRE:
1065                 case ARM_ADDR_LSWUB_SCALED_POST:
1066                     if (decodedInstruction.numOperands != 4)
1067                     {
1068                         DNBLogError("Expected 4 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1069                         return false;
1070                     }
1071 
1072                     // Get baseAddress from register (at index=1)
1073                     baseAddressIndex = decodedInstruction.op[1].value;
1074                     baseAddress = m_state.context.gpr.__r[baseAddressIndex];
1075 
1076                     // Get immediateOffset from register (at index=2)
1077                     addressOffsetFromRegisterIndex = decodedInstruction.op[2].value;
1078                     addressOffsetFromRegister = m_state.context.gpr.__r[addressOffsetFromRegisterIndex];
1079 
1080                     // Get shiftAmount (at index=3)
1081                     shiftAmount = decodedInstruction.op[3].value;
1082 
1083                     break;
1084 
1085                 default:
1086                     break;
1087             }
1088             break;
1089 
1090             // 32b load multiple operations can load the PC along with everything else,
1091             //  usually to return from a function call
1092         case ARM_INST_LDMDA:
1093         case ARM_INST_LDMDB:
1094         case ARM_INST_LDMIA:
1095         case ARM_INST_LDMIB:
1096             if (decodedInstruction.op[LDM_REGLIST].value & PC_REGLIST_BIT)
1097             {
1098                 if (decodedInstruction.numOperands != 2)
1099                 {
1100                     DNBLogError("Expected 2 operands in decoded instruction structure. numOperands is %d!", decodedInstruction.numOperands);
1101                     return false;
1102                 }
1103 
1104                 // Get baseAddress from register (at index=0)
1105                 baseAddressIndex = decodedInstruction.op[0].value;
1106                 baseAddress = m_state.context.gpr.__r[baseAddressIndex];
1107 
1108                 // Get registerList from register (at index=1)
1109                 registerList16 = (uint16_t)decodedInstruction.op[1].value;
1110 
1111                 // Count number of registers to load in the multiple register list excluding the PC
1112                 registerList16NoPC = registerList16&0x3FFF; // exclude the PC
1113                 numRegistersToLoad=0;
1114                 for (int i = 0; i < 16; i++)
1115                 {
1116                     if (registerList16NoPC & 0x1) numRegistersToLoad++;
1117                     registerList16NoPC = registerList16NoPC >> 1;
1118                 }
1119             }
1120             else
1121             {
1122                 DNBLogError("Destination register is not a PC! %s routine should be called on on instructions that modify the PC. Destination register is R%d!", __FUNCTION__, decodedInstruction.op[0].value);
1123                 return false;
1124             }
1125             break;
1126 
1127             // Normal 16-bit LD multiple can't touch R15, but POP can
1128         case ARM_INST_POP:  // Can also get the PC & updates SP
1129             // Get baseAddress from SP (at index=0)
1130             baseAddress = m_state.context.gpr.__sp;
1131 
1132             if (decodedInstruction.thumb16b)
1133             {
1134                 // Get registerList from register (at index=0)
1135                 registerList8 = (uint8_t)decodedInstruction.op[0].value;
1136 
1137                 // Count number of registers to load in the multiple register list
1138                 numRegistersToLoad=0;
1139                 for (int i = 0; i < 8; i++)
1140                 {
1141                     if (registerList8 & 0x1) numRegistersToLoad++;
1142                     registerList8 = registerList8 >> 1;
1143                 }
1144             }
1145             else
1146             {
1147                 // Get registerList from register (at index=0)
1148                 registerList16 = (uint16_t)decodedInstruction.op[0].value;
1149 
1150                 // Count number of registers to load in the multiple register list excluding the PC
1151                 registerList16NoPC = registerList16&0x3FFF; // exclude the PC
1152                 numRegistersToLoad=0;
1153                 for (int i = 0; i < 16; i++)
1154                 {
1155                     if (registerList16NoPC & 0x1) numRegistersToLoad++;
1156                     registerList16NoPC = registerList16NoPC >> 1;
1157                 }
1158             }
1159             break;
1160 
1161             // 16b TBB and TBH instructions load a jump address from a table
1162         case ARM_INST_TBB:
1163         case ARM_INST_TBH:
1164             // Get baseAddress from register (at index=0)
1165             baseAddressIndex = decodedInstruction.op[0].value;
1166             baseAddress = m_state.context.gpr.__r[baseAddressIndex];
1167 
1168             // Get immediateOffset from register (at index=1)
1169             addressOffsetFromRegisterIndex = decodedInstruction.op[1].value;
1170             addressOffsetFromRegister = m_state.context.gpr.__r[addressOffsetFromRegisterIndex];
1171             break;
1172 
1173             // ThumbEE branch-to-handler instructions: Jump to handlers at some offset
1174             //  from a special base pointer register (which is unknown at disassembly time)
1175         case ARM_INST_HB:
1176         case ARM_INST_HBP:
1177 //          TODO: ARM_INST_HB, ARM_INST_HBP
1178             break;
1179 
1180         case ARM_INST_HBL:
1181         case ARM_INST_HBLP:
1182 //          TODO: ARM_INST_HBL, ARM_INST_HBLP
1183             break;
1184 
1185             // Breakpoint and software interrupt jump to interrupt handler (always ARM)
1186         case ARM_INST_BKPT:
1187         case ARM_INST_SMC:
1188         case ARM_INST_SVC:
1189 
1190             // Return from exception, obviously modifies PC [interrupt only!]
1191         case ARM_INST_RFEDA:
1192         case ARM_INST_RFEDB:
1193         case ARM_INST_RFEIA:
1194         case ARM_INST_RFEIB:
1195 
1196             // Other instructions either can't change R15 or are "undefined" if you do,
1197             //  so no sane compiler should ever generate them & we don't care here.
1198             //  Also, R15 can only legally be used in a read-only manner for the
1199             //  various ARM addressing mode (to get PC-relative addressing of constants),
1200             //  but can NOT be used with any of the update modes.
1201         default:
1202             DNBLogError("%s should not be called for instruction code %d!", __FUNCTION__, decodedInstruction.instruction->code);
1203             return false;
1204             break;
1205     }
1206 
1207     // Adjust PC if PC is one of the input operands
1208     if (baseAddressIndex == PC_REG)
1209     {
1210         if (currentPCIsThumb)
1211             baseAddress += 4;
1212         else
1213             baseAddress += 8;
1214     }
1215 
1216     if (firstOperandIndex == PC_REG)
1217     {
1218         if (currentPCIsThumb)
1219             firstOperand += 4;
1220         else
1221             firstOperand += 8;
1222     }
1223 
1224     if (secondOperandIndex == PC_REG)
1225     {
1226         if (currentPCIsThumb)
1227             secondOperand += 4;
1228         else
1229             secondOperand += 8;
1230     }
1231 
1232     if (addressOffsetFromRegisterIndex == PC_REG)
1233     {
1234         if (currentPCIsThumb)
1235             addressOffsetFromRegister += 4;
1236         else
1237             addressOffsetFromRegister += 8;
1238     }
1239 
1240     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE,
1241         "%s: firstOperand=%8.8x, secondOperand=%8.8x, immediateValue = %d, shiftAmount = %d, baseAddress = %8.8x, addressOffsetFromRegister = %8.8x, immediateOffset = %d, numRegistersToLoad = %d",
1242         __FUNCTION__,
1243         firstOperand,
1244         secondOperand,
1245         immediateValue,
1246         shiftAmount,
1247         baseAddress,
1248         addressOffsetFromRegister,
1249         immediateOffset,
1250         numRegistersToLoad);
1251 
1252 
1253     // Calculate following values after applying shiftAmount:
1254     //   - immediateOffsetAfterShift, secondOperandAfterShift
1255 
1256     switch (decodedInstruction.scaleMode)
1257     {
1258         case ARM_SCALE_NONE:
1259             addressOffsetFromRegisterAfterShift = addressOffsetFromRegister;
1260             secondOperandAfterShift = secondOperand;
1261             break;
1262 
1263         case ARM_SCALE_LSL:             // Logical shift left
1264             addressOffsetFromRegisterAfterShift = addressOffsetFromRegister << shiftAmount;
1265             secondOperandAfterShift = secondOperand << shiftAmount;
1266             break;
1267 
1268         case ARM_SCALE_LSR:             // Logical shift right
1269             addressOffsetFromRegisterAfterShift = addressOffsetFromRegister >> shiftAmount;
1270             secondOperandAfterShift = secondOperand >> shiftAmount;
1271             break;
1272 
1273         case ARM_SCALE_ASR:             // Arithmetic shift right
1274             asm("mov %0, %1, asr %2" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister), "r" (shiftAmount));
1275             asm("mov %0, %1, asr %2" : "=r" (secondOperandAfterShift) : "r" (secondOperand), "r" (shiftAmount));
1276             break;
1277 
1278         case ARM_SCALE_ROR:             // Rotate right
1279             asm("mov %0, %1, ror %2" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister), "r" (shiftAmount));
1280             asm("mov %0, %1, ror %2" : "=r" (secondOperandAfterShift) : "r" (secondOperand), "r" (shiftAmount));
1281             break;
1282 
1283         case ARM_SCALE_RRX:             // Rotate right, pulling in carry (1-bit shift only)
1284             asm("mov %0, %1, rrx" : "=r" (addressOffsetFromRegisterAfterShift) : "r" (addressOffsetFromRegister));
1285             asm("mov %0, %1, rrx" : "=r" (secondOperandAfterShift) : "r" (secondOperand));
1286             break;
1287     }
1288 
1289     // Emulate instruction to calculate targetPC
1290     // All branches are already handled in the first switch statement. A branch should not reach this switch
1291     switch (decodedInstruction.instruction->code)
1292     {
1293             // Arithmetic operations that can change the PC
1294         case ARM_INST_ADC:
1295         case ARM_INST_ADCS:
1296             // Add with Carry
1297             *targetPC = firstOperand + (secondOperandAfterShift + immediateValue) + cpsr_c;
1298             break;
1299 
1300         case ARM_INST_ADD:
1301         case ARM_INST_ADDS:
1302             *targetPC = firstOperand + (secondOperandAfterShift + immediateValue);
1303             break;
1304 
1305         case ARM_INST_AND:
1306         case ARM_INST_ANDS:
1307             *targetPC = firstOperand & (secondOperandAfterShift + immediateValue);
1308             break;
1309 
1310         case ARM_INST_ASR:
1311         case ARM_INST_ASRS:
1312             asm("mov %0, %1, asr %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1313             *targetPC = myTargetPC;
1314             break;
1315 
1316         case ARM_INST_BIC:
1317         case ARM_INST_BICS:
1318             asm("bic %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1319             *targetPC = myTargetPC;
1320             break;
1321 
1322         case ARM_INST_EOR:
1323         case ARM_INST_EORS:
1324             asm("eor %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1325             *targetPC = myTargetPC;
1326             break;
1327 
1328         case ARM_INST_ORR:
1329         case ARM_INST_ORRS:
1330             asm("orr %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1331             *targetPC = myTargetPC;
1332             break;
1333 
1334         case ARM_INST_RSB:
1335         case ARM_INST_RSBS:
1336             asm("rsb %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1337             *targetPC = myTargetPC;
1338             break;
1339 
1340         case ARM_INST_RSC:
1341         case ARM_INST_RSCS:
1342             myTargetPC = secondOperandAfterShift - (firstOperand + !cpsr_c);
1343             *targetPC = myTargetPC;
1344             break;
1345 
1346         case ARM_INST_SBC:
1347         case ARM_INST_SBCS:
1348             asm("sbc %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue  + !cpsr_c));
1349             *targetPC = myTargetPC;
1350             break;
1351 
1352         case ARM_INST_SUB:
1353         case ARM_INST_SUBS:
1354             asm("sub %0, %1, %2" : "=r" (myTargetPC) : "r" (firstOperand), "r" (secondOperandAfterShift + immediateValue));
1355             *targetPC = myTargetPC;
1356             break;
1357 
1358             // Logical shifts and move operations that can change the PC
1359         case ARM_INST_LSL:
1360         case ARM_INST_LSLS:
1361         case ARM_INST_LSR:
1362         case ARM_INST_LSRS:
1363         case ARM_INST_MOV:
1364         case ARM_INST_MOVS:
1365         case ARM_INST_ROR:
1366         case ARM_INST_RORS:
1367         case ARM_INST_RRX:
1368         case ARM_INST_RRXS:
1369             myTargetPC = secondOperandAfterShift + immediateValue;
1370             *targetPC = myTargetPC;
1371             break;
1372 
1373         case ARM_INST_MVN:
1374         case ARM_INST_MVNS:
1375             myTargetPC = !(secondOperandAfterShift + immediateValue);
1376             *targetPC = myTargetPC;
1377             break;
1378 
1379             // Load register can be used to load PC, usually with a function pointer
1380         case ARM_INST_LDR:
1381             switch (decodedInstruction.addressMode) {
1382                 case ARM_ADDR_LSWUB_IMM_POST:
1383                 case ARM_ADDR_LSWUB_REG_POST:
1384                 case ARM_ADDR_LSWUB_SCALED_POST:
1385                     addressWherePCLives = baseAddress;
1386                     break;
1387 
1388                 case ARM_ADDR_LSWUB_IMM:
1389                 case ARM_ADDR_LSWUB_REG:
1390                 case ARM_ADDR_LSWUB_SCALED:
1391                 case ARM_ADDR_LSWUB_IMM_PRE:
1392                 case ARM_ADDR_LSWUB_REG_PRE:
1393                 case ARM_ADDR_LSWUB_SCALED_PRE:
1394                     addressWherePCLives = baseAddress + (addressOffsetFromRegisterAfterShift + immediateOffset);
1395                     break;
1396 
1397                 default:
1398                     break;
1399             }
1400 
1401             mypid = m_thread->ProcessID();
1402             if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) !=  sizeof(nub_addr_t))
1403             {
1404                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
1405                 return false;
1406             }
1407 
1408             *targetPC = myTargetPC;
1409             break;
1410 
1411             // 32b load multiple operations can load the PC along with everything else,
1412             //  usually to return from a function call
1413         case ARM_INST_LDMDA:
1414             mypid = m_thread->ProcessID();
1415             addressWherePCLives = baseAddress;
1416             if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) !=  sizeof(nub_addr_t))
1417             {
1418                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
1419                 return false;
1420             }
1421 
1422             *targetPC = myTargetPC;
1423             break;
1424 
1425         case ARM_INST_LDMDB:
1426             mypid = m_thread->ProcessID();
1427             addressWherePCLives = baseAddress - 4;
1428             if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) !=  sizeof(nub_addr_t))
1429             {
1430                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
1431                 return false;
1432             }
1433 
1434             *targetPC = myTargetPC;
1435             break;
1436 
1437         case ARM_INST_LDMIB:
1438             mypid = m_thread->ProcessID();
1439             addressWherePCLives = baseAddress + numRegistersToLoad*4 + 4;
1440             if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) !=  sizeof(nub_addr_t))
1441             {
1442                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
1443                 return false;
1444             }
1445 
1446             *targetPC = myTargetPC;
1447             break;
1448 
1449         case ARM_INST_LDMIA: // same as pop
1450             // Normal 16-bit LD multiple can't touch R15, but POP can
1451         case ARM_INST_POP:  // Can also get the PC & updates SP
1452             mypid = m_thread->ProcessID();
1453             addressWherePCLives = baseAddress + numRegistersToLoad*4;
1454             if (DNBProcessMemoryRead(mypid, addressWherePCLives, sizeof(nub_addr_t), &myTargetPC) !=  sizeof(nub_addr_t))
1455             {
1456                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the pop instruction!", addressWherePCLives);
1457                 return false;
1458             }
1459 
1460             *targetPC = myTargetPC;
1461             break;
1462 
1463             // 16b TBB and TBH instructions load a jump address from a table
1464         case ARM_INST_TBB:
1465             mypid = m_thread->ProcessID();
1466             addressWherePCLives = baseAddress + addressOffsetFromRegisterAfterShift;
1467             if (DNBProcessMemoryRead(mypid, addressWherePCLives, 1, &halfwords) !=  1)
1468             {
1469                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the TBB instruction!", addressWherePCLives);
1470                 return false;
1471             }
1472             // add 4 to currentPC since we are in Thumb mode and then add 2*halfwords
1473             *targetPC = (currentPC + 4) + 2*halfwords;
1474             break;
1475 
1476         case ARM_INST_TBH:
1477             mypid = m_thread->ProcessID();
1478             addressWherePCLives = ((baseAddress + (addressOffsetFromRegisterAfterShift << 1)) & ~0x1);
1479             if (DNBProcessMemoryRead(mypid, addressWherePCLives, 2, &halfwords) !=  2)
1480             {
1481                 DNBLogError("Could not read memory at %8.8x to get targetPC when processing the TBH instruction!", addressWherePCLives);
1482                 return false;
1483             }
1484             // add 4 to currentPC since we are in Thumb mode and then add 2*halfwords
1485             *targetPC = (currentPC + 4) + 2*halfwords;
1486             break;
1487 
1488             // ThumbEE branch-to-handler instructions: Jump to handlers at some offset
1489             //  from a special base pointer register (which is unknown at disassembly time)
1490         case ARM_INST_HB:
1491         case ARM_INST_HBP:
1492             //          TODO: ARM_INST_HB, ARM_INST_HBP
1493             break;
1494 
1495         case ARM_INST_HBL:
1496         case ARM_INST_HBLP:
1497             //          TODO: ARM_INST_HBL, ARM_INST_HBLP
1498             break;
1499 
1500             // Breakpoint and software interrupt jump to interrupt handler (always ARM)
1501         case ARM_INST_BKPT:
1502         case ARM_INST_SMC:
1503         case ARM_INST_SVC:
1504             //          TODO: ARM_INST_BKPT, ARM_INST_SMC, ARM_INST_SVC
1505             break;
1506 
1507             // Return from exception, obviously modifies PC [interrupt only!]
1508         case ARM_INST_RFEDA:
1509         case ARM_INST_RFEDB:
1510         case ARM_INST_RFEIA:
1511         case ARM_INST_RFEIB:
1512             //          TODO: ARM_INST_RFEDA, ARM_INST_RFEDB, ARM_INST_RFEIA, ARM_INST_RFEIB
1513             break;
1514 
1515             // Other instructions either can't change R15 or are "undefined" if you do,
1516             //  so no sane compiler should ever generate them & we don't care here.
1517             //  Also, R15 can only legally be used in a read-only manner for the
1518             //  various ARM addressing mode (to get PC-relative addressing of constants),
1519             //  but can NOT be used with any of the update modes.
1520         default:
1521             DNBLogError("%s should not be called for instruction code %d!", __FUNCTION__, decodedInstruction.instruction->code);
1522             return false;
1523             break;
1524     }
1525 
1526     return true;
1527 }
1528 
1529 void
1530 DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup(nub_addr_t currentPC, uint32_t cpsr, bool currentPCIsThumb, nub_addr_t *nextPC, bool *nextPCIsThumb)
1531 {
1532     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "DNBArchMachARM::EvaluateNextInstructionForSoftwareBreakpointSetup() called");
1533 
1534     nub_addr_t targetPC = INVALID_NUB_ADDRESS;
1535     uint32_t registerValue;
1536     arm_error_t decodeError;
1537     nub_addr_t currentPCInITBlock, nextPCInITBlock;
1538     int i;
1539     bool last_decoded_instruction_executes = true;
1540 
1541     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: default nextPC=0x%8.8x (%s)", __FUNCTION__, *nextPC, *nextPCIsThumb ? "Thumb" : "ARM");
1542 
1543     // Update *nextPC and *nextPCIsThumb for special cases
1544     if (m_last_decode_thumb.itBlockRemaining) // we are in an IT block
1545     {
1546         // Set the nextPC to the PC of the instruction which will execute in the IT block
1547         // If none of the instruction execute in the IT block based on the condition flags,
1548         // then point to the instruction immediately following the IT block
1549         const int itBlockRemaining = m_last_decode_thumb.itBlockRemaining;
1550         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: itBlockRemaining=%8.8x", __FUNCTION__, itBlockRemaining);
1551 
1552         // Determine the PC at which the next instruction resides
1553         if (m_last_decode_arm.thumb16b)
1554             currentPCInITBlock = currentPC + 2;
1555         else
1556             currentPCInITBlock = currentPC + 4;
1557 
1558         for (i = 0; i < itBlockRemaining; i++)
1559         {
1560             DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: currentPCInITBlock=%8.8x", __FUNCTION__, currentPCInITBlock);
1561             decodeError = DecodeInstructionUsingDisassembler(currentPCInITBlock, cpsr, &m_last_decode_arm, &m_last_decode_thumb, &nextPCInITBlock);
1562 
1563             if (decodeError != ARM_SUCCESS)
1564                 DNBLogError("unable to disassemble instruction at 0x%8.8lx", currentPCInITBlock);
1565 
1566             DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: condition=%d", __FUNCTION__, m_last_decode_arm.condition);
1567             if (ConditionPassed(m_last_decode_arm.condition, cpsr))
1568             {
1569                 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition codes matched for instruction %d", __FUNCTION__, i);
1570                 break; // break from the for loop
1571             }
1572             else
1573             {
1574                 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition codes DID NOT matched for instruction %d", __FUNCTION__, i);
1575             }
1576 
1577             // update currentPC and nextPCInITBlock
1578             currentPCInITBlock = nextPCInITBlock;
1579         }
1580 
1581         if (i == itBlockRemaining) // We came out of the IT block without executing any instructions
1582             last_decoded_instruction_executes = false;
1583 
1584         *nextPC = currentPCInITBlock;
1585         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: After IT block step-through: *nextPC=%8.8x", __FUNCTION__, *nextPC);
1586     }
1587 
1588     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE,
1589                     "%s: cpsr = %8.8x, thumb16b = %d, thumb = %d, branch = %d, conditional = %d, knownTarget = %d, links = %d, canSwitchMode = %d, doesSwitchMode = %d",
1590                     __FUNCTION__,
1591                     cpsr,
1592                     m_last_decode_arm.thumb16b,
1593                     m_last_decode_arm.thumb,
1594                     m_last_decode_arm.branch,
1595                     m_last_decode_arm.conditional,
1596                     m_last_decode_arm.knownTarget,
1597                     m_last_decode_arm.links,
1598                     m_last_decode_arm.canSwitchMode,
1599                     m_last_decode_arm.doesSwitchMode);
1600 
1601 
1602     if (last_decoded_instruction_executes &&                    // Was this a conditional instruction that did execute?
1603         m_last_decode_arm.branch &&                             // Can this instruction change the PC?
1604         (m_last_decode_arm.instruction->code != ARM_INST_SVC))  // If this instruction is not an SVC instruction
1605     {
1606         // Set targetPC. Compute if needed.
1607         if (m_last_decode_arm.knownTarget)
1608         {
1609             // Fixed, known PC-relative
1610             targetPC = m_last_decode_arm.targetPC;
1611         }
1612         else
1613         {
1614             // if targetPC is not known at compile time (PC-relative target), compute targetPC
1615             if (!ComputeNextPC(currentPC, m_last_decode_arm, currentPCIsThumb, &targetPC))
1616             {
1617                 DNBLogError("%s: Unable to compute targetPC for instruction at 0x%8.8lx", __FUNCTION__, currentPC);
1618                 targetPC = INVALID_NUB_ADDRESS;
1619             }
1620         }
1621 
1622         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: targetPC=0x%8.8x, cpsr=0x%8.8x, condition=0x%hhx", __FUNCTION__, targetPC, cpsr, m_last_decode_arm.condition);
1623 
1624         // Refine nextPC computation
1625         if ((m_last_decode_arm.instruction->code == ARM_INST_CBZ) ||
1626             (m_last_decode_arm.instruction->code == ARM_INST_CBNZ))
1627         {
1628             // Compare and branch on zero/non-zero (Thumb-16 only)
1629             // Unusual condition check built into the instruction
1630             registerValue = m_state.context.gpr.__r[m_last_decode_arm.op[REG_RD].value];
1631 
1632             if (m_last_decode_arm.instruction->code == ARM_INST_CBZ)
1633             {
1634                 if (registerValue == 0)
1635                     *nextPC = targetPC;
1636             }
1637             else
1638             {
1639                 if (registerValue != 0)
1640                     *nextPC = targetPC;
1641             }
1642         }
1643         else if (m_last_decode_arm.conditional) // Is the change conditional on flag results?
1644         {
1645             if (ConditionPassed(m_last_decode_arm.condition, cpsr)) // conditions match
1646             {
1647                 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition matched!", __FUNCTION__);
1648                 *nextPC = targetPC;
1649             }
1650             else
1651             {
1652                 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Condition did not match!", __FUNCTION__);
1653             }
1654         }
1655         else
1656         {
1657             *nextPC = targetPC;
1658         }
1659 
1660         // Refine nextPCIsThumb computation
1661         if (m_last_decode_arm.doesSwitchMode)
1662         {
1663             *nextPCIsThumb = !currentPCIsThumb;
1664         }
1665         else if (m_last_decode_arm.canSwitchMode)
1666         {
1667             // Legal to switch ARM <--> Thumb mode with this branch
1668             // dependent on bit[0] of targetPC
1669             *nextPCIsThumb = (*nextPC & 1u) != 0;
1670         }
1671         else
1672         {
1673             *nextPCIsThumb = currentPCIsThumb;
1674         }
1675     }
1676 
1677     DNBLogThreadedIf(LOG_STEP, "%s: calculated nextPC=0x%8.8x (%s)", __FUNCTION__, *nextPC, *nextPCIsThumb ? "Thumb" : "ARM");
1678 }
1679 
1680 
1681 arm_error_t
1682 DNBArchMachARM::DecodeInstructionUsingDisassembler(nub_addr_t curr_pc, uint32_t curr_cpsr, arm_decoded_instruction_t *decodedInstruction, thumb_static_data_t *thumbStaticData, nub_addr_t *next_pc)
1683 {
1684 
1685     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: pc=0x%8.8x, cpsr=0x%8.8x", __FUNCTION__, curr_pc, curr_cpsr);
1686 
1687     const uint32_t isetstate_mask = MASK_CPSR_T | MASK_CPSR_J;
1688     const uint32_t curr_isetstate = curr_cpsr & isetstate_mask;
1689     uint32_t opcode32;
1690     nub_addr_t nextPC = curr_pc;
1691     arm_error_t decodeReturnCode = ARM_SUCCESS;
1692 
1693     m_last_decode_pc = curr_pc;
1694     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: last_decode_pc=0x%8.8x", __FUNCTION__, m_last_decode_pc);
1695 
1696     switch (curr_isetstate) {
1697         case 0x0: // ARM Instruction
1698             // Read the ARM opcode
1699             if (m_thread->Process()->Task().ReadMemory(curr_pc, 4, &opcode32) != 4)
1700             {
1701                 DNBLogError("unable to read opcode bits 31:0 for an ARM opcode at 0x%8.8lx", curr_pc);
1702                 decodeReturnCode = ARM_ERROR;
1703             }
1704             else
1705             {
1706                 nextPC += 4;
1707                 decodeReturnCode = ArmDisassembler((uint64_t)curr_pc, opcode32, false, decodedInstruction, NULL, 0, NULL, 0);
1708 
1709                 if (decodeReturnCode != ARM_SUCCESS)
1710                     DNBLogError("Unable to decode ARM instruction 0x%8.8x at 0x%8.8lx", opcode32, curr_pc);
1711             }
1712             break;
1713 
1714         case 0x20: // Thumb Instruction
1715             uint16_t opcode16;
1716             // Read the a 16 bit Thumb opcode
1717             if (m_thread->Process()->Task().ReadMemory(curr_pc, 2, &opcode16) != 2)
1718             {
1719                 DNBLogError("unable to read opcode bits 15:0 for a thumb opcode at 0x%8.8lx", curr_pc);
1720                 decodeReturnCode = ARM_ERROR;
1721             }
1722             else
1723             {
1724                 nextPC += 2;
1725                 opcode32 = opcode16;
1726 
1727                 decodeReturnCode = ThumbDisassembler((uint64_t)curr_pc, opcode16, false, false, thumbStaticData, decodedInstruction, NULL, 0, NULL, 0);
1728 
1729                 switch (decodeReturnCode) {
1730                     case ARM_SKIP:
1731                         // 32 bit thumb opcode
1732                         nextPC += 2;
1733                         if (m_thread->Process()->Task().ReadMemory(curr_pc+2, 2, &opcode16) != 2)
1734                         {
1735                             DNBLogError("unable to read opcode bits 15:0 for a thumb opcode at 0x%8.8lx", curr_pc+2);
1736                         }
1737                         else
1738                         {
1739                             opcode32 = (opcode32 << 16) | opcode16;
1740 
1741                             decodeReturnCode = ThumbDisassembler((uint64_t)(curr_pc+2), opcode16, false, false, thumbStaticData, decodedInstruction, NULL, 0, NULL, 0);
1742 
1743                             if (decodeReturnCode != ARM_SUCCESS)
1744                                 DNBLogError("Unable to decode 2nd half of Thumb instruction 0x%8.4hx at 0x%8.8lx", opcode16, curr_pc+2);
1745                             break;
1746                         }
1747                         break;
1748 
1749                     case ARM_SUCCESS:
1750                         // 16 bit thumb opcode; at this point we are done decoding the opcode
1751                         break;
1752 
1753                     default:
1754                         DNBLogError("Unable to decode Thumb instruction 0x%8.4hx at 0x%8.8lx", opcode16, curr_pc);
1755                         decodeReturnCode = ARM_ERROR;
1756                         break;
1757                 }
1758             }
1759             break;
1760 
1761         default:
1762             break;
1763     }
1764 
1765     if (next_pc)
1766         *next_pc = nextPC;
1767 
1768     return decodeReturnCode;
1769 }
1770 
1771 nub_bool_t
1772 DNBArchMachARM::BreakpointHit (nub_process_t pid, nub_thread_t tid, nub_break_t breakID, void *baton)
1773 {
1774     nub_addr_t bkpt_pc = (nub_addr_t)baton;
1775     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s(pid = %i, tid = %4.4x, breakID = %u, baton = %p): Setting PC to 0x%8.8x", __FUNCTION__, pid, tid, breakID, baton, bkpt_pc);
1776 
1777     DNBRegisterValue pc_value;
1778     DNBThreadGetRegisterValueByID (pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_value);
1779     pc_value.value.uint32 = bkpt_pc;
1780     return DNBThreadSetRegisterValueByID (pid, tid, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_value);
1781 }
1782 
1783 // Set the single step bit in the processor status register.
1784 kern_return_t
1785 DNBArchMachARM::SetSingleStepSoftwareBreakpoints()
1786 {
1787     DNBError err;
1788     err = GetGPRState(false);
1789 
1790     if (err.Fail())
1791     {
1792         err.LogThreaded("%s: failed to read the GPR registers", __FUNCTION__);
1793         return err.Error();
1794     }
1795 
1796     nub_addr_t curr_pc = m_state.context.gpr.__pc;
1797     uint32_t curr_cpsr = m_state.context.gpr.__cpsr;
1798     nub_addr_t next_pc = curr_pc;
1799 
1800     bool curr_pc_is_thumb = (m_state.context.gpr.__cpsr & 0x20) != 0;
1801     bool next_pc_is_thumb = curr_pc_is_thumb;
1802 
1803     uint32_t curr_itstate = ((curr_cpsr & 0x6000000) >> 25) | ((curr_cpsr & 0xFC00) >> 8);
1804     bool inITBlock = (curr_itstate & 0xF) ? 1 : 0;
1805     bool lastInITBlock = ((curr_itstate & 0xF) == 0x8) ? 1 : 0;
1806 
1807     DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: curr_pc=0x%8.8x (%s), curr_itstate=0x%x, inITBlock=%d, lastInITBlock=%d", __FUNCTION__, curr_pc, curr_pc_is_thumb ? "Thumb" : "ARM", curr_itstate, inITBlock, lastInITBlock);
1808 
1809     // If the instruction is not in the IT block, then decode using the Disassembler and compute next_pc
1810     if (!inITBlock)
1811     {
1812         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Decoding an instruction NOT in the IT block", __FUNCTION__);
1813 
1814         arm_error_t decodeReturnCode =  DecodeInstructionUsingDisassembler(curr_pc, curr_cpsr, &m_last_decode_arm, &m_last_decode_thumb, &next_pc);
1815 
1816         if (decodeReturnCode != ARM_SUCCESS)
1817         {
1818             err = KERN_INVALID_ARGUMENT;
1819             DNBLogError("DNBArchMachARM::SetSingleStepSoftwareBreakpoints: Unable to disassemble instruction at 0x%8.8lx", curr_pc);
1820         }
1821     }
1822     else
1823     {
1824         next_pc = curr_pc + ((m_last_decode_arm.thumb16b) ? 2 : 4);
1825     }
1826 
1827     // Instruction is NOT in the IT block OR
1828     if (!inITBlock)
1829     {
1830         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: normal instruction", __FUNCTION__);
1831         EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.context.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb);
1832     }
1833     else if (inITBlock && !m_last_decode_arm.setsFlags)
1834     {
1835         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: IT instruction that doesn't set flags", __FUNCTION__);
1836         EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.context.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb);
1837     }
1838     else if (lastInITBlock && m_last_decode_arm.branch)
1839     {
1840         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: IT instruction which last in the IT block and is a branch", __FUNCTION__);
1841         EvaluateNextInstructionForSoftwareBreakpointSetup(curr_pc, m_state.context.gpr.__cpsr, curr_pc_is_thumb, &next_pc, &next_pc_is_thumb);
1842     }
1843     else
1844     {
1845         // Instruction is in IT block and can modify the CPSR flags
1846         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: IT instruction that sets flags", __FUNCTION__);
1847 
1848         // NOTE: When this point of code is reached, the instruction at curr_pc has already been decoded
1849         // inside the function ThreadDidStop(). Therefore m_last_decode_arm, m_last_decode_thumb
1850         // reflect the decoded instruction at curr_pc
1851 
1852         // If we find an instruction inside the IT block which will set/modify the condition flags (NZCV bits in CPSR),
1853         // we set breakpoints at all remaining instructions inside the IT block starting from the instruction immediately
1854         // following this one AND a breakpoint at the instruction immediately following the IT block. We do this because
1855         // we cannot determine the next_pc until the instruction at which we are currently stopped executes. Hence we
1856         // insert (m_last_decode_thumb.itBlockRemaining+1) 16-bit Thumb breakpoints at consecutive memory locations
1857         // starting at addrOfNextInstructionInITBlock. We record these breakpoints in class variable m_sw_single_step_itblock_break_id[],
1858         // and also record the total number of IT breakpoints set in the variable 'm_sw_single_step_itblock_break_count'.
1859 
1860         // The instructions inside the IT block, which are replaced by the 16-bit Thumb breakpoints (opcode=0xDEFE)
1861         // instructions, can be either Thumb-16 or Thumb-32. When a Thumb-32 instruction (say, inst#1) is replaced  Thumb
1862         // by a 16-bit breakpoint (OS only supports 16-bit breakpoints in Thumb mode and 32-bit breakpoints in ARM mode), the
1863         // breakpoint for the next instruction (say instr#2) is saved in the upper half of this Thumb-32 (instr#1)
1864         // instruction. Hence if the execution stops at Breakpoint2 corresponding to instr#2, the PC is offset by 16-bits.
1865         // We therefore have to keep track of PC of each instruction in the IT block that is being replaced with the 16-bit
1866         // Thumb breakpoint, to ensure that when the breakpoint is hit, the PC is adjusted to the correct value. We save
1867         // the actual PC corresponding to each instruction in the IT block by associating a call back with each breakpoint
1868         // we set and passing it as a baton. When the breakpoint hits and the callback routine is called, the routine
1869         // adjusts the PC based on the baton that is passed to it.
1870 
1871         nub_addr_t addrOfNextInstructionInITBlock, pcInITBlock, nextPCInITBlock, bpAddressInITBlock;
1872         uint16_t opcode16;
1873         uint32_t opcode32;
1874 
1875         addrOfNextInstructionInITBlock = (m_last_decode_arm.thumb16b) ? curr_pc + 2 : curr_pc + 4;
1876 
1877         pcInITBlock = addrOfNextInstructionInITBlock;
1878 
1879         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: itBlockRemaining=%d", __FUNCTION__, m_last_decode_thumb.itBlockRemaining);
1880 
1881         m_sw_single_step_itblock_break_count = 0;
1882         for (int i = 0; i <= m_last_decode_thumb.itBlockRemaining; i++)
1883         {
1884             if (NUB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i]))
1885             {
1886                 DNBLogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Array m_sw_single_step_itblock_break_id should not contain any valid breakpoint IDs at this point. But found a valid breakID=%d at index=%d", m_sw_single_step_itblock_break_id[i], i);
1887             }
1888             else
1889             {
1890                 nextPCInITBlock = pcInITBlock;
1891                 // Compute nextPCInITBlock based on opcode present at pcInITBlock
1892                 if (m_thread->Process()->Task().ReadMemory(pcInITBlock, 2, &opcode16) == 2)
1893                 {
1894                     opcode32 = opcode16;
1895                     nextPCInITBlock += 2;
1896 
1897                     // Check for 32 bit thumb opcode and read the upper 16 bits if needed
1898                     if (((opcode32 & 0xE000) == 0xE000) && (opcode32 & 0x1800))
1899                     {
1900                         // Adjust 'next_pc_in_itblock' to point to the default next Thumb instruction for
1901                         // a 32 bit Thumb opcode
1902                         // Read bits 31:16 of a 32 bit Thumb opcode
1903                         if (m_thread->Process()->Task().ReadMemory(pcInITBlock+2, 2, &opcode16) == 2)
1904                         {
1905                             // 32 bit thumb opcode
1906                             opcode32 = (opcode32 << 16) | opcode16;
1907                             nextPCInITBlock += 2;
1908                         }
1909                         else
1910                         {
1911                             DNBLogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Unable to read opcode bits 31:16 for a 32 bit thumb opcode at pc=0x%8.8lx", nextPCInITBlock);
1912                         }
1913                     }
1914                 }
1915                 else
1916                 {
1917                     DNBLogError("FunctionProfiler::SetSingleStepSoftwareBreakpoints(): Error reading 16-bit Thumb instruction at pc=0x%8.8x", nextPCInITBlock);
1918                 }
1919 
1920 
1921                 // Set breakpoint and associate a callback function with it
1922                 bpAddressInITBlock = addrOfNextInstructionInITBlock + 2*i;
1923                 DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Setting IT breakpoint[%d] at address: 0x%8.8x", __FUNCTION__, i, bpAddressInITBlock);
1924 
1925                 m_sw_single_step_itblock_break_id[i] = m_thread->Process()->CreateBreakpoint(bpAddressInITBlock, 2, false, m_thread->ThreadID());
1926                 if (!NUB_BREAK_ID_IS_VALID(m_sw_single_step_itblock_break_id[i]))
1927                     err = KERN_INVALID_ARGUMENT;
1928                 else
1929                 {
1930                     DNBLogThreadedIf(LOG_STEP, "%s: Set IT breakpoint[%i]=%d set at 0x%8.8x for instruction at 0x%8.8x", __FUNCTION__, i, m_sw_single_step_itblock_break_id[i], bpAddressInITBlock, pcInITBlock);
1931 
1932                     // Set the breakpoint callback for these special IT breakpoints
1933                     // so that if one of these breakpoints gets hit, it knows to
1934                     // update the PC to the original address of the conditional
1935                     // IT instruction.
1936                     DNBBreakpointSetCallback(m_thread->ProcessID(), m_sw_single_step_itblock_break_id[i], DNBArchMachARM::BreakpointHit, (void*)pcInITBlock);
1937                     m_sw_single_step_itblock_break_count++;
1938                 }
1939             }
1940 
1941             pcInITBlock = nextPCInITBlock;
1942         }
1943 
1944         DNBLogThreadedIf(LOG_STEP | LOG_VERBOSE, "%s: Set %u IT software single breakpoints.", __FUNCTION__, m_sw_single_step_itblock_break_count);
1945 
1946     }
1947 
1948     DNBLogThreadedIf(LOG_STEP, "%s: next_pc=0x%8.8x (%s)", __FUNCTION__, next_pc, next_pc_is_thumb ? "Thumb" : "ARM");
1949 
1950     if (next_pc & 0x1)
1951     {
1952         assert(next_pc_is_thumb);
1953     }
1954 
1955     if (next_pc_is_thumb)
1956     {
1957         next_pc &= ~0x1;
1958     }
1959     else
1960     {
1961         assert((next_pc & 0x3) == 0);
1962     }
1963 
1964     if (!inITBlock || (inITBlock && !m_last_decode_arm.setsFlags) || (lastInITBlock && m_last_decode_arm.branch))
1965     {
1966         err = KERN_SUCCESS;
1967 
1968 #if defined DNB_ARCH_MACH_ARM_DEBUG_SW_STEP
1969         m_sw_single_step_next_pc = next_pc;
1970         if (next_pc_is_thumb)
1971             m_sw_single_step_next_pc |= 1;  // Set bit zero if the next PC is expected to be Thumb
1972 #else
1973         const DNBBreakpoint *bp = m_thread->Process()->Breakpoints().FindByAddress(next_pc);
1974 
1975         if (bp == NULL)
1976         {
1977             m_sw_single_step_break_id = m_thread->Process()->CreateBreakpoint(next_pc, next_pc_is_thumb ? 2 : 4, false, m_thread->ThreadID());
1978             if (!NUB_BREAK_ID_IS_VALID(m_sw_single_step_break_id))
1979                 err = KERN_INVALID_ARGUMENT;
1980             DNBLogThreadedIf(LOG_STEP, "%s: software single step breakpoint with breakID=%d set at 0x%8.8x", __FUNCTION__, m_sw_single_step_break_id, next_pc);
1981         }
1982 #endif
1983     }
1984 
1985     return err.Error();
1986 }
1987 
1988 uint32_t
1989 DNBArchMachARM::NumSupportedHardwareBreakpoints()
1990 {
1991     // Set the init value to something that will let us know that we need to
1992     // autodetect how many breakpoints are supported dynamically...
1993     static uint32_t g_num_supported_hw_breakpoints = UINT_MAX;
1994     if (g_num_supported_hw_breakpoints == UINT_MAX)
1995     {
1996         // Set this to zero in case we can't tell if there are any HW breakpoints
1997         g_num_supported_hw_breakpoints = 0;
1998 
1999         // Read the DBGDIDR to get the number of available hardware breakpoints
2000         // However, in some of our current armv7 processors, hardware
2001         // breakpoints/watchpoints were not properly connected. So detect those
2002         // cases using a field in a sysctl. For now we are using "hw.cpusubtype"
2003         // field to distinguish CPU architectures. This is a hack until we can
2004         // get <rdar://problem/6372672> fixed, at which point we will switch to
2005         // using a different sysctl string that will tell us how many BRPs
2006         // are available to us directly without having to read DBGDIDR.
2007         uint32_t register_DBGDIDR;
2008 
2009         asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
2010         uint32_t numBRPs = bits(register_DBGDIDR, 27, 24);
2011         // Zero is reserved for the BRP count, so don't increment it if it is zero
2012         if (numBRPs > 0)
2013             numBRPs++;
2014         DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, numBRPs);
2015 
2016         if (numBRPs > 0)
2017         {
2018             uint32_t cpusubtype;
2019             size_t len;
2020             len = sizeof(cpusubtype);
2021             // TODO: remove this hack and change to using hw.optional.xx when implmented
2022             if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
2023             {
2024                 DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype);
2025                 if (cpusubtype == CPU_SUBTYPE_ARM_V7)
2026                     DNBLogThreadedIf(LOG_THREAD, "Hardware breakpoints disabled for armv7 (rdar://problem/6372672)");
2027                 else
2028                     g_num_supported_hw_breakpoints = numBRPs;
2029             }
2030         }
2031 
2032     }
2033     return g_num_supported_hw_breakpoints;
2034 }
2035 
2036 
2037 uint32_t
2038 DNBArchMachARM::NumSupportedHardwareWatchpoints()
2039 {
2040     // Set the init value to something that will let us know that we need to
2041     // autodetect how many watchpoints are supported dynamically...
2042     static uint32_t g_num_supported_hw_watchpoints = UINT_MAX;
2043     if (g_num_supported_hw_watchpoints == UINT_MAX)
2044     {
2045         // Set this to zero in case we can't tell if there are any HW breakpoints
2046         g_num_supported_hw_watchpoints = 0;
2047         // Read the DBGDIDR to get the number of available hardware breakpoints
2048         // However, in some of our current armv7 processors, hardware
2049         // breakpoints/watchpoints were not properly connected. So detect those
2050         // cases using a field in a sysctl. For now we are using "hw.cpusubtype"
2051         // field to distinguish CPU architectures. This is a hack until we can
2052         // get <rdar://problem/6372672> fixed, at which point we will switch to
2053         // using a different sysctl string that will tell us how many WRPs
2054         // are available to us directly without having to read DBGDIDR.
2055 
2056         uint32_t register_DBGDIDR;
2057         asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
2058         uint32_t numWRPs = bits(register_DBGDIDR, 31, 28) + 1;
2059         DNBLogThreadedIf(LOG_THREAD, "DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, numWRPs);
2060 
2061         if (numWRPs > 0)
2062         {
2063             uint32_t cpusubtype;
2064             size_t len;
2065             len = sizeof(cpusubtype);
2066             // TODO: remove this hack and change to using hw.optional.xx when implmented
2067             if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) == 0)
2068             {
2069                 DNBLogThreadedIf(LOG_THREAD, "hw.cpusubtype=0x%d", cpusubtype);
2070 
2071                 if (cpusubtype == CPU_SUBTYPE_ARM_V7)
2072                     DNBLogThreadedIf(LOG_THREAD, "Hardware watchpoints disabled for armv7 (rdar://problem/6372672)");
2073                 else
2074                     g_num_supported_hw_watchpoints = numWRPs;
2075             }
2076         }
2077 
2078     }
2079     return g_num_supported_hw_watchpoints;
2080 }
2081 
2082 
2083 uint32_t
2084 DNBArchMachARM::EnableHardwareBreakpoint (nub_addr_t addr, nub_size_t size)
2085 {
2086     // Make sure our address isn't bogus
2087     if (addr & 1)
2088         return INVALID_NUB_HW_INDEX;
2089 
2090     kern_return_t kret = GetDBGState(false);
2091 
2092     if (kret == KERN_SUCCESS)
2093     {
2094         const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
2095         uint32_t i;
2096         for (i=0; i<num_hw_breakpoints; ++i)
2097         {
2098             if ((m_state.dbg.__bcr[i] & BCR_ENABLE) == 0)
2099                 break; // We found an available hw breakpoint slot (in i)
2100         }
2101 
2102         // See if we found an available hw breakpoint slot above
2103         if (i < num_hw_breakpoints)
2104         {
2105             // Make sure bits 1:0 are clear in our address
2106             m_state.dbg.__bvr[i] = addr & ~((nub_addr_t)3);
2107 
2108             if (size == 2 || addr & 2)
2109             {
2110                 uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1;
2111 
2112                 // We have a thumb breakpoint
2113                 // We have an ARM breakpoint
2114                 m_state.dbg.__bcr[i] =  BCR_M_IMVA_MATCH |  // Stop on address mismatch
2115                                         byte_addr_select |  // Set the correct byte address select so we only trigger on the correct opcode
2116                                         S_USER |            // Which modes should this breakpoint stop in?
2117                                         BCR_ENABLE;         // Enable this hardware breakpoint
2118                 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)",
2119                         addr,
2120                         size,
2121                         i,
2122                         i,
2123                         m_state.dbg.__bvr[i],
2124                         m_state.dbg.__bcr[i]);
2125             }
2126             else if (size == 4)
2127             {
2128                 // We have an ARM breakpoint
2129                 m_state.dbg.__bcr[i] =  BCR_M_IMVA_MATCH |  // Stop on address mismatch
2130                                         BAS_IMVA_ALL |      // Stop on any of the four bytes following the IMVA
2131                                         S_USER |            // Which modes should this breakpoint stop in?
2132                                         BCR_ENABLE;         // Enable this hardware breakpoint
2133                 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)",
2134                         addr,
2135                         size,
2136                         i,
2137                         i,
2138                         m_state.dbg.__bvr[i],
2139                         m_state.dbg.__bcr[i]);
2140             }
2141 
2142             kret = SetDBGState();
2143             DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint() SetDBGState() => 0x%8.8x.", kret);
2144 
2145             if (kret == KERN_SUCCESS)
2146                 return i;
2147         }
2148         else
2149         {
2150             DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::EnableHardwareBreakpoint(addr = %8.8p, size = %u) => all hardware breakpoint resources are being used.", addr, size);
2151         }
2152     }
2153 
2154     return INVALID_NUB_HW_INDEX;
2155 }
2156 
2157 bool
2158 DNBArchMachARM::DisableHardwareBreakpoint (uint32_t hw_index)
2159 {
2160     kern_return_t kret = GetDBGState(false);
2161 
2162     const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
2163     if (kret == KERN_SUCCESS)
2164     {
2165         if (hw_index < num_hw_points)
2166         {
2167             m_state.dbg.__bcr[hw_index] = 0;
2168             DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBArchMachARM::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x  BCR%u = 0x%8.8x",
2169                     hw_index,
2170                     hw_index,
2171                     m_state.dbg.__bvr[hw_index],
2172                     hw_index,
2173                     m_state.dbg.__bcr[hw_index]);
2174 
2175             kret = SetDBGState();
2176 
2177             if (kret == KERN_SUCCESS)
2178                 return true;
2179         }
2180     }
2181     return false;
2182 }
2183 
2184 uint32_t
2185 DNBArchMachARM::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write)
2186 {
2187     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write);
2188 
2189     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
2190 
2191     // Can't watch zero bytes
2192     if (size == 0)
2193         return INVALID_NUB_HW_INDEX;
2194 
2195     // We must watch for either read or write
2196     if (read == false && write == false)
2197         return INVALID_NUB_HW_INDEX;
2198 
2199     // Can't watch more than 4 bytes per WVR/WCR pair
2200     if (size > 4)
2201         return INVALID_NUB_HW_INDEX;
2202 
2203     // We can only watch up to four bytes that follow a 4 byte aligned address
2204     // per watchpoint register pair. Since we have at most so we can only watch
2205     // until the next 4 byte boundary and we need to make sure we can properly
2206     // encode this.
2207     uint32_t addr_word_offset = addr % 4;
2208     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset);
2209 
2210     uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
2211     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask);
2212     if (byte_mask > 0xfu)
2213         return INVALID_NUB_HW_INDEX;
2214 
2215     // Read the debug state
2216     kern_return_t kret = GetDBGState(false);
2217 
2218     if (kret == KERN_SUCCESS)
2219     {
2220         // Check to make sure we have the needed hardware support
2221         uint32_t i = 0;
2222 
2223         for (i=0; i<num_hw_watchpoints; ++i)
2224         {
2225             if ((m_state.dbg.__wcr[i] & WCR_ENABLE) == 0)
2226                 break; // We found an available hw breakpoint slot (in i)
2227         }
2228 
2229         // See if we found an available hw breakpoint slot above
2230         if (i < num_hw_watchpoints)
2231         {
2232             // Make the byte_mask into a valid Byte Address Select mask
2233             uint32_t byte_address_select = byte_mask << 5;
2234             // Make sure bits 1:0 are clear in our address
2235             m_state.dbg.__wvr[i] = addr & ~((nub_addr_t)3);
2236             m_state.dbg.__wcr[i] =  byte_address_select |       // Which bytes that follow the IMVA that we will watch
2237                                     S_USER |                    // Stop only in user mode
2238                                     (read ? WCR_LOAD : 0) |     // Stop on read access?
2239                                     (write ? WCR_STORE : 0) |   // Stop on write access?
2240                                     WCR_ENABLE;                 // Enable this watchpoint;
2241 
2242             kret = SetDBGState();
2243             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret);
2244 
2245             if (kret == KERN_SUCCESS)
2246                 return i;
2247         }
2248         else
2249         {
2250             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
2251         }
2252     }
2253     return INVALID_NUB_HW_INDEX;
2254 }
2255 
2256 bool
2257 DNBArchMachARM::DisableHardwareWatchpoint (uint32_t hw_index)
2258 {
2259     kern_return_t kret = GetDBGState(false);
2260 
2261     const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
2262     if (kret == KERN_SUCCESS)
2263     {
2264         if (hw_index < num_hw_points)
2265         {
2266             m_state.dbg.__wcr[hw_index] = 0;
2267             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
2268                     hw_index,
2269                     hw_index,
2270                     m_state.dbg.__wvr[hw_index],
2271                     hw_index,
2272                     m_state.dbg.__wcr[hw_index]);
2273 
2274             kret = SetDBGState();
2275 
2276             if (kret == KERN_SUCCESS)
2277                 return true;
2278         }
2279     }
2280     return false;
2281 }
2282 
2283 //----------------------------------------------------------------------
2284 // Register information defintions for 32 bit ARMV6.
2285 //----------------------------------------------------------------------
2286 enum gpr_regnums
2287 {
2288     gpr_r0 = 0,
2289     gpr_r1,
2290     gpr_r2,
2291     gpr_r3,
2292     gpr_r4,
2293     gpr_r5,
2294     gpr_r6,
2295     gpr_r7,
2296     gpr_r8,
2297     gpr_r9,
2298     gpr_r10,
2299     gpr_r11,
2300     gpr_r12,
2301     gpr_sp,
2302     gpr_lr,
2303     gpr_pc,
2304     gpr_cpsr
2305 };
2306 
2307 enum
2308 {
2309     vfp_s0 = 0,
2310     vfp_s1,
2311     vfp_s2,
2312     vfp_s3,
2313     vfp_s4,
2314     vfp_s5,
2315     vfp_s6,
2316     vfp_s7,
2317     vfp_s8,
2318     vfp_s9,
2319     vfp_s10,
2320     vfp_s11,
2321     vfp_s12,
2322     vfp_s13,
2323     vfp_s14,
2324     vfp_s15,
2325     vfp_s16,
2326     vfp_s17,
2327     vfp_s18,
2328     vfp_s19,
2329     vfp_s20,
2330     vfp_s21,
2331     vfp_s22,
2332     vfp_s23,
2333     vfp_s24,
2334     vfp_s25,
2335     vfp_s26,
2336     vfp_s27,
2337     vfp_s28,
2338     vfp_s29,
2339     vfp_s30,
2340     vfp_s31,
2341     vfp_d16,
2342     vfp_d17,
2343     vfp_d18,
2344     vfp_d19,
2345     vfp_d20,
2346     vfp_d21,
2347     vfp_d22,
2348     vfp_d23,
2349     vfp_d24,
2350     vfp_d25,
2351     vfp_d26,
2352     vfp_d27,
2353     vfp_d28,
2354     vfp_d29,
2355     vfp_d30,
2356     vfp_d31,
2357     vfp_fpscr
2358 };
2359 
2360 enum
2361 {
2362     exc_exception,
2363 	exc_fsr,
2364 	exc_far,
2365 };
2366 
2367 enum
2368 {
2369     gdb_r0 = 0,
2370     gdb_r1,
2371     gdb_r2,
2372     gdb_r3,
2373     gdb_r4,
2374     gdb_r5,
2375     gdb_r6,
2376     gdb_r7,
2377     gdb_r8,
2378     gdb_r9,
2379     gdb_r10,
2380     gdb_r11,
2381     gdb_r12,
2382     gdb_sp,
2383     gdb_lr,
2384     gdb_pc,
2385     gdb_f0,
2386     gdb_f1,
2387     gdb_f2,
2388     gdb_f3,
2389     gdb_f4,
2390     gdb_f5,
2391     gdb_f6,
2392     gdb_f7,
2393     gdb_f8,
2394     gdb_cpsr,
2395     gdb_s0,
2396     gdb_s1,
2397     gdb_s2,
2398     gdb_s3,
2399     gdb_s4,
2400     gdb_s5,
2401     gdb_s6,
2402     gdb_s7,
2403     gdb_s8,
2404     gdb_s9,
2405     gdb_s10,
2406     gdb_s11,
2407     gdb_s12,
2408     gdb_s13,
2409     gdb_s14,
2410     gdb_s15,
2411     gdb_s16,
2412     gdb_s17,
2413     gdb_s18,
2414     gdb_s19,
2415     gdb_s20,
2416     gdb_s21,
2417     gdb_s22,
2418     gdb_s23,
2419     gdb_s24,
2420     gdb_s25,
2421     gdb_s26,
2422     gdb_s27,
2423     gdb_s28,
2424     gdb_s29,
2425     gdb_s30,
2426     gdb_s31,
2427     gdb_fpscr,
2428     gdb_d0,
2429     gdb_d1,
2430     gdb_d2,
2431     gdb_d3,
2432     gdb_d4,
2433     gdb_d5,
2434     gdb_d6,
2435     gdb_d7,
2436     gdb_d8,
2437     gdb_d9,
2438     gdb_d10,
2439     gdb_d11,
2440     gdb_d12,
2441     gdb_d13,
2442     gdb_d14,
2443     gdb_d15
2444 };
2445 
2446 #define GPR_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::GPR, __r[idx]))
2447 #define GPR_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::GPR, __##reg))
2448 #define VFP_S_OFFSET_IDX(idx) (offsetof (DNBArchMachARM::FPU, __r[idx]) + offsetof (DNBArchMachARM::Context, vfp))
2449 #define VFP_D_OFFSET_IDX(idx) (VFP_S_OFFSET_IDX (32) + (((idx) - 16) * 8))
2450 #define VFP_OFFSET_NAME(reg) (offsetof (DNBArchMachARM::FPU, __##reg) + offsetof (DNBArchMachARM::Context, vfp))
2451 #define EXC_OFFSET(reg)      (offsetof (DNBArchMachARM::EXC, __##reg)  + offsetof (DNBArchMachARM::Context, exc))
2452 
2453 // These macros will auto define the register name, alt name, register size,
2454 // register offset, encoding, format and native register. This ensures that
2455 // the register state structures are defined correctly and have the correct
2456 // sizes and offsets.
2457 #define DEFINE_GPR_IDX(idx, reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_IDX(idx), gcc_##reg, dwarf_##reg, gen, gdb_##reg }
2458 #define DEFINE_GPR_NAME(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, 4, GPR_OFFSET_NAME(reg), gcc_##reg, dwarf_##reg, gen, gdb_##reg }
2459 
2460 #define DEFINE_VFP_S_IDX(idx) { e_regSetVFP, vfp_s##idx, "s" #idx, NULL, IEEE754, 4, Float, VFP_S_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, INVALID_NUB_REGNUM, gdb_s##idx }
2461 #define DEFINE_VFP_D_IDX(idx) { e_regSetVFP, vfp_d##idx, "d" #idx, NULL, IEEE754, 8, Float, VFP_D_OFFSET_IDX(idx), INVALID_NUB_REGNUM, dwarf_s##idx, INVALID_NUB_REGNUM, gdb_s##idx }
2462 
2463 // General purpose registers
2464 const DNBRegisterInfo
2465 DNBArchMachARM::g_gpr_registers[] =
2466 {
2467     DEFINE_GPR_IDX ( 0,  r0,  NULL, INVALID_NUB_REGNUM   ),
2468     DEFINE_GPR_IDX ( 1,  r1,  NULL, INVALID_NUB_REGNUM   ),
2469     DEFINE_GPR_IDX ( 2,  r2,  NULL, INVALID_NUB_REGNUM   ),
2470     DEFINE_GPR_IDX ( 3,  r3,  NULL, INVALID_NUB_REGNUM   ),
2471     DEFINE_GPR_IDX ( 4,  r4,  NULL, INVALID_NUB_REGNUM   ),
2472     DEFINE_GPR_IDX ( 5,  r5,  NULL, INVALID_NUB_REGNUM   ),
2473     DEFINE_GPR_IDX ( 6,  r6,  NULL, INVALID_NUB_REGNUM   ),
2474     DEFINE_GPR_IDX ( 7,  r7,  NULL, GENERIC_REGNUM_FP    ),
2475     DEFINE_GPR_IDX ( 8,  r8,  NULL, INVALID_NUB_REGNUM   ),
2476     DEFINE_GPR_IDX ( 9,  r9,  NULL, INVALID_NUB_REGNUM   ),
2477     DEFINE_GPR_IDX (10, r10,  NULL, INVALID_NUB_REGNUM   ),
2478     DEFINE_GPR_IDX (11, r11,  NULL, INVALID_NUB_REGNUM   ),
2479     DEFINE_GPR_IDX (12, r12,  NULL, INVALID_NUB_REGNUM   ),
2480     DEFINE_GPR_NAME (sp, "r13", GENERIC_REGNUM_SP    ),
2481     DEFINE_GPR_NAME (lr, "r14", GENERIC_REGNUM_RA    ),
2482     DEFINE_GPR_NAME (pc, "r15", GENERIC_REGNUM_PC    ),
2483     DEFINE_GPR_NAME (cpsr,  NULL, GENERIC_REGNUM_FLAGS )
2484 };
2485 
2486 // Floating point registers
2487 const DNBRegisterInfo
2488 DNBArchMachARM::g_vfp_registers[] =
2489 {
2490     DEFINE_VFP_S_IDX ( 0),
2491     DEFINE_VFP_S_IDX ( 1),
2492     DEFINE_VFP_S_IDX ( 2),
2493     DEFINE_VFP_S_IDX ( 3),
2494     DEFINE_VFP_S_IDX ( 4),
2495     DEFINE_VFP_S_IDX ( 5),
2496     DEFINE_VFP_S_IDX ( 6),
2497     DEFINE_VFP_S_IDX ( 7),
2498     DEFINE_VFP_S_IDX ( 8),
2499     DEFINE_VFP_S_IDX ( 9),
2500     DEFINE_VFP_S_IDX (10),
2501     DEFINE_VFP_S_IDX (11),
2502     DEFINE_VFP_S_IDX (12),
2503     DEFINE_VFP_S_IDX (13),
2504     DEFINE_VFP_S_IDX (14),
2505     DEFINE_VFP_S_IDX (15),
2506     DEFINE_VFP_S_IDX (16),
2507     DEFINE_VFP_S_IDX (17),
2508     DEFINE_VFP_S_IDX (18),
2509     DEFINE_VFP_S_IDX (19),
2510     DEFINE_VFP_S_IDX (20),
2511     DEFINE_VFP_S_IDX (21),
2512     DEFINE_VFP_S_IDX (22),
2513     DEFINE_VFP_S_IDX (23),
2514     DEFINE_VFP_S_IDX (24),
2515     DEFINE_VFP_S_IDX (25),
2516     DEFINE_VFP_S_IDX (26),
2517     DEFINE_VFP_S_IDX (27),
2518     DEFINE_VFP_S_IDX (28),
2519     DEFINE_VFP_S_IDX (29),
2520     DEFINE_VFP_S_IDX (30),
2521     DEFINE_VFP_S_IDX (31),
2522     DEFINE_VFP_D_IDX (16),
2523     DEFINE_VFP_D_IDX (17),
2524     DEFINE_VFP_D_IDX (18),
2525     DEFINE_VFP_D_IDX (19),
2526     DEFINE_VFP_D_IDX (20),
2527     DEFINE_VFP_D_IDX (21),
2528     DEFINE_VFP_D_IDX (22),
2529     DEFINE_VFP_D_IDX (23),
2530     DEFINE_VFP_D_IDX (24),
2531     DEFINE_VFP_D_IDX (25),
2532     DEFINE_VFP_D_IDX (26),
2533     DEFINE_VFP_D_IDX (27),
2534     DEFINE_VFP_D_IDX (28),
2535     DEFINE_VFP_D_IDX (29),
2536     DEFINE_VFP_D_IDX (30),
2537     DEFINE_VFP_D_IDX (31),
2538     { e_regSetVFP, vfp_fpscr, "fpscr", NULL, Uint, 4, Hex, VFP_OFFSET_NAME(fpscr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gdb_fpscr }
2539 };
2540 
2541 // Exception registers
2542 
2543 const DNBRegisterInfo
2544 DNBArchMachARM::g_exc_registers[] =
2545 {
2546   { e_regSetVFP, exc_exception  , "exception"   , NULL, Uint, 4, Hex, EXC_OFFSET(exception) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM },
2547   { e_regSetVFP, exc_fsr        , "fsr"         , NULL, Uint, 4, Hex, EXC_OFFSET(fsr)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM },
2548   { e_regSetVFP, exc_far        , "far"         , NULL, Uint, 4, Hex, EXC_OFFSET(far)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM }
2549 };
2550 
2551 // Number of registers in each register set
2552 const size_t DNBArchMachARM::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo);
2553 const size_t DNBArchMachARM::k_num_vfp_registers = sizeof(g_vfp_registers)/sizeof(DNBRegisterInfo);
2554 const size_t DNBArchMachARM::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo);
2555 const size_t DNBArchMachARM::k_num_all_registers = k_num_gpr_registers + k_num_vfp_registers + k_num_exc_registers;
2556 
2557 //----------------------------------------------------------------------
2558 // Register set definitions. The first definitions at register set index
2559 // of zero is for all registers, followed by other registers sets. The
2560 // register information for the all register set need not be filled in.
2561 //----------------------------------------------------------------------
2562 const DNBRegisterSetInfo
2563 DNBArchMachARM::g_reg_sets[] =
2564 {
2565     { "ARM Registers",              NULL,               k_num_all_registers     },
2566     { "General Purpose Registers",  g_gpr_registers,    k_num_gpr_registers     },
2567     { "Floating Point Registers",   g_vfp_registers,    k_num_vfp_registers     },
2568     { "Exception State Registers",  g_exc_registers,    k_num_exc_registers     }
2569 };
2570 // Total number of register sets for this architecture
2571 const size_t DNBArchMachARM::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo);
2572 
2573 
2574 const DNBRegisterSetInfo *
2575 DNBArchMachARM::GetRegisterSetInfo(nub_size_t *num_reg_sets)
2576 {
2577     *num_reg_sets = k_num_register_sets;
2578     return g_reg_sets;
2579 }
2580 
2581 bool
2582 DNBArchMachARM::GetRegisterValue(int set, int reg, DNBRegisterValue *value)
2583 {
2584     if (set == REGISTER_SET_GENERIC)
2585     {
2586         switch (reg)
2587         {
2588         case GENERIC_REGNUM_PC:     // Program Counter
2589             set = e_regSetGPR;
2590             reg = gpr_pc;
2591             break;
2592 
2593         case GENERIC_REGNUM_SP:     // Stack Pointer
2594             set = e_regSetGPR;
2595             reg = gpr_sp;
2596             break;
2597 
2598         case GENERIC_REGNUM_FP:     // Frame Pointer
2599             set = e_regSetGPR;
2600             reg = gpr_r7;   // is this the right reg?
2601             break;
2602 
2603         case GENERIC_REGNUM_RA:     // Return Address
2604             set = e_regSetGPR;
2605             reg = gpr_lr;
2606             break;
2607 
2608         case GENERIC_REGNUM_FLAGS:  // Processor flags register
2609             set = e_regSetGPR;
2610             reg = gpr_cpsr;
2611             break;
2612 
2613         default:
2614             return false;
2615         }
2616     }
2617 
2618     if (GetRegisterState(set, false) != KERN_SUCCESS)
2619         return false;
2620 
2621     const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
2622     if (regInfo)
2623     {
2624         value->info = *regInfo;
2625         switch (set)
2626         {
2627         case e_regSetGPR:
2628             if (reg < k_num_gpr_registers)
2629             {
2630                 value->value.uint32 = m_state.context.gpr.__r[reg];
2631                 return true;
2632             }
2633             break;
2634 
2635         case e_regSetVFP:
2636             if (reg < 32)
2637             {
2638                 value->value.uint32 = m_state.context.vfp.__r[reg];
2639                 return true;
2640             }
2641             else if (reg == 32)
2642             {
2643                 value->value.uint32 = m_state.context.vfp.__fpscr;
2644                 return true;
2645             }
2646             break;
2647 
2648         case e_regSetEXC:
2649             if (reg < k_num_exc_registers)
2650             {
2651                 value->value.uint32 = (&m_state.context.exc.__exception)[reg];
2652                 return true;
2653             }
2654             break;
2655         }
2656     }
2657     return false;
2658 }
2659 
2660 bool
2661 DNBArchMachARM::SetRegisterValue(int set, int reg, const DNBRegisterValue *value)
2662 {
2663     if (set == REGISTER_SET_GENERIC)
2664     {
2665         switch (reg)
2666         {
2667         case GENERIC_REGNUM_PC:     // Program Counter
2668             set = e_regSetGPR;
2669             reg = gpr_pc;
2670             break;
2671 
2672         case GENERIC_REGNUM_SP:     // Stack Pointer
2673             set = e_regSetGPR;
2674             reg = gpr_sp;
2675             break;
2676 
2677         case GENERIC_REGNUM_FP:     // Frame Pointer
2678             set = e_regSetGPR;
2679             reg = gpr_r7;
2680             break;
2681 
2682         case GENERIC_REGNUM_RA:     // Return Address
2683             set = e_regSetGPR;
2684             reg = gpr_lr;
2685             break;
2686 
2687         case GENERIC_REGNUM_FLAGS:  // Processor flags register
2688             set = e_regSetGPR;
2689             reg = gpr_cpsr;
2690             break;
2691 
2692         default:
2693             return false;
2694         }
2695     }
2696 
2697     if (GetRegisterState(set, false) != KERN_SUCCESS)
2698         return false;
2699 
2700     bool success = false;
2701     const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
2702     if (regInfo)
2703     {
2704         switch (set)
2705         {
2706         case e_regSetGPR:
2707             if (reg < k_num_gpr_registers)
2708             {
2709                 m_state.context.gpr.__r[reg] = value->value.uint32;
2710                 success = true;
2711             }
2712             break;
2713 
2714         case e_regSetVFP:
2715             if (reg < 32)
2716             {
2717                 m_state.context.vfp.__r[reg] = value->value.float64;
2718                 success = true;
2719             }
2720             else if (reg == 32)
2721             {
2722                 m_state.context.vfp.__fpscr = value->value.uint32;
2723                 success = true;
2724             }
2725             break;
2726 
2727         case e_regSetEXC:
2728             if (reg < k_num_exc_registers)
2729             {
2730                 (&m_state.context.exc.__exception)[reg] = value->value.uint32;
2731                 success = true;
2732             }
2733             break;
2734         }
2735 
2736     }
2737     if (success)
2738         return SetRegisterState(set) == KERN_SUCCESS;
2739     return false;
2740 }
2741 
2742 kern_return_t
2743 DNBArchMachARM::GetRegisterState(int set, bool force)
2744 {
2745     switch (set)
2746     {
2747     case e_regSetALL:   return GetGPRState(force) |
2748                                GetVFPState(force) |
2749                                GetEXCState(force) |
2750                                GetDBGState(force);
2751     case e_regSetGPR:   return GetGPRState(force);
2752     case e_regSetVFP:   return GetVFPState(force);
2753     case e_regSetEXC:   return GetEXCState(force);
2754     case e_regSetDBG:   return GetDBGState(force);
2755     default: break;
2756     }
2757     return KERN_INVALID_ARGUMENT;
2758 }
2759 
2760 kern_return_t
2761 DNBArchMachARM::SetRegisterState(int set)
2762 {
2763     // Make sure we have a valid context to set.
2764     kern_return_t err = GetRegisterState(set, false);
2765     if (err != KERN_SUCCESS)
2766         return err;
2767 
2768     switch (set)
2769     {
2770     case e_regSetALL:   return SetGPRState() |
2771                                SetVFPState() |
2772                                SetEXCState() |
2773                                SetDBGState();
2774     case e_regSetGPR:   return SetGPRState();
2775     case e_regSetVFP:   return SetVFPState();
2776     case e_regSetEXC:   return SetEXCState();
2777     case e_regSetDBG:   return SetDBGState();
2778     default: break;
2779     }
2780     return KERN_INVALID_ARGUMENT;
2781 }
2782 
2783 bool
2784 DNBArchMachARM::RegisterSetStateIsValid (int set) const
2785 {
2786     return m_state.RegsAreValid(set);
2787 }
2788 
2789 
2790 nub_size_t
2791 DNBArchMachARM::GetRegisterContext (void *buf, nub_size_t buf_len)
2792 {
2793     nub_size_t size = sizeof (m_state.context);
2794 
2795     if (buf && buf_len)
2796     {
2797         if (size > buf_len)
2798             size = buf_len;
2799 
2800         bool force = false;
2801         if (GetGPRState(force) | GetVFPState(force) | GetEXCState(force))
2802             return 0;
2803         ::memcpy (buf, &m_state.context, size);
2804     }
2805     DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
2806     // Return the size of the register context even if NULL was passed in
2807     return size;
2808 }
2809 
2810 nub_size_t
2811 DNBArchMachARM::SetRegisterContext (const void *buf, nub_size_t buf_len)
2812 {
2813     nub_size_t size = sizeof (m_state.context);
2814     if (buf == NULL || buf_len == 0)
2815         size = 0;
2816 
2817     if (size)
2818     {
2819         if (size > buf_len)
2820             size = buf_len;
2821 
2822         ::memcpy (&m_state.context, buf, size);
2823         SetGPRState();
2824         SetVFPState();
2825         SetEXCState();
2826     }
2827     DNBLogThreadedIf (LOG_THREAD, "DNBArchMachARM::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
2828     return size;
2829 }
2830 
2831 
2832 #endif    // #if defined (__arm__)
2833 
2834