diff options
Diffstat (limited to 'tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp')
| -rw-r--r-- | tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp | 569 | 
1 files changed, 569 insertions, 0 deletions
| diff --git a/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp b/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp new file mode 100644 index 000000000000..c6f1a718ac92 --- /dev/null +++ b/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.cpp @@ -0,0 +1,569 @@ +//===-- DNBArchImpl.cpp -----------------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +//  Created by Greg Clayton on 6/25/07. +// +//===----------------------------------------------------------------------===// + +#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) + +#if __DARWIN_UNIX03 +#define PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(reg) __##reg +#else +#define PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(reg) reg +#endif + +#include "MacOSX/ppc/DNBArchImpl.h" +#include "MacOSX/MachThread.h" +#include "DNBBreakpoint.h" +#include "DNBLog.h" +#include "DNBRegisterInfo.h" + +static const uint8_t g_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 }; + +const uint8_t * +DNBArchMachPPC::SoftwareBreakpointOpcode (nub_size_t size) +{ +    if (size == 4) +        return g_breakpoint_opcode; +    return NULL; +} + +uint32_t +DNBArchMachPPC::GetCPUType() +{ +    return CPU_TYPE_POWERPC; +} + +uint64_t +DNBArchMachPPC::GetPC(uint64_t failValue) +{ +    // Get program counter +    if (GetGPRState(false) == KERN_SUCCESS) +        return m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0); +    return failValue; +} + +kern_return_t +DNBArchMachPPC::SetPC(uint64_t value) +{ +    // Get program counter +    kern_return_t err = GetGPRState(false); +    if (err == KERN_SUCCESS) +    { +        m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0) = value; +        err = SetGPRState(); +    } +    return err == KERN_SUCCESS; +} + +uint64_t +DNBArchMachPPC::GetSP(uint64_t failValue) +{ +    // Get stack pointer +    if (GetGPRState(false) == KERN_SUCCESS) +        return m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(r1); +    return failValue; +} + +kern_return_t +DNBArchMachPPC::GetGPRState(bool force) +{ +    if (force || m_state.GetError(e_regSetGPR, Read)) +    { +        mach_msg_type_number_t count = e_regSetWordSizeGPR; +        m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetGPR, (thread_state_t)&m_state.gpr, &count)); +    } +    return m_state.GetError(e_regSetGPR, Read); +} + +kern_return_t +DNBArchMachPPC::GetFPRState(bool force) +{ +    if (force || m_state.GetError(e_regSetFPR, Read)) +    { +        mach_msg_type_number_t count = e_regSetWordSizeFPR; +        m_state.SetError(e_regSetFPR, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetFPR, (thread_state_t)&m_state.fpr, &count)); +    } +    return m_state.GetError(e_regSetFPR, Read); +} + +kern_return_t +DNBArchMachPPC::GetEXCState(bool force) +{ +    if (force || m_state.GetError(e_regSetEXC, Read)) +    { +        mach_msg_type_number_t count = e_regSetWordSizeEXC; +        m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetEXC, (thread_state_t)&m_state.exc, &count)); +    } +    return m_state.GetError(e_regSetEXC, Read); +} + +kern_return_t +DNBArchMachPPC::GetVECState(bool force) +{ +    if (force || m_state.GetError(e_regSetVEC, Read)) +    { +        mach_msg_type_number_t count = e_regSetWordSizeVEC; +        m_state.SetError(e_regSetVEC, Read, ::thread_get_state(m_thread->MachPortNumber(), e_regSetVEC, (thread_state_t)&m_state.vec, &count)); +    } +    return m_state.GetError(e_regSetVEC, Read); +} + +kern_return_t +DNBArchMachPPC::SetGPRState() +{ +    m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetGPR, (thread_state_t)&m_state.gpr, e_regSetWordSizeGPR)); +    return m_state.GetError(e_regSetGPR, Write); +} + +kern_return_t +DNBArchMachPPC::SetFPRState() +{ +    m_state.SetError(e_regSetFPR, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetFPR, (thread_state_t)&m_state.fpr, e_regSetWordSizeFPR)); +    return m_state.GetError(e_regSetFPR, Write); +} + +kern_return_t +DNBArchMachPPC::SetEXCState() +{ +    m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetEXC, (thread_state_t)&m_state.exc, e_regSetWordSizeEXC)); +    return m_state.GetError(e_regSetEXC, Write); +} + +kern_return_t +DNBArchMachPPC::SetVECState() +{ +    m_state.SetError(e_regSetVEC, Write, ::thread_set_state(m_thread->MachPortNumber(), e_regSetVEC, (thread_state_t)&m_state.vec, e_regSetWordSizeVEC)); +    return m_state.GetError(e_regSetVEC, Write); +} + +bool +DNBArchMachPPC::ThreadWillResume() +{ +    bool success = true; + +    // Do we need to step this thread? If so, let the mach thread tell us so. +    if (m_thread->IsStepping()) +    { +        // This is the primary thread, let the arch do anything it needs +        success = EnableHardwareSingleStep(true) == KERN_SUCCESS; +    } +    return success; +} + +bool +DNBArchMachPPC::ThreadDidStop() +{ +    bool success = true; + +    m_state.InvalidateAllRegisterStates(); + +    // Are we stepping a single instruction? +    if (GetGPRState(true) == KERN_SUCCESS) +    { +        // We are single stepping, was this the primary thread? +        if (m_thread->IsStepping()) +        { +            // This was the primary thread, we need to clear the trace +            // bit if so. +            success = EnableHardwareSingleStep(false) == KERN_SUCCESS; +        } +        else +        { +            // The MachThread will automatically restore the suspend count +            // in ThreadDidStop(), so we don't need to do anything here if +            // we weren't the primary thread the last time +        } +    } +    return success; +} + + +// Set the single step bit in the processor status register. +kern_return_t +DNBArchMachPPC::EnableHardwareSingleStep (bool enable) +{ +    DNBLogThreadedIf(LOG_STEP, "DNBArchMachPPC::EnableHardwareSingleStep( enable = %d )", enable); +    if (GetGPRState(false) == KERN_SUCCESS) +    { +        const uint32_t trace_bit = 0x400; +        if (enable) +            m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr1) |= trace_bit; +        else +            m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr1) &= ~trace_bit; +        return SetGPRState(); +    } +    return m_state.GetError(e_regSetGPR, Read); +} + +//---------------------------------------------------------------------- +// Register information definitions for 32 bit PowerPC. +//---------------------------------------------------------------------- + +enum gpr_regnums +{ +    e_regNumGPR_srr0, +    e_regNumGPR_srr1, +    e_regNumGPR_r0, +    e_regNumGPR_r1, +    e_regNumGPR_r2, +    e_regNumGPR_r3, +    e_regNumGPR_r4, +    e_regNumGPR_r5, +    e_regNumGPR_r6, +    e_regNumGPR_r7, +    e_regNumGPR_r8, +    e_regNumGPR_r9, +    e_regNumGPR_r10, +    e_regNumGPR_r11, +    e_regNumGPR_r12, +    e_regNumGPR_r13, +    e_regNumGPR_r14, +    e_regNumGPR_r15, +    e_regNumGPR_r16, +    e_regNumGPR_r17, +    e_regNumGPR_r18, +    e_regNumGPR_r19, +    e_regNumGPR_r20, +    e_regNumGPR_r21, +    e_regNumGPR_r22, +    e_regNumGPR_r23, +    e_regNumGPR_r24, +    e_regNumGPR_r25, +    e_regNumGPR_r26, +    e_regNumGPR_r27, +    e_regNumGPR_r28, +    e_regNumGPR_r29, +    e_regNumGPR_r30, +    e_regNumGPR_r31, +    e_regNumGPR_cr, +    e_regNumGPR_xer, +    e_regNumGPR_lr, +    e_regNumGPR_ctr, +    e_regNumGPR_mq, +    e_regNumGPR_vrsave +}; + + + + +// General purpose registers +static DNBRegisterInfo g_gpr_registers[] = +{ +  { "srr0"  , Uint, 4, Hex }, +  { "srr1"  , Uint, 4, Hex }, +  { "r0"    , Uint, 4, Hex }, +  { "r1"    , Uint, 4, Hex }, +  { "r2"    , Uint, 4, Hex }, +  { "r3"    , Uint, 4, Hex }, +  { "r4"    , Uint, 4, Hex }, +  { "r5"    , Uint, 4, Hex }, +  { "r6"    , Uint, 4, Hex }, +  { "r7"    , Uint, 4, Hex }, +  { "r8"    , Uint, 4, Hex }, +  { "r9"    , Uint, 4, Hex }, +  { "r10"   , Uint, 4, Hex }, +  { "r11"   , Uint, 4, Hex }, +  { "r12"   , Uint, 4, Hex }, +  { "r13"   , Uint, 4, Hex }, +  { "r14"   , Uint, 4, Hex }, +  { "r15"   , Uint, 4, Hex }, +  { "r16"   , Uint, 4, Hex }, +  { "r17"   , Uint, 4, Hex }, +  { "r18"   , Uint, 4, Hex }, +  { "r19"   , Uint, 4, Hex }, +  { "r20"   , Uint, 4, Hex }, +  { "r21"   , Uint, 4, Hex }, +  { "r22"   , Uint, 4, Hex }, +  { "r23"   , Uint, 4, Hex }, +  { "r24"   , Uint, 4, Hex }, +  { "r25"   , Uint, 4, Hex }, +  { "r26"   , Uint, 4, Hex }, +  { "r27"   , Uint, 4, Hex }, +  { "r28"   , Uint, 4, Hex }, +  { "r29"   , Uint, 4, Hex }, +  { "r30"   , Uint, 4, Hex }, +  { "r31"   , Uint, 4, Hex }, +  { "cr"    , Uint, 4, Hex }, +  { "xer"   , Uint, 4, Hex }, +  { "lr"    , Uint, 4, Hex }, +  { "ctr"   , Uint, 4, Hex }, +  { "mq"    , Uint, 4, Hex }, +  { "vrsave", Uint, 4, Hex }, +}; + +// Floating point registers +static DNBRegisterInfo g_fpr_registers[] = +{ +  { "fp0"   , IEEE754, 8, Float }, +  { "fp1"   , IEEE754, 8, Float }, +  { "fp2"   , IEEE754, 8, Float }, +  { "fp3"   , IEEE754, 8, Float }, +  { "fp4"   , IEEE754, 8, Float }, +  { "fp5"   , IEEE754, 8, Float }, +  { "fp6"   , IEEE754, 8, Float }, +  { "fp7"   , IEEE754, 8, Float }, +  { "fp8"   , IEEE754, 8, Float }, +  { "fp9"   , IEEE754, 8, Float }, +  { "fp10"  , IEEE754, 8, Float }, +  { "fp11"  , IEEE754, 8, Float }, +  { "fp12"  , IEEE754, 8, Float }, +  { "fp13"  , IEEE754, 8, Float }, +  { "fp14"  , IEEE754, 8, Float }, +  { "fp15"  , IEEE754, 8, Float }, +  { "fp16"  , IEEE754, 8, Float }, +  { "fp17"  , IEEE754, 8, Float }, +  { "fp18"  , IEEE754, 8, Float }, +  { "fp19"  , IEEE754, 8, Float }, +  { "fp20"  , IEEE754, 8, Float }, +  { "fp21"  , IEEE754, 8, Float }, +  { "fp22"  , IEEE754, 8, Float }, +  { "fp23"  , IEEE754, 8, Float }, +  { "fp24"  , IEEE754, 8, Float }, +  { "fp25"  , IEEE754, 8, Float }, +  { "fp26"  , IEEE754, 8, Float }, +  { "fp27"  , IEEE754, 8, Float }, +  { "fp28"  , IEEE754, 8, Float }, +  { "fp29"  , IEEE754, 8, Float }, +  { "fp30"  , IEEE754, 8, Float }, +  { "fp31"  , IEEE754, 8, Float }, +  { "fpscr" , Uint, 4, Hex } +}; + +// Exception registers + +static DNBRegisterInfo g_exc_registers[] = +{ +  { "dar"       , Uint, 4, Hex }, +  { "dsisr"     , Uint, 4, Hex }, +  { "exception" , Uint, 4, Hex } +}; + +// Altivec registers +static DNBRegisterInfo g_vec_registers[] = +{ +  { "vr0"   , Vector, 16, VectorOfFloat32 }, +  { "vr1"   , Vector, 16, VectorOfFloat32 }, +  { "vr2"   , Vector, 16, VectorOfFloat32 }, +  { "vr3"   , Vector, 16, VectorOfFloat32 }, +  { "vr4"   , Vector, 16, VectorOfFloat32 }, +  { "vr5"   , Vector, 16, VectorOfFloat32 }, +  { "vr6"   , Vector, 16, VectorOfFloat32 }, +  { "vr7"   , Vector, 16, VectorOfFloat32 }, +  { "vr8"   , Vector, 16, VectorOfFloat32 }, +  { "vr9"   , Vector, 16, VectorOfFloat32 }, +  { "vr10"  , Vector, 16, VectorOfFloat32 }, +  { "vr11"  , Vector, 16, VectorOfFloat32 }, +  { "vr12"  , Vector, 16, VectorOfFloat32 }, +  { "vr13"  , Vector, 16, VectorOfFloat32 }, +  { "vr14"  , Vector, 16, VectorOfFloat32 }, +  { "vr15"  , Vector, 16, VectorOfFloat32 }, +  { "vr16"  , Vector, 16, VectorOfFloat32 }, +  { "vr17"  , Vector, 16, VectorOfFloat32 }, +  { "vr18"  , Vector, 16, VectorOfFloat32 }, +  { "vr19"  , Vector, 16, VectorOfFloat32 }, +  { "vr20"  , Vector, 16, VectorOfFloat32 }, +  { "vr21"  , Vector, 16, VectorOfFloat32 }, +  { "vr22"  , Vector, 16, VectorOfFloat32 }, +  { "vr23"  , Vector, 16, VectorOfFloat32 }, +  { "vr24"  , Vector, 16, VectorOfFloat32 }, +  { "vr25"  , Vector, 16, VectorOfFloat32 }, +  { "vr26"  , Vector, 16, VectorOfFloat32 }, +  { "vr27"  , Vector, 16, VectorOfFloat32 }, +  { "vr28"  , Vector, 16, VectorOfFloat32 }, +  { "vr29"  , Vector, 16, VectorOfFloat32 }, +  { "vr30"  , Vector, 16, VectorOfFloat32 }, +  { "vr31"  , Vector, 16, VectorOfFloat32 }, +  { "vscr"  , Uint, 16, Hex }, +  { "vrvalid" , Uint, 4, Hex } +}; + +// Number of registers in each register set +const size_t k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo); +const size_t k_num_fpr_registers = sizeof(g_fpr_registers)/sizeof(DNBRegisterInfo); +const size_t k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo); +const size_t k_num_vec_registers = sizeof(g_vec_registers)/sizeof(DNBRegisterInfo); +// Total number of registers for this architecture +const size_t k_num_ppc_registers = k_num_gpr_registers + k_num_fpr_registers + k_num_exc_registers + k_num_vec_registers; + +//---------------------------------------------------------------------- +// Register set definitions. The first definitions at register set index +// of zero is for all registers, followed by other registers sets. The +// register information for the all register set need not be filled in. +//---------------------------------------------------------------------- +static const DNBRegisterSetInfo g_reg_sets[] = +{ +    { "PowerPC Registers",            NULL,             k_num_ppc_registers }, +    { "General Purpose Registers",    g_gpr_registers, k_num_gpr_registers }, +    { "Floating Point Registers",    g_fpr_registers, k_num_fpr_registers }, +    { "Exception State Registers",    g_exc_registers, k_num_exc_registers }, +    { "Altivec Registers",            g_vec_registers, k_num_vec_registers } +}; +// Total number of register sets for this architecture +const size_t k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); + + +const DNBRegisterSetInfo * +DNBArchMachPPC::GetRegisterSetInfo(nub_size_t *num_reg_sets) const +{ +    *num_reg_sets = k_num_register_sets; +    return g_reg_sets; +} + +bool +DNBArchMachPPC::GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value) const +{ +    if (set == REGISTER_SET_GENERIC) +    { +        switch (reg) +        { +        case GENERIC_REGNUM_PC:     // Program Counter +            set = e_regSetGPR; +            reg = e_regNumGPR_srr0; +            break; + +        case GENERIC_REGNUM_SP:     // Stack Pointer +            set = e_regSetGPR; +            reg = e_regNumGPR_r1; +            break; + +        case GENERIC_REGNUM_FP:     // Frame Pointer +            // Return false for now instead of returning r30 as gcc 3.x would +            // use a variety of registers for the FP and it takes inspecting +            // the stack to make sure there is a frame pointer before we can +            // determine the FP. +            return false; + +        case GENERIC_REGNUM_RA:     // Return Address +            set = e_regSetGPR; +            reg = e_regNumGPR_lr; +            break; + +        case GENERIC_REGNUM_FLAGS:  // Processor flags register +            set = e_regSetGPR; +            reg = e_regNumGPR_srr1; +            break; + +        default: +            return false; +        } +    } + +    if (!m_state.RegsAreValid(set)) +        return false; + +    const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg); +    if (regInfo) +    { +        value->info = *regInfo; +        switch (set) +        { +        case e_regSetGPR: +            if (reg < k_num_gpr_registers) +            { +                value->value.uint32 = (&m_state.gpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(srr0))[reg]; +                return true; +            } +            break; + +        case e_regSetFPR: +            if (reg < 32) +            { +                value->value.float64 = m_state.fpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(fpregs)[reg]; +                return true; +            } +            else if (reg == 32) +            { +                value->value.uint32 = m_state.fpr.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(fpscr); +                return true; +            } +            break; + +        case e_regSetEXC: +            if (reg < k_num_exc_registers) +            { +                value->value.uint32 = (&m_state.exc.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(dar))[reg]; +                return true; +            } +            break; + +        case e_regSetVEC: +            if (reg < k_num_vec_registers) +            { +                if (reg < 33)            // FP0 - FP31 and VSCR +                { +                    // Copy all 4 uint32 values for this vector register +                    value->value.v_uint32[0] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][0]; +                    value->value.v_uint32[1] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][1]; +                    value->value.v_uint32[2] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][2]; +                    value->value.v_uint32[3] = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vr)[reg][3]; +                    return true; +                } +                else if (reg == 34)    // VRVALID +                { +                    value->value.uint32 = m_state.vec.PREFIX_DOUBLE_UNDERSCORE_DARWIN_UNIX03(save_vrvalid); +                    return true; +                } +            } +            break; +        } +    } +    return false; +} + + +kern_return_t +DNBArchMachPPC::GetRegisterState(int set, bool force) +{ +    switch (set) +    { +    case e_regSetALL: +        return  GetGPRState(force) | +                GetFPRState(force) | +                GetEXCState(force) | +                GetVECState(force); +    case e_regSetGPR:    return GetGPRState(force); +    case e_regSetFPR:    return GetFPRState(force); +    case e_regSetEXC:    return GetEXCState(force); +    case e_regSetVEC:    return GetVECState(force); +    default: break; +    } +    return KERN_INVALID_ARGUMENT; +} + +kern_return_t +DNBArchMachPPC::SetRegisterState(int set) +{ +    // Make sure we have a valid context to set. +    kern_return_t err = GetRegisterState(set, false); +    if (err != KERN_SUCCESS) +        return err; + +    switch (set) +    { +    case e_regSetALL:    return SetGPRState() | SetFPRState() | SetEXCState() | SetVECState(); +    case e_regSetGPR:    return SetGPRState(); +    case e_regSetFPR:    return SetFPRState(); +    case e_regSetEXC:    return SetEXCState(); +    case e_regSetVEC:    return SetVECState(); +    default: break; +    } +    return KERN_INVALID_ARGUMENT; +} + +bool +DNBArchMachPPC::RegisterSetStateIsValid (int set) const +{ +    return m_state.RegsAreValid(set); +} + + +#endif    // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) + | 
