hw/ppc: Implement fw_cfg_arch_key_name()
[qemu/kevin.git] / disas / riscv.c
blob59a9b0437a5f24a497744c30d2b645200b8a8637
1 /*
2 * QEMU RISC-V Disassembler
4 * Copyright (c) 2016-2017 Michael Clark <michaeljclark@mac.com>
5 * Copyright (c) 2017-2018 SiFive, Inc.
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.
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.
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/>.
20 #include "qemu/osdep.h"
21 #include "disas/dis-asm.h"
24 /* types */
26 typedef uint64_t rv_inst;
27 typedef uint16_t rv_opcode;
29 /* enums */
31 typedef enum {
32 rv32,
33 rv64,
34 rv128
35 } rv_isa;
37 typedef enum {
38 rv_rm_rne = 0,
39 rv_rm_rtz = 1,
40 rv_rm_rdn = 2,
41 rv_rm_rup = 3,
42 rv_rm_rmm = 4,
43 rv_rm_dyn = 7,
44 } rv_rm;
46 typedef enum {
47 rv_fence_i = 8,
48 rv_fence_o = 4,
49 rv_fence_r = 2,
50 rv_fence_w = 1,
51 } rv_fence;
53 typedef enum {
54 rv_ireg_zero,
55 rv_ireg_ra,
56 rv_ireg_sp,
57 rv_ireg_gp,
58 rv_ireg_tp,
59 rv_ireg_t0,
60 rv_ireg_t1,
61 rv_ireg_t2,
62 rv_ireg_s0,
63 rv_ireg_s1,
64 rv_ireg_a0,
65 rv_ireg_a1,
66 rv_ireg_a2,
67 rv_ireg_a3,
68 rv_ireg_a4,
69 rv_ireg_a5,
70 rv_ireg_a6,
71 rv_ireg_a7,
72 rv_ireg_s2,
73 rv_ireg_s3,
74 rv_ireg_s4,
75 rv_ireg_s5,
76 rv_ireg_s6,
77 rv_ireg_s7,
78 rv_ireg_s8,
79 rv_ireg_s9,
80 rv_ireg_s10,
81 rv_ireg_s11,
82 rv_ireg_t3,
83 rv_ireg_t4,
84 rv_ireg_t5,
85 rv_ireg_t6,
86 } rv_ireg;
88 typedef enum {
89 rvc_end,
90 rvc_rd_eq_ra,
91 rvc_rd_eq_x0,
92 rvc_rs1_eq_x0,
93 rvc_rs2_eq_x0,
94 rvc_rs2_eq_rs1,
95 rvc_rs1_eq_ra,
96 rvc_imm_eq_zero,
97 rvc_imm_eq_n1,
98 rvc_imm_eq_p1,
99 rvc_csr_eq_0x001,
100 rvc_csr_eq_0x002,
101 rvc_csr_eq_0x003,
102 rvc_csr_eq_0xc00,
103 rvc_csr_eq_0xc01,
104 rvc_csr_eq_0xc02,
105 rvc_csr_eq_0xc80,
106 rvc_csr_eq_0xc81,
107 rvc_csr_eq_0xc82,
108 } rvc_constraint;
110 typedef enum {
111 rv_codec_illegal,
112 rv_codec_none,
113 rv_codec_u,
114 rv_codec_uj,
115 rv_codec_i,
116 rv_codec_i_sh5,
117 rv_codec_i_sh6,
118 rv_codec_i_sh7,
119 rv_codec_i_csr,
120 rv_codec_s,
121 rv_codec_sb,
122 rv_codec_r,
123 rv_codec_r_m,
124 rv_codec_r4_m,
125 rv_codec_r_a,
126 rv_codec_r_l,
127 rv_codec_r_f,
128 rv_codec_cb,
129 rv_codec_cb_imm,
130 rv_codec_cb_sh5,
131 rv_codec_cb_sh6,
132 rv_codec_ci,
133 rv_codec_ci_sh5,
134 rv_codec_ci_sh6,
135 rv_codec_ci_16sp,
136 rv_codec_ci_lwsp,
137 rv_codec_ci_ldsp,
138 rv_codec_ci_lqsp,
139 rv_codec_ci_li,
140 rv_codec_ci_lui,
141 rv_codec_ci_none,
142 rv_codec_ciw_4spn,
143 rv_codec_cj,
144 rv_codec_cj_jal,
145 rv_codec_cl_lw,
146 rv_codec_cl_ld,
147 rv_codec_cl_lq,
148 rv_codec_cr,
149 rv_codec_cr_mv,
150 rv_codec_cr_jalr,
151 rv_codec_cr_jr,
152 rv_codec_cs,
153 rv_codec_cs_sw,
154 rv_codec_cs_sd,
155 rv_codec_cs_sq,
156 rv_codec_css_swsp,
157 rv_codec_css_sdsp,
158 rv_codec_css_sqsp,
159 } rv_codec;
161 typedef enum {
162 rv_op_illegal = 0,
163 rv_op_lui = 1,
164 rv_op_auipc = 2,
165 rv_op_jal = 3,
166 rv_op_jalr = 4,
167 rv_op_beq = 5,
168 rv_op_bne = 6,
169 rv_op_blt = 7,
170 rv_op_bge = 8,
171 rv_op_bltu = 9,
172 rv_op_bgeu = 10,
173 rv_op_lb = 11,
174 rv_op_lh = 12,
175 rv_op_lw = 13,
176 rv_op_lbu = 14,
177 rv_op_lhu = 15,
178 rv_op_sb = 16,
179 rv_op_sh = 17,
180 rv_op_sw = 18,
181 rv_op_addi = 19,
182 rv_op_slti = 20,
183 rv_op_sltiu = 21,
184 rv_op_xori = 22,
185 rv_op_ori = 23,
186 rv_op_andi = 24,
187 rv_op_slli = 25,
188 rv_op_srli = 26,
189 rv_op_srai = 27,
190 rv_op_add = 28,
191 rv_op_sub = 29,
192 rv_op_sll = 30,
193 rv_op_slt = 31,
194 rv_op_sltu = 32,
195 rv_op_xor = 33,
196 rv_op_srl = 34,
197 rv_op_sra = 35,
198 rv_op_or = 36,
199 rv_op_and = 37,
200 rv_op_fence = 38,
201 rv_op_fence_i = 39,
202 rv_op_lwu = 40,
203 rv_op_ld = 41,
204 rv_op_sd = 42,
205 rv_op_addiw = 43,
206 rv_op_slliw = 44,
207 rv_op_srliw = 45,
208 rv_op_sraiw = 46,
209 rv_op_addw = 47,
210 rv_op_subw = 48,
211 rv_op_sllw = 49,
212 rv_op_srlw = 50,
213 rv_op_sraw = 51,
214 rv_op_ldu = 52,
215 rv_op_lq = 53,
216 rv_op_sq = 54,
217 rv_op_addid = 55,
218 rv_op_sllid = 56,
219 rv_op_srlid = 57,
220 rv_op_sraid = 58,
221 rv_op_addd = 59,
222 rv_op_subd = 60,
223 rv_op_slld = 61,
224 rv_op_srld = 62,
225 rv_op_srad = 63,
226 rv_op_mul = 64,
227 rv_op_mulh = 65,
228 rv_op_mulhsu = 66,
229 rv_op_mulhu = 67,
230 rv_op_div = 68,
231 rv_op_divu = 69,
232 rv_op_rem = 70,
233 rv_op_remu = 71,
234 rv_op_mulw = 72,
235 rv_op_divw = 73,
236 rv_op_divuw = 74,
237 rv_op_remw = 75,
238 rv_op_remuw = 76,
239 rv_op_muld = 77,
240 rv_op_divd = 78,
241 rv_op_divud = 79,
242 rv_op_remd = 80,
243 rv_op_remud = 81,
244 rv_op_lr_w = 82,
245 rv_op_sc_w = 83,
246 rv_op_amoswap_w = 84,
247 rv_op_amoadd_w = 85,
248 rv_op_amoxor_w = 86,
249 rv_op_amoor_w = 87,
250 rv_op_amoand_w = 88,
251 rv_op_amomin_w = 89,
252 rv_op_amomax_w = 90,
253 rv_op_amominu_w = 91,
254 rv_op_amomaxu_w = 92,
255 rv_op_lr_d = 93,
256 rv_op_sc_d = 94,
257 rv_op_amoswap_d = 95,
258 rv_op_amoadd_d = 96,
259 rv_op_amoxor_d = 97,
260 rv_op_amoor_d = 98,
261 rv_op_amoand_d = 99,
262 rv_op_amomin_d = 100,
263 rv_op_amomax_d = 101,
264 rv_op_amominu_d = 102,
265 rv_op_amomaxu_d = 103,
266 rv_op_lr_q = 104,
267 rv_op_sc_q = 105,
268 rv_op_amoswap_q = 106,
269 rv_op_amoadd_q = 107,
270 rv_op_amoxor_q = 108,
271 rv_op_amoor_q = 109,
272 rv_op_amoand_q = 110,
273 rv_op_amomin_q = 111,
274 rv_op_amomax_q = 112,
275 rv_op_amominu_q = 113,
276 rv_op_amomaxu_q = 114,
277 rv_op_ecall = 115,
278 rv_op_ebreak = 116,
279 rv_op_uret = 117,
280 rv_op_sret = 118,
281 rv_op_hret = 119,
282 rv_op_mret = 120,
283 rv_op_dret = 121,
284 rv_op_sfence_vm = 122,
285 rv_op_sfence_vma = 123,
286 rv_op_wfi = 124,
287 rv_op_csrrw = 125,
288 rv_op_csrrs = 126,
289 rv_op_csrrc = 127,
290 rv_op_csrrwi = 128,
291 rv_op_csrrsi = 129,
292 rv_op_csrrci = 130,
293 rv_op_flw = 131,
294 rv_op_fsw = 132,
295 rv_op_fmadd_s = 133,
296 rv_op_fmsub_s = 134,
297 rv_op_fnmsub_s = 135,
298 rv_op_fnmadd_s = 136,
299 rv_op_fadd_s = 137,
300 rv_op_fsub_s = 138,
301 rv_op_fmul_s = 139,
302 rv_op_fdiv_s = 140,
303 rv_op_fsgnj_s = 141,
304 rv_op_fsgnjn_s = 142,
305 rv_op_fsgnjx_s = 143,
306 rv_op_fmin_s = 144,
307 rv_op_fmax_s = 145,
308 rv_op_fsqrt_s = 146,
309 rv_op_fle_s = 147,
310 rv_op_flt_s = 148,
311 rv_op_feq_s = 149,
312 rv_op_fcvt_w_s = 150,
313 rv_op_fcvt_wu_s = 151,
314 rv_op_fcvt_s_w = 152,
315 rv_op_fcvt_s_wu = 153,
316 rv_op_fmv_x_s = 154,
317 rv_op_fclass_s = 155,
318 rv_op_fmv_s_x = 156,
319 rv_op_fcvt_l_s = 157,
320 rv_op_fcvt_lu_s = 158,
321 rv_op_fcvt_s_l = 159,
322 rv_op_fcvt_s_lu = 160,
323 rv_op_fld = 161,
324 rv_op_fsd = 162,
325 rv_op_fmadd_d = 163,
326 rv_op_fmsub_d = 164,
327 rv_op_fnmsub_d = 165,
328 rv_op_fnmadd_d = 166,
329 rv_op_fadd_d = 167,
330 rv_op_fsub_d = 168,
331 rv_op_fmul_d = 169,
332 rv_op_fdiv_d = 170,
333 rv_op_fsgnj_d = 171,
334 rv_op_fsgnjn_d = 172,
335 rv_op_fsgnjx_d = 173,
336 rv_op_fmin_d = 174,
337 rv_op_fmax_d = 175,
338 rv_op_fcvt_s_d = 176,
339 rv_op_fcvt_d_s = 177,
340 rv_op_fsqrt_d = 178,
341 rv_op_fle_d = 179,
342 rv_op_flt_d = 180,
343 rv_op_feq_d = 181,
344 rv_op_fcvt_w_d = 182,
345 rv_op_fcvt_wu_d = 183,
346 rv_op_fcvt_d_w = 184,
347 rv_op_fcvt_d_wu = 185,
348 rv_op_fclass_d = 186,
349 rv_op_fcvt_l_d = 187,
350 rv_op_fcvt_lu_d = 188,
351 rv_op_fmv_x_d = 189,
352 rv_op_fcvt_d_l = 190,
353 rv_op_fcvt_d_lu = 191,
354 rv_op_fmv_d_x = 192,
355 rv_op_flq = 193,
356 rv_op_fsq = 194,
357 rv_op_fmadd_q = 195,
358 rv_op_fmsub_q = 196,
359 rv_op_fnmsub_q = 197,
360 rv_op_fnmadd_q = 198,
361 rv_op_fadd_q = 199,
362 rv_op_fsub_q = 200,
363 rv_op_fmul_q = 201,
364 rv_op_fdiv_q = 202,
365 rv_op_fsgnj_q = 203,
366 rv_op_fsgnjn_q = 204,
367 rv_op_fsgnjx_q = 205,
368 rv_op_fmin_q = 206,
369 rv_op_fmax_q = 207,
370 rv_op_fcvt_s_q = 208,
371 rv_op_fcvt_q_s = 209,
372 rv_op_fcvt_d_q = 210,
373 rv_op_fcvt_q_d = 211,
374 rv_op_fsqrt_q = 212,
375 rv_op_fle_q = 213,
376 rv_op_flt_q = 214,
377 rv_op_feq_q = 215,
378 rv_op_fcvt_w_q = 216,
379 rv_op_fcvt_wu_q = 217,
380 rv_op_fcvt_q_w = 218,
381 rv_op_fcvt_q_wu = 219,
382 rv_op_fclass_q = 220,
383 rv_op_fcvt_l_q = 221,
384 rv_op_fcvt_lu_q = 222,
385 rv_op_fcvt_q_l = 223,
386 rv_op_fcvt_q_lu = 224,
387 rv_op_fmv_x_q = 225,
388 rv_op_fmv_q_x = 226,
389 rv_op_c_addi4spn = 227,
390 rv_op_c_fld = 228,
391 rv_op_c_lw = 229,
392 rv_op_c_flw = 230,
393 rv_op_c_fsd = 231,
394 rv_op_c_sw = 232,
395 rv_op_c_fsw = 233,
396 rv_op_c_nop = 234,
397 rv_op_c_addi = 235,
398 rv_op_c_jal = 236,
399 rv_op_c_li = 237,
400 rv_op_c_addi16sp = 238,
401 rv_op_c_lui = 239,
402 rv_op_c_srli = 240,
403 rv_op_c_srai = 241,
404 rv_op_c_andi = 242,
405 rv_op_c_sub = 243,
406 rv_op_c_xor = 244,
407 rv_op_c_or = 245,
408 rv_op_c_and = 246,
409 rv_op_c_subw = 247,
410 rv_op_c_addw = 248,
411 rv_op_c_j = 249,
412 rv_op_c_beqz = 250,
413 rv_op_c_bnez = 251,
414 rv_op_c_slli = 252,
415 rv_op_c_fldsp = 253,
416 rv_op_c_lwsp = 254,
417 rv_op_c_flwsp = 255,
418 rv_op_c_jr = 256,
419 rv_op_c_mv = 257,
420 rv_op_c_ebreak = 258,
421 rv_op_c_jalr = 259,
422 rv_op_c_add = 260,
423 rv_op_c_fsdsp = 261,
424 rv_op_c_swsp = 262,
425 rv_op_c_fswsp = 263,
426 rv_op_c_ld = 264,
427 rv_op_c_sd = 265,
428 rv_op_c_addiw = 266,
429 rv_op_c_ldsp = 267,
430 rv_op_c_sdsp = 268,
431 rv_op_c_lq = 269,
432 rv_op_c_sq = 270,
433 rv_op_c_lqsp = 271,
434 rv_op_c_sqsp = 272,
435 rv_op_nop = 273,
436 rv_op_mv = 274,
437 rv_op_not = 275,
438 rv_op_neg = 276,
439 rv_op_negw = 277,
440 rv_op_sext_w = 278,
441 rv_op_seqz = 279,
442 rv_op_snez = 280,
443 rv_op_sltz = 281,
444 rv_op_sgtz = 282,
445 rv_op_fmv_s = 283,
446 rv_op_fabs_s = 284,
447 rv_op_fneg_s = 285,
448 rv_op_fmv_d = 286,
449 rv_op_fabs_d = 287,
450 rv_op_fneg_d = 288,
451 rv_op_fmv_q = 289,
452 rv_op_fabs_q = 290,
453 rv_op_fneg_q = 291,
454 rv_op_beqz = 292,
455 rv_op_bnez = 293,
456 rv_op_blez = 294,
457 rv_op_bgez = 295,
458 rv_op_bltz = 296,
459 rv_op_bgtz = 297,
460 rv_op_ble = 298,
461 rv_op_bleu = 299,
462 rv_op_bgt = 300,
463 rv_op_bgtu = 301,
464 rv_op_j = 302,
465 rv_op_ret = 303,
466 rv_op_jr = 304,
467 rv_op_rdcycle = 305,
468 rv_op_rdtime = 306,
469 rv_op_rdinstret = 307,
470 rv_op_rdcycleh = 308,
471 rv_op_rdtimeh = 309,
472 rv_op_rdinstreth = 310,
473 rv_op_frcsr = 311,
474 rv_op_frrm = 312,
475 rv_op_frflags = 313,
476 rv_op_fscsr = 314,
477 rv_op_fsrm = 315,
478 rv_op_fsflags = 316,
479 rv_op_fsrmi = 317,
480 rv_op_fsflagsi = 318,
481 } rv_op;
483 /* structures */
485 typedef struct {
486 uint64_t pc;
487 uint64_t inst;
488 int32_t imm;
489 uint16_t op;
490 uint8_t codec;
491 uint8_t rd;
492 uint8_t rs1;
493 uint8_t rs2;
494 uint8_t rs3;
495 uint8_t rm;
496 uint8_t pred;
497 uint8_t succ;
498 uint8_t aq;
499 uint8_t rl;
500 } rv_decode;
502 typedef struct {
503 const int op;
504 const rvc_constraint *constraints;
505 } rv_comp_data;
507 typedef struct {
508 const char * const name;
509 const rv_codec codec;
510 const char * const format;
511 const rv_comp_data *pseudo;
512 const int decomp_rv32;
513 const int decomp_rv64;
514 const int decomp_rv128;
515 } rv_opcode_data;
517 /* register names */
519 static const char rv_ireg_name_sym[32][5] = {
520 "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
521 "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
522 "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
523 "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6",
526 static const char rv_freg_name_sym[32][5] = {
527 "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
528 "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
529 "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
530 "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
533 /* instruction formats */
535 #define rv_fmt_none "O\t"
536 #define rv_fmt_rs1 "O\t1"
537 #define rv_fmt_offset "O\to"
538 #define rv_fmt_pred_succ "O\tp,s"
539 #define rv_fmt_rs1_rs2 "O\t1,2"
540 #define rv_fmt_rd_imm "O\t0,i"
541 #define rv_fmt_rd_offset "O\t0,o"
542 #define rv_fmt_rd_rs1_rs2 "O\t0,1,2"
543 #define rv_fmt_frd_rs1 "O\t3,1"
544 #define rv_fmt_rd_frs1 "O\t0,4"
545 #define rv_fmt_rd_frs1_frs2 "O\t0,4,5"
546 #define rv_fmt_frd_frs1_frs2 "O\t3,4,5"
547 #define rv_fmt_rm_frd_frs1 "O\tr,3,4"
548 #define rv_fmt_rm_frd_rs1 "O\tr,3,1"
549 #define rv_fmt_rm_rd_frs1 "O\tr,0,4"
550 #define rv_fmt_rm_frd_frs1_frs2 "O\tr,3,4,5"
551 #define rv_fmt_rm_frd_frs1_frs2_frs3 "O\tr,3,4,5,6"
552 #define rv_fmt_rd_rs1_imm "O\t0,1,i"
553 #define rv_fmt_rd_rs1_offset "O\t0,1,i"
554 #define rv_fmt_rd_offset_rs1 "O\t0,i(1)"
555 #define rv_fmt_frd_offset_rs1 "O\t3,i(1)"
556 #define rv_fmt_rd_csr_rs1 "O\t0,c,1"
557 #define rv_fmt_rd_csr_zimm "O\t0,c,7"
558 #define rv_fmt_rs2_offset_rs1 "O\t2,i(1)"
559 #define rv_fmt_frs2_offset_rs1 "O\t5,i(1)"
560 #define rv_fmt_rs1_rs2_offset "O\t1,2,o"
561 #define rv_fmt_rs2_rs1_offset "O\t2,1,o"
562 #define rv_fmt_aqrl_rd_rs2_rs1 "OAR\t0,2,(1)"
563 #define rv_fmt_aqrl_rd_rs1 "OAR\t0,(1)"
564 #define rv_fmt_rd "O\t0"
565 #define rv_fmt_rd_zimm "O\t0,7"
566 #define rv_fmt_rd_rs1 "O\t0,1"
567 #define rv_fmt_rd_rs2 "O\t0,2"
568 #define rv_fmt_rs1_offset "O\t1,o"
569 #define rv_fmt_rs2_offset "O\t2,o"
571 /* pseudo-instruction constraints */
573 static const rvc_constraint rvcc_jal[] = { rvc_rd_eq_ra, rvc_end };
574 static const rvc_constraint rvcc_jalr[] = { rvc_rd_eq_ra, rvc_imm_eq_zero, rvc_end };
575 static const rvc_constraint rvcc_nop[] = { rvc_rd_eq_x0, rvc_rs1_eq_x0, rvc_imm_eq_zero, rvc_end };
576 static const rvc_constraint rvcc_mv[] = { rvc_imm_eq_zero, rvc_end };
577 static const rvc_constraint rvcc_not[] = { rvc_imm_eq_n1, rvc_end };
578 static const rvc_constraint rvcc_neg[] = { rvc_rs1_eq_x0, rvc_end };
579 static const rvc_constraint rvcc_negw[] = { rvc_rs1_eq_x0, rvc_end };
580 static const rvc_constraint rvcc_sext_w[] = { rvc_imm_eq_zero, rvc_end };
581 static const rvc_constraint rvcc_seqz[] = { rvc_imm_eq_p1, rvc_end };
582 static const rvc_constraint rvcc_snez[] = { rvc_rs1_eq_x0, rvc_end };
583 static const rvc_constraint rvcc_sltz[] = { rvc_rs2_eq_x0, rvc_end };
584 static const rvc_constraint rvcc_sgtz[] = { rvc_rs1_eq_x0, rvc_end };
585 static const rvc_constraint rvcc_fmv_s[] = { rvc_rs2_eq_rs1, rvc_end };
586 static const rvc_constraint rvcc_fabs_s[] = { rvc_rs2_eq_rs1, rvc_end };
587 static const rvc_constraint rvcc_fneg_s[] = { rvc_rs2_eq_rs1, rvc_end };
588 static const rvc_constraint rvcc_fmv_d[] = { rvc_rs2_eq_rs1, rvc_end };
589 static const rvc_constraint rvcc_fabs_d[] = { rvc_rs2_eq_rs1, rvc_end };
590 static const rvc_constraint rvcc_fneg_d[] = { rvc_rs2_eq_rs1, rvc_end };
591 static const rvc_constraint rvcc_fmv_q[] = { rvc_rs2_eq_rs1, rvc_end };
592 static const rvc_constraint rvcc_fabs_q[] = { rvc_rs2_eq_rs1, rvc_end };
593 static const rvc_constraint rvcc_fneg_q[] = { rvc_rs2_eq_rs1, rvc_end };
594 static const rvc_constraint rvcc_beqz[] = { rvc_rs2_eq_x0, rvc_end };
595 static const rvc_constraint rvcc_bnez[] = { rvc_rs2_eq_x0, rvc_end };
596 static const rvc_constraint rvcc_blez[] = { rvc_rs1_eq_x0, rvc_end };
597 static const rvc_constraint rvcc_bgez[] = { rvc_rs2_eq_x0, rvc_end };
598 static const rvc_constraint rvcc_bltz[] = { rvc_rs2_eq_x0, rvc_end };
599 static const rvc_constraint rvcc_bgtz[] = { rvc_rs1_eq_x0, rvc_end };
600 static const rvc_constraint rvcc_ble[] = { rvc_end };
601 static const rvc_constraint rvcc_bleu[] = { rvc_end };
602 static const rvc_constraint rvcc_bgt[] = { rvc_end };
603 static const rvc_constraint rvcc_bgtu[] = { rvc_end };
604 static const rvc_constraint rvcc_j[] = { rvc_rd_eq_x0, rvc_end };
605 static const rvc_constraint rvcc_ret[] = { rvc_rd_eq_x0, rvc_rs1_eq_ra, rvc_end };
606 static const rvc_constraint rvcc_jr[] = { rvc_rd_eq_x0, rvc_imm_eq_zero, rvc_end };
607 static const rvc_constraint rvcc_rdcycle[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc00, rvc_end };
608 static const rvc_constraint rvcc_rdtime[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc01, rvc_end };
609 static const rvc_constraint rvcc_rdinstret[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc02, rvc_end };
610 static const rvc_constraint rvcc_rdcycleh[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc80, rvc_end };
611 static const rvc_constraint rvcc_rdtimeh[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc81, rvc_end };
612 static const rvc_constraint rvcc_rdinstreth[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc80, rvc_end };
613 static const rvc_constraint rvcc_frcsr[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x003, rvc_end };
614 static const rvc_constraint rvcc_frrm[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x002, rvc_end };
615 static const rvc_constraint rvcc_frflags[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x001, rvc_end };
616 static const rvc_constraint rvcc_fscsr[] = { rvc_csr_eq_0x003, rvc_end };
617 static const rvc_constraint rvcc_fsrm[] = { rvc_csr_eq_0x002, rvc_end };
618 static const rvc_constraint rvcc_fsflags[] = { rvc_csr_eq_0x001, rvc_end };
619 static const rvc_constraint rvcc_fsrmi[] = { rvc_csr_eq_0x002, rvc_end };
620 static const rvc_constraint rvcc_fsflagsi[] = { rvc_csr_eq_0x001, rvc_end };
622 /* pseudo-instruction metadata */
624 static const rv_comp_data rvcp_jal[] = {
625 { rv_op_j, rvcc_j },
626 { rv_op_jal, rvcc_jal },
627 { rv_op_illegal, NULL }
630 static const rv_comp_data rvcp_jalr[] = {
631 { rv_op_ret, rvcc_ret },
632 { rv_op_jr, rvcc_jr },
633 { rv_op_jalr, rvcc_jalr },
634 { rv_op_illegal, NULL }
637 static const rv_comp_data rvcp_beq[] = {
638 { rv_op_beqz, rvcc_beqz },
639 { rv_op_illegal, NULL }
642 static const rv_comp_data rvcp_bne[] = {
643 { rv_op_bnez, rvcc_bnez },
644 { rv_op_illegal, NULL }
647 static const rv_comp_data rvcp_blt[] = {
648 { rv_op_bltz, rvcc_bltz },
649 { rv_op_bgtz, rvcc_bgtz },
650 { rv_op_bgt, rvcc_bgt },
651 { rv_op_illegal, NULL }
654 static const rv_comp_data rvcp_bge[] = {
655 { rv_op_blez, rvcc_blez },
656 { rv_op_bgez, rvcc_bgez },
657 { rv_op_ble, rvcc_ble },
658 { rv_op_illegal, NULL }
661 static const rv_comp_data rvcp_bltu[] = {
662 { rv_op_bgtu, rvcc_bgtu },
663 { rv_op_illegal, NULL }
666 static const rv_comp_data rvcp_bgeu[] = {
667 { rv_op_bleu, rvcc_bleu },
668 { rv_op_illegal, NULL }
671 static const rv_comp_data rvcp_addi[] = {
672 { rv_op_nop, rvcc_nop },
673 { rv_op_mv, rvcc_mv },
674 { rv_op_illegal, NULL }
677 static const rv_comp_data rvcp_sltiu[] = {
678 { rv_op_seqz, rvcc_seqz },
679 { rv_op_illegal, NULL }
682 static const rv_comp_data rvcp_xori[] = {
683 { rv_op_not, rvcc_not },
684 { rv_op_illegal, NULL }
687 static const rv_comp_data rvcp_sub[] = {
688 { rv_op_neg, rvcc_neg },
689 { rv_op_illegal, NULL }
692 static const rv_comp_data rvcp_slt[] = {
693 { rv_op_sltz, rvcc_sltz },
694 { rv_op_sgtz, rvcc_sgtz },
695 { rv_op_illegal, NULL }
698 static const rv_comp_data rvcp_sltu[] = {
699 { rv_op_snez, rvcc_snez },
700 { rv_op_illegal, NULL }
703 static const rv_comp_data rvcp_addiw[] = {
704 { rv_op_sext_w, rvcc_sext_w },
705 { rv_op_illegal, NULL }
708 static const rv_comp_data rvcp_subw[] = {
709 { rv_op_negw, rvcc_negw },
710 { rv_op_illegal, NULL }
713 static const rv_comp_data rvcp_csrrw[] = {
714 { rv_op_fscsr, rvcc_fscsr },
715 { rv_op_fsrm, rvcc_fsrm },
716 { rv_op_fsflags, rvcc_fsflags },
717 { rv_op_illegal, NULL }
720 static const rv_comp_data rvcp_csrrs[] = {
721 { rv_op_rdcycle, rvcc_rdcycle },
722 { rv_op_rdtime, rvcc_rdtime },
723 { rv_op_rdinstret, rvcc_rdinstret },
724 { rv_op_rdcycleh, rvcc_rdcycleh },
725 { rv_op_rdtimeh, rvcc_rdtimeh },
726 { rv_op_rdinstreth, rvcc_rdinstreth },
727 { rv_op_frcsr, rvcc_frcsr },
728 { rv_op_frrm, rvcc_frrm },
729 { rv_op_frflags, rvcc_frflags },
730 { rv_op_illegal, NULL }
733 static const rv_comp_data rvcp_csrrwi[] = {
734 { rv_op_fsrmi, rvcc_fsrmi },
735 { rv_op_fsflagsi, rvcc_fsflagsi },
736 { rv_op_illegal, NULL }
739 static const rv_comp_data rvcp_fsgnj_s[] = {
740 { rv_op_fmv_s, rvcc_fmv_s },
741 { rv_op_illegal, NULL }
744 static const rv_comp_data rvcp_fsgnjn_s[] = {
745 { rv_op_fneg_s, rvcc_fneg_s },
746 { rv_op_illegal, NULL }
749 static const rv_comp_data rvcp_fsgnjx_s[] = {
750 { rv_op_fabs_s, rvcc_fabs_s },
751 { rv_op_illegal, NULL }
754 static const rv_comp_data rvcp_fsgnj_d[] = {
755 { rv_op_fmv_d, rvcc_fmv_d },
756 { rv_op_illegal, NULL }
759 static const rv_comp_data rvcp_fsgnjn_d[] = {
760 { rv_op_fneg_d, rvcc_fneg_d },
761 { rv_op_illegal, NULL }
764 static const rv_comp_data rvcp_fsgnjx_d[] = {
765 { rv_op_fabs_d, rvcc_fabs_d },
766 { rv_op_illegal, NULL }
769 static const rv_comp_data rvcp_fsgnj_q[] = {
770 { rv_op_fmv_q, rvcc_fmv_q },
771 { rv_op_illegal, NULL }
774 static const rv_comp_data rvcp_fsgnjn_q[] = {
775 { rv_op_fneg_q, rvcc_fneg_q },
776 { rv_op_illegal, NULL }
779 static const rv_comp_data rvcp_fsgnjx_q[] = {
780 { rv_op_fabs_q, rvcc_fabs_q },
781 { rv_op_illegal, NULL }
784 /* instruction metadata */
786 const rv_opcode_data opcode_data[] = {
787 { "illegal", rv_codec_illegal, rv_fmt_none, NULL, 0, 0, 0 },
788 { "lui", rv_codec_u, rv_fmt_rd_imm, NULL, 0, 0, 0 },
789 { "auipc", rv_codec_u, rv_fmt_rd_offset, NULL, 0, 0, 0 },
790 { "jal", rv_codec_uj, rv_fmt_rd_offset, rvcp_jal, 0, 0, 0 },
791 { "jalr", rv_codec_i, rv_fmt_rd_rs1_offset, rvcp_jalr, 0, 0, 0 },
792 { "beq", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_beq, 0, 0, 0 },
793 { "bne", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bne, 0, 0, 0 },
794 { "blt", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_blt, 0, 0, 0 },
795 { "bge", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bge, 0, 0, 0 },
796 { "bltu", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bltu, 0, 0, 0 },
797 { "bgeu", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bgeu, 0, 0, 0 },
798 { "lb", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
799 { "lh", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
800 { "lw", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
801 { "lbu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
802 { "lhu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
803 { "sb", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
804 { "sh", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
805 { "sw", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
806 { "addi", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_addi, 0, 0, 0 },
807 { "slti", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
808 { "sltiu", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_sltiu, 0, 0, 0 },
809 { "xori", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_xori, 0, 0, 0 },
810 { "ori", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
811 { "andi", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
812 { "slli", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
813 { "srli", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
814 { "srai", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
815 { "add", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
816 { "sub", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_sub, 0, 0, 0 },
817 { "sll", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
818 { "slt", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_slt, 0, 0, 0 },
819 { "sltu", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_sltu, 0, 0, 0 },
820 { "xor", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
821 { "srl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
822 { "sra", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
823 { "or", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
824 { "and", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
825 { "fence", rv_codec_r_f, rv_fmt_pred_succ, NULL, 0, 0, 0 },
826 { "fence.i", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
827 { "lwu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
828 { "ld", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
829 { "sd", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
830 { "addiw", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_addiw, 0, 0, 0 },
831 { "slliw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
832 { "srliw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
833 { "sraiw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
834 { "addw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
835 { "subw", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_subw, 0, 0, 0 },
836 { "sllw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
837 { "srlw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
838 { "sraw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
839 { "ldu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
840 { "lq", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
841 { "sq", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
842 { "addid", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
843 { "sllid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
844 { "srlid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
845 { "sraid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
846 { "addd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
847 { "subd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
848 { "slld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
849 { "srld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
850 { "srad", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
851 { "mul", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
852 { "mulh", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
853 { "mulhsu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
854 { "mulhu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
855 { "div", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
856 { "divu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
857 { "rem", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
858 { "remu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
859 { "mulw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
860 { "divw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
861 { "divuw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
862 { "remw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
863 { "remuw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
864 { "muld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
865 { "divd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
866 { "divud", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
867 { "remd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
868 { "remud", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
869 { "lr.w", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 },
870 { "sc.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
871 { "amoswap.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
872 { "amoadd.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
873 { "amoxor.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
874 { "amoor.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
875 { "amoand.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
876 { "amomin.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
877 { "amomax.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
878 { "amominu.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
879 { "amomaxu.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
880 { "lr.d", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 },
881 { "sc.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
882 { "amoswap.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
883 { "amoadd.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
884 { "amoxor.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
885 { "amoor.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
886 { "amoand.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
887 { "amomin.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
888 { "amomax.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
889 { "amominu.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
890 { "amomaxu.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
891 { "lr.q", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 },
892 { "sc.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
893 { "amoswap.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
894 { "amoadd.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
895 { "amoxor.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
896 { "amoor.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
897 { "amoand.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
898 { "amomin.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
899 { "amomax.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
900 { "amominu.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
901 { "amomaxu.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
902 { "ecall", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
903 { "ebreak", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
904 { "uret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
905 { "sret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
906 { "hret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
907 { "mret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
908 { "dret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
909 { "sfence.vm", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
910 { "sfence.vma", rv_codec_r, rv_fmt_rs1_rs2, NULL, 0, 0, 0 },
911 { "wfi", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
912 { "csrrw", rv_codec_i_csr, rv_fmt_rd_csr_rs1, rvcp_csrrw, 0, 0, 0 },
913 { "csrrs", rv_codec_i_csr, rv_fmt_rd_csr_rs1, rvcp_csrrs, 0, 0, 0 },
914 { "csrrc", rv_codec_i_csr, rv_fmt_rd_csr_rs1, NULL, 0, 0, 0 },
915 { "csrrwi", rv_codec_i_csr, rv_fmt_rd_csr_zimm, rvcp_csrrwi, 0, 0, 0 },
916 { "csrrsi", rv_codec_i_csr, rv_fmt_rd_csr_zimm, NULL, 0, 0, 0 },
917 { "csrrci", rv_codec_i_csr, rv_fmt_rd_csr_zimm, NULL, 0, 0, 0 },
918 { "flw", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 },
919 { "fsw", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 },
920 { "fmadd.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
921 { "fmsub.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
922 { "fnmsub.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
923 { "fnmadd.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
924 { "fadd.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
925 { "fsub.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
926 { "fmul.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
927 { "fdiv.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
928 { "fsgnj.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_s, 0, 0, 0 },
929 { "fsgnjn.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_s, 0, 0, 0 },
930 { "fsgnjx.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_s, 0, 0, 0 },
931 { "fmin.s", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
932 { "fmax.s", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
933 { "fsqrt.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
934 { "fle.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
935 { "flt.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
936 { "feq.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
937 { "fcvt.w.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
938 { "fcvt.wu.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
939 { "fcvt.s.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
940 { "fcvt.s.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
941 { "fmv.x.s", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
942 { "fclass.s", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
943 { "fmv.s.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 },
944 { "fcvt.l.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
945 { "fcvt.lu.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
946 { "fcvt.s.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
947 { "fcvt.s.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
948 { "fld", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 },
949 { "fsd", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 },
950 { "fmadd.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
951 { "fmsub.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
952 { "fnmsub.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
953 { "fnmadd.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
954 { "fadd.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
955 { "fsub.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
956 { "fmul.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
957 { "fdiv.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
958 { "fsgnj.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_d, 0, 0, 0 },
959 { "fsgnjn.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_d, 0, 0, 0 },
960 { "fsgnjx.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_d, 0, 0, 0 },
961 { "fmin.d", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
962 { "fmax.d", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
963 { "fcvt.s.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
964 { "fcvt.d.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
965 { "fsqrt.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
966 { "fle.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
967 { "flt.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
968 { "feq.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
969 { "fcvt.w.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
970 { "fcvt.wu.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
971 { "fcvt.d.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
972 { "fcvt.d.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
973 { "fclass.d", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
974 { "fcvt.l.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
975 { "fcvt.lu.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
976 { "fmv.x.d", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
977 { "fcvt.d.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
978 { "fcvt.d.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
979 { "fmv.d.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 },
980 { "flq", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 },
981 { "fsq", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 },
982 { "fmadd.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
983 { "fmsub.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
984 { "fnmsub.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
985 { "fnmadd.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
986 { "fadd.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
987 { "fsub.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
988 { "fmul.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
989 { "fdiv.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
990 { "fsgnj.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_q, 0, 0, 0 },
991 { "fsgnjn.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_q, 0, 0, 0 },
992 { "fsgnjx.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_q, 0, 0, 0 },
993 { "fmin.q", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
994 { "fmax.q", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
995 { "fcvt.s.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
996 { "fcvt.q.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
997 { "fcvt.d.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
998 { "fcvt.q.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
999 { "fsqrt.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1000 { "fle.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
1001 { "flt.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
1002 { "feq.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
1003 { "fcvt.w.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1004 { "fcvt.wu.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1005 { "fcvt.q.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1006 { "fcvt.q.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1007 { "fclass.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
1008 { "fcvt.l.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1009 { "fcvt.lu.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1010 { "fcvt.q.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1011 { "fcvt.q.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1012 { "fmv.x.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
1013 { "fmv.q.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 },
1014 { "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1015 { "c.fld", rv_codec_cl_ld, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, 0 },
1016 { "c.lw", rv_codec_cl_lw, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw },
1017 { "c.flw", rv_codec_cl_lw, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 },
1018 { "c.fsd", rv_codec_cs_sd, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, rv_op_fsd, 0 },
1019 { "c.sw", rv_codec_cs_sw, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw },
1020 { "c.fsw", rv_codec_cs_sw, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 },
1021 { "c.nop", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1022 { "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1023 { "c.jal", rv_codec_cj_jal, rv_fmt_rd_offset, NULL, rv_op_jal, 0, 0 },
1024 { "c.li", rv_codec_ci_li, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1025 { "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1026 { "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui, rv_op_lui },
1027 { "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli, rv_op_srli, rv_op_srli },
1028 { "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai, rv_op_srai, rv_op_srai },
1029 { "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi, rv_op_andi, rv_op_andi },
1030 { "c.sub", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_sub, rv_op_sub, rv_op_sub },
1031 { "c.xor", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_xor, rv_op_xor, rv_op_xor },
1032 { "c.or", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_or, rv_op_or, rv_op_or },
1033 { "c.and", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_and, rv_op_and, rv_op_and },
1034 { "c.subw", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_subw, rv_op_subw, rv_op_subw },
1035 { "c.addw", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_addw, rv_op_addw, rv_op_addw },
1036 { "c.j", rv_codec_cj, rv_fmt_rd_offset, NULL, rv_op_jal, rv_op_jal, rv_op_jal },
1037 { "c.beqz", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_beq, rv_op_beq, rv_op_beq },
1038 { "c.bnez", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_bne, rv_op_bne, rv_op_bne },
1039 { "c.slli", rv_codec_ci_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_slli, rv_op_slli, rv_op_slli },
1040 { "c.fldsp", rv_codec_ci_ldsp, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, rv_op_fld },
1041 { "c.lwsp", rv_codec_ci_lwsp, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw },
1042 { "c.flwsp", rv_codec_ci_lwsp, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 },
1043 { "c.jr", rv_codec_cr_jr, rv_fmt_rd_rs1_offset, NULL, rv_op_jalr, rv_op_jalr, rv_op_jalr },
1044 { "c.mv", rv_codec_cr_mv, rv_fmt_rd_rs1_rs2, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1045 { "c.ebreak", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_ebreak, rv_op_ebreak, rv_op_ebreak },
1046 { "c.jalr", rv_codec_cr_jalr, rv_fmt_rd_rs1_offset, NULL, rv_op_jalr, rv_op_jalr, rv_op_jalr },
1047 { "c.add", rv_codec_cr, rv_fmt_rd_rs1_rs2, NULL, rv_op_add, rv_op_add, rv_op_add },
1048 { "c.fsdsp", rv_codec_css_sdsp, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, rv_op_fsd, rv_op_fsd },
1049 { "c.swsp", rv_codec_css_swsp, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw },
1050 { "c.fswsp", rv_codec_css_swsp, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 },
1051 { "c.ld", rv_codec_cl_ld, rv_fmt_rd_offset_rs1, NULL, 0, rv_op_ld, rv_op_ld },
1052 { "c.sd", rv_codec_cs_sd, rv_fmt_rs2_offset_rs1, NULL, 0, rv_op_sd, rv_op_sd },
1053 { "c.addiw", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, 0, rv_op_addiw, rv_op_addiw },
1054 { "c.ldsp", rv_codec_ci_ldsp, rv_fmt_rd_offset_rs1, NULL, 0, rv_op_ld, rv_op_ld },
1055 { "c.sdsp", rv_codec_css_sdsp, rv_fmt_rs2_offset_rs1, NULL, 0, rv_op_sd, rv_op_sd },
1056 { "c.lq", rv_codec_cl_lq, rv_fmt_rd_offset_rs1, NULL, 0, 0, rv_op_lq },
1057 { "c.sq", rv_codec_cs_sq, rv_fmt_rs2_offset_rs1, NULL, 0, 0, rv_op_sq },
1058 { "c.lqsp", rv_codec_ci_lqsp, rv_fmt_rd_offset_rs1, NULL, 0, 0, rv_op_lq },
1059 { "c.sqsp", rv_codec_css_sqsp, rv_fmt_rs2_offset_rs1, NULL, 0, 0, rv_op_sq },
1060 { "nop", rv_codec_i, rv_fmt_none, NULL, 0, 0, 0 },
1061 { "mv", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1062 { "not", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1063 { "neg", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1064 { "negw", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1065 { "sext.w", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1066 { "seqz", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1067 { "snez", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1068 { "sltz", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1069 { "sgtz", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1070 { "fmv.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1071 { "fabs.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1072 { "fneg.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1073 { "fmv.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1074 { "fabs.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1075 { "fneg.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1076 { "fmv.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1077 { "fabs.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1078 { "fneg.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1079 { "beqz", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1080 { "bnez", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1081 { "blez", rv_codec_sb, rv_fmt_rs2_offset, NULL, 0, 0, 0 },
1082 { "bgez", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1083 { "bltz", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1084 { "bgtz", rv_codec_sb, rv_fmt_rs2_offset, NULL, 0, 0, 0 },
1085 { "ble", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1086 { "bleu", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1087 { "bgt", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1088 { "bgtu", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1089 { "j", rv_codec_uj, rv_fmt_offset, NULL, 0, 0, 0 },
1090 { "ret", rv_codec_i, rv_fmt_none, NULL, 0, 0, 0 },
1091 { "jr", rv_codec_i, rv_fmt_rs1, NULL, 0, 0, 0 },
1092 { "rdcycle", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1093 { "rdtime", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1094 { "rdinstret", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1095 { "rdcycleh", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1096 { "rdtimeh", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1097 { "rdinstreth", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1098 { "frcsr", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1099 { "frrm", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1100 { "frflags", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1101 { "fscsr", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1102 { "fsrm", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1103 { "fsflags", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1104 { "fsrmi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 },
1105 { "fsflagsi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 },
1108 /* CSR names */
1110 static const char *csr_name(int csrno)
1112 switch (csrno) {
1113 case 0x0000: return "ustatus";
1114 case 0x0001: return "fflags";
1115 case 0x0002: return "frm";
1116 case 0x0003: return "fcsr";
1117 case 0x0004: return "uie";
1118 case 0x0005: return "utvec";
1119 case 0x0040: return "uscratch";
1120 case 0x0041: return "uepc";
1121 case 0x0042: return "ucause";
1122 case 0x0043: return "utval";
1123 case 0x0044: return "uip";
1124 case 0x0100: return "sstatus";
1125 case 0x0102: return "sedeleg";
1126 case 0x0103: return "sideleg";
1127 case 0x0104: return "sie";
1128 case 0x0105: return "stvec";
1129 case 0x0106: return "scounteren";
1130 case 0x0140: return "sscratch";
1131 case 0x0141: return "sepc";
1132 case 0x0142: return "scause";
1133 case 0x0143: return "stval";
1134 case 0x0144: return "sip";
1135 case 0x0180: return "satp";
1136 case 0x0200: return "hstatus";
1137 case 0x0202: return "hedeleg";
1138 case 0x0203: return "hideleg";
1139 case 0x0204: return "hie";
1140 case 0x0205: return "htvec";
1141 case 0x0240: return "hscratch";
1142 case 0x0241: return "hepc";
1143 case 0x0242: return "hcause";
1144 case 0x0243: return "hbadaddr";
1145 case 0x0244: return "hip";
1146 case 0x0300: return "mstatus";
1147 case 0x0301: return "misa";
1148 case 0x0302: return "medeleg";
1149 case 0x0303: return "mideleg";
1150 case 0x0304: return "mie";
1151 case 0x0305: return "mtvec";
1152 case 0x0306: return "mcounteren";
1153 case 0x0320: return "mucounteren";
1154 case 0x0321: return "mscounteren";
1155 case 0x0322: return "mhcounteren";
1156 case 0x0323: return "mhpmevent3";
1157 case 0x0324: return "mhpmevent4";
1158 case 0x0325: return "mhpmevent5";
1159 case 0x0326: return "mhpmevent6";
1160 case 0x0327: return "mhpmevent7";
1161 case 0x0328: return "mhpmevent8";
1162 case 0x0329: return "mhpmevent9";
1163 case 0x032a: return "mhpmevent10";
1164 case 0x032b: return "mhpmevent11";
1165 case 0x032c: return "mhpmevent12";
1166 case 0x032d: return "mhpmevent13";
1167 case 0x032e: return "mhpmevent14";
1168 case 0x032f: return "mhpmevent15";
1169 case 0x0330: return "mhpmevent16";
1170 case 0x0331: return "mhpmevent17";
1171 case 0x0332: return "mhpmevent18";
1172 case 0x0333: return "mhpmevent19";
1173 case 0x0334: return "mhpmevent20";
1174 case 0x0335: return "mhpmevent21";
1175 case 0x0336: return "mhpmevent22";
1176 case 0x0337: return "mhpmevent23";
1177 case 0x0338: return "mhpmevent24";
1178 case 0x0339: return "mhpmevent25";
1179 case 0x033a: return "mhpmevent26";
1180 case 0x033b: return "mhpmevent27";
1181 case 0x033c: return "mhpmevent28";
1182 case 0x033d: return "mhpmevent29";
1183 case 0x033e: return "mhpmevent30";
1184 case 0x033f: return "mhpmevent31";
1185 case 0x0340: return "mscratch";
1186 case 0x0341: return "mepc";
1187 case 0x0342: return "mcause";
1188 case 0x0343: return "mtval";
1189 case 0x0344: return "mip";
1190 case 0x0380: return "mbase";
1191 case 0x0381: return "mbound";
1192 case 0x0382: return "mibase";
1193 case 0x0383: return "mibound";
1194 case 0x0384: return "mdbase";
1195 case 0x0385: return "mdbound";
1196 case 0x03a0: return "pmpcfg3";
1197 case 0x03b0: return "pmpaddr0";
1198 case 0x03b1: return "pmpaddr1";
1199 case 0x03b2: return "pmpaddr2";
1200 case 0x03b3: return "pmpaddr3";
1201 case 0x03b4: return "pmpaddr4";
1202 case 0x03b5: return "pmpaddr5";
1203 case 0x03b6: return "pmpaddr6";
1204 case 0x03b7: return "pmpaddr7";
1205 case 0x03b8: return "pmpaddr8";
1206 case 0x03b9: return "pmpaddr9";
1207 case 0x03ba: return "pmpaddr10";
1208 case 0x03bb: return "pmpaddr11";
1209 case 0x03bc: return "pmpaddr12";
1210 case 0x03bd: return "pmpaddr14";
1211 case 0x03be: return "pmpaddr13";
1212 case 0x03bf: return "pmpaddr15";
1213 case 0x0780: return "mtohost";
1214 case 0x0781: return "mfromhost";
1215 case 0x0782: return "mreset";
1216 case 0x0783: return "mipi";
1217 case 0x0784: return "miobase";
1218 case 0x07a0: return "tselect";
1219 case 0x07a1: return "tdata1";
1220 case 0x07a2: return "tdata2";
1221 case 0x07a3: return "tdata3";
1222 case 0x07b0: return "dcsr";
1223 case 0x07b1: return "dpc";
1224 case 0x07b2: return "dscratch";
1225 case 0x0b00: return "mcycle";
1226 case 0x0b01: return "mtime";
1227 case 0x0b02: return "minstret";
1228 case 0x0b03: return "mhpmcounter3";
1229 case 0x0b04: return "mhpmcounter4";
1230 case 0x0b05: return "mhpmcounter5";
1231 case 0x0b06: return "mhpmcounter6";
1232 case 0x0b07: return "mhpmcounter7";
1233 case 0x0b08: return "mhpmcounter8";
1234 case 0x0b09: return "mhpmcounter9";
1235 case 0x0b0a: return "mhpmcounter10";
1236 case 0x0b0b: return "mhpmcounter11";
1237 case 0x0b0c: return "mhpmcounter12";
1238 case 0x0b0d: return "mhpmcounter13";
1239 case 0x0b0e: return "mhpmcounter14";
1240 case 0x0b0f: return "mhpmcounter15";
1241 case 0x0b10: return "mhpmcounter16";
1242 case 0x0b11: return "mhpmcounter17";
1243 case 0x0b12: return "mhpmcounter18";
1244 case 0x0b13: return "mhpmcounter19";
1245 case 0x0b14: return "mhpmcounter20";
1246 case 0x0b15: return "mhpmcounter21";
1247 case 0x0b16: return "mhpmcounter22";
1248 case 0x0b17: return "mhpmcounter23";
1249 case 0x0b18: return "mhpmcounter24";
1250 case 0x0b19: return "mhpmcounter25";
1251 case 0x0b1a: return "mhpmcounter26";
1252 case 0x0b1b: return "mhpmcounter27";
1253 case 0x0b1c: return "mhpmcounter28";
1254 case 0x0b1d: return "mhpmcounter29";
1255 case 0x0b1e: return "mhpmcounter30";
1256 case 0x0b1f: return "mhpmcounter31";
1257 case 0x0b80: return "mcycleh";
1258 case 0x0b81: return "mtimeh";
1259 case 0x0b82: return "minstreth";
1260 case 0x0b83: return "mhpmcounter3h";
1261 case 0x0b84: return "mhpmcounter4h";
1262 case 0x0b85: return "mhpmcounter5h";
1263 case 0x0b86: return "mhpmcounter6h";
1264 case 0x0b87: return "mhpmcounter7h";
1265 case 0x0b88: return "mhpmcounter8h";
1266 case 0x0b89: return "mhpmcounter9h";
1267 case 0x0b8a: return "mhpmcounter10h";
1268 case 0x0b8b: return "mhpmcounter11h";
1269 case 0x0b8c: return "mhpmcounter12h";
1270 case 0x0b8d: return "mhpmcounter13h";
1271 case 0x0b8e: return "mhpmcounter14h";
1272 case 0x0b8f: return "mhpmcounter15h";
1273 case 0x0b90: return "mhpmcounter16h";
1274 case 0x0b91: return "mhpmcounter17h";
1275 case 0x0b92: return "mhpmcounter18h";
1276 case 0x0b93: return "mhpmcounter19h";
1277 case 0x0b94: return "mhpmcounter20h";
1278 case 0x0b95: return "mhpmcounter21h";
1279 case 0x0b96: return "mhpmcounter22h";
1280 case 0x0b97: return "mhpmcounter23h";
1281 case 0x0b98: return "mhpmcounter24h";
1282 case 0x0b99: return "mhpmcounter25h";
1283 case 0x0b9a: return "mhpmcounter26h";
1284 case 0x0b9b: return "mhpmcounter27h";
1285 case 0x0b9c: return "mhpmcounter28h";
1286 case 0x0b9d: return "mhpmcounter29h";
1287 case 0x0b9e: return "mhpmcounter30h";
1288 case 0x0b9f: return "mhpmcounter31h";
1289 case 0x0c00: return "cycle";
1290 case 0x0c01: return "time";
1291 case 0x0c02: return "instret";
1292 case 0x0c80: return "cycleh";
1293 case 0x0c81: return "timeh";
1294 case 0x0c82: return "instreth";
1295 case 0x0d00: return "scycle";
1296 case 0x0d01: return "stime";
1297 case 0x0d02: return "sinstret";
1298 case 0x0d80: return "scycleh";
1299 case 0x0d81: return "stimeh";
1300 case 0x0d82: return "sinstreth";
1301 case 0x0e00: return "hcycle";
1302 case 0x0e01: return "htime";
1303 case 0x0e02: return "hinstret";
1304 case 0x0e80: return "hcycleh";
1305 case 0x0e81: return "htimeh";
1306 case 0x0e82: return "hinstreth";
1307 case 0x0f11: return "mvendorid";
1308 case 0x0f12: return "marchid";
1309 case 0x0f13: return "mimpid";
1310 case 0x0f14: return "mhartid";
1311 default: return NULL;
1315 /* decode opcode */
1317 static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
1319 rv_inst inst = dec->inst;
1320 rv_opcode op = rv_op_illegal;
1321 switch (((inst >> 0) & 0b11)) {
1322 case 0:
1323 switch (((inst >> 13) & 0b111)) {
1324 case 0: op = rv_op_c_addi4spn; break;
1325 case 1:
1326 if (isa == rv128) {
1327 op = rv_op_c_lq;
1328 } else {
1329 op = rv_op_c_fld;
1331 break;
1332 case 2: op = rv_op_c_lw; break;
1333 case 3:
1334 if (isa == rv32) {
1335 op = rv_op_c_flw;
1336 } else {
1337 op = rv_op_c_ld;
1339 break;
1340 case 5:
1341 if (isa == rv128) {
1342 op = rv_op_c_sq;
1343 } else {
1344 op = rv_op_c_fsd;
1346 break;
1347 case 6: op = rv_op_c_sw; break;
1348 case 7:
1349 if (isa == rv32) {
1350 op = rv_op_c_fsw;
1351 } else {
1352 op = rv_op_c_sd;
1354 break;
1356 break;
1357 case 1:
1358 switch (((inst >> 13) & 0b111)) {
1359 case 0:
1360 switch (((inst >> 2) & 0b11111111111)) {
1361 case 0: op = rv_op_c_nop; break;
1362 default: op = rv_op_c_addi; break;
1364 break;
1365 case 1:
1366 if (isa == rv32) {
1367 op = rv_op_c_jal;
1368 } else {
1369 op = rv_op_c_addiw;
1371 break;
1372 case 2: op = rv_op_c_li; break;
1373 case 3:
1374 switch (((inst >> 7) & 0b11111)) {
1375 case 2: op = rv_op_c_addi16sp; break;
1376 default: op = rv_op_c_lui; break;
1378 break;
1379 case 4:
1380 switch (((inst >> 10) & 0b11)) {
1381 case 0:
1382 op = rv_op_c_srli;
1383 break;
1384 case 1:
1385 op = rv_op_c_srai;
1386 break;
1387 case 2: op = rv_op_c_andi; break;
1388 case 3:
1389 switch (((inst >> 10) & 0b100) | ((inst >> 5) & 0b011)) {
1390 case 0: op = rv_op_c_sub; break;
1391 case 1: op = rv_op_c_xor; break;
1392 case 2: op = rv_op_c_or; break;
1393 case 3: op = rv_op_c_and; break;
1394 case 4: op = rv_op_c_subw; break;
1395 case 5: op = rv_op_c_addw; break;
1397 break;
1399 break;
1400 case 5: op = rv_op_c_j; break;
1401 case 6: op = rv_op_c_beqz; break;
1402 case 7: op = rv_op_c_bnez; break;
1404 break;
1405 case 2:
1406 switch (((inst >> 13) & 0b111)) {
1407 case 0:
1408 op = rv_op_c_slli;
1409 break;
1410 case 1:
1411 if (isa == rv128) {
1412 op = rv_op_c_lqsp;
1413 } else {
1414 op = rv_op_c_fldsp;
1416 break;
1417 case 2: op = rv_op_c_lwsp; break;
1418 case 3:
1419 if (isa == rv32) {
1420 op = rv_op_c_flwsp;
1421 } else {
1422 op = rv_op_c_ldsp;
1424 break;
1425 case 4:
1426 switch (((inst >> 12) & 0b1)) {
1427 case 0:
1428 switch (((inst >> 2) & 0b11111)) {
1429 case 0: op = rv_op_c_jr; break;
1430 default: op = rv_op_c_mv; break;
1432 break;
1433 case 1:
1434 switch (((inst >> 2) & 0b11111)) {
1435 case 0:
1436 switch (((inst >> 7) & 0b11111)) {
1437 case 0: op = rv_op_c_ebreak; break;
1438 default: op = rv_op_c_jalr; break;
1440 break;
1441 default: op = rv_op_c_add; break;
1443 break;
1445 break;
1446 case 5:
1447 if (isa == rv128) {
1448 op = rv_op_c_sqsp;
1449 } else {
1450 op = rv_op_c_fsdsp;
1452 break;
1453 case 6: op = rv_op_c_swsp; break;
1454 case 7:
1455 if (isa == rv32) {
1456 op = rv_op_c_fswsp;
1457 } else {
1458 op = rv_op_c_sdsp;
1460 break;
1462 break;
1463 case 3:
1464 switch (((inst >> 2) & 0b11111)) {
1465 case 0:
1466 switch (((inst >> 12) & 0b111)) {
1467 case 0: op = rv_op_lb; break;
1468 case 1: op = rv_op_lh; break;
1469 case 2: op = rv_op_lw; break;
1470 case 3: op = rv_op_ld; break;
1471 case 4: op = rv_op_lbu; break;
1472 case 5: op = rv_op_lhu; break;
1473 case 6: op = rv_op_lwu; break;
1474 case 7: op = rv_op_ldu; break;
1476 break;
1477 case 1:
1478 switch (((inst >> 12) & 0b111)) {
1479 case 2: op = rv_op_flw; break;
1480 case 3: op = rv_op_fld; break;
1481 case 4: op = rv_op_flq; break;
1483 break;
1484 case 3:
1485 switch (((inst >> 12) & 0b111)) {
1486 case 0: op = rv_op_fence; break;
1487 case 1: op = rv_op_fence_i; break;
1488 case 2: op = rv_op_lq; break;
1490 break;
1491 case 4:
1492 switch (((inst >> 12) & 0b111)) {
1493 case 0: op = rv_op_addi; break;
1494 case 1:
1495 switch (((inst >> 27) & 0b11111)) {
1496 case 0: op = rv_op_slli; break;
1498 break;
1499 case 2: op = rv_op_slti; break;
1500 case 3: op = rv_op_sltiu; break;
1501 case 4: op = rv_op_xori; break;
1502 case 5:
1503 switch (((inst >> 27) & 0b11111)) {
1504 case 0: op = rv_op_srli; break;
1505 case 8: op = rv_op_srai; break;
1507 break;
1508 case 6: op = rv_op_ori; break;
1509 case 7: op = rv_op_andi; break;
1511 break;
1512 case 5: op = rv_op_auipc; break;
1513 case 6:
1514 switch (((inst >> 12) & 0b111)) {
1515 case 0: op = rv_op_addiw; break;
1516 case 1:
1517 switch (((inst >> 25) & 0b1111111)) {
1518 case 0: op = rv_op_slliw; break;
1520 break;
1521 case 5:
1522 switch (((inst >> 25) & 0b1111111)) {
1523 case 0: op = rv_op_srliw; break;
1524 case 32: op = rv_op_sraiw; break;
1526 break;
1528 break;
1529 case 8:
1530 switch (((inst >> 12) & 0b111)) {
1531 case 0: op = rv_op_sb; break;
1532 case 1: op = rv_op_sh; break;
1533 case 2: op = rv_op_sw; break;
1534 case 3: op = rv_op_sd; break;
1535 case 4: op = rv_op_sq; break;
1537 break;
1538 case 9:
1539 switch (((inst >> 12) & 0b111)) {
1540 case 2: op = rv_op_fsw; break;
1541 case 3: op = rv_op_fsd; break;
1542 case 4: op = rv_op_fsq; break;
1544 break;
1545 case 11:
1546 switch (((inst >> 24) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1547 case 2: op = rv_op_amoadd_w; break;
1548 case 3: op = rv_op_amoadd_d; break;
1549 case 4: op = rv_op_amoadd_q; break;
1550 case 10: op = rv_op_amoswap_w; break;
1551 case 11: op = rv_op_amoswap_d; break;
1552 case 12: op = rv_op_amoswap_q; break;
1553 case 18:
1554 switch (((inst >> 20) & 0b11111)) {
1555 case 0: op = rv_op_lr_w; break;
1557 break;
1558 case 19:
1559 switch (((inst >> 20) & 0b11111)) {
1560 case 0: op = rv_op_lr_d; break;
1562 break;
1563 case 20:
1564 switch (((inst >> 20) & 0b11111)) {
1565 case 0: op = rv_op_lr_q; break;
1567 break;
1568 case 26: op = rv_op_sc_w; break;
1569 case 27: op = rv_op_sc_d; break;
1570 case 28: op = rv_op_sc_q; break;
1571 case 34: op = rv_op_amoxor_w; break;
1572 case 35: op = rv_op_amoxor_d; break;
1573 case 36: op = rv_op_amoxor_q; break;
1574 case 66: op = rv_op_amoor_w; break;
1575 case 67: op = rv_op_amoor_d; break;
1576 case 68: op = rv_op_amoor_q; break;
1577 case 98: op = rv_op_amoand_w; break;
1578 case 99: op = rv_op_amoand_d; break;
1579 case 100: op = rv_op_amoand_q; break;
1580 case 130: op = rv_op_amomin_w; break;
1581 case 131: op = rv_op_amomin_d; break;
1582 case 132: op = rv_op_amomin_q; break;
1583 case 162: op = rv_op_amomax_w; break;
1584 case 163: op = rv_op_amomax_d; break;
1585 case 164: op = rv_op_amomax_q; break;
1586 case 194: op = rv_op_amominu_w; break;
1587 case 195: op = rv_op_amominu_d; break;
1588 case 196: op = rv_op_amominu_q; break;
1589 case 226: op = rv_op_amomaxu_w; break;
1590 case 227: op = rv_op_amomaxu_d; break;
1591 case 228: op = rv_op_amomaxu_q; break;
1593 break;
1594 case 12:
1595 switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) {
1596 case 0: op = rv_op_add; break;
1597 case 1: op = rv_op_sll; break;
1598 case 2: op = rv_op_slt; break;
1599 case 3: op = rv_op_sltu; break;
1600 case 4: op = rv_op_xor; break;
1601 case 5: op = rv_op_srl; break;
1602 case 6: op = rv_op_or; break;
1603 case 7: op = rv_op_and; break;
1604 case 8: op = rv_op_mul; break;
1605 case 9: op = rv_op_mulh; break;
1606 case 10: op = rv_op_mulhsu; break;
1607 case 11: op = rv_op_mulhu; break;
1608 case 12: op = rv_op_div; break;
1609 case 13: op = rv_op_divu; break;
1610 case 14: op = rv_op_rem; break;
1611 case 15: op = rv_op_remu; break;
1612 case 256: op = rv_op_sub; break;
1613 case 261: op = rv_op_sra; break;
1615 break;
1616 case 13: op = rv_op_lui; break;
1617 case 14:
1618 switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) {
1619 case 0: op = rv_op_addw; break;
1620 case 1: op = rv_op_sllw; break;
1621 case 5: op = rv_op_srlw; break;
1622 case 8: op = rv_op_mulw; break;
1623 case 12: op = rv_op_divw; break;
1624 case 13: op = rv_op_divuw; break;
1625 case 14: op = rv_op_remw; break;
1626 case 15: op = rv_op_remuw; break;
1627 case 256: op = rv_op_subw; break;
1628 case 261: op = rv_op_sraw; break;
1630 break;
1631 case 16:
1632 switch (((inst >> 25) & 0b11)) {
1633 case 0: op = rv_op_fmadd_s; break;
1634 case 1: op = rv_op_fmadd_d; break;
1635 case 3: op = rv_op_fmadd_q; break;
1637 break;
1638 case 17:
1639 switch (((inst >> 25) & 0b11)) {
1640 case 0: op = rv_op_fmsub_s; break;
1641 case 1: op = rv_op_fmsub_d; break;
1642 case 3: op = rv_op_fmsub_q; break;
1644 break;
1645 case 18:
1646 switch (((inst >> 25) & 0b11)) {
1647 case 0: op = rv_op_fnmsub_s; break;
1648 case 1: op = rv_op_fnmsub_d; break;
1649 case 3: op = rv_op_fnmsub_q; break;
1651 break;
1652 case 19:
1653 switch (((inst >> 25) & 0b11)) {
1654 case 0: op = rv_op_fnmadd_s; break;
1655 case 1: op = rv_op_fnmadd_d; break;
1656 case 3: op = rv_op_fnmadd_q; break;
1658 break;
1659 case 20:
1660 switch (((inst >> 25) & 0b1111111)) {
1661 case 0: op = rv_op_fadd_s; break;
1662 case 1: op = rv_op_fadd_d; break;
1663 case 3: op = rv_op_fadd_q; break;
1664 case 4: op = rv_op_fsub_s; break;
1665 case 5: op = rv_op_fsub_d; break;
1666 case 7: op = rv_op_fsub_q; break;
1667 case 8: op = rv_op_fmul_s; break;
1668 case 9: op = rv_op_fmul_d; break;
1669 case 11: op = rv_op_fmul_q; break;
1670 case 12: op = rv_op_fdiv_s; break;
1671 case 13: op = rv_op_fdiv_d; break;
1672 case 15: op = rv_op_fdiv_q; break;
1673 case 16:
1674 switch (((inst >> 12) & 0b111)) {
1675 case 0: op = rv_op_fsgnj_s; break;
1676 case 1: op = rv_op_fsgnjn_s; break;
1677 case 2: op = rv_op_fsgnjx_s; break;
1679 break;
1680 case 17:
1681 switch (((inst >> 12) & 0b111)) {
1682 case 0: op = rv_op_fsgnj_d; break;
1683 case 1: op = rv_op_fsgnjn_d; break;
1684 case 2: op = rv_op_fsgnjx_d; break;
1686 break;
1687 case 19:
1688 switch (((inst >> 12) & 0b111)) {
1689 case 0: op = rv_op_fsgnj_q; break;
1690 case 1: op = rv_op_fsgnjn_q; break;
1691 case 2: op = rv_op_fsgnjx_q; break;
1693 break;
1694 case 20:
1695 switch (((inst >> 12) & 0b111)) {
1696 case 0: op = rv_op_fmin_s; break;
1697 case 1: op = rv_op_fmax_s; break;
1699 break;
1700 case 21:
1701 switch (((inst >> 12) & 0b111)) {
1702 case 0: op = rv_op_fmin_d; break;
1703 case 1: op = rv_op_fmax_d; break;
1705 break;
1706 case 23:
1707 switch (((inst >> 12) & 0b111)) {
1708 case 0: op = rv_op_fmin_q; break;
1709 case 1: op = rv_op_fmax_q; break;
1711 break;
1712 case 32:
1713 switch (((inst >> 20) & 0b11111)) {
1714 case 1: op = rv_op_fcvt_s_d; break;
1715 case 3: op = rv_op_fcvt_s_q; break;
1717 break;
1718 case 33:
1719 switch (((inst >> 20) & 0b11111)) {
1720 case 0: op = rv_op_fcvt_d_s; break;
1721 case 3: op = rv_op_fcvt_d_q; break;
1723 break;
1724 case 35:
1725 switch (((inst >> 20) & 0b11111)) {
1726 case 0: op = rv_op_fcvt_q_s; break;
1727 case 1: op = rv_op_fcvt_q_d; break;
1729 break;
1730 case 44:
1731 switch (((inst >> 20) & 0b11111)) {
1732 case 0: op = rv_op_fsqrt_s; break;
1734 break;
1735 case 45:
1736 switch (((inst >> 20) & 0b11111)) {
1737 case 0: op = rv_op_fsqrt_d; break;
1739 break;
1740 case 47:
1741 switch (((inst >> 20) & 0b11111)) {
1742 case 0: op = rv_op_fsqrt_q; break;
1744 break;
1745 case 80:
1746 switch (((inst >> 12) & 0b111)) {
1747 case 0: op = rv_op_fle_s; break;
1748 case 1: op = rv_op_flt_s; break;
1749 case 2: op = rv_op_feq_s; break;
1751 break;
1752 case 81:
1753 switch (((inst >> 12) & 0b111)) {
1754 case 0: op = rv_op_fle_d; break;
1755 case 1: op = rv_op_flt_d; break;
1756 case 2: op = rv_op_feq_d; break;
1758 break;
1759 case 83:
1760 switch (((inst >> 12) & 0b111)) {
1761 case 0: op = rv_op_fle_q; break;
1762 case 1: op = rv_op_flt_q; break;
1763 case 2: op = rv_op_feq_q; break;
1765 break;
1766 case 96:
1767 switch (((inst >> 20) & 0b11111)) {
1768 case 0: op = rv_op_fcvt_w_s; break;
1769 case 1: op = rv_op_fcvt_wu_s; break;
1770 case 2: op = rv_op_fcvt_l_s; break;
1771 case 3: op = rv_op_fcvt_lu_s; break;
1773 break;
1774 case 97:
1775 switch (((inst >> 20) & 0b11111)) {
1776 case 0: op = rv_op_fcvt_w_d; break;
1777 case 1: op = rv_op_fcvt_wu_d; break;
1778 case 2: op = rv_op_fcvt_l_d; break;
1779 case 3: op = rv_op_fcvt_lu_d; break;
1781 break;
1782 case 99:
1783 switch (((inst >> 20) & 0b11111)) {
1784 case 0: op = rv_op_fcvt_w_q; break;
1785 case 1: op = rv_op_fcvt_wu_q; break;
1786 case 2: op = rv_op_fcvt_l_q; break;
1787 case 3: op = rv_op_fcvt_lu_q; break;
1789 break;
1790 case 104:
1791 switch (((inst >> 20) & 0b11111)) {
1792 case 0: op = rv_op_fcvt_s_w; break;
1793 case 1: op = rv_op_fcvt_s_wu; break;
1794 case 2: op = rv_op_fcvt_s_l; break;
1795 case 3: op = rv_op_fcvt_s_lu; break;
1797 break;
1798 case 105:
1799 switch (((inst >> 20) & 0b11111)) {
1800 case 0: op = rv_op_fcvt_d_w; break;
1801 case 1: op = rv_op_fcvt_d_wu; break;
1802 case 2: op = rv_op_fcvt_d_l; break;
1803 case 3: op = rv_op_fcvt_d_lu; break;
1805 break;
1806 case 107:
1807 switch (((inst >> 20) & 0b11111)) {
1808 case 0: op = rv_op_fcvt_q_w; break;
1809 case 1: op = rv_op_fcvt_q_wu; break;
1810 case 2: op = rv_op_fcvt_q_l; break;
1811 case 3: op = rv_op_fcvt_q_lu; break;
1813 break;
1814 case 112:
1815 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1816 case 0: op = rv_op_fmv_x_s; break;
1817 case 1: op = rv_op_fclass_s; break;
1819 break;
1820 case 113:
1821 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1822 case 0: op = rv_op_fmv_x_d; break;
1823 case 1: op = rv_op_fclass_d; break;
1825 break;
1826 case 115:
1827 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1828 case 0: op = rv_op_fmv_x_q; break;
1829 case 1: op = rv_op_fclass_q; break;
1831 break;
1832 case 120:
1833 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1834 case 0: op = rv_op_fmv_s_x; break;
1836 break;
1837 case 121:
1838 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1839 case 0: op = rv_op_fmv_d_x; break;
1841 break;
1842 case 123:
1843 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1844 case 0: op = rv_op_fmv_q_x; break;
1846 break;
1848 break;
1849 case 22:
1850 switch (((inst >> 12) & 0b111)) {
1851 case 0: op = rv_op_addid; break;
1852 case 1:
1853 switch (((inst >> 26) & 0b111111)) {
1854 case 0: op = rv_op_sllid; break;
1856 break;
1857 case 5:
1858 switch (((inst >> 26) & 0b111111)) {
1859 case 0: op = rv_op_srlid; break;
1860 case 16: op = rv_op_sraid; break;
1862 break;
1864 break;
1865 case 24:
1866 switch (((inst >> 12) & 0b111)) {
1867 case 0: op = rv_op_beq; break;
1868 case 1: op = rv_op_bne; break;
1869 case 4: op = rv_op_blt; break;
1870 case 5: op = rv_op_bge; break;
1871 case 6: op = rv_op_bltu; break;
1872 case 7: op = rv_op_bgeu; break;
1874 break;
1875 case 25:
1876 switch (((inst >> 12) & 0b111)) {
1877 case 0: op = rv_op_jalr; break;
1879 break;
1880 case 27: op = rv_op_jal; break;
1881 case 28:
1882 switch (((inst >> 12) & 0b111)) {
1883 case 0:
1884 switch (((inst >> 20) & 0b111111100000) | ((inst >> 7) & 0b000000011111)) {
1885 case 0:
1886 switch (((inst >> 15) & 0b1111111111)) {
1887 case 0: op = rv_op_ecall; break;
1888 case 32: op = rv_op_ebreak; break;
1889 case 64: op = rv_op_uret; break;
1891 break;
1892 case 256:
1893 switch (((inst >> 20) & 0b11111)) {
1894 case 2:
1895 switch (((inst >> 15) & 0b11111)) {
1896 case 0: op = rv_op_sret; break;
1898 break;
1899 case 4: op = rv_op_sfence_vm; break;
1900 case 5:
1901 switch (((inst >> 15) & 0b11111)) {
1902 case 0: op = rv_op_wfi; break;
1904 break;
1906 break;
1907 case 288: op = rv_op_sfence_vma; break;
1908 case 512:
1909 switch (((inst >> 15) & 0b1111111111)) {
1910 case 64: op = rv_op_hret; break;
1912 break;
1913 case 768:
1914 switch (((inst >> 15) & 0b1111111111)) {
1915 case 64: op = rv_op_mret; break;
1917 break;
1918 case 1952:
1919 switch (((inst >> 15) & 0b1111111111)) {
1920 case 576: op = rv_op_dret; break;
1922 break;
1924 break;
1925 case 1: op = rv_op_csrrw; break;
1926 case 2: op = rv_op_csrrs; break;
1927 case 3: op = rv_op_csrrc; break;
1928 case 5: op = rv_op_csrrwi; break;
1929 case 6: op = rv_op_csrrsi; break;
1930 case 7: op = rv_op_csrrci; break;
1932 break;
1933 case 30:
1934 switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) {
1935 case 0: op = rv_op_addd; break;
1936 case 1: op = rv_op_slld; break;
1937 case 5: op = rv_op_srld; break;
1938 case 8: op = rv_op_muld; break;
1939 case 12: op = rv_op_divd; break;
1940 case 13: op = rv_op_divud; break;
1941 case 14: op = rv_op_remd; break;
1942 case 15: op = rv_op_remud; break;
1943 case 256: op = rv_op_subd; break;
1944 case 261: op = rv_op_srad; break;
1946 break;
1948 break;
1950 dec->op = op;
1953 /* operand extractors */
1955 static uint32_t operand_rd(rv_inst inst)
1957 return (inst << 52) >> 59;
1960 static uint32_t operand_rs1(rv_inst inst)
1962 return (inst << 44) >> 59;
1965 static uint32_t operand_rs2(rv_inst inst)
1967 return (inst << 39) >> 59;
1970 static uint32_t operand_rs3(rv_inst inst)
1972 return (inst << 32) >> 59;
1975 static uint32_t operand_aq(rv_inst inst)
1977 return (inst << 37) >> 63;
1980 static uint32_t operand_rl(rv_inst inst)
1982 return (inst << 38) >> 63;
1985 static uint32_t operand_pred(rv_inst inst)
1987 return (inst << 36) >> 60;
1990 static uint32_t operand_succ(rv_inst inst)
1992 return (inst << 40) >> 60;
1995 static uint32_t operand_rm(rv_inst inst)
1997 return (inst << 49) >> 61;
2000 static uint32_t operand_shamt5(rv_inst inst)
2002 return (inst << 39) >> 59;
2005 static uint32_t operand_shamt6(rv_inst inst)
2007 return (inst << 38) >> 58;
2010 static uint32_t operand_shamt7(rv_inst inst)
2012 return (inst << 37) >> 57;
2015 static uint32_t operand_crdq(rv_inst inst)
2017 return (inst << 59) >> 61;
2020 static uint32_t operand_crs1q(rv_inst inst)
2022 return (inst << 54) >> 61;
2025 static uint32_t operand_crs1rdq(rv_inst inst)
2027 return (inst << 54) >> 61;
2030 static uint32_t operand_crs2q(rv_inst inst)
2032 return (inst << 59) >> 61;
2035 static uint32_t operand_crd(rv_inst inst)
2037 return (inst << 52) >> 59;
2040 static uint32_t operand_crs1(rv_inst inst)
2042 return (inst << 52) >> 59;
2045 static uint32_t operand_crs1rd(rv_inst inst)
2047 return (inst << 52) >> 59;
2050 static uint32_t operand_crs2(rv_inst inst)
2052 return (inst << 57) >> 59;
2055 static uint32_t operand_cimmsh5(rv_inst inst)
2057 return (inst << 57) >> 59;
2060 static uint32_t operand_csr12(rv_inst inst)
2062 return (inst << 32) >> 52;
2065 static int32_t operand_imm12(rv_inst inst)
2067 return ((int64_t)inst << 32) >> 52;
2070 static int32_t operand_imm20(rv_inst inst)
2072 return (((int64_t)inst << 32) >> 44) << 12;
2075 static int32_t operand_jimm20(rv_inst inst)
2077 return (((int64_t)inst << 32) >> 63) << 20 |
2078 ((inst << 33) >> 54) << 1 |
2079 ((inst << 43) >> 63) << 11 |
2080 ((inst << 44) >> 56) << 12;
2083 static int32_t operand_simm12(rv_inst inst)
2085 return (((int64_t)inst << 32) >> 57) << 5 |
2086 (inst << 52) >> 59;
2089 static int32_t operand_sbimm12(rv_inst inst)
2091 return (((int64_t)inst << 32) >> 63) << 12 |
2092 ((inst << 33) >> 58) << 5 |
2093 ((inst << 52) >> 60) << 1 |
2094 ((inst << 56) >> 63) << 11;
2097 static uint32_t operand_cimmsh6(rv_inst inst)
2099 return ((inst << 51) >> 63) << 5 |
2100 (inst << 57) >> 59;
2103 static int32_t operand_cimmi(rv_inst inst)
2105 return (((int64_t)inst << 51) >> 63) << 5 |
2106 (inst << 57) >> 59;
2109 static int32_t operand_cimmui(rv_inst inst)
2111 return (((int64_t)inst << 51) >> 63) << 17 |
2112 ((inst << 57) >> 59) << 12;
2115 static uint32_t operand_cimmlwsp(rv_inst inst)
2117 return ((inst << 51) >> 63) << 5 |
2118 ((inst << 57) >> 61) << 2 |
2119 ((inst << 60) >> 62) << 6;
2122 static uint32_t operand_cimmldsp(rv_inst inst)
2124 return ((inst << 51) >> 63) << 5 |
2125 ((inst << 57) >> 62) << 3 |
2126 ((inst << 59) >> 61) << 6;
2129 static uint32_t operand_cimmlqsp(rv_inst inst)
2131 return ((inst << 51) >> 63) << 5 |
2132 ((inst << 57) >> 63) << 4 |
2133 ((inst << 58) >> 60) << 6;
2136 static int32_t operand_cimm16sp(rv_inst inst)
2138 return (((int64_t)inst << 51) >> 63) << 9 |
2139 ((inst << 57) >> 63) << 4 |
2140 ((inst << 58) >> 63) << 6 |
2141 ((inst << 59) >> 62) << 7 |
2142 ((inst << 61) >> 63) << 5;
2145 static int32_t operand_cimmj(rv_inst inst)
2147 return (((int64_t)inst << 51) >> 63) << 11 |
2148 ((inst << 52) >> 63) << 4 |
2149 ((inst << 53) >> 62) << 8 |
2150 ((inst << 55) >> 63) << 10 |
2151 ((inst << 56) >> 63) << 6 |
2152 ((inst << 57) >> 63) << 7 |
2153 ((inst << 58) >> 61) << 1 |
2154 ((inst << 61) >> 63) << 5;
2157 static int32_t operand_cimmb(rv_inst inst)
2159 return (((int64_t)inst << 51) >> 63) << 8 |
2160 ((inst << 52) >> 62) << 3 |
2161 ((inst << 57) >> 62) << 6 |
2162 ((inst << 59) >> 62) << 1 |
2163 ((inst << 61) >> 63) << 5;
2166 static uint32_t operand_cimmswsp(rv_inst inst)
2168 return ((inst << 51) >> 60) << 2 |
2169 ((inst << 55) >> 62) << 6;
2172 static uint32_t operand_cimmsdsp(rv_inst inst)
2174 return ((inst << 51) >> 61) << 3 |
2175 ((inst << 54) >> 61) << 6;
2178 static uint32_t operand_cimmsqsp(rv_inst inst)
2180 return ((inst << 51) >> 62) << 4 |
2181 ((inst << 53) >> 60) << 6;
2184 static uint32_t operand_cimm4spn(rv_inst inst)
2186 return ((inst << 51) >> 62) << 4 |
2187 ((inst << 53) >> 60) << 6 |
2188 ((inst << 57) >> 63) << 2 |
2189 ((inst << 58) >> 63) << 3;
2192 static uint32_t operand_cimmw(rv_inst inst)
2194 return ((inst << 51) >> 61) << 3 |
2195 ((inst << 57) >> 63) << 2 |
2196 ((inst << 58) >> 63) << 6;
2199 static uint32_t operand_cimmd(rv_inst inst)
2201 return ((inst << 51) >> 61) << 3 |
2202 ((inst << 57) >> 62) << 6;
2205 static uint32_t operand_cimmq(rv_inst inst)
2207 return ((inst << 51) >> 62) << 4 |
2208 ((inst << 53) >> 63) << 8 |
2209 ((inst << 57) >> 62) << 6;
2212 /* decode operands */
2214 static void decode_inst_operands(rv_decode *dec)
2216 rv_inst inst = dec->inst;
2217 dec->codec = opcode_data[dec->op].codec;
2218 switch (dec->codec) {
2219 case rv_codec_none:
2220 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2221 dec->imm = 0;
2222 break;
2223 case rv_codec_u:
2224 dec->rd = operand_rd(inst);
2225 dec->rs1 = dec->rs2 = rv_ireg_zero;
2226 dec->imm = operand_imm20(inst);
2227 break;
2228 case rv_codec_uj:
2229 dec->rd = operand_rd(inst);
2230 dec->rs1 = dec->rs2 = rv_ireg_zero;
2231 dec->imm = operand_jimm20(inst);
2232 break;
2233 case rv_codec_i:
2234 dec->rd = operand_rd(inst);
2235 dec->rs1 = operand_rs1(inst);
2236 dec->rs2 = rv_ireg_zero;
2237 dec->imm = operand_imm12(inst);
2238 break;
2239 case rv_codec_i_sh5:
2240 dec->rd = operand_rd(inst);
2241 dec->rs1 = operand_rs1(inst);
2242 dec->rs2 = rv_ireg_zero;
2243 dec->imm = operand_shamt5(inst);
2244 break;
2245 case rv_codec_i_sh6:
2246 dec->rd = operand_rd(inst);
2247 dec->rs1 = operand_rs1(inst);
2248 dec->rs2 = rv_ireg_zero;
2249 dec->imm = operand_shamt6(inst);
2250 break;
2251 case rv_codec_i_sh7:
2252 dec->rd = operand_rd(inst);
2253 dec->rs1 = operand_rs1(inst);
2254 dec->rs2 = rv_ireg_zero;
2255 dec->imm = operand_shamt7(inst);
2256 break;
2257 case rv_codec_i_csr:
2258 dec->rd = operand_rd(inst);
2259 dec->rs1 = operand_rs1(inst);
2260 dec->rs2 = rv_ireg_zero;
2261 dec->imm = operand_csr12(inst);
2262 break;
2263 case rv_codec_s:
2264 dec->rd = rv_ireg_zero;
2265 dec->rs1 = operand_rs1(inst);
2266 dec->rs2 = operand_rs2(inst);
2267 dec->imm = operand_simm12(inst);
2268 break;
2269 case rv_codec_sb:
2270 dec->rd = rv_ireg_zero;
2271 dec->rs1 = operand_rs1(inst);
2272 dec->rs2 = operand_rs2(inst);
2273 dec->imm = operand_sbimm12(inst);
2274 break;
2275 case rv_codec_r:
2276 dec->rd = operand_rd(inst);
2277 dec->rs1 = operand_rs1(inst);
2278 dec->rs2 = operand_rs2(inst);
2279 dec->imm = 0;
2280 break;
2281 case rv_codec_r_m:
2282 dec->rd = operand_rd(inst);
2283 dec->rs1 = operand_rs1(inst);
2284 dec->rs2 = operand_rs2(inst);
2285 dec->imm = 0;
2286 dec->rm = operand_rm(inst);
2287 break;
2288 case rv_codec_r4_m:
2289 dec->rd = operand_rd(inst);
2290 dec->rs1 = operand_rs1(inst);
2291 dec->rs2 = operand_rs2(inst);
2292 dec->rs3 = operand_rs3(inst);
2293 dec->imm = 0;
2294 dec->rm = operand_rm(inst);
2295 break;
2296 case rv_codec_r_a:
2297 dec->rd = operand_rd(inst);
2298 dec->rs1 = operand_rs1(inst);
2299 dec->rs2 = operand_rs2(inst);
2300 dec->imm = 0;
2301 dec->aq = operand_aq(inst);
2302 dec->rl = operand_rl(inst);
2303 break;
2304 case rv_codec_r_l:
2305 dec->rd = operand_rd(inst);
2306 dec->rs1 = operand_rs1(inst);
2307 dec->rs2 = rv_ireg_zero;
2308 dec->imm = 0;
2309 dec->aq = operand_aq(inst);
2310 dec->rl = operand_rl(inst);
2311 break;
2312 case rv_codec_r_f:
2313 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2314 dec->pred = operand_pred(inst);
2315 dec->succ = operand_succ(inst);
2316 dec->imm = 0;
2317 break;
2318 case rv_codec_cb:
2319 dec->rd = rv_ireg_zero;
2320 dec->rs1 = operand_crs1q(inst) + 8;
2321 dec->rs2 = rv_ireg_zero;
2322 dec->imm = operand_cimmb(inst);
2323 break;
2324 case rv_codec_cb_imm:
2325 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2326 dec->rs2 = rv_ireg_zero;
2327 dec->imm = operand_cimmi(inst);
2328 break;
2329 case rv_codec_cb_sh5:
2330 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2331 dec->rs2 = rv_ireg_zero;
2332 dec->imm = operand_cimmsh5(inst);
2333 break;
2334 case rv_codec_cb_sh6:
2335 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2336 dec->rs2 = rv_ireg_zero;
2337 dec->imm = operand_cimmsh6(inst);
2338 break;
2339 case rv_codec_ci:
2340 dec->rd = dec->rs1 = operand_crs1rd(inst);
2341 dec->rs2 = rv_ireg_zero;
2342 dec->imm = operand_cimmi(inst);
2343 break;
2344 case rv_codec_ci_sh5:
2345 dec->rd = dec->rs1 = operand_crs1rd(inst);
2346 dec->rs2 = rv_ireg_zero;
2347 dec->imm = operand_cimmsh5(inst);
2348 break;
2349 case rv_codec_ci_sh6:
2350 dec->rd = dec->rs1 = operand_crs1rd(inst);
2351 dec->rs2 = rv_ireg_zero;
2352 dec->imm = operand_cimmsh6(inst);
2353 break;
2354 case rv_codec_ci_16sp:
2355 dec->rd = rv_ireg_sp;
2356 dec->rs1 = rv_ireg_sp;
2357 dec->rs2 = rv_ireg_zero;
2358 dec->imm = operand_cimm16sp(inst);
2359 break;
2360 case rv_codec_ci_lwsp:
2361 dec->rd = operand_crd(inst);
2362 dec->rs1 = rv_ireg_sp;
2363 dec->rs2 = rv_ireg_zero;
2364 dec->imm = operand_cimmlwsp(inst);
2365 break;
2366 case rv_codec_ci_ldsp:
2367 dec->rd = operand_crd(inst);
2368 dec->rs1 = rv_ireg_sp;
2369 dec->rs2 = rv_ireg_zero;
2370 dec->imm = operand_cimmldsp(inst);
2371 break;
2372 case rv_codec_ci_lqsp:
2373 dec->rd = operand_crd(inst);
2374 dec->rs1 = rv_ireg_sp;
2375 dec->rs2 = rv_ireg_zero;
2376 dec->imm = operand_cimmlqsp(inst);
2377 break;
2378 case rv_codec_ci_li:
2379 dec->rd = operand_crd(inst);
2380 dec->rs1 = rv_ireg_zero;
2381 dec->rs2 = rv_ireg_zero;
2382 dec->imm = operand_cimmi(inst);
2383 break;
2384 case rv_codec_ci_lui:
2385 dec->rd = operand_crd(inst);
2386 dec->rs1 = rv_ireg_zero;
2387 dec->rs2 = rv_ireg_zero;
2388 dec->imm = operand_cimmui(inst);
2389 break;
2390 case rv_codec_ci_none:
2391 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2392 dec->imm = 0;
2393 break;
2394 case rv_codec_ciw_4spn:
2395 dec->rd = operand_crdq(inst) + 8;
2396 dec->rs1 = rv_ireg_sp;
2397 dec->rs2 = rv_ireg_zero;
2398 dec->imm = operand_cimm4spn(inst);
2399 break;
2400 case rv_codec_cj:
2401 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2402 dec->imm = operand_cimmj(inst);
2403 break;
2404 case rv_codec_cj_jal:
2405 dec->rd = rv_ireg_ra;
2406 dec->rs1 = dec->rs2 = rv_ireg_zero;
2407 dec->imm = operand_cimmj(inst);
2408 break;
2409 case rv_codec_cl_lw:
2410 dec->rd = operand_crdq(inst) + 8;
2411 dec->rs1 = operand_crs1q(inst) + 8;
2412 dec->rs2 = rv_ireg_zero;
2413 dec->imm = operand_cimmw(inst);
2414 break;
2415 case rv_codec_cl_ld:
2416 dec->rd = operand_crdq(inst) + 8;
2417 dec->rs1 = operand_crs1q(inst) + 8;
2418 dec->rs2 = rv_ireg_zero;
2419 dec->imm = operand_cimmd(inst);
2420 break;
2421 case rv_codec_cl_lq:
2422 dec->rd = operand_crdq(inst) + 8;
2423 dec->rs1 = operand_crs1q(inst) + 8;
2424 dec->rs2 = rv_ireg_zero;
2425 dec->imm = operand_cimmq(inst);
2426 break;
2427 case rv_codec_cr:
2428 dec->rd = dec->rs1 = operand_crs1rd(inst);
2429 dec->rs2 = operand_crs2(inst);
2430 dec->imm = 0;
2431 break;
2432 case rv_codec_cr_mv:
2433 dec->rd = operand_crd(inst);
2434 dec->rs1 = operand_crs2(inst);
2435 dec->rs2 = rv_ireg_zero;
2436 dec->imm = 0;
2437 break;
2438 case rv_codec_cr_jalr:
2439 dec->rd = rv_ireg_ra;
2440 dec->rs1 = operand_crs1(inst);
2441 dec->rs2 = rv_ireg_zero;
2442 dec->imm = 0;
2443 break;
2444 case rv_codec_cr_jr:
2445 dec->rd = rv_ireg_zero;
2446 dec->rs1 = operand_crs1(inst);
2447 dec->rs2 = rv_ireg_zero;
2448 dec->imm = 0;
2449 break;
2450 case rv_codec_cs:
2451 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2452 dec->rs2 = operand_crs2q(inst) + 8;
2453 dec->imm = 0;
2454 break;
2455 case rv_codec_cs_sw:
2456 dec->rd = rv_ireg_zero;
2457 dec->rs1 = operand_crs1q(inst) + 8;
2458 dec->rs2 = operand_crs2q(inst) + 8;
2459 dec->imm = operand_cimmw(inst);
2460 break;
2461 case rv_codec_cs_sd:
2462 dec->rd = rv_ireg_zero;
2463 dec->rs1 = operand_crs1q(inst) + 8;
2464 dec->rs2 = operand_crs2q(inst) + 8;
2465 dec->imm = operand_cimmd(inst);
2466 break;
2467 case rv_codec_cs_sq:
2468 dec->rd = rv_ireg_zero;
2469 dec->rs1 = operand_crs1q(inst) + 8;
2470 dec->rs2 = operand_crs2q(inst) + 8;
2471 dec->imm = operand_cimmq(inst);
2472 break;
2473 case rv_codec_css_swsp:
2474 dec->rd = rv_ireg_zero;
2475 dec->rs1 = rv_ireg_sp;
2476 dec->rs2 = operand_crs2(inst);
2477 dec->imm = operand_cimmswsp(inst);
2478 break;
2479 case rv_codec_css_sdsp:
2480 dec->rd = rv_ireg_zero;
2481 dec->rs1 = rv_ireg_sp;
2482 dec->rs2 = operand_crs2(inst);
2483 dec->imm = operand_cimmsdsp(inst);
2484 break;
2485 case rv_codec_css_sqsp:
2486 dec->rd = rv_ireg_zero;
2487 dec->rs1 = rv_ireg_sp;
2488 dec->rs2 = operand_crs2(inst);
2489 dec->imm = operand_cimmsqsp(inst);
2490 break;
2494 /* check constraint */
2496 static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
2498 int32_t imm = dec->imm;
2499 uint8_t rd = dec->rd, rs1 = dec->rs1, rs2 = dec->rs2;
2500 while (*c != rvc_end) {
2501 switch (*c) {
2502 case rvc_rd_eq_ra:
2503 if (!(rd == 1)) {
2504 return false;
2506 break;
2507 case rvc_rd_eq_x0:
2508 if (!(rd == 0)) {
2509 return false;
2511 break;
2512 case rvc_rs1_eq_x0:
2513 if (!(rs1 == 0)) {
2514 return false;
2516 break;
2517 case rvc_rs2_eq_x0:
2518 if (!(rs2 == 0)) {
2519 return false;
2521 break;
2522 case rvc_rs2_eq_rs1:
2523 if (!(rs2 == rs1)) {
2524 return false;
2526 break;
2527 case rvc_rs1_eq_ra:
2528 if (!(rs1 == 1)) {
2529 return false;
2531 break;
2532 case rvc_imm_eq_zero:
2533 if (!(imm == 0)) {
2534 return false;
2536 break;
2537 case rvc_imm_eq_n1:
2538 if (!(imm == -1)) {
2539 return false;
2541 break;
2542 case rvc_imm_eq_p1:
2543 if (!(imm == 1)) {
2544 return false;
2546 break;
2547 case rvc_csr_eq_0x001:
2548 if (!(imm == 0x001)) {
2549 return false;
2551 break;
2552 case rvc_csr_eq_0x002:
2553 if (!(imm == 0x002)) {
2554 return false;
2556 break;
2557 case rvc_csr_eq_0x003:
2558 if (!(imm == 0x003)) {
2559 return false;
2561 break;
2562 case rvc_csr_eq_0xc00:
2563 if (!(imm == 0xc00)) {
2564 return false;
2566 break;
2567 case rvc_csr_eq_0xc01:
2568 if (!(imm == 0xc01)) {
2569 return false;
2571 break;
2572 case rvc_csr_eq_0xc02:
2573 if (!(imm == 0xc02)) {
2574 return false;
2576 break;
2577 case rvc_csr_eq_0xc80:
2578 if (!(imm == 0xc80)) {
2579 return false;
2581 break;
2582 case rvc_csr_eq_0xc81:
2583 if (!(imm == 0xc81)) {
2584 return false;
2586 break;
2587 case rvc_csr_eq_0xc82:
2588 if (!(imm == 0xc82)) {
2589 return false;
2591 break;
2592 default: break;
2594 c++;
2596 return true;
2599 /* instruction length */
2601 static size_t inst_length(rv_inst inst)
2603 /* NOTE: supports maximum instruction size of 64-bits */
2605 /* instruction length coding
2607 * aa - 16 bit aa != 11
2608 * bbb11 - 32 bit bbb != 111
2609 * 011111 - 48 bit
2610 * 0111111 - 64 bit
2613 return (inst & 0b11) != 0b11 ? 2
2614 : (inst & 0b11100) != 0b11100 ? 4
2615 : (inst & 0b111111) == 0b011111 ? 6
2616 : (inst & 0b1111111) == 0b0111111 ? 8
2617 : 0;
2620 /* format instruction */
2622 static void append(char *s1, const char *s2, size_t n)
2624 size_t l1 = strlen(s1);
2625 if (n - l1 - 1 > 0) {
2626 strncat(s1, s2, n - l1);
2630 static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
2632 char tmp[64];
2633 const char *fmt;
2635 fmt = opcode_data[dec->op].format;
2636 while (*fmt) {
2637 switch (*fmt) {
2638 case 'O':
2639 append(buf, opcode_data[dec->op].name, buflen);
2640 break;
2641 case '(':
2642 append(buf, "(", buflen);
2643 break;
2644 case ',':
2645 append(buf, ",", buflen);
2646 break;
2647 case ')':
2648 append(buf, ")", buflen);
2649 break;
2650 case '0':
2651 append(buf, rv_ireg_name_sym[dec->rd], buflen);
2652 break;
2653 case '1':
2654 append(buf, rv_ireg_name_sym[dec->rs1], buflen);
2655 break;
2656 case '2':
2657 append(buf, rv_ireg_name_sym[dec->rs2], buflen);
2658 break;
2659 case '3':
2660 append(buf, rv_freg_name_sym[dec->rd], buflen);
2661 break;
2662 case '4':
2663 append(buf, rv_freg_name_sym[dec->rs1], buflen);
2664 break;
2665 case '5':
2666 append(buf, rv_freg_name_sym[dec->rs2], buflen);
2667 break;
2668 case '6':
2669 append(buf, rv_freg_name_sym[dec->rs3], buflen);
2670 break;
2671 case '7':
2672 snprintf(tmp, sizeof(tmp), "%d", dec->rs1);
2673 append(buf, tmp, buflen);
2674 break;
2675 case 'i':
2676 snprintf(tmp, sizeof(tmp), "%d", dec->imm);
2677 append(buf, tmp, buflen);
2678 break;
2679 case 'o':
2680 snprintf(tmp, sizeof(tmp), "%d", dec->imm);
2681 append(buf, tmp, buflen);
2682 while (strlen(buf) < tab * 2) {
2683 append(buf, " ", buflen);
2685 snprintf(tmp, sizeof(tmp), "# 0x%" PRIx64,
2686 dec->pc + dec->imm);
2687 append(buf, tmp, buflen);
2688 break;
2689 case 'c': {
2690 const char *name = csr_name(dec->imm & 0xfff);
2691 if (name) {
2692 append(buf, name, buflen);
2693 } else {
2694 snprintf(tmp, sizeof(tmp), "0x%03x", dec->imm & 0xfff);
2695 append(buf, tmp, buflen);
2697 break;
2699 case 'r':
2700 switch (dec->rm) {
2701 case rv_rm_rne:
2702 append(buf, "rne", buflen);
2703 break;
2704 case rv_rm_rtz:
2705 append(buf, "rtz", buflen);
2706 break;
2707 case rv_rm_rdn:
2708 append(buf, "rdn", buflen);
2709 break;
2710 case rv_rm_rup:
2711 append(buf, "rup", buflen);
2712 break;
2713 case rv_rm_rmm:
2714 append(buf, "rmm", buflen);
2715 break;
2716 case rv_rm_dyn:
2717 append(buf, "dyn", buflen);
2718 break;
2719 default:
2720 append(buf, "inv", buflen);
2721 break;
2723 break;
2724 case 'p':
2725 if (dec->pred & rv_fence_i) {
2726 append(buf, "i", buflen);
2728 if (dec->pred & rv_fence_o) {
2729 append(buf, "o", buflen);
2731 if (dec->pred & rv_fence_r) {
2732 append(buf, "r", buflen);
2734 if (dec->pred & rv_fence_w) {
2735 append(buf, "w", buflen);
2737 break;
2738 case 's':
2739 if (dec->succ & rv_fence_i) {
2740 append(buf, "i", buflen);
2742 if (dec->succ & rv_fence_o) {
2743 append(buf, "o", buflen);
2745 if (dec->succ & rv_fence_r) {
2746 append(buf, "r", buflen);
2748 if (dec->succ & rv_fence_w) {
2749 append(buf, "w", buflen);
2751 break;
2752 case '\t':
2753 while (strlen(buf) < tab) {
2754 append(buf, " ", buflen);
2756 break;
2757 case 'A':
2758 if (dec->aq) {
2759 append(buf, ".aq", buflen);
2761 break;
2762 case 'R':
2763 if (dec->rl) {
2764 append(buf, ".rl", buflen);
2766 break;
2767 default:
2768 break;
2770 fmt++;
2774 /* lift instruction to pseudo-instruction */
2776 static void decode_inst_lift_pseudo(rv_decode *dec)
2778 const rv_comp_data *comp_data = opcode_data[dec->op].pseudo;
2779 if (!comp_data) {
2780 return;
2782 while (comp_data->constraints) {
2783 if (check_constraints(dec, comp_data->constraints)) {
2784 dec->op = comp_data->op;
2785 dec->codec = opcode_data[dec->op].codec;
2786 return;
2788 comp_data++;
2792 /* decompress instruction */
2794 static void decode_inst_decompress_rv32(rv_decode *dec)
2796 int decomp_op = opcode_data[dec->op].decomp_rv32;
2797 if (decomp_op != rv_op_illegal) {
2798 dec->op = decomp_op;
2799 dec->codec = opcode_data[decomp_op].codec;
2803 static void decode_inst_decompress_rv64(rv_decode *dec)
2805 int decomp_op = opcode_data[dec->op].decomp_rv64;
2806 if (decomp_op != rv_op_illegal) {
2807 dec->op = decomp_op;
2808 dec->codec = opcode_data[decomp_op].codec;
2812 static void decode_inst_decompress_rv128(rv_decode *dec)
2814 int decomp_op = opcode_data[dec->op].decomp_rv128;
2815 if (decomp_op != rv_op_illegal) {
2816 dec->op = decomp_op;
2817 dec->codec = opcode_data[decomp_op].codec;
2821 static void decode_inst_decompress(rv_decode *dec, rv_isa isa)
2823 switch (isa) {
2824 case rv32:
2825 decode_inst_decompress_rv32(dec);
2826 break;
2827 case rv64:
2828 decode_inst_decompress_rv64(dec);
2829 break;
2830 case rv128:
2831 decode_inst_decompress_rv128(dec);
2832 break;
2836 /* disassemble instruction */
2838 static void
2839 disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst)
2841 rv_decode dec = { 0 };
2842 dec.pc = pc;
2843 dec.inst = inst;
2844 decode_inst_opcode(&dec, isa);
2845 decode_inst_operands(&dec);
2846 decode_inst_decompress(&dec, isa);
2847 decode_inst_lift_pseudo(&dec);
2848 format_inst(buf, buflen, 16, &dec);
2851 #define INST_FMT_2 "%04" PRIx64 " "
2852 #define INST_FMT_4 "%08" PRIx64 " "
2853 #define INST_FMT_6 "%012" PRIx64 " "
2854 #define INST_FMT_8 "%016" PRIx64 " "
2856 static int
2857 print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa)
2859 char buf[128] = { 0 };
2860 bfd_byte packet[2];
2861 rv_inst inst = 0;
2862 size_t len = 2;
2863 bfd_vma n;
2864 int status;
2866 /* Instructions are made of 2-byte packets in little-endian order */
2867 for (n = 0; n < len; n += 2) {
2868 status = (*info->read_memory_func)(memaddr + n, packet, 2, info);
2869 if (status != 0) {
2870 /* Don't fail just because we fell off the end. */
2871 if (n > 0) {
2872 break;
2874 (*info->memory_error_func)(status, memaddr, info);
2875 return status;
2877 inst |= ((rv_inst) bfd_getl16(packet)) << (8 * n);
2878 if (n == 0) {
2879 len = inst_length(inst);
2883 switch (len) {
2884 case 2:
2885 (*info->fprintf_func)(info->stream, INST_FMT_2, inst);
2886 break;
2887 case 4:
2888 (*info->fprintf_func)(info->stream, INST_FMT_4, inst);
2889 break;
2890 case 6:
2891 (*info->fprintf_func)(info->stream, INST_FMT_6, inst);
2892 break;
2893 default:
2894 (*info->fprintf_func)(info->stream, INST_FMT_8, inst);
2895 break;
2898 disasm_inst(buf, sizeof(buf), isa, memaddr, inst);
2899 (*info->fprintf_func)(info->stream, "%s", buf);
2901 return len;
2904 int print_insn_riscv32(bfd_vma memaddr, struct disassemble_info *info)
2906 return print_insn_riscv(memaddr, info, rv32);
2909 int print_insn_riscv64(bfd_vma memaddr, struct disassemble_info *info)
2911 return print_insn_riscv(memaddr, info, rv64);