summaryrefslogtreecommitdiffstats
path: root/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h
blob: 8aed9fc0f80aec9e1a280c63b1598680d8fd3783 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
//===-- 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__
OpenPOWER on IntegriCloud