DNBArchImpl.cpp revision 44eb9fb021023027159df55f91c3e95384088970
17a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org//===-- DNBArchImpl.cpp -----------------------------------------*- C++ -*-===//
27a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org//
37a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org//                     The LLVM Compiler Infrastructure
47a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org//
57a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org// This file is distributed under the University of Illinois Open Source
67a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org// License. See LICENSE.TXT for details.
77a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org//
88c4953c6f176469ad287c3270ab146e292b23badcommit-bot@chromium.org//===----------------------------------------------------------------------===//
97a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org//
10f49a0955e26fe57bd6d4498cc71d3c90b6a800f6senorblanco@chromium.org//  Created by Greg Clayton on 6/25/07.
117a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org//
127a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org//===----------------------------------------------------------------------===//
137a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org
147a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__)
157a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org
167a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#if __DARWIN_UNIX03
177a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#define PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(reg) __##reg
187a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#else
197a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#define PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(reg) reg
207a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#endif
217a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org
227a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#include "MacOSX/ppc/DNBArchImpl.h"
237a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#include "MacOSX/MachThread.h"
247a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#include "DNBBreakpoint.h"
257a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#include "DNBLog.h"
267a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org#include "DNBRegisterInfo.h"
277a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org
287a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgstatic const uint8_t g_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 };
297a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org
307a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgconst uint8_t * const
317a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgDNBArchMachPPC::SoftwareBreakpointOpcode (nub_size_t size)
327a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org{
337a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    if (size == 4)
347a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org        return g_breakpoint_opcode;
357a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    return NULL;
367a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org}
377a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org
387a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orguint32_t
397a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgDNBArchMachPPC::GetCPUType()
407a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org{
417a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    return CPU_TYPE_POWERPC;
427a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org}
437a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org
447a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orguint64_t
457a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgDNBArchMachPPC::GetPC(uint64_t failValue)
467a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org{
477a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    // Get program counter
487a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    if (GetGPRState(false) == KERN_SUCCESS)
498c4953c6f176469ad287c3270ab146e292b23badcommit-bot@chromium.org        return m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0);
508c4953c6f176469ad287c3270ab146e292b23badcommit-bot@chromium.org    return failValue;
518c4953c6f176469ad287c3270ab146e292b23badcommit-bot@chromium.org}
528c4953c6f176469ad287c3270ab146e292b23badcommit-bot@chromium.org
538c4953c6f176469ad287c3270ab146e292b23badcommit-bot@chromium.orgkern_return_t
548c4953c6f176469ad287c3270ab146e292b23badcommit-bot@chromium.orgDNBArchMachPPC::SetPC(uint64_t value)
557a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org{
567a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    // Get program counter
577a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    kern_return_t err = GetGPRState(false);
587a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    if (err == KERN_SUCCESS)
597a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    {
607a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org        m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0) = value;
617a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org        err = SetGPRState();
627a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    }
637a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    return err == KERN_SUCCESS;
647a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org}
657a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org
667a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orguint64_t
677a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgDNBArchMachPPC::GetSP(uint64_t failValue)
687a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org{
697a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    // Get stack pointer
707a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    if (GetGPRState(false) == KERN_SUCCESS)
717a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org        return m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(r1);
727a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    return failValue;
737a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org}
747a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org
757a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgkern_return_t
767a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.orgDNBArchMachPPC::GetGPRState(bool force)
777a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org{
787a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    if (force || m_state.GetError(e_regSetGPR, Read))
797a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org    {
807a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org        mach_msg_type_number_t count = e_regSetWordSizeGPR;
817a47ad3bacb36ca7609490bd7cbd85d2c49a0042senorblanco@chromium.org        m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetGPR, (thread_state_t)&m_state.gpr, &count));
82    }
83    return m_state.GetError(e_regSetGPR, Read);
84}
85
86kern_return_t
87DNBArchMachPPC::GetFPRState(bool force)
88{
89    if (force || m_state.GetError(e_regSetFPR, Read))
90    {
91        mach_msg_type_number_t count = e_regSetWordSizeFPR;
92        m_state.SetError(e_regSetFPR, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetFPR, (thread_state_t)&m_state.fpr, &count));
93    }
94    return m_state.GetError(e_regSetFPR, Read);
95}
96
97kern_return_t
98DNBArchMachPPC::GetEXCState(bool force)
99{
100    if (force || m_state.GetError(e_regSetEXC, Read))
101    {
102        mach_msg_type_number_t count = e_regSetWordSizeEXC;
103        m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetEXC, (thread_state_t)&m_state.exc, &count));
104    }
105    return m_state.GetError(e_regSetEXC, Read);
106}
107
108kern_return_t
109DNBArchMachPPC::GetVECState(bool force)
110{
111    if (force || m_state.GetError(e_regSetVEC, Read))
112    {
113        mach_msg_type_number_t count = e_regSetWordSizeVEC;
114        m_state.SetError(e_regSetVEC, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetVEC, (thread_state_t)&m_state.vec, &count));
115    }
116    return m_state.GetError(e_regSetVEC, Read);
117}
118
119kern_return_t
120DNBArchMachPPC::SetGPRState()
121{
122    m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetGPR, (thread_state_t)&m_state.gpr, e_regSetWordSizeGPR));
123    return m_state.GetError(e_regSetGPR, Write);
124}
125
126kern_return_t
127DNBArchMachPPC::SetFPRState()
128{
129    m_state.SetError(e_regSetFPR, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetFPR, (thread_state_t)&m_state.fpr, e_regSetWordSizeFPR));
130    return m_state.GetError(e_regSetFPR, Write);
131}
132
133kern_return_t
134DNBArchMachPPC::SetEXCState()
135{
136    m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetEXC, (thread_state_t)&m_state.exc, e_regSetWordSizeEXC));
137    return m_state.GetError(e_regSetEXC, Write);
138}
139
140kern_return_t
141DNBArchMachPPC::SetVECState()
142{
143    m_state.SetError(e_regSetVEC, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetVEC, (thread_state_t)&m_state.vec, e_regSetWordSizeVEC));
144    return m_state.GetError(e_regSetVEC, Write);
145}
146
147bool
148DNBArchMachPPC::ThreadWillResume()
149{
150    bool success = true;
151
152    // Do we need to step this thread? If so, let the mach thread tell us so.
153    if (m_thread->IsStepping())
154    {
155        // This is the primary thread, let the arch do anything it needs
156        success = EnableHardwareSingleStep(true) == KERN_SUCCESS;
157    }
158    return success;
159}
160
161bool
162DNBArchMachPPC::ThreadDidStop()
163{
164    bool success = true;
165
166    m_state.InvalidateAllRegisterStates();
167
168    // Are we stepping a single instruction?
169    if (GetGPRState(true) == KERN_SUCCESS)
170    {
171        // We are single stepping, was this the primary thread?
172        if (m_thread->IsStepping())
173        {
174            // This was the primary thread, we need to clear the trace
175            // bit if so.
176            success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
177        }
178        else
179        {
180            // The MachThread will automatically restore the suspend count
181            // in ThreadDidStop(), so we don't need to do anything here if
182            // we weren't the primary thread the last time
183        }
184    }
185    return success;
186}
187
188
189// Set the single step bit in the processor status register.
190kern_return_t
191DNBArchMachPPC::EnableHardwareSingleStep (bool enable)
192{
193    DNBLogThreadedIf(LOG_STEP, "DNBArchMachPPC::EnableHardwareSingleStep( enable = %d )", enable);
194    if (GetGPRState(false) == KERN_SUCCESS)
195    {
196        const uint32_t trace_bit = 0x400;
197        if (enable)
198            m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr1) |= trace_bit;
199        else
200            m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr1) &= ~trace_bit;
201        return SetGPRState();
202    }
203    return m_state.GetError(e_regSetGPR, Read);
204}
205
206//----------------------------------------------------------------------
207// Register information defintions for 32 bit PowerPC.
208//----------------------------------------------------------------------
209
210enum gpr_regnums
211{
212    e_regNumGPR_srr0,
213    e_regNumGPR_srr1,
214    e_regNumGPR_r0,
215    e_regNumGPR_r1,
216    e_regNumGPR_r2,
217    e_regNumGPR_r3,
218    e_regNumGPR_r4,
219    e_regNumGPR_r5,
220    e_regNumGPR_r6,
221    e_regNumGPR_r7,
222    e_regNumGPR_r8,
223    e_regNumGPR_r9,
224    e_regNumGPR_r10,
225    e_regNumGPR_r11,
226    e_regNumGPR_r12,
227    e_regNumGPR_r13,
228    e_regNumGPR_r14,
229    e_regNumGPR_r15,
230    e_regNumGPR_r16,
231    e_regNumGPR_r17,
232    e_regNumGPR_r18,
233    e_regNumGPR_r19,
234    e_regNumGPR_r20,
235    e_regNumGPR_r21,
236    e_regNumGPR_r22,
237    e_regNumGPR_r23,
238    e_regNumGPR_r24,
239    e_regNumGPR_r25,
240    e_regNumGPR_r26,
241    e_regNumGPR_r27,
242    e_regNumGPR_r28,
243    e_regNumGPR_r29,
244    e_regNumGPR_r30,
245    e_regNumGPR_r31,
246    e_regNumGPR_cr,
247    e_regNumGPR_xer,
248    e_regNumGPR_lr,
249    e_regNumGPR_ctr,
250    e_regNumGPR_mq,
251    e_regNumGPR_vrsave
252};
253
254
255
256
257// General purpose registers
258static DNBRegisterInfo g_gpr_registers[] =
259{
260  { "srr0"  , Uint, 4, Hex },
261  { "srr1"  , Uint, 4, Hex },
262  { "r0"    , Uint, 4, Hex },
263  { "r1"    , Uint, 4, Hex },
264  { "r2"    , Uint, 4, Hex },
265  { "r3"    , Uint, 4, Hex },
266  { "r4"    , Uint, 4, Hex },
267  { "r5"    , Uint, 4, Hex },
268  { "r6"    , Uint, 4, Hex },
269  { "r7"    , Uint, 4, Hex },
270  { "r8"    , Uint, 4, Hex },
271  { "r9"    , Uint, 4, Hex },
272  { "r10"   , Uint, 4, Hex },
273  { "r11"   , Uint, 4, Hex },
274  { "r12"   , Uint, 4, Hex },
275  { "r13"   , Uint, 4, Hex },
276  { "r14"   , Uint, 4, Hex },
277  { "r15"   , Uint, 4, Hex },
278  { "r16"   , Uint, 4, Hex },
279  { "r17"   , Uint, 4, Hex },
280  { "r18"   , Uint, 4, Hex },
281  { "r19"   , Uint, 4, Hex },
282  { "r20"   , Uint, 4, Hex },
283  { "r21"   , Uint, 4, Hex },
284  { "r22"   , Uint, 4, Hex },
285  { "r23"   , Uint, 4, Hex },
286  { "r24"   , Uint, 4, Hex },
287  { "r25"   , Uint, 4, Hex },
288  { "r26"   , Uint, 4, Hex },
289  { "r27"   , Uint, 4, Hex },
290  { "r28"   , Uint, 4, Hex },
291  { "r29"   , Uint, 4, Hex },
292  { "r30"   , Uint, 4, Hex },
293  { "r31"   , Uint, 4, Hex },
294  { "cr"    , Uint, 4, Hex },
295  { "xer"   , Uint, 4, Hex },
296  { "lr"    , Uint, 4, Hex },
297  { "ctr"   , Uint, 4, Hex },
298  { "mq"    , Uint, 4, Hex },
299  { "vrsave", Uint, 4, Hex },
300};
301
302// Floating point registers
303static DNBRegisterInfo g_fpr_registers[] =
304{
305  { "fp0"   , IEEE754, 8, Float },
306  { "fp1"   , IEEE754, 8, Float },
307  { "fp2"   , IEEE754, 8, Float },
308  { "fp3"   , IEEE754, 8, Float },
309  { "fp4"   , IEEE754, 8, Float },
310  { "fp5"   , IEEE754, 8, Float },
311  { "fp6"   , IEEE754, 8, Float },
312  { "fp7"   , IEEE754, 8, Float },
313  { "fp8"   , IEEE754, 8, Float },
314  { "fp9"   , IEEE754, 8, Float },
315  { "fp10"  , IEEE754, 8, Float },
316  { "fp11"  , IEEE754, 8, Float },
317  { "fp12"  , IEEE754, 8, Float },
318  { "fp13"  , IEEE754, 8, Float },
319  { "fp14"  , IEEE754, 8, Float },
320  { "fp15"  , IEEE754, 8, Float },
321  { "fp16"  , IEEE754, 8, Float },
322  { "fp17"  , IEEE754, 8, Float },
323  { "fp18"  , IEEE754, 8, Float },
324  { "fp19"  , IEEE754, 8, Float },
325  { "fp20"  , IEEE754, 8, Float },
326  { "fp21"  , IEEE754, 8, Float },
327  { "fp22"  , IEEE754, 8, Float },
328  { "fp23"  , IEEE754, 8, Float },
329  { "fp24"  , IEEE754, 8, Float },
330  { "fp25"  , IEEE754, 8, Float },
331  { "fp26"  , IEEE754, 8, Float },
332  { "fp27"  , IEEE754, 8, Float },
333  { "fp28"  , IEEE754, 8, Float },
334  { "fp29"  , IEEE754, 8, Float },
335  { "fp30"  , IEEE754, 8, Float },
336  { "fp31"  , IEEE754, 8, Float },
337  { "fpscr" , Uint, 4, Hex }
338};
339
340// Exception registers
341
342static DNBRegisterInfo g_exc_registers[] =
343{
344  { "dar"       , Uint, 4, Hex },
345  { "dsisr"     , Uint, 4, Hex },
346  { "exception" , Uint, 4, Hex }
347};
348
349// Altivec registers
350static DNBRegisterInfo g_vec_registers[] =
351{
352  { "vr0"   , Vector, 16, VectorOfFloat32 },
353  { "vr1"   , Vector, 16, VectorOfFloat32 },
354  { "vr2"   , Vector, 16, VectorOfFloat32 },
355  { "vr3"   , Vector, 16, VectorOfFloat32 },
356  { "vr4"   , Vector, 16, VectorOfFloat32 },
357  { "vr5"   , Vector, 16, VectorOfFloat32 },
358  { "vr6"   , Vector, 16, VectorOfFloat32 },
359  { "vr7"   , Vector, 16, VectorOfFloat32 },
360  { "vr8"   , Vector, 16, VectorOfFloat32 },
361  { "vr9"   , Vector, 16, VectorOfFloat32 },
362  { "vr10"  , Vector, 16, VectorOfFloat32 },
363  { "vr11"  , Vector, 16, VectorOfFloat32 },
364  { "vr12"  , Vector, 16, VectorOfFloat32 },
365  { "vr13"  , Vector, 16, VectorOfFloat32 },
366  { "vr14"  , Vector, 16, VectorOfFloat32 },
367  { "vr15"  , Vector, 16, VectorOfFloat32 },
368  { "vr16"  , Vector, 16, VectorOfFloat32 },
369  { "vr17"  , Vector, 16, VectorOfFloat32 },
370  { "vr18"  , Vector, 16, VectorOfFloat32 },
371  { "vr19"  , Vector, 16, VectorOfFloat32 },
372  { "vr20"  , Vector, 16, VectorOfFloat32 },
373  { "vr21"  , Vector, 16, VectorOfFloat32 },
374  { "vr22"  , Vector, 16, VectorOfFloat32 },
375  { "vr23"  , Vector, 16, VectorOfFloat32 },
376  { "vr24"  , Vector, 16, VectorOfFloat32 },
377  { "vr25"  , Vector, 16, VectorOfFloat32 },
378  { "vr26"  , Vector, 16, VectorOfFloat32 },
379  { "vr27"  , Vector, 16, VectorOfFloat32 },
380  { "vr28"  , Vector, 16, VectorOfFloat32 },
381  { "vr29"  , Vector, 16, VectorOfFloat32 },
382  { "vr30"  , Vector, 16, VectorOfFloat32 },
383  { "vr31"  , Vector, 16, VectorOfFloat32 },
384  { "vscr"  , Uint, 16, Hex },
385  { "vrvalid" , Uint, 4, Hex }
386};
387
388// Number of registers in each register set
389const size_t k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo);
390const size_t k_num_fpr_registers = sizeof(g_fpr_registers)/sizeof(DNBRegisterInfo);
391const size_t k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo);
392const size_t k_num_vec_registers = sizeof(g_vec_registers)/sizeof(DNBRegisterInfo);
393// Total number of registers for this architecture
394const size_t k_num_ppc_registers = k_num_gpr_registers + k_num_fpr_registers + k_num_exc_registers + k_num_vec_registers;
395
396//----------------------------------------------------------------------
397// Register set definitions. The first definitions at register set index
398// of zero is for all registers, followed by other registers sets. The
399// register information for the all register set need not be filled in.
400//----------------------------------------------------------------------
401static const DNBRegisterSetInfo g_reg_sets[] =
402{
403    { "PowerPC Registers",            NULL,             k_num_ppc_registers },
404    { "General Purpose Registers",    g_gpr_registers, k_num_gpr_registers },
405    { "Floating Point Registers",    g_fpr_registers, k_num_fpr_registers },
406    { "Exception State Registers",    g_exc_registers, k_num_exc_registers },
407    { "Altivec Registers",            g_vec_registers, k_num_vec_registers }
408};
409// Total number of register sets for this architecture
410const size_t k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo);
411
412
413const DNBRegisterSetInfo *
414DNBArchMachPPC::GetRegisterSetInfo(nub_size_t *num_reg_sets) const
415{
416    *num_reg_sets = k_num_register_sets;
417    return g_reg_sets;
418}
419
420bool
421DNBArchMachPPC::GetRegisterValue(int set, int reg, DNBRegisterValue *value) const
422{
423    if (set == REGISTER_SET_GENERIC)
424    {
425        switch (reg)
426        {
427        case GENERIC_REGNUM_PC:     // Program Counter
428            set = e_regSetGPR;
429            reg = e_regNumGPR_srr0;
430            break;
431
432        case GENERIC_REGNUM_SP:     // Stack Pointer
433            set = e_regSetGPR;
434            reg = e_regNumGPR_r1;
435            break;
436
437        case GENERIC_REGNUM_FP:     // Frame Pointer
438            // Return false for now instead of returning r30 as gcc 3.x would
439            // use a variety of registers for the FP and it takes inspecting
440            // the stack to make sure there is a frame pointer before we can
441            // determine the FP.
442            return false;
443
444        case GENERIC_REGNUM_RA:     // Return Address
445            set = e_regSetGPR;
446            reg = e_regNumGPR_lr;
447            break;
448
449        case GENERIC_REGNUM_FLAGS:  // Processor flags register
450            set = e_regSetGPR;
451            reg = e_regNumGPR_srr1;
452            break;
453
454        default:
455            return false;
456        }
457    }
458
459    if (!m_state.RegsAreValid(set))
460        return false;
461
462    const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
463    if (regInfo)
464    {
465        value->info = *regInfo;
466        switch (set)
467        {
468        case e_regSetGPR:
469            if (reg < k_num_gpr_registers)
470            {
471                value->value.uint32 = (&m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0))[reg];
472                return true;
473            }
474            break;
475
476        case e_regSetFPR:
477            if (reg < 32)
478            {
479                value->value.float64 = m_state.fpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(fpregs)[reg];
480                return true;
481            }
482            else if (reg == 32)
483            {
484                value->value.uint32 = m_state.fpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(fpscr);
485                return true;
486            }
487            break;
488
489        case e_regSetEXC:
490            if (reg < k_num_exc_registers)
491            {
492                value->value.uint32 = (&m_state.exc.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(dar))[reg];
493                return true;
494            }
495            break;
496
497        case e_regSetVEC:
498            if (reg < k_num_vec_registers)
499            {
500                if (reg < 33)            // FP0 - FP31 and VSCR
501                {
502                    // Copy all 4 uint32 values for this vector register
503                    value->value.v_uint32[0] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][0];
504                    value->value.v_uint32[1] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][1];
505                    value->value.v_uint32[2] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][2];
506                    value->value.v_uint32[3] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][3];
507                    return true;
508                }
509                else if (reg == 34)    // VRVALID
510                {
511                    value->value.uint32 = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vrvalid);
512                    return true;
513                }
514            }
515            break;
516        }
517    }
518    return false;
519}
520
521
522kern_return_t
523DNBArchMachPPC::GetRegisterState(int set, bool force)
524{
525    switch (set)
526    {
527    case e_regSetALL:
528        return  GetGPRState(force) |
529                GetFPRState(force) |
530                GetEXCState(force) |
531                GetVECState(force);
532    case e_regSetGPR:    return GetGPRState(force);
533    case e_regSetFPR:    return GetFPRState(force);
534    case e_regSetEXC:    return GetEXCState(force);
535    case e_regSetVEC:    return GetVECState(force);
536    default: break;
537    }
538    return KERN_INVALID_ARGUMENT;
539}
540
541kern_return_t
542DNBArchMachPPC::SetRegisterState(int set)
543{
544    // Make sure we have a valid context to set.
545    kern_return_t err = GetRegisterState(set, false);
546    if (err != KERN_SUCCESS)
547        return err;
548
549    switch (set)
550    {
551    case e_regSetALL:    return SetGPRState() | SetFPRState() | SetEXCState() | SetVECState();
552    case e_regSetGPR:    return SetGPRState();
553    case e_regSetFPR:    return SetFPRState();
554    case e_regSetEXC:    return SetEXCState();
555    case e_regSetVEC:    return SetVECState();
556    default: break;
557    }
558    return KERN_INVALID_ARGUMENT;
559}
560
561bool
562DNBArchMachPPC::RegisterSetStateIsValid (int set) const
563{
564    return m_state.RegsAreValid(set);
565}
566
567
568#endif    // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__)
569
570