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