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