//===-- DNBArchImpl.h -------------------------------------------*- 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. // //===----------------------------------------------------------------------===// #ifndef __DebugNubArchMachPPC_h__ #define __DebugNubArchMachPPC_h__ #if defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) #include "DNBArch.h" class MachThread; class DNBArchMachPPC : public DNBArchProtocol { public: DNBArchMachPPC(MachThread *thread) : m_thread(thread), m_state() {} virtual ~DNBArchMachPPC() {} virtual const DNBRegisterSetInfo * GetRegisterSetInfo(nub_size_t *num_reg_sets) const; virtual bool GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value) const; virtual kern_return_t GetRegisterState(int set, bool force); virtual kern_return_t SetRegisterState(int set); virtual bool RegisterSetStateIsValid(int set) const; virtual uint64_t GetPC(uint64_t failValue); // Get program counter virtual kern_return_t SetPC(uint64_t value); virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer virtual bool ThreadWillResume(); virtual bool ThreadDidStop(); static const uint8_t *SoftwareBreakpointOpcode(nub_size_t byte_size); static uint32_t GetCPUType(); protected: kern_return_t EnableHardwareSingleStep(bool enable); typedef enum RegisterSetTag { e_regSetALL = REGISTER_SET_ALL, e_regSetGPR, e_regSetFPR, e_regSetEXC, e_regSetVEC, kNumRegisterSets } RegisterSet; typedef enum RegisterSetWordSizeTag { e_regSetWordSizeGPR = PPC_THREAD_STATE_COUNT, e_regSetWordSizeFPR = PPC_FLOAT_STATE_COUNT, e_regSetWordSizeEXC = PPC_EXCEPTION_STATE_COUNT, e_regSetWordSizeVEC = PPC_VECTOR_STATE_COUNT } RegisterSetWordSize; enum { Read = 0, Write = 1, kNumErrors = 2 }; struct State { ppc_thread_state_t gpr; ppc_float_state_t fpr; ppc_exception_state_t exc; ppc_vector_state_t vec; kern_return_t gpr_errs[2]; // Read/Write errors kern_return_t fpr_errs[2]; // Read/Write errors kern_return_t exc_errs[2]; // Read/Write errors kern_return_t vec_errs[2]; // Read/Write errors State() { uint32_t i; for (i = 0; i < kNumErrors; i++) { gpr_errs[i] = -1; fpr_errs[i] = -1; exc_errs[i] = -1; vec_errs[i] = -1; } } void InvalidateAllRegisterStates() { SetError(e_regSetALL, Read, -1); } kern_return_t GetError(int set, uint32_t err_idx) const { if (err_idx < kNumErrors) { switch (set) { // When getting all errors, just OR all values together to see if // we got any kind of error. case e_regSetALL: return gpr_errs[err_idx] | fpr_errs[err_idx] | exc_errs[err_idx] | vec_errs[err_idx]; case e_regSetGPR: return gpr_errs[err_idx]; case e_regSetFPR: return fpr_errs[err_idx]; case e_regSetEXC: return exc_errs[err_idx]; case e_regSetVEC: return vec_errs[err_idx]; default: break; } } return -1; } bool SetError(int set, uint32_t err_idx, kern_return_t err) { if (err_idx < kNumErrors) { switch (set) { case e_regSetALL: gpr_errs[err_idx] = fpr_errs[err_idx] = exc_errs[err_idx] = vec_errs[err_idx] = err; return true; case e_regSetGPR: gpr_errs[err_idx] = err; return true; case e_regSetFPR: fpr_errs[err_idx] = err; return true; case e_regSetEXC: exc_errs[err_idx] = err; return true; case e_regSetVEC: vec_errs[err_idx] = err; return true; default: break; } } return false; } bool RegsAreValid(int set) const { return GetError(set, Read) == KERN_SUCCESS; } }; kern_return_t GetGPRState(bool force); kern_return_t GetFPRState(bool force); kern_return_t GetEXCState(bool force); kern_return_t GetVECState(bool force); kern_return_t SetGPRState(); kern_return_t SetFPRState(); kern_return_t SetEXCState(); kern_return_t SetVECState(); protected: MachThread *m_thread; State m_state; }; #endif // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) #endif // #ifndef __DebugNubArchMachPPC_h__