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