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