change htif to link against libfesvr
[riscv-isa-sim.git] / riscv / decode.h
1 #ifndef _RISCV_DECODE_H
2 #define _RISCV_DECODE_H
3
4 #define __STDC_LIMIT_MACROS
5 #include <stdint.h>
6 #include "pcr.h"
7 #include "config.h"
8
9 typedef int int128_t __attribute__((mode(TI)));
10 typedef unsigned int uint128_t __attribute__((mode(TI)));
11
12 typedef int64_t sreg_t;
13 typedef uint64_t reg_t;
14 typedef uint64_t freg_t;
15
16 const int OPCODE_BITS = 7;
17
18 const int XPRID_BITS = 5;
19 const int NXPR = 1 << XPRID_BITS;
20
21 const int FPR_BITS = 64;
22 const int FPRID_BITS = 5;
23 const int NFPR = 1 << FPRID_BITS;
24
25 const int IMM_BITS = 12;
26 const int IMMLO_BITS = 7;
27 const int TARGET_BITS = 25;
28 const int FUNCT_BITS = 3;
29 const int FUNCTR_BITS = 7;
30 const int FFUNCT_BITS = 2;
31 const int RM_BITS = 3;
32 const int BIGIMM_BITS = 20;
33 const int BRANCH_ALIGN_BITS = 1;
34 const int JUMP_ALIGN_BITS = 1;
35
36 #define FP_RD_NE 0
37 #define FP_RD_0 1
38 #define FP_RD_DN 2
39 #define FP_RD_UP 3
40 #define FP_RD_NMM 4
41
42 #define FSR_RD_SHIFT 5
43 #define FSR_RD (0x7 << FSR_RD_SHIFT)
44
45 #define FPEXC_NX 0x01
46 #define FPEXC_UF 0x02
47 #define FPEXC_OF 0x04
48 #define FPEXC_DZ 0x08
49 #define FPEXC_NV 0x10
50
51 #define FSR_AEXC_SHIFT 0
52 #define FSR_NVA (FPEXC_NV << FSR_AEXC_SHIFT)
53 #define FSR_OFA (FPEXC_OF << FSR_AEXC_SHIFT)
54 #define FSR_UFA (FPEXC_UF << FSR_AEXC_SHIFT)
55 #define FSR_DZA (FPEXC_DZ << FSR_AEXC_SHIFT)
56 #define FSR_NXA (FPEXC_NX << FSR_AEXC_SHIFT)
57 #define FSR_AEXC (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA)
58
59 #define FSR_ZERO ~(FSR_RD | FSR_AEXC)
60
61 // note: bit fields are in little-endian order
62 struct itype_t
63 {
64 unsigned opcode : OPCODE_BITS;
65 unsigned funct : FUNCT_BITS;
66 signed imm12 : IMM_BITS;
67 unsigned rs1 : XPRID_BITS;
68 unsigned rd : XPRID_BITS;
69 };
70
71 struct btype_t
72 {
73 unsigned opcode : OPCODE_BITS;
74 unsigned funct : FUNCT_BITS;
75 unsigned immlo : IMMLO_BITS;
76 unsigned rs2 : XPRID_BITS;
77 unsigned rs1 : XPRID_BITS;
78 signed immhi : IMM_BITS-IMMLO_BITS;
79 };
80
81 struct jtype_t
82 {
83 unsigned jump_opcode : OPCODE_BITS;
84 signed target : TARGET_BITS;
85 };
86
87 struct rtype_t
88 {
89 unsigned opcode : OPCODE_BITS;
90 unsigned funct : FUNCT_BITS;
91 unsigned functr : FUNCTR_BITS;
92 unsigned rs2 : XPRID_BITS;
93 unsigned rs1 : XPRID_BITS;
94 unsigned rd : XPRID_BITS;
95 };
96
97 struct ltype_t
98 {
99 unsigned opcode : OPCODE_BITS;
100 unsigned bigimm : BIGIMM_BITS;
101 unsigned rd : XPRID_BITS;
102 };
103
104 struct ftype_t
105 {
106 unsigned opcode : OPCODE_BITS;
107 unsigned ffunct : FFUNCT_BITS;
108 unsigned rm : RM_BITS;
109 unsigned rs3 : FPRID_BITS;
110 unsigned rs2 : FPRID_BITS;
111 unsigned rs1 : FPRID_BITS;
112 unsigned rd : FPRID_BITS;
113 };
114
115 union insn_t
116 {
117 itype_t itype;
118 jtype_t jtype;
119 rtype_t rtype;
120 btype_t btype;
121 ltype_t ltype;
122 ftype_t ftype;
123 uint32_t bits;
124 };
125
126 #include <stdio.h>
127 template <class T>
128 class write_port_t
129 {
130 public:
131 write_port_t(T& _t) : t(_t) {}
132 T& operator = (const T& rhs)
133 {
134 return t = rhs;
135 }
136 operator T()
137 {
138 return t;
139 }
140 private:
141 T& t;
142 };
143 template <class T, size_t N, bool zero_reg>
144 class regfile_t
145 {
146 public:
147 void reset()
148 {
149 memset(data, 0, sizeof(data));
150 }
151 write_port_t<T> write_port(size_t i)
152 {
153 return write_port_t<T>(data[i]);
154 }
155 const T& operator [] (size_t i) const
156 {
157 if (zero_reg)
158 const_cast<T&>(data[0]) = 0;
159 return data[i];
160 }
161 private:
162 T data[N];
163 };
164
165 #define throw_illegal_instruction \
166 ({ if (utmode) throw trap_vector_illegal_instruction; \
167 else throw trap_illegal_instruction; })
168
169 // helpful macros, etc
170 #define RS1 XPR[insn.rtype.rs1]
171 #define RS2 XPR[insn.rtype.rs2]
172 #define RD XPR.write_port(insn.rtype.rd)
173 #define RA XPR.write_port(1)
174 #define FRS1 FPR[insn.ftype.rs1]
175 #define FRS2 FPR[insn.ftype.rs2]
176 #define FRS3 FPR[insn.ftype.rs3]
177 #define FRD FPR.write_port(insn.ftype.rd)
178 #define BIGIMM insn.ltype.bigimm
179 #define SIMM insn.itype.imm12
180 #define BIMM ((signed)insn.btype.immlo | (insn.btype.immhi << IMMLO_BITS))
181 #define SHAMT (insn.itype.imm12 & 0x3F)
182 #define SHAMTW (insn.itype.imm12 & 0x1F)
183 #define TARGET insn.jtype.target
184 #define BRANCH_TARGET (pc + (BIMM << BRANCH_ALIGN_BITS))
185 #define JUMP_TARGET (pc + (TARGET << JUMP_ALIGN_BITS))
186 #define RM ({ int rm = insn.ftype.rm; \
187 if(rm == 7) rm = (fsr & FSR_RD) >> FSR_RD_SHIFT; \
188 if(rm > 4) throw_illegal_instruction; \
189 rm; })
190
191 #define xpr64 (xprlen == 64)
192
193 #define require_supervisor if(unlikely(!(sr & SR_S))) throw trap_privileged_instruction
194 #define require_xpr64 if(unlikely(!xpr64)) throw_illegal_instruction
195 #define require_xpr32 if(unlikely(xpr64)) throw_illegal_instruction
196 #ifndef RISCV_ENABLE_FPU
197 # define require_fp throw trap_illegal_instruction
198 #else
199 # define require_fp if(unlikely(!(sr & SR_EF))) throw trap_fp_disabled
200 #endif
201 #ifndef RISCV_ENABLE_VEC
202 # define require_vector throw trap_illegal_instruction
203 #else
204 # define require_vector \
205 ({ if(!(sr & SR_EV)) throw trap_vector_disabled; \
206 else if (!utmode && (vecbanks_count < 3)) throw trap_vector_bank; \
207 })
208 #endif
209
210 #define cmp_trunc(reg) (reg_t(reg) << (64-xprlen))
211 #define set_fp_exceptions ({ set_fsr(fsr | \
212 (softfloat_exceptionFlags << FSR_AEXC_SHIFT)); \
213 softfloat_exceptionFlags = 0; })
214
215 #define sext32(x) ((sreg_t)(int32_t)(x))
216 #define zext32(x) ((reg_t)(uint32_t)(x))
217 #define sext_xprlen(x) (((sreg_t)(x) << (64-xprlen)) >> (64-xprlen))
218 #define zext_xprlen(x) (((reg_t)(x) << (64-xprlen)) >> (64-xprlen))
219
220 // RVC stuff
221
222 #define INSN_IS_RVC(x) (((x) & 0x3) < 0x3)
223 #define insn_length(x) (INSN_IS_RVC(x) ? 2 : 4)
224 #define require_rvc if(!(sr & SR_EC)) throw_illegal_instruction
225
226 #define CRD_REGNUM ((insn.bits >> 5) & 0x1f)
227 #define CRD XPR.write_port(CRD_REGNUM)
228 #define CRS1 XPR[(insn.bits >> 10) & 0x1f]
229 #define CRS2 XPR[(insn.bits >> 5) & 0x1f]
230 #define CIMM6 ((int32_t)((insn.bits >> 10) & 0x3f) << 26 >> 26)
231 #define CIMM5U ((insn.bits >> 5) & 0x1f)
232 #define CIMM5 ((int32_t)CIMM5U << 27 >> 27)
233 #define CIMM10 ((int32_t)((insn.bits >> 5) & 0x3ff) << 22 >> 22)
234 #define CBRANCH_TARGET (pc + (CIMM5 << BRANCH_ALIGN_BITS))
235 #define CJUMP_TARGET (pc + (CIMM10 << JUMP_ALIGN_BITS))
236
237 static const int rvc_rs1_regmap[8] = { 20, 21, 2, 3, 4, 5, 6, 7 };
238 #define rvc_rd_regmap rvc_rs1_regmap
239 #define rvc_rs2b_regmap rvc_rs1_regmap
240 static const int rvc_rs2_regmap[8] = { 20, 21, 2, 3, 4, 5, 6, 0 };
241 #define CRDS XPR.write_port(rvc_rd_regmap[(insn.bits >> 13) & 0x7])
242 #define FCRDS FPR.write_port(rvc_rd_regmap[(insn.bits >> 13) & 0x7])
243 #define CRS1S XPR[rvc_rs1_regmap[(insn.bits >> 10) & 0x7]]
244 #define CRS2S XPR[rvc_rs2_regmap[(insn.bits >> 13) & 0x7]]
245 #define CRS2BS XPR[rvc_rs2b_regmap[(insn.bits >> 5) & 0x7]]
246 #define FCRS2S FPR[rvc_rs2_regmap[(insn.bits >> 13) & 0x7]]
247
248 // vector stuff
249 #define VL vl
250
251 #define UT_RS1(idx) uts[idx]->XPR[insn.rtype.rs1]
252 #define UT_RS2(idx) uts[idx]->XPR[insn.rtype.rs2]
253 #define UT_RD(idx) uts[idx]->XPR.write_port(insn.rtype.rd)
254 #define UT_RA(idx) uts[idx]->XPR.write_port(1)
255 #define UT_FRS1(idx) uts[idx]->FPR[insn.ftype.rs1]
256 #define UT_FRS2(idx) uts[idx]->FPR[insn.ftype.rs2]
257 #define UT_FRS3(idx) uts[idx]->FPR[insn.ftype.rs3]
258 #define UT_FRD(idx) uts[idx]->FPR.write_port(insn.ftype.rd)
259 #define UT_RM(idx) ((insn.ftype.rm != 7) ? insn.ftype.rm : \
260 ((uts[idx]->fsr & FSR_RD) >> FSR_RD_SHIFT))
261
262 #define UT_LOOP_START for (int i=0;i<VL; i++) {
263 #define UT_LOOP_END }
264 #define UT_LOOP_RS1 UT_RS1(i)
265 #define UT_LOOP_RS2 UT_RS2(i)
266 #define UT_LOOP_RD UT_RD(i)
267 #define UT_LOOP_RA UT_RA(i)
268 #define UT_LOOP_FRS1 UT_FRS1(i)
269 #define UT_LOOP_FRS2 UT_FRS2(i)
270 #define UT_LOOP_FRS3 UT_FRS3(i)
271 #define UT_LOOP_FRD UT_FRD(i)
272 #define UT_LOOP_RM UT_RM(i)
273
274 #define VEC_LOAD(dst, func, inc) \
275 reg_t addr = RS1; \
276 UT_LOOP_START \
277 UT_LOOP_##dst = mmu.func(addr); \
278 addr += inc; \
279 UT_LOOP_END
280
281 #define VEC_STORE(src, func, inc) \
282 reg_t addr = RS1; \
283 UT_LOOP_START \
284 mmu.func(addr, UT_LOOP_##src); \
285 addr += inc; \
286 UT_LOOP_END
287
288 enum vt_command_t
289 {
290 vt_command_stop,
291 };
292
293 #endif