Instructions are no longer member functions
[riscv-isa-sim.git] / riscv / decode.h
1 // See LICENSE for license details.
2
3 #ifndef _RISCV_DECODE_H
4 #define _RISCV_DECODE_H
5
6 #define __STDC_LIMIT_MACROS
7 #include <stdint.h>
8 #include <string.h>
9 #include "pcr.h"
10 #include "config.h"
11 #include "common.h"
12
13 typedef int int128_t __attribute__((mode(TI)));
14 typedef unsigned int uint128_t __attribute__((mode(TI)));
15
16 typedef int64_t sreg_t;
17 typedef uint64_t reg_t;
18 typedef uint64_t freg_t;
19
20 const int OPCODE_BITS = 7;
21
22 const int XPRID_BITS = 5;
23 const int NXPR = 1 << XPRID_BITS;
24
25 const int FPR_BITS = 64;
26 const int FPRID_BITS = 5;
27 const int NFPR = 1 << FPRID_BITS;
28
29 const int IMM_BITS = 12;
30 const int IMMLO_BITS = 7;
31 const int TARGET_BITS = 25;
32 const int FUNCT_BITS = 3;
33 const int FUNCTR_BITS = 7;
34 const int FFUNCT_BITS = 2;
35 const int RM_BITS = 3;
36 const int BIGIMM_BITS = 20;
37 const int BRANCH_ALIGN_BITS = 1;
38 const int JUMP_ALIGN_BITS = 1;
39
40 #define FP_RD_NE 0
41 #define FP_RD_0 1
42 #define FP_RD_DN 2
43 #define FP_RD_UP 3
44 #define FP_RD_NMM 4
45
46 #define FSR_RD_SHIFT 5
47 #define FSR_RD (0x7 << FSR_RD_SHIFT)
48
49 #define FPEXC_NX 0x01
50 #define FPEXC_UF 0x02
51 #define FPEXC_OF 0x04
52 #define FPEXC_DZ 0x08
53 #define FPEXC_NV 0x10
54
55 #define FSR_AEXC_SHIFT 0
56 #define FSR_NVA (FPEXC_NV << FSR_AEXC_SHIFT)
57 #define FSR_OFA (FPEXC_OF << FSR_AEXC_SHIFT)
58 #define FSR_UFA (FPEXC_UF << FSR_AEXC_SHIFT)
59 #define FSR_DZA (FPEXC_DZ << FSR_AEXC_SHIFT)
60 #define FSR_NXA (FPEXC_NX << FSR_AEXC_SHIFT)
61 #define FSR_AEXC (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA)
62
63 #define FSR_ZERO ~(FSR_RD | FSR_AEXC)
64
65 // note: bit fields are in little-endian order
66 struct itype_t
67 {
68 unsigned opcode : OPCODE_BITS;
69 unsigned funct : FUNCT_BITS;
70 signed imm12 : IMM_BITS;
71 unsigned rs1 : XPRID_BITS;
72 unsigned rd : XPRID_BITS;
73 };
74
75 struct btype_t
76 {
77 unsigned opcode : OPCODE_BITS;
78 unsigned funct : FUNCT_BITS;
79 unsigned immlo : IMMLO_BITS;
80 unsigned rs2 : XPRID_BITS;
81 unsigned rs1 : XPRID_BITS;
82 signed immhi : IMM_BITS-IMMLO_BITS;
83 };
84
85 struct jtype_t
86 {
87 unsigned jump_opcode : OPCODE_BITS;
88 signed target : TARGET_BITS;
89 };
90
91 struct rtype_t
92 {
93 unsigned opcode : OPCODE_BITS;
94 unsigned funct : FUNCT_BITS;
95 unsigned functr : FUNCTR_BITS;
96 unsigned rs2 : XPRID_BITS;
97 unsigned rs1 : XPRID_BITS;
98 unsigned rd : XPRID_BITS;
99 };
100
101 struct ltype_t
102 {
103 unsigned opcode : OPCODE_BITS;
104 unsigned bigimm : BIGIMM_BITS;
105 unsigned rd : XPRID_BITS;
106 };
107
108 struct ftype_t
109 {
110 unsigned opcode : OPCODE_BITS;
111 unsigned ffunct : FFUNCT_BITS;
112 unsigned rm : RM_BITS;
113 unsigned rs3 : FPRID_BITS;
114 unsigned rs2 : FPRID_BITS;
115 unsigned rs1 : FPRID_BITS;
116 unsigned rd : FPRID_BITS;
117 };
118
119 union insn_t
120 {
121 itype_t itype;
122 jtype_t jtype;
123 rtype_t rtype;
124 btype_t btype;
125 ltype_t ltype;
126 ftype_t ftype;
127 uint_fast32_t bits;
128 };
129
130 template <class T>
131 class write_port_t
132 {
133 public:
134 write_port_t(T& _t) : t(_t) {}
135 T& operator = (const T& rhs)
136 {
137 return t = rhs;
138 }
139 operator T()
140 {
141 return t;
142 }
143 private:
144 T& t;
145 };
146 template <class T, size_t N, bool zero_reg>
147 class regfile_t
148 {
149 public:
150 void reset()
151 {
152 memset(data, 0, sizeof(data));
153 }
154 write_port_t<T> write_port(size_t i)
155 {
156 if (zero_reg)
157 const_cast<T&>(data[0]) = 0;
158 return write_port_t<T>(data[i]);
159 }
160 const T& operator [] (size_t i) const
161 {
162 if (zero_reg)
163 const_cast<T&>(data[0]) = 0;
164 return data[i];
165 }
166 private:
167 T data[N];
168 };
169
170 // helpful macros, etc
171 #define MMU (*p->get_mmu())
172 #define RS1 p->get_state()->XPR[insn.rtype.rs1]
173 #define RS2 p->get_state()->XPR[insn.rtype.rs2]
174 #define RD p->get_state()->XPR.write_port(insn.rtype.rd)
175 #define RA p->get_state()->XPR.write_port(1)
176 #define FRS1 p->get_state()->FPR[insn.ftype.rs1]
177 #define FRS2 p->get_state()->FPR[insn.ftype.rs2]
178 #define FRS3 p->get_state()->FPR[insn.ftype.rs3]
179 #define FRD p->get_state()->FPR.write_port(insn.ftype.rd)
180 #define BIGIMM insn.ltype.bigimm
181 #define SIMM insn.itype.imm12
182 #define BIMM ((signed)insn.btype.immlo | (insn.btype.immhi << IMMLO_BITS))
183 #define SHAMT (insn.itype.imm12 & 0x3F)
184 #define SHAMTW (insn.itype.imm12 & 0x1F)
185 #define TARGET insn.jtype.target
186 #define BRANCH_TARGET (pc + (BIMM << BRANCH_ALIGN_BITS))
187 #define JUMP_TARGET (pc + (TARGET << JUMP_ALIGN_BITS))
188 #define ITYPE_EADDR sext_xprlen(RS1 + SIMM)
189 #define BTYPE_EADDR sext_xprlen(RS1 + BIMM)
190 #define RM ({ int rm = insn.ftype.rm; \
191 if(rm == 7) rm = (p->get_state()->fsr & FSR_RD) >> FSR_RD_SHIFT; \
192 if(rm > 4) throw trap_illegal_instruction(); \
193 rm; })
194
195 #define xpr64 (xprlen == 64)
196
197 #define require_supervisor if(unlikely(!(p->get_state()->sr & SR_S))) throw trap_privileged_instruction()
198 #define require_xpr64 if(unlikely(!xpr64)) throw trap_illegal_instruction()
199 #define require_xpr32 if(unlikely(xpr64)) throw trap_illegal_instruction()
200 #ifndef RISCV_ENABLE_FPU
201 # define require_fp throw trap_illegal_instruction()
202 #else
203 # define require_fp if(unlikely(!(p->get_state()->sr & SR_EF))) throw trap_fp_disabled()
204 #endif
205
206 #define cmp_trunc(reg) (reg_t(reg) << (64-xprlen))
207 #define set_fp_exceptions ({ p->set_fsr(p->get_state()->fsr | \
208 (softfloat_exceptionFlags << FSR_AEXC_SHIFT)); \
209 softfloat_exceptionFlags = 0; })
210
211 #define sext32(x) ((sreg_t)(int32_t)(x))
212 #define zext32(x) ((reg_t)(uint32_t)(x))
213 #define sext_xprlen(x) (((sreg_t)(x) << (64-xprlen)) >> (64-xprlen))
214 #define zext_xprlen(x) (((reg_t)(x) << (64-xprlen)) >> (64-xprlen))
215
216 #define insn_length(x) \
217 (((x) & 0x03) < 0x03 ? 2 : \
218 ((x) & 0x1f) < 0x1f ? 4 : \
219 ((x) & 0x3f) < 0x3f ? 6 : \
220 8)
221
222 #define set_pc(x) \
223 do { if ((x) & 3 /* For now... */) \
224 throw trap_instruction_address_misaligned(); \
225 npc = (x); \
226 } while(0)
227
228 #endif