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