DebugServer2
Loading...
Searching...
No Matches
CPUState.h
1// Copyright 2022 Saleem Abdulrasool <compnerd@compnerd.org>
2
3#pragma once
4
5#if !defined(CPUSTATE_H_INTERNAL)
6#error "You shall not include this file directly."
7#endif
8
9#if __riscv_xlen == 32
10#include "DebugServer2/Architecture/RISCV32/RegistersDescriptors.h"
11#elif __riscv_xlen == 64
12#include "DebugServer2/Architecture/RISCV64/RegistersDescriptors.h"
13#elif __riscv_xlen == 128
14#include "DebugServer2/Architecture/RISCV128/RegistersDescriptors.h"
15#endif
16
17#include <algorithm>
18
19namespace ds2 {
20namespace Architecture {
21namespace RISCV {
22
23#pragma pack(push)
24
25struct CPUState {
26 union {
27 uintptr_t regs[32];
28 struct {
29 // NOTE: pc takes the x0 slot to match `struct user_reg_state`. x0 is
30 // hardwired to zero, so the value can always be materialized.
31 uintptr_t pc, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14,
32 x15, x16, x17, x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28,
33 x29, x30, x31;
34 };
35 } gp = {0};
36
37 // TODO(compnerd) support quad precision
38 struct {
39 union {
40 uint32_t sng[32];
41 uint64_t dbl[32];
42 };
43 uint32_t fcsr;
44 } fp = {0};
45
46public:
47 //
48 // Accessors
49 //
50
51 inline uintptr_t pc() const { return gp.pc; }
52 inline void setPC(uintptr_t pc) { gp.pc = pc; }
53
54 inline uintptr_t retval() const { return gp.x1; }
55
56public:
57 inline void getGPState(GPRegisterValueVector &regs) const {
58 regs.clear();
59 regs.emplace_back(GPRegisterValue{sizeof(uintptr_t), 0x0});
60 std::transform(std::next(std::begin(gp.regs)), std::end(gp.regs),
61 std::back_inserter(regs),
62 [](uintptr_t reg) -> GPRegisterValue {
63 return GPRegisterValue{sizeof(reg), reg};
64 });
65 regs.emplace_back(GPRegisterValue{sizeof(uintptr_t), gp.pc});
66 }
67
68 inline void setGPState(std::vector<uintptr_t> const &regs) {
69 for (size_t reg = 1, nregs = std::min(std::size(regs), std::size(gp.regs));
70 reg < nregs; ++reg)
71 gp.regs[reg % (std::size(gp.regs) - 1)] = regs[reg];
72 }
73
74public:
75 inline void getStopGPState(GPRegisterStopMap &regs, bool forLLDB) const {
76#if __riscv_xlen == 32
77 using namespace ds2::Architecture::RISCV32;
78#elif __riscv_xlen == 64
79 using namespace ds2::Architecture::RISCV64;
80#elif __riscv_xlen == 128
81 using namespace ds2::Architecture::RISCV128;
82#endif
83
84 if (forLLDB) {
85 regs[reg_lldb_x0] = GPRegisterValue{sizeof(uintptr_t), 0};
86 for (size_t reg = 1, nregs = std::size(gp.regs); reg < nregs; ++reg)
87 regs[reg_lldb_x0 + reg] =
88 GPRegisterValue{sizeof(uintptr_t), gp.regs[reg]};
89 regs[reg_lldb_pc] = GPRegisterValue{sizeof(uintptr_t), gp.pc};
90 } else {
91 regs[reg_gdb_x0] = GPRegisterValue{sizeof(uintptr_t), 0};
92 for (size_t reg = 1, nregs = std::size(gp.regs); reg < nregs; ++reg)
93 regs[reg_gdb_x0 + reg] =
94 GPRegisterValue{sizeof(uintptr_t), gp.regs[reg]};
95 regs[reg_gdb_pc] = GPRegisterValue{sizeof(uintptr_t), gp.pc};
96 }
97 }
98
99public:
100 inline bool getLLDBRegisterPtr(int regno, void **ptr, size_t *length) const {
101#if __riscv_xlen == 32
102 using namespace ds2::Architecture::RISCV32;
103#elif __riscv_xlen == 64
104 using namespace ds2::Architecture::RISCV64;
105#elif __riscv_xlen == 128
106 using namespace ds2::Architecture::RISCV128;
107#endif
108
109 if (regno >= reg_lldb_x1 && regno <= reg_lldb_x31) {
110 *ptr = const_cast<uintptr_t *>(&gp.regs[regno - reg_lldb_x1]);
111 *length = sizeof(gp.regs[0]);
112 } else if (regno == reg_lldb_pc) {
113 *ptr = const_cast<uintptr_t *>(&gp.pc);
114 *length = sizeof(gp.pc);
115 } else if (regno >= reg_lldb_f0 && regno <= reg_lldb_f31) {
116#if __riscv_flen == 32
117 *ptr = const_cast<uint32_t *>(&fp.sng[regno - reg_lldb_f0]);
118 *length = sizeof(fp.sng[0]);
119#elif __riscv_flen == 64
120 *ptr = const_cast<uint64_t *>(&fp.dbl[regno - reg_lldb_f0]);
121 *length = sizeof(fp.dbl[0]);
122#elif __riscv_flen == 128
123#error "quad precision floating point support unimplemented"
124#else
125 return false;
126#endif
127 } else if (regno == reg_lldb_fcsr) {
128 *ptr = const_cast<uint32_t *>(&fp.fcsr);
129 *length = sizeof(fp.fcsr);
130 } else {
131 return false;
132 }
133 return true;
134 }
135
136 inline bool getGDBRegisterPtr(int regno, void **ptr, size_t *length) const {
137#if __riscv_xlen == 32
138 using namespace ds2::Architecture::RISCV32;
139#elif __riscv_xlen == 64
140 using namespace ds2::Architecture::RISCV64;
141#elif __riscv_xlen == 128
142 using namespace ds2::Architecture::RISCV128;
143#endif
144
145 if (regno >= reg_gdb_x1 && regno <= reg_gdb_x31) {
146 *ptr = const_cast<uintptr_t *>(&gp.regs[regno - reg_gdb_x1]);
147 *length = sizeof(gp.regs[0]);
148 } else if (regno == reg_gdb_pc) {
149 *ptr = const_cast<uintptr_t *>(&gp.pc);
150 *length = sizeof(gp.pc);
151 } else if (regno >= reg_gdb_f0 && regno <= reg_gdb_f31) {
152#if __riscv_flen == 32
153 *ptr = const_cast<uint32_t *>(&fp.sng[regno - reg_gdb_f0]);
154 *length = sizeof(fp.sng[0]);
155#elif __riscv_flen == 64
156 *ptr = const_cast<uint64_t *>(&fp.dbl[regno - reg_gdb_f0]);
157 *length = sizeof(fp.dbl[0]);
158#elif __riscv_flen == 128
159#error "quad precision floating point support unimplemented"
160#else
161 return false;
162#endif
163 } else if (regno == reg_gdb_fcsr) {
164 *ptr = const_cast<uint32_t *>(&fp.fcsr);
165 *length = sizeof(fp.fcsr);
166 } else {
167 return false;
168 }
169 return true;
170 }
171};
172
173#pragma pack(pop)
174
175} // namespace RISCV
176} // namespace Architecture
177} // namespace ds2
Definition RegisterLayout.h:167
Definition CPUState.h:25