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