1 |
2 |
sergeykhbr |
/**
|
2 |
|
|
* @file
|
3 |
|
|
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
|
4 |
|
|
* @author Sergey Khabarov - sergeykhbr@gmail.com
|
5 |
|
|
* @brief Base ISA implementation (extension I, privileged level).
|
6 |
|
|
*/
|
7 |
|
|
|
8 |
|
|
#include "api_utils.h"
|
9 |
|
|
#include "riscv-isa.h"
|
10 |
|
|
#include "instructions.h"
|
11 |
|
|
|
12 |
|
|
namespace debugger {
|
13 |
|
|
|
14 |
|
|
void generateException(uint64_t code, CpuContextType *data);
|
15 |
|
|
void generateInterrupt(uint64_t code, CpuContextType *data);
|
16 |
|
|
|
17 |
|
|
uint64_t readCSR(uint32_t idx, CpuContextType *data) {
|
18 |
|
|
uint64_t ret = data->csr[idx];
|
19 |
|
|
switch (idx) {
|
20 |
|
|
case CSR_mtime:
|
21 |
|
|
ret = data->step_cnt;
|
22 |
|
|
break;
|
23 |
|
|
default:;
|
24 |
|
|
}
|
25 |
|
|
return ret;
|
26 |
|
|
}
|
27 |
|
|
|
28 |
|
|
void writeCSR(uint32_t idx, uint64_t val, CpuContextType *data) {
|
29 |
|
|
switch (idx) {
|
30 |
|
|
// Read-Only registers
|
31 |
|
|
case CSR_misa:
|
32 |
|
|
case CSR_mvendorid:
|
33 |
|
|
case CSR_marchid:
|
34 |
|
|
case CSR_mimplementationid:
|
35 |
|
|
case CSR_mhartid:
|
36 |
|
|
break;
|
37 |
|
|
case CSR_mtime:
|
38 |
|
|
break;
|
39 |
|
|
default:
|
40 |
|
|
data->csr[idx] = val;
|
41 |
|
|
}
|
42 |
|
|
}
|
43 |
|
|
|
44 |
|
|
/**
|
45 |
|
|
* @brief The CSRRC (Atomic Read and Clear Bit in CSR).
|
46 |
|
|
*
|
47 |
|
|
* Instruction reads the value of the CSR, zeroextends the value to XLEN bits,
|
48 |
|
|
* and writes it to integer register rd. The initial value in integer
|
49 |
|
|
* register rs1 specifies bit positions to be cleared in the CSR. Any bit that
|
50 |
|
|
* is high in rs1 will cause the corresponding bit to be cleared in the CSR,
|
51 |
|
|
* if that CSR bit is writable. Other bits in the CSR are unaffected.
|
52 |
|
|
*/
|
53 |
|
|
class CSRRC : public IsaProcessor {
|
54 |
|
|
public:
|
55 |
|
|
CSRRC() : IsaProcessor("CSRRC", "?????????????????011?????1110011") {}
|
56 |
|
|
|
57 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
58 |
|
|
ISA_I_type u;
|
59 |
|
|
u.value = payload[0];
|
60 |
|
|
|
61 |
|
|
uint64_t clr_mask = ~data->regs[u.bits.rs1];
|
62 |
|
|
uint64_t csr = readCSR(u.bits.imm, data);
|
63 |
|
|
if (u.bits.rd) {
|
64 |
|
|
data->regs[u.bits.rd] = csr;
|
65 |
|
|
}
|
66 |
|
|
writeCSR(u.bits.imm, (csr & clr_mask), data);
|
67 |
|
|
data->npc = data->pc + 4;
|
68 |
|
|
}
|
69 |
|
|
};
|
70 |
|
|
|
71 |
|
|
/**
|
72 |
|
|
* @brief The CSRRCI (Atomic Read and Clear Bit in CSR immediate).
|
73 |
|
|
*
|
74 |
|
|
* Similar to CSRRC except it updates the CSR using a 5-bit zero-extended
|
75 |
|
|
* immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
|
76 |
|
|
* an integer register.
|
77 |
|
|
*/
|
78 |
|
|
class CSRRCI : public IsaProcessor {
|
79 |
|
|
public:
|
80 |
|
|
CSRRCI() : IsaProcessor("CSRRCI", "?????????????????111?????1110011") {}
|
81 |
|
|
|
82 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
83 |
|
|
ISA_I_type u;
|
84 |
|
|
u.value = payload[0];
|
85 |
|
|
|
86 |
|
|
uint64_t clr_mask = ~static_cast<uint64_t>((u.bits.rs1));
|
87 |
|
|
uint64_t csr = readCSR(u.bits.imm, data);
|
88 |
|
|
if (u.bits.rd) {
|
89 |
|
|
data->regs[u.bits.rd] = csr;
|
90 |
|
|
}
|
91 |
|
|
writeCSR(u.bits.imm, (csr & clr_mask), data);
|
92 |
|
|
data->npc = data->pc + 4;
|
93 |
|
|
}
|
94 |
|
|
};
|
95 |
|
|
|
96 |
|
|
/**
|
97 |
|
|
* @brief The CSRRS (Atomic Read and Set Bit in CSR).
|
98 |
|
|
*
|
99 |
|
|
* Instruction reads the value of the CSR, zero-extends the value to XLEN
|
100 |
|
|
* bits, and writes it to integer register rd. The initial value in integer
|
101 |
|
|
* register rs1 specifies bit positions to be set in the CSR. Any bit that is
|
102 |
|
|
* high in rs1 will cause the corresponding bit to be set in the CSR, if that
|
103 |
|
|
* CSR bit is writable. Other bits in the CSR are unaffected (though CSRs
|
104 |
|
|
* might have side effects when written).
|
105 |
|
|
* The CSRR pseudo instruction (read CSR), when rs1 = 0.
|
106 |
|
|
*/
|
107 |
|
|
class CSRRS : public IsaProcessor {
|
108 |
|
|
public:
|
109 |
|
|
CSRRS() : IsaProcessor("CSRRS", "?????????????????010?????1110011") {}
|
110 |
|
|
|
111 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
112 |
|
|
ISA_I_type u;
|
113 |
|
|
u.value = payload[0];
|
114 |
|
|
|
115 |
|
|
uint64_t set_mask = data->regs[u.bits.rs1];
|
116 |
|
|
uint64_t csr = readCSR(u.bits.imm, data);
|
117 |
|
|
if (u.bits.rd) {
|
118 |
|
|
data->regs[u.bits.rd] = csr;
|
119 |
|
|
}
|
120 |
|
|
writeCSR(u.bits.imm, (csr | set_mask), data);
|
121 |
|
|
data->npc = data->pc + 4;
|
122 |
|
|
}
|
123 |
|
|
};
|
124 |
|
|
|
125 |
|
|
/**
|
126 |
|
|
* @brief The CSRRSI (Atomic Read and Set Bit in CSR immediate).
|
127 |
|
|
*
|
128 |
|
|
* Similar to CSRRS except it updates the CSR using a 5-bit zero-extended
|
129 |
|
|
* immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
|
130 |
|
|
* an integer register.
|
131 |
|
|
*/
|
132 |
|
|
class CSRRSI : public IsaProcessor {
|
133 |
|
|
public:
|
134 |
|
|
CSRRSI() : IsaProcessor("CSRRSI", "?????????????????110?????1110011") {}
|
135 |
|
|
|
136 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
137 |
|
|
ISA_I_type u;
|
138 |
|
|
u.value = payload[0];
|
139 |
|
|
|
140 |
|
|
uint64_t set_mask = u.bits.rs1;
|
141 |
|
|
uint64_t csr = readCSR(u.bits.imm, data);
|
142 |
|
|
if (u.bits.rd) {
|
143 |
|
|
data->regs[u.bits.rd] = csr;
|
144 |
|
|
}
|
145 |
|
|
writeCSR(u.bits.imm, (csr | set_mask), data);
|
146 |
|
|
data->npc = data->pc + 4;
|
147 |
|
|
}
|
148 |
|
|
};
|
149 |
|
|
|
150 |
|
|
/**
|
151 |
|
|
* @brief The CSRRW (Atomic Read/Write CSR).
|
152 |
|
|
*
|
153 |
|
|
* Instruction atomically swaps values in the CSRs and integer registers.
|
154 |
|
|
* CSRRW reads the old value of the CSR, zero-extends the value to XLEN bits,
|
155 |
|
|
* then writes it to integer register rd. The initial value in rs1 is written
|
156 |
|
|
* to the CSR.
|
157 |
|
|
* The CSRW pseudo instruction (write CSR), when rs1 = 0.
|
158 |
|
|
*/
|
159 |
|
|
class CSRRW : public IsaProcessor {
|
160 |
|
|
public:
|
161 |
|
|
CSRRW() : IsaProcessor("CSRRW", "?????????????????001?????1110011") {}
|
162 |
|
|
|
163 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
164 |
|
|
ISA_I_type u;
|
165 |
|
|
u.value = payload[0];
|
166 |
|
|
|
167 |
|
|
uint64_t wr_value = data->regs[u.bits.rs1];
|
168 |
|
|
if (u.bits.rd) {
|
169 |
|
|
data->regs[u.bits.rd] = readCSR(u.bits.imm, data);
|
170 |
|
|
}
|
171 |
|
|
writeCSR(u.bits.imm, wr_value, data);
|
172 |
|
|
data->npc = data->pc + 4;
|
173 |
|
|
}
|
174 |
|
|
};
|
175 |
|
|
|
176 |
|
|
/**
|
177 |
|
|
* @brief The CSRRWI (Atomic Read/Write CSR immediate).
|
178 |
|
|
*
|
179 |
|
|
* Similar to CSRRW except it updates the CSR using a 5-bit zero-extended
|
180 |
|
|
* immediate (zimm[4:0]) encoded in the rs1 field instead of a value from
|
181 |
|
|
* an integer register.
|
182 |
|
|
*/
|
183 |
|
|
class CSRRWI : public IsaProcessor {
|
184 |
|
|
public:
|
185 |
|
|
CSRRWI() : IsaProcessor("CSRRWI", "?????????????????101?????1110011") {}
|
186 |
|
|
|
187 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
188 |
|
|
ISA_I_type u;
|
189 |
|
|
u.value = payload[0];
|
190 |
|
|
|
191 |
|
|
uint64_t wr_value = u.bits.rs1;
|
192 |
|
|
if (u.bits.rd) {
|
193 |
|
|
data->regs[u.bits.rd] = readCSR(u.bits.imm, data);
|
194 |
|
|
}
|
195 |
|
|
writeCSR(u.bits.imm, wr_value, data);
|
196 |
|
|
data->npc = data->pc + 4;
|
197 |
|
|
}
|
198 |
|
|
};
|
199 |
|
|
|
200 |
|
|
/**
|
201 |
|
|
* @brief MRET, HRET, SRET, or URET
|
202 |
|
|
*
|
203 |
|
|
* These instructions are used to return from traps in M-mode, Hmode,
|
204 |
|
|
* S-mode, or U-mode respectively. When executing an xRET instruction,
|
205 |
|
|
* supposing x PP holds the value y, y IE is set to x PIE; the privilege
|
206 |
|
|
* mode is changed to y; x PIE is set to 1; and x PP is set to U
|
207 |
|
|
* (or M if user-mode is not supported).
|
208 |
|
|
*
|
209 |
|
|
* User-level interrupts are an optional extension and have been allocated
|
210 |
|
|
* the ISA extension letter N. If user-level interrupts are omitted, the UIE
|
211 |
|
|
* and UPIE bits are hardwired to zero. For all other supported privilege
|
212 |
|
|
* modes x, the x IE, x PIE, and x PP fields are required to be implemented.
|
213 |
|
|
*/
|
214 |
|
|
class URET : public IsaProcessor {
|
215 |
|
|
public:
|
216 |
|
|
URET() : IsaProcessor("URET", "00000000001000000000000001110011") {}
|
217 |
|
|
|
218 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
219 |
|
|
if (data->cur_prv_level != PRV_U) {
|
220 |
|
|
generateException(EXCEPTION_InstrIllegal, data);
|
221 |
|
|
return;
|
222 |
|
|
}
|
223 |
|
|
csr_mstatus_type mstatus;
|
224 |
|
|
mstatus.value = readCSR(CSR_mstatus, data);
|
225 |
|
|
|
226 |
|
|
uint64_t xepc = (PRV_U << 8) + 0x41;
|
227 |
|
|
data->npc = readCSR(static_cast<uint32_t>(xepc), data);
|
228 |
|
|
|
229 |
|
|
bool is_N_extension = false;
|
230 |
|
|
if (is_N_extension) {
|
231 |
|
|
mstatus.bits.UIE = mstatus.bits.UPIE;
|
232 |
|
|
mstatus.bits.UPIE = 1;
|
233 |
|
|
// User mode not changed.
|
234 |
|
|
} else {
|
235 |
|
|
mstatus.bits.UIE = 0;
|
236 |
|
|
mstatus.bits.UPIE = 0;
|
237 |
|
|
}
|
238 |
|
|
data->cur_prv_level = PRV_U;
|
239 |
|
|
writeCSR(CSR_mstatus, mstatus.value, data);
|
240 |
|
|
}
|
241 |
|
|
};
|
242 |
|
|
|
243 |
|
|
/**
|
244 |
|
|
* @brief SRET return from super-user mode
|
245 |
|
|
*/
|
246 |
|
|
class SRET : public IsaProcessor {
|
247 |
|
|
public:
|
248 |
|
|
SRET() : IsaProcessor("SRET", "00010000001000000000000001110011") {}
|
249 |
|
|
|
250 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
251 |
|
|
if (data->cur_prv_level != PRV_S) {
|
252 |
|
|
generateException(EXCEPTION_InstrIllegal, data);
|
253 |
|
|
return;
|
254 |
|
|
}
|
255 |
|
|
csr_mstatus_type mstatus;
|
256 |
|
|
mstatus.value = readCSR(CSR_mstatus, data);
|
257 |
|
|
|
258 |
|
|
uint64_t xepc = (PRV_S << 8) + 0x41;
|
259 |
|
|
data->npc = readCSR(static_cast<uint32_t>(xepc), data);
|
260 |
|
|
|
261 |
|
|
mstatus.bits.SIE = mstatus.bits.SPIE;
|
262 |
|
|
mstatus.bits.SPIE = 1;
|
263 |
|
|
data->cur_prv_level = mstatus.bits.SPP;
|
264 |
|
|
mstatus.bits.SPP = PRV_U;
|
265 |
|
|
|
266 |
|
|
writeCSR(CSR_mstatus, mstatus.value, data);
|
267 |
|
|
}
|
268 |
|
|
};
|
269 |
|
|
|
270 |
|
|
/**
|
271 |
|
|
* @brief HRET return from hypervisor mode
|
272 |
|
|
*/
|
273 |
|
|
class HRET : public IsaProcessor {
|
274 |
|
|
public:
|
275 |
|
|
HRET() : IsaProcessor("HRET", "00100000001000000000000001110011") {}
|
276 |
|
|
|
277 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
278 |
|
|
if (data->cur_prv_level != PRV_H) {
|
279 |
|
|
generateException(EXCEPTION_InstrIllegal, data);
|
280 |
|
|
return;
|
281 |
|
|
}
|
282 |
|
|
csr_mstatus_type mstatus;
|
283 |
|
|
mstatus.value = readCSR(CSR_mstatus, data);
|
284 |
|
|
|
285 |
|
|
uint64_t xepc = (PRV_H << 8) + 0x41;
|
286 |
|
|
data->npc = readCSR(static_cast<uint32_t>(xepc), data);
|
287 |
|
|
|
288 |
|
|
mstatus.bits.HIE = mstatus.bits.HPIE;
|
289 |
|
|
mstatus.bits.HPIE = 1;
|
290 |
|
|
data->cur_prv_level = mstatus.bits.HPP;
|
291 |
|
|
mstatus.bits.HPP = PRV_U;
|
292 |
|
|
|
293 |
|
|
writeCSR(CSR_mstatus, mstatus.value, data);
|
294 |
|
|
}
|
295 |
|
|
};
|
296 |
|
|
|
297 |
|
|
/**
|
298 |
|
|
* @brief MRET return from machine mode
|
299 |
|
|
*/
|
300 |
|
|
class MRET : public IsaProcessor {
|
301 |
|
|
public:
|
302 |
|
|
MRET() : IsaProcessor("MRET", "00110000001000000000000001110011") {}
|
303 |
|
|
|
304 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
305 |
|
|
if (data->cur_prv_level != PRV_M) {
|
306 |
|
|
generateException(EXCEPTION_InstrIllegal, data);
|
307 |
|
|
return;
|
308 |
|
|
}
|
309 |
|
|
csr_mstatus_type mstatus;
|
310 |
|
|
mstatus.value = readCSR(CSR_mstatus, data);
|
311 |
|
|
|
312 |
|
|
uint64_t xepc = (PRV_M << 8) + 0x41;
|
313 |
|
|
data->npc = readCSR(static_cast<uint32_t>(xepc), data);
|
314 |
|
|
|
315 |
|
|
mstatus.bits.MIE = mstatus.bits.MPIE;
|
316 |
|
|
mstatus.bits.MPIE = 1;
|
317 |
|
|
data->cur_prv_level = mstatus.bits.MPP;
|
318 |
|
|
mstatus.bits.MPP = PRV_U;
|
319 |
|
|
|
320 |
|
|
// Emulating interrupt strob (not pulse from external controller)
|
321 |
|
|
if (data->interrupt_pending) {
|
322 |
|
|
generateInterrupt(INTERRUPT_MExternal, data);
|
323 |
|
|
}
|
324 |
|
|
|
325 |
|
|
writeCSR(CSR_mstatus, mstatus.value, data);
|
326 |
|
|
}
|
327 |
|
|
};
|
328 |
|
|
|
329 |
|
|
|
330 |
|
|
/**
|
331 |
|
|
* @brief FENCE (memory barrier)
|
332 |
|
|
*
|
333 |
|
|
* Not used in functional model so that cache is not modeling.
|
334 |
|
|
*/
|
335 |
|
|
class FENCE : public IsaProcessor {
|
336 |
|
|
public:
|
337 |
|
|
FENCE() : IsaProcessor("FENCE", "?????????????????000?????0001111") {}
|
338 |
|
|
|
339 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
340 |
|
|
data->npc = data->pc + 4;
|
341 |
|
|
}
|
342 |
|
|
};
|
343 |
|
|
|
344 |
|
|
/**
|
345 |
|
|
* @brief FENCE_I (memory barrier)
|
346 |
|
|
*
|
347 |
|
|
* Not used in functional model so that cache is not modeling.
|
348 |
|
|
*/
|
349 |
|
|
class FENCE_I : public IsaProcessor {
|
350 |
|
|
public:
|
351 |
|
|
FENCE_I() : IsaProcessor("FENCE_I", "?????????????????001?????0001111") {}
|
352 |
|
|
|
353 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
354 |
|
|
data->npc = data->pc + 4;
|
355 |
|
|
}
|
356 |
|
|
};
|
357 |
|
|
|
358 |
|
|
/**
|
359 |
|
|
* @brief EBREAK (breakpoint instruction)
|
360 |
|
|
*
|
361 |
|
|
* The EBREAK instruction is used by debuggers to cause control to be
|
362 |
|
|
* transferred back to a debug-ging environment.
|
363 |
|
|
*/
|
364 |
|
|
class EBREAK : public IsaProcessor {
|
365 |
|
|
public:
|
366 |
|
|
EBREAK() : IsaProcessor("EBREAK", "00000000000100000000000001110011") {}
|
367 |
|
|
|
368 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
369 |
|
|
data->npc = data->pc + 4;
|
370 |
|
|
data->br_status_ena = true;
|
371 |
|
|
generateException(EXCEPTION_Breakpoint, data);
|
372 |
|
|
}
|
373 |
|
|
};
|
374 |
|
|
|
375 |
|
|
/**
|
376 |
|
|
* @brief ECALL (environment call instruction)
|
377 |
|
|
*
|
378 |
|
|
* The ECALL instruction is used to make a request to the supporting execution
|
379 |
|
|
* environment, which isusually an operating system. The ABI for the system
|
380 |
|
|
* will define how parameters for the environment request are passed, but usually
|
381 |
|
|
* these will be in defined locations in the integer register file.
|
382 |
|
|
*/
|
383 |
|
|
class ECALL : public IsaProcessor {
|
384 |
|
|
public:
|
385 |
|
|
ECALL() : IsaProcessor("ECALL", "00000000000000000000000001110011") {}
|
386 |
|
|
|
387 |
|
|
virtual void exec(uint32_t *payload, CpuContextType *data) {
|
388 |
|
|
data->npc = data->pc + 4;
|
389 |
|
|
switch (data->cur_prv_level) {
|
390 |
|
|
case PRV_M:
|
391 |
|
|
generateException(EXCEPTION_CallFromMmode, data);
|
392 |
|
|
break;
|
393 |
|
|
case PRV_U:
|
394 |
|
|
generateException(EXCEPTION_CallFromUmode, data);
|
395 |
|
|
break;
|
396 |
|
|
default:;
|
397 |
|
|
}
|
398 |
|
|
}
|
399 |
|
|
};
|
400 |
|
|
|
401 |
|
|
|
402 |
|
|
void addIsaPrivilegedRV64I(CpuContextType *data, AttributeType *out) {
|
403 |
|
|
addSupportedInstruction(new CSRRC, out);
|
404 |
|
|
addSupportedInstruction(new CSRRCI, out);
|
405 |
|
|
addSupportedInstruction(new CSRRS, out);
|
406 |
|
|
addSupportedInstruction(new CSRRSI, out);
|
407 |
|
|
addSupportedInstruction(new CSRRW, out);
|
408 |
|
|
addSupportedInstruction(new CSRRWI, out);
|
409 |
|
|
addSupportedInstruction(new URET, out);
|
410 |
|
|
addSupportedInstruction(new SRET, out);
|
411 |
|
|
addSupportedInstruction(new HRET, out);
|
412 |
|
|
addSupportedInstruction(new MRET, out);
|
413 |
|
|
addSupportedInstruction(new FENCE, out);
|
414 |
|
|
addSupportedInstruction(new FENCE_I, out);
|
415 |
|
|
addSupportedInstruction(new ECALL, out);
|
416 |
|
|
addSupportedInstruction(new EBREAK, out);
|
417 |
|
|
// TODO:
|
418 |
|
|
/*
|
419 |
|
|
def DRET = BitPat("b01111011001000000000000001110011")
|
420 |
|
|
def SFENCE_VM = BitPat("b000100000100?????000000001110011")
|
421 |
|
|
def WFI = BitPat("b00010000010100000000000001110011") // wait for interrupt
|
422 |
|
|
|
423 |
|
|
def RDCYCLE = BitPat("b11000000000000000010?????1110011")
|
424 |
|
|
def RDTIME = BitPat("b11000000000100000010?????1110011")
|
425 |
|
|
def RDINSTRET = BitPat("b11000000001000000010?????1110011")
|
426 |
|
|
def RDCYCLEH = BitPat("b11001000000000000010?????1110011")
|
427 |
|
|
def RDTIMEH = BitPat("b11001000000100000010?????1110011")
|
428 |
|
|
def RDINSTRETH = BitPat("b11001000001000000010?????1110011")
|
429 |
|
|
def ECALL = BitPat("b00000000000000000000000001110011")
|
430 |
|
|
def EBREAK = BitPat("b00000000000100000000000001110011")
|
431 |
|
|
*/
|
432 |
|
|
|
433 |
|
|
/**
|
434 |
|
|
* The 'U', 'S', and 'H' bits will be set if there is support for
|
435 |
|
|
* user, supervisor, and hypervisor privilege modes respectively.
|
436 |
|
|
*/
|
437 |
|
|
data->csr[CSR_misa] |= (1LL << ('U' - 'A'));
|
438 |
|
|
data->csr[CSR_misa] |= (1LL << ('S' - 'A'));
|
439 |
|
|
data->csr[CSR_misa] |= (1LL << ('H' - 'A'));
|
440 |
|
|
}
|
441 |
|
|
|
442 |
|
|
} // namespace debugger
|