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