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