xref: /openbmc/qemu/target/riscv/cpu.h (revision 69077dd6)
1 /*
2  * QEMU RISC-V CPU
3  *
4  * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5  * Copyright (c) 2017-2018 SiFive, Inc.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU General Public License,
9  * version 2 or later, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along with
17  * this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef RISCV_CPU_H
21 #define RISCV_CPU_H
22 
23 #include "hw/core/cpu.h"
24 #include "hw/registerfields.h"
25 #include "exec/cpu-defs.h"
26 #include "fpu/softfloat-types.h"
27 #include "qom/object.h"
28 #include "qemu/int128.h"
29 #include "cpu_bits.h"
30 
31 #define TCG_GUEST_DEFAULT_MO 0
32 
33 #define TYPE_RISCV_CPU "riscv-cpu"
34 
35 #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU
36 #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX)
37 #define CPU_RESOLVING_TYPE TYPE_RISCV_CPU
38 
39 #define TYPE_RISCV_CPU_ANY              RISCV_CPU_TYPE_NAME("any")
40 #define TYPE_RISCV_CPU_BASE32           RISCV_CPU_TYPE_NAME("rv32")
41 #define TYPE_RISCV_CPU_BASE64           RISCV_CPU_TYPE_NAME("rv64")
42 #define TYPE_RISCV_CPU_BASE128          RISCV_CPU_TYPE_NAME("x-rv128")
43 #define TYPE_RISCV_CPU_IBEX             RISCV_CPU_TYPE_NAME("lowrisc-ibex")
44 #define TYPE_RISCV_CPU_SHAKTI_C         RISCV_CPU_TYPE_NAME("shakti-c")
45 #define TYPE_RISCV_CPU_SIFIVE_E31       RISCV_CPU_TYPE_NAME("sifive-e31")
46 #define TYPE_RISCV_CPU_SIFIVE_E34       RISCV_CPU_TYPE_NAME("sifive-e34")
47 #define TYPE_RISCV_CPU_SIFIVE_E51       RISCV_CPU_TYPE_NAME("sifive-e51")
48 #define TYPE_RISCV_CPU_SIFIVE_U34       RISCV_CPU_TYPE_NAME("sifive-u34")
49 #define TYPE_RISCV_CPU_SIFIVE_U54       RISCV_CPU_TYPE_NAME("sifive-u54")
50 #define TYPE_RISCV_CPU_HOST             RISCV_CPU_TYPE_NAME("host")
51 
52 #if defined(TARGET_RISCV32)
53 # define TYPE_RISCV_CPU_BASE            TYPE_RISCV_CPU_BASE32
54 #elif defined(TARGET_RISCV64)
55 # define TYPE_RISCV_CPU_BASE            TYPE_RISCV_CPU_BASE64
56 #endif
57 
58 #define RV(x) ((target_ulong)1 << (x - 'A'))
59 
60 #define RVI RV('I')
61 #define RVE RV('E') /* E and I are mutually exclusive */
62 #define RVM RV('M')
63 #define RVA RV('A')
64 #define RVF RV('F')
65 #define RVD RV('D')
66 #define RVV RV('V')
67 #define RVC RV('C')
68 #define RVS RV('S')
69 #define RVU RV('U')
70 #define RVH RV('H')
71 #define RVJ RV('J')
72 
73 /* S extension denotes that Supervisor mode exists, however it is possible
74    to have a core that support S mode but does not have an MMU and there
75    is currently no bit in misa to indicate whether an MMU exists or not
76    so a cpu features bitfield is required, likewise for optional PMP support */
77 enum {
78     RISCV_FEATURE_MMU,
79     RISCV_FEATURE_PMP,
80     RISCV_FEATURE_EPMP,
81     RISCV_FEATURE_MISA,
82     RISCV_FEATURE_AIA
83 };
84 
85 #define PRIV_VERSION_1_10_0 0x00011000
86 #define PRIV_VERSION_1_11_0 0x00011100
87 
88 #define VEXT_VERSION_1_00_0 0x00010000
89 
90 enum {
91     TRANSLATE_SUCCESS,
92     TRANSLATE_FAIL,
93     TRANSLATE_PMP_FAIL,
94     TRANSLATE_G_STAGE_FAIL
95 };
96 
97 #define MMU_USER_IDX 3
98 
99 #define MAX_RISCV_PMPS (16)
100 
101 typedef struct CPURISCVState CPURISCVState;
102 
103 #if !defined(CONFIG_USER_ONLY)
104 #include "pmp.h"
105 #endif
106 
107 #define RV_VLEN_MAX 1024
108 
109 FIELD(VTYPE, VLMUL, 0, 3)
110 FIELD(VTYPE, VSEW, 3, 3)
111 FIELD(VTYPE, VTA, 6, 1)
112 FIELD(VTYPE, VMA, 7, 1)
113 FIELD(VTYPE, VEDIV, 8, 2)
114 FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
115 
116 struct CPURISCVState {
117     target_ulong gpr[32];
118     target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
119     uint64_t fpr[32]; /* assume both F and D extensions */
120 
121     /* vector coprocessor state. */
122     uint64_t vreg[32 * RV_VLEN_MAX / 64] QEMU_ALIGNED(16);
123     target_ulong vxrm;
124     target_ulong vxsat;
125     target_ulong vl;
126     target_ulong vstart;
127     target_ulong vtype;
128     bool vill;
129 
130     target_ulong pc;
131     target_ulong load_res;
132     target_ulong load_val;
133 
134     target_ulong frm;
135 
136     target_ulong badaddr;
137     uint32_t bins;
138 
139     target_ulong guest_phys_fault_addr;
140 
141     target_ulong priv_ver;
142     target_ulong bext_ver;
143     target_ulong vext_ver;
144 
145     /* RISCVMXL, but uint32_t for vmstate migration */
146     uint32_t misa_mxl;      /* current mxl */
147     uint32_t misa_mxl_max;  /* max mxl for this cpu */
148     uint32_t misa_ext;      /* current extensions */
149     uint32_t misa_ext_mask; /* max ext for this cpu */
150     uint32_t xl;            /* current xlen */
151 
152     /* 128-bit helpers upper part return value */
153     target_ulong retxh;
154 
155     uint32_t features;
156 
157 #ifdef CONFIG_USER_ONLY
158     uint32_t elf_flags;
159 #endif
160 
161 #ifndef CONFIG_USER_ONLY
162     target_ulong priv;
163     /* This contains QEMU specific information about the virt state. */
164     target_ulong virt;
165     target_ulong geilen;
166     target_ulong resetvec;
167 
168     target_ulong mhartid;
169     /*
170      * For RV32 this is 32-bit mstatus and 32-bit mstatush.
171      * For RV64 this is a 64-bit mstatus.
172      */
173     uint64_t mstatus;
174 
175     target_ulong mip;
176 
177     uint32_t miclaim;
178 
179     target_ulong mie;
180     target_ulong mideleg;
181 
182     target_ulong satp;   /* since: priv-1.10.0 */
183     target_ulong stval;
184     target_ulong medeleg;
185 
186     target_ulong stvec;
187     target_ulong sepc;
188     target_ulong scause;
189 
190     target_ulong mtvec;
191     target_ulong mepc;
192     target_ulong mcause;
193     target_ulong mtval;  /* since: priv-1.10.0 */
194 
195     /* Hypervisor CSRs */
196     target_ulong hstatus;
197     target_ulong hedeleg;
198     target_ulong hideleg;
199     target_ulong hcounteren;
200     target_ulong htval;
201     target_ulong htinst;
202     target_ulong hgatp;
203     target_ulong hgeie;
204     target_ulong hgeip;
205     uint64_t htimedelta;
206 
207     /* Upper 64-bits of 128-bit CSRs */
208     uint64_t mscratchh;
209     uint64_t sscratchh;
210 
211     /* Virtual CSRs */
212     /*
213      * For RV32 this is 32-bit vsstatus and 32-bit vsstatush.
214      * For RV64 this is a 64-bit vsstatus.
215      */
216     uint64_t vsstatus;
217     target_ulong vstvec;
218     target_ulong vsscratch;
219     target_ulong vsepc;
220     target_ulong vscause;
221     target_ulong vstval;
222     target_ulong vsatp;
223 
224     target_ulong mtval2;
225     target_ulong mtinst;
226 
227     /* HS Backup CSRs */
228     target_ulong stvec_hs;
229     target_ulong sscratch_hs;
230     target_ulong sepc_hs;
231     target_ulong scause_hs;
232     target_ulong stval_hs;
233     target_ulong satp_hs;
234     uint64_t mstatus_hs;
235 
236     /* Signals whether the current exception occurred with two-stage address
237        translation active. */
238     bool two_stage_lookup;
239 
240     target_ulong scounteren;
241     target_ulong mcounteren;
242 
243     target_ulong sscratch;
244     target_ulong mscratch;
245 
246     /* temporary htif regs */
247     uint64_t mfromhost;
248     uint64_t mtohost;
249     uint64_t timecmp;
250 
251     /* physical memory protection */
252     pmp_table_t pmp_state;
253     target_ulong mseccfg;
254 
255     /* machine specific rdtime callback */
256     uint64_t (*rdtime_fn)(uint32_t);
257     uint32_t rdtime_fn_arg;
258 
259     /* machine specific AIA ireg read-modify-write callback */
260 #define AIA_MAKE_IREG(__isel, __priv, __virt, __vgein, __xlen) \
261     ((((__xlen) & 0xff) << 24) | \
262      (((__vgein) & 0x3f) << 20) | \
263      (((__virt) & 0x1) << 18) | \
264      (((__priv) & 0x3) << 16) | \
265      (__isel & 0xffff))
266 #define AIA_IREG_ISEL(__ireg)                  ((__ireg) & 0xffff)
267 #define AIA_IREG_PRIV(__ireg)                  (((__ireg) >> 16) & 0x3)
268 #define AIA_IREG_VIRT(__ireg)                  (((__ireg) >> 18) & 0x1)
269 #define AIA_IREG_VGEIN(__ireg)                 (((__ireg) >> 20) & 0x3f)
270 #define AIA_IREG_XLEN(__ireg)                  (((__ireg) >> 24) & 0xff)
271     int (*aia_ireg_rmw_fn[4])(void *arg, target_ulong reg,
272         target_ulong *val, target_ulong new_val, target_ulong write_mask);
273     void *aia_ireg_rmw_fn_arg[4];
274 
275     /* True if in debugger mode.  */
276     bool debugger;
277 
278     /*
279      * CSRs for PointerMasking extension
280      */
281     target_ulong mmte;
282     target_ulong mpmmask;
283     target_ulong mpmbase;
284     target_ulong spmmask;
285     target_ulong spmbase;
286     target_ulong upmmask;
287     target_ulong upmbase;
288 #endif
289     target_ulong cur_pmmask;
290     target_ulong cur_pmbase;
291 
292     float_status fp_status;
293 
294     /* Fields from here on are preserved across CPU reset. */
295     QEMUTimer *timer; /* Internal timer */
296 
297     hwaddr kernel_addr;
298     hwaddr fdt_addr;
299 
300     /* kvm timer */
301     bool kvm_timer_dirty;
302     uint64_t kvm_timer_time;
303     uint64_t kvm_timer_compare;
304     uint64_t kvm_timer_state;
305     uint64_t kvm_timer_frequency;
306 };
307 
308 OBJECT_DECLARE_TYPE(RISCVCPU, RISCVCPUClass,
309                     RISCV_CPU)
310 
311 /**
312  * RISCVCPUClass:
313  * @parent_realize: The parent class' realize handler.
314  * @parent_reset: The parent class' reset handler.
315  *
316  * A RISCV CPU model.
317  */
318 struct RISCVCPUClass {
319     /*< private >*/
320     CPUClass parent_class;
321     /*< public >*/
322     DeviceRealize parent_realize;
323     DeviceReset parent_reset;
324 };
325 
326 struct RISCVCPUConfig {
327     bool ext_i;
328     bool ext_e;
329     bool ext_g;
330     bool ext_m;
331     bool ext_a;
332     bool ext_f;
333     bool ext_d;
334     bool ext_c;
335     bool ext_s;
336     bool ext_u;
337     bool ext_h;
338     bool ext_j;
339     bool ext_v;
340     bool ext_zba;
341     bool ext_zbb;
342     bool ext_zbc;
343     bool ext_zbs;
344     bool ext_counters;
345     bool ext_ifencei;
346     bool ext_icsr;
347     bool ext_zfh;
348     bool ext_zfhmin;
349     bool ext_zve32f;
350     bool ext_zve64f;
351 
352     /* Vendor-specific custom extensions */
353     bool ext_XVentanaCondOps;
354 
355     char *priv_spec;
356     char *user_spec;
357     char *bext_spec;
358     char *vext_spec;
359     uint16_t vlen;
360     uint16_t elen;
361     bool mmu;
362     bool pmp;
363     bool epmp;
364     uint64_t resetvec;
365 };
366 
367 typedef struct RISCVCPUConfig RISCVCPUConfig;
368 
369 /**
370  * RISCVCPU:
371  * @env: #CPURISCVState
372  *
373  * A RISCV CPU.
374  */
375 struct RISCVCPU {
376     /*< private >*/
377     CPUState parent_obj;
378     /*< public >*/
379     CPUNegativeOffsetState neg;
380     CPURISCVState env;
381 
382     char *dyn_csr_xml;
383     char *dyn_vreg_xml;
384 
385     /* Configuration Settings */
386     RISCVCPUConfig cfg;
387 };
388 
389 static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
390 {
391     return (env->misa_ext & ext) != 0;
392 }
393 
394 static inline bool riscv_feature(CPURISCVState *env, int feature)
395 {
396     return env->features & (1ULL << feature);
397 }
398 
399 static inline void riscv_set_feature(CPURISCVState *env, int feature)
400 {
401     env->features |= (1ULL << feature);
402 }
403 
404 #include "cpu_user.h"
405 
406 extern const char * const riscv_int_regnames[];
407 extern const char * const riscv_int_regnamesh[];
408 extern const char * const riscv_fpr_regnames[];
409 
410 const char *riscv_cpu_get_trap_name(target_ulong cause, bool async);
411 void riscv_cpu_do_interrupt(CPUState *cpu);
412 int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
413                                int cpuid, void *opaque);
414 int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
415                                int cpuid, void *opaque);
416 int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
417 int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
418 bool riscv_cpu_fp_enabled(CPURISCVState *env);
419 target_ulong riscv_cpu_get_geilen(CPURISCVState *env);
420 void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen);
421 bool riscv_cpu_vector_enabled(CPURISCVState *env);
422 bool riscv_cpu_virt_enabled(CPURISCVState *env);
423 void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
424 bool riscv_cpu_two_stage_lookup(int mmu_idx);
425 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch);
426 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
427 void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
428                                     MMUAccessType access_type, int mmu_idx,
429                                     uintptr_t retaddr) QEMU_NORETURN;
430 bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
431                         MMUAccessType access_type, int mmu_idx,
432                         bool probe, uintptr_t retaddr);
433 void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
434                                      vaddr addr, unsigned size,
435                                      MMUAccessType access_type,
436                                      int mmu_idx, MemTxAttrs attrs,
437                                      MemTxResult response, uintptr_t retaddr);
438 char *riscv_isa_string(RISCVCPU *cpu);
439 void riscv_cpu_list(void);
440 
441 #define cpu_list riscv_cpu_list
442 #define cpu_mmu_index riscv_cpu_mmu_index
443 
444 #ifndef CONFIG_USER_ONLY
445 bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request);
446 void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env);
447 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t interrupts);
448 uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value);
449 #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */
450 void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(uint32_t),
451                              uint32_t arg);
452 void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv,
453                                    int (*rmw_fn)(void *arg,
454                                                  target_ulong reg,
455                                                  target_ulong *val,
456                                                  target_ulong new_val,
457                                                  target_ulong write_mask),
458                                    void *rmw_fn_arg);
459 #endif
460 void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
461 
462 void riscv_translate_init(void);
463 void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
464                                          uint32_t exception, uintptr_t pc);
465 
466 target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
467 void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
468 
469 #define TB_FLAGS_PRIV_MMU_MASK                3
470 #define TB_FLAGS_PRIV_HYP_ACCESS_MASK   (1 << 2)
471 #define TB_FLAGS_MSTATUS_FS MSTATUS_FS
472 #define TB_FLAGS_MSTATUS_VS MSTATUS_VS
473 
474 typedef CPURISCVState CPUArchState;
475 typedef RISCVCPU ArchCPU;
476 #include "exec/cpu-all.h"
477 
478 FIELD(TB_FLAGS, MEM_IDX, 0, 3)
479 FIELD(TB_FLAGS, LMUL, 3, 3)
480 FIELD(TB_FLAGS, SEW, 6, 3)
481 /* Skip MSTATUS_VS (0x600) bits */
482 FIELD(TB_FLAGS, VL_EQ_VLMAX, 11, 1)
483 FIELD(TB_FLAGS, VILL, 12, 1)
484 /* Skip MSTATUS_FS (0x6000) bits */
485 /* Is a Hypervisor instruction load/store allowed? */
486 FIELD(TB_FLAGS, HLSX, 15, 1)
487 FIELD(TB_FLAGS, MSTATUS_HS_FS, 16, 2)
488 FIELD(TB_FLAGS, MSTATUS_HS_VS, 18, 2)
489 /* The combination of MXL/SXL/UXL that applies to the current cpu mode. */
490 FIELD(TB_FLAGS, XL, 20, 2)
491 /* If PointerMasking should be applied */
492 FIELD(TB_FLAGS, PM_MASK_ENABLED, 22, 1)
493 FIELD(TB_FLAGS, PM_BASE_ENABLED, 23, 1)
494 
495 #ifdef TARGET_RISCV32
496 #define riscv_cpu_mxl(env)  ((void)(env), MXL_RV32)
497 #else
498 static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env)
499 {
500     return env->misa_mxl;
501 }
502 #endif
503 
504 #if defined(TARGET_RISCV32)
505 #define cpu_recompute_xl(env)  ((void)(env), MXL_RV32)
506 #else
507 static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
508 {
509     RISCVMXL xl = env->misa_mxl;
510 #if !defined(CONFIG_USER_ONLY)
511     /*
512      * When emulating a 32-bit-only cpu, use RV32.
513      * When emulating a 64-bit cpu, and MXL has been reduced to RV32,
514      * MSTATUSH doesn't have UXL/SXL, therefore XLEN cannot be widened
515      * back to RV64 for lower privs.
516      */
517     if (xl != MXL_RV32) {
518         switch (env->priv) {
519         case PRV_M:
520             break;
521         case PRV_U:
522             xl = get_field(env->mstatus, MSTATUS64_UXL);
523             break;
524         default: /* PRV_S | PRV_H */
525             xl = get_field(env->mstatus, MSTATUS64_SXL);
526             break;
527         }
528     }
529 #endif
530     return xl;
531 }
532 #endif
533 
534 static inline int riscv_cpu_xlen(CPURISCVState *env)
535 {
536     return 16 << env->xl;
537 }
538 
539 /*
540  * Encode LMUL to lmul as follows:
541  *     LMUL    vlmul    lmul
542  *      1       000       0
543  *      2       001       1
544  *      4       010       2
545  *      8       011       3
546  *      -       100       -
547  *     1/8      101      -3
548  *     1/4      110      -2
549  *     1/2      111      -1
550  *
551  * then, we can calculate VLMAX = vlen >> (vsew + 3 - lmul)
552  * e.g. vlen = 256 bits, SEW = 16, LMUL = 1/8
553  *      => VLMAX = vlen >> (1 + 3 - (-3))
554  *               = 256 >> 7
555  *               = 2
556  */
557 static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, target_ulong vtype)
558 {
559     uint8_t sew = FIELD_EX64(vtype, VTYPE, VSEW);
560     int8_t lmul = sextract32(FIELD_EX64(vtype, VTYPE, VLMUL), 0, 3);
561     return cpu->cfg.vlen >> (sew + 3 - lmul);
562 }
563 
564 void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
565                           target_ulong *cs_base, uint32_t *pflags);
566 
567 void riscv_cpu_update_mask(CPURISCVState *env);
568 
569 RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
570                            target_ulong *ret_value,
571                            target_ulong new_value, target_ulong write_mask);
572 RISCVException riscv_csrrw_debug(CPURISCVState *env, int csrno,
573                                  target_ulong *ret_value,
574                                  target_ulong new_value,
575                                  target_ulong write_mask);
576 
577 static inline void riscv_csr_write(CPURISCVState *env, int csrno,
578                                    target_ulong val)
579 {
580     riscv_csrrw(env, csrno, NULL, val, MAKE_64BIT_MASK(0, TARGET_LONG_BITS));
581 }
582 
583 static inline target_ulong riscv_csr_read(CPURISCVState *env, int csrno)
584 {
585     target_ulong val = 0;
586     riscv_csrrw(env, csrno, &val, 0, 0);
587     return val;
588 }
589 
590 typedef RISCVException (*riscv_csr_predicate_fn)(CPURISCVState *env,
591                                                  int csrno);
592 typedef RISCVException (*riscv_csr_read_fn)(CPURISCVState *env, int csrno,
593                                             target_ulong *ret_value);
594 typedef RISCVException (*riscv_csr_write_fn)(CPURISCVState *env, int csrno,
595                                              target_ulong new_value);
596 typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno,
597                                           target_ulong *ret_value,
598                                           target_ulong new_value,
599                                           target_ulong write_mask);
600 
601 RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
602                                 Int128 *ret_value,
603                                 Int128 new_value, Int128 write_mask);
604 
605 typedef RISCVException (*riscv_csr_read128_fn)(CPURISCVState *env, int csrno,
606                                                Int128 *ret_value);
607 typedef RISCVException (*riscv_csr_write128_fn)(CPURISCVState *env, int csrno,
608                                              Int128 new_value);
609 
610 typedef struct {
611     const char *name;
612     riscv_csr_predicate_fn predicate;
613     riscv_csr_read_fn read;
614     riscv_csr_write_fn write;
615     riscv_csr_op_fn op;
616     riscv_csr_read128_fn read128;
617     riscv_csr_write128_fn write128;
618 } riscv_csr_operations;
619 
620 /* CSR function table constants */
621 enum {
622     CSR_TABLE_SIZE = 0x1000
623 };
624 
625 /* CSR function table */
626 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
627 
628 void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops);
629 void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
630 
631 void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
632 
633 #endif /* RISCV_CPU_H */
634