qdev: Fix two typos
[qemu/armbru.git] / disas / riscv.c
blob278d9be9247e411acc42a46dd8930644d4b542ab
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 enum {
508 rvcd_imm_nz = 0x1
511 typedef struct {
512 const char * const name;
513 const rv_codec codec;
514 const char * const format;
515 const rv_comp_data *pseudo;
516 const short decomp_rv32;
517 const short decomp_rv64;
518 const short decomp_rv128;
519 const short decomp_data;
520 } rv_opcode_data;
522 /* register names */
524 static const char rv_ireg_name_sym[32][5] = {
525 "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
526 "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
527 "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
528 "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6",
531 static const char rv_freg_name_sym[32][5] = {
532 "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
533 "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
534 "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
535 "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
538 /* instruction formats */
540 #define rv_fmt_none "O\t"
541 #define rv_fmt_rs1 "O\t1"
542 #define rv_fmt_offset "O\to"
543 #define rv_fmt_pred_succ "O\tp,s"
544 #define rv_fmt_rs1_rs2 "O\t1,2"
545 #define rv_fmt_rd_imm "O\t0,i"
546 #define rv_fmt_rd_offset "O\t0,o"
547 #define rv_fmt_rd_rs1_rs2 "O\t0,1,2"
548 #define rv_fmt_frd_rs1 "O\t3,1"
549 #define rv_fmt_rd_frs1 "O\t0,4"
550 #define rv_fmt_rd_frs1_frs2 "O\t0,4,5"
551 #define rv_fmt_frd_frs1_frs2 "O\t3,4,5"
552 #define rv_fmt_rm_frd_frs1 "O\tr,3,4"
553 #define rv_fmt_rm_frd_rs1 "O\tr,3,1"
554 #define rv_fmt_rm_rd_frs1 "O\tr,0,4"
555 #define rv_fmt_rm_frd_frs1_frs2 "O\tr,3,4,5"
556 #define rv_fmt_rm_frd_frs1_frs2_frs3 "O\tr,3,4,5,6"
557 #define rv_fmt_rd_rs1_imm "O\t0,1,i"
558 #define rv_fmt_rd_rs1_offset "O\t0,1,i"
559 #define rv_fmt_rd_offset_rs1 "O\t0,i(1)"
560 #define rv_fmt_frd_offset_rs1 "O\t3,i(1)"
561 #define rv_fmt_rd_csr_rs1 "O\t0,c,1"
562 #define rv_fmt_rd_csr_zimm "O\t0,c,7"
563 #define rv_fmt_rs2_offset_rs1 "O\t2,i(1)"
564 #define rv_fmt_frs2_offset_rs1 "O\t5,i(1)"
565 #define rv_fmt_rs1_rs2_offset "O\t1,2,o"
566 #define rv_fmt_rs2_rs1_offset "O\t2,1,o"
567 #define rv_fmt_aqrl_rd_rs2_rs1 "OAR\t0,2,(1)"
568 #define rv_fmt_aqrl_rd_rs1 "OAR\t0,(1)"
569 #define rv_fmt_rd "O\t0"
570 #define rv_fmt_rd_zimm "O\t0,7"
571 #define rv_fmt_rd_rs1 "O\t0,1"
572 #define rv_fmt_rd_rs2 "O\t0,2"
573 #define rv_fmt_rs1_offset "O\t1,o"
574 #define rv_fmt_rs2_offset "O\t2,o"
576 /* pseudo-instruction constraints */
578 static const rvc_constraint rvcc_jal[] = { rvc_rd_eq_ra, rvc_end };
579 static const rvc_constraint rvcc_jalr[] = { rvc_rd_eq_ra, rvc_imm_eq_zero, rvc_end };
580 static const rvc_constraint rvcc_nop[] = { rvc_rd_eq_x0, rvc_rs1_eq_x0, rvc_imm_eq_zero, rvc_end };
581 static const rvc_constraint rvcc_mv[] = { rvc_imm_eq_zero, rvc_end };
582 static const rvc_constraint rvcc_not[] = { rvc_imm_eq_n1, rvc_end };
583 static const rvc_constraint rvcc_neg[] = { rvc_rs1_eq_x0, rvc_end };
584 static const rvc_constraint rvcc_negw[] = { rvc_rs1_eq_x0, rvc_end };
585 static const rvc_constraint rvcc_sext_w[] = { rvc_imm_eq_zero, rvc_end };
586 static const rvc_constraint rvcc_seqz[] = { rvc_imm_eq_p1, rvc_end };
587 static const rvc_constraint rvcc_snez[] = { rvc_rs1_eq_x0, rvc_end };
588 static const rvc_constraint rvcc_sltz[] = { rvc_rs2_eq_x0, rvc_end };
589 static const rvc_constraint rvcc_sgtz[] = { rvc_rs1_eq_x0, rvc_end };
590 static const rvc_constraint rvcc_fmv_s[] = { rvc_rs2_eq_rs1, rvc_end };
591 static const rvc_constraint rvcc_fabs_s[] = { rvc_rs2_eq_rs1, rvc_end };
592 static const rvc_constraint rvcc_fneg_s[] = { rvc_rs2_eq_rs1, rvc_end };
593 static const rvc_constraint rvcc_fmv_d[] = { rvc_rs2_eq_rs1, rvc_end };
594 static const rvc_constraint rvcc_fabs_d[] = { rvc_rs2_eq_rs1, rvc_end };
595 static const rvc_constraint rvcc_fneg_d[] = { rvc_rs2_eq_rs1, rvc_end };
596 static const rvc_constraint rvcc_fmv_q[] = { rvc_rs2_eq_rs1, rvc_end };
597 static const rvc_constraint rvcc_fabs_q[] = { rvc_rs2_eq_rs1, rvc_end };
598 static const rvc_constraint rvcc_fneg_q[] = { rvc_rs2_eq_rs1, rvc_end };
599 static const rvc_constraint rvcc_beqz[] = { rvc_rs2_eq_x0, rvc_end };
600 static const rvc_constraint rvcc_bnez[] = { rvc_rs2_eq_x0, rvc_end };
601 static const rvc_constraint rvcc_blez[] = { rvc_rs1_eq_x0, rvc_end };
602 static const rvc_constraint rvcc_bgez[] = { rvc_rs2_eq_x0, rvc_end };
603 static const rvc_constraint rvcc_bltz[] = { rvc_rs2_eq_x0, rvc_end };
604 static const rvc_constraint rvcc_bgtz[] = { rvc_rs1_eq_x0, rvc_end };
605 static const rvc_constraint rvcc_ble[] = { rvc_end };
606 static const rvc_constraint rvcc_bleu[] = { rvc_end };
607 static const rvc_constraint rvcc_bgt[] = { rvc_end };
608 static const rvc_constraint rvcc_bgtu[] = { rvc_end };
609 static const rvc_constraint rvcc_j[] = { rvc_rd_eq_x0, rvc_end };
610 static const rvc_constraint rvcc_ret[] = { rvc_rd_eq_x0, rvc_rs1_eq_ra, rvc_end };
611 static const rvc_constraint rvcc_jr[] = { rvc_rd_eq_x0, rvc_imm_eq_zero, rvc_end };
612 static const rvc_constraint rvcc_rdcycle[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc00, rvc_end };
613 static const rvc_constraint rvcc_rdtime[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc01, rvc_end };
614 static const rvc_constraint rvcc_rdinstret[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc02, rvc_end };
615 static const rvc_constraint rvcc_rdcycleh[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc80, rvc_end };
616 static const rvc_constraint rvcc_rdtimeh[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc81, rvc_end };
617 static const rvc_constraint rvcc_rdinstreth[] = { rvc_rs1_eq_x0,
618 rvc_csr_eq_0xc82, rvc_end };
619 static const rvc_constraint rvcc_frcsr[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x003, rvc_end };
620 static const rvc_constraint rvcc_frrm[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x002, rvc_end };
621 static const rvc_constraint rvcc_frflags[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x001, rvc_end };
622 static const rvc_constraint rvcc_fscsr[] = { rvc_csr_eq_0x003, rvc_end };
623 static const rvc_constraint rvcc_fsrm[] = { rvc_csr_eq_0x002, rvc_end };
624 static const rvc_constraint rvcc_fsflags[] = { rvc_csr_eq_0x001, rvc_end };
625 static const rvc_constraint rvcc_fsrmi[] = { rvc_csr_eq_0x002, rvc_end };
626 static const rvc_constraint rvcc_fsflagsi[] = { rvc_csr_eq_0x001, rvc_end };
628 /* pseudo-instruction metadata */
630 static const rv_comp_data rvcp_jal[] = {
631 { rv_op_j, rvcc_j },
632 { rv_op_jal, rvcc_jal },
633 { rv_op_illegal, NULL }
636 static const rv_comp_data rvcp_jalr[] = {
637 { rv_op_ret, rvcc_ret },
638 { rv_op_jr, rvcc_jr },
639 { rv_op_jalr, rvcc_jalr },
640 { rv_op_illegal, NULL }
643 static const rv_comp_data rvcp_beq[] = {
644 { rv_op_beqz, rvcc_beqz },
645 { rv_op_illegal, NULL }
648 static const rv_comp_data rvcp_bne[] = {
649 { rv_op_bnez, rvcc_bnez },
650 { rv_op_illegal, NULL }
653 static const rv_comp_data rvcp_blt[] = {
654 { rv_op_bltz, rvcc_bltz },
655 { rv_op_bgtz, rvcc_bgtz },
656 { rv_op_bgt, rvcc_bgt },
657 { rv_op_illegal, NULL }
660 static const rv_comp_data rvcp_bge[] = {
661 { rv_op_blez, rvcc_blez },
662 { rv_op_bgez, rvcc_bgez },
663 { rv_op_ble, rvcc_ble },
664 { rv_op_illegal, NULL }
667 static const rv_comp_data rvcp_bltu[] = {
668 { rv_op_bgtu, rvcc_bgtu },
669 { rv_op_illegal, NULL }
672 static const rv_comp_data rvcp_bgeu[] = {
673 { rv_op_bleu, rvcc_bleu },
674 { rv_op_illegal, NULL }
677 static const rv_comp_data rvcp_addi[] = {
678 { rv_op_nop, rvcc_nop },
679 { rv_op_mv, rvcc_mv },
680 { rv_op_illegal, NULL }
683 static const rv_comp_data rvcp_sltiu[] = {
684 { rv_op_seqz, rvcc_seqz },
685 { rv_op_illegal, NULL }
688 static const rv_comp_data rvcp_xori[] = {
689 { rv_op_not, rvcc_not },
690 { rv_op_illegal, NULL }
693 static const rv_comp_data rvcp_sub[] = {
694 { rv_op_neg, rvcc_neg },
695 { rv_op_illegal, NULL }
698 static const rv_comp_data rvcp_slt[] = {
699 { rv_op_sltz, rvcc_sltz },
700 { rv_op_sgtz, rvcc_sgtz },
701 { rv_op_illegal, NULL }
704 static const rv_comp_data rvcp_sltu[] = {
705 { rv_op_snez, rvcc_snez },
706 { rv_op_illegal, NULL }
709 static const rv_comp_data rvcp_addiw[] = {
710 { rv_op_sext_w, rvcc_sext_w },
711 { rv_op_illegal, NULL }
714 static const rv_comp_data rvcp_subw[] = {
715 { rv_op_negw, rvcc_negw },
716 { rv_op_illegal, NULL }
719 static const rv_comp_data rvcp_csrrw[] = {
720 { rv_op_fscsr, rvcc_fscsr },
721 { rv_op_fsrm, rvcc_fsrm },
722 { rv_op_fsflags, rvcc_fsflags },
723 { rv_op_illegal, NULL }
726 static const rv_comp_data rvcp_csrrs[] = {
727 { rv_op_rdcycle, rvcc_rdcycle },
728 { rv_op_rdtime, rvcc_rdtime },
729 { rv_op_rdinstret, rvcc_rdinstret },
730 { rv_op_rdcycleh, rvcc_rdcycleh },
731 { rv_op_rdtimeh, rvcc_rdtimeh },
732 { rv_op_rdinstreth, rvcc_rdinstreth },
733 { rv_op_frcsr, rvcc_frcsr },
734 { rv_op_frrm, rvcc_frrm },
735 { rv_op_frflags, rvcc_frflags },
736 { rv_op_illegal, NULL }
739 static const rv_comp_data rvcp_csrrwi[] = {
740 { rv_op_fsrmi, rvcc_fsrmi },
741 { rv_op_fsflagsi, rvcc_fsflagsi },
742 { rv_op_illegal, NULL }
745 static const rv_comp_data rvcp_fsgnj_s[] = {
746 { rv_op_fmv_s, rvcc_fmv_s },
747 { rv_op_illegal, NULL }
750 static const rv_comp_data rvcp_fsgnjn_s[] = {
751 { rv_op_fneg_s, rvcc_fneg_s },
752 { rv_op_illegal, NULL }
755 static const rv_comp_data rvcp_fsgnjx_s[] = {
756 { rv_op_fabs_s, rvcc_fabs_s },
757 { rv_op_illegal, NULL }
760 static const rv_comp_data rvcp_fsgnj_d[] = {
761 { rv_op_fmv_d, rvcc_fmv_d },
762 { rv_op_illegal, NULL }
765 static const rv_comp_data rvcp_fsgnjn_d[] = {
766 { rv_op_fneg_d, rvcc_fneg_d },
767 { rv_op_illegal, NULL }
770 static const rv_comp_data rvcp_fsgnjx_d[] = {
771 { rv_op_fabs_d, rvcc_fabs_d },
772 { rv_op_illegal, NULL }
775 static const rv_comp_data rvcp_fsgnj_q[] = {
776 { rv_op_fmv_q, rvcc_fmv_q },
777 { rv_op_illegal, NULL }
780 static const rv_comp_data rvcp_fsgnjn_q[] = {
781 { rv_op_fneg_q, rvcc_fneg_q },
782 { rv_op_illegal, NULL }
785 static const rv_comp_data rvcp_fsgnjx_q[] = {
786 { rv_op_fabs_q, rvcc_fabs_q },
787 { rv_op_illegal, NULL }
790 /* instruction metadata */
792 const rv_opcode_data opcode_data[] = {
793 { "illegal", rv_codec_illegal, rv_fmt_none, NULL, 0, 0, 0 },
794 { "lui", rv_codec_u, rv_fmt_rd_imm, NULL, 0, 0, 0 },
795 { "auipc", rv_codec_u, rv_fmt_rd_offset, NULL, 0, 0, 0 },
796 { "jal", rv_codec_uj, rv_fmt_rd_offset, rvcp_jal, 0, 0, 0 },
797 { "jalr", rv_codec_i, rv_fmt_rd_rs1_offset, rvcp_jalr, 0, 0, 0 },
798 { "beq", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_beq, 0, 0, 0 },
799 { "bne", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bne, 0, 0, 0 },
800 { "blt", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_blt, 0, 0, 0 },
801 { "bge", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bge, 0, 0, 0 },
802 { "bltu", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bltu, 0, 0, 0 },
803 { "bgeu", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bgeu, 0, 0, 0 },
804 { "lb", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
805 { "lh", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
806 { "lw", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
807 { "lbu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
808 { "lhu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
809 { "sb", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
810 { "sh", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
811 { "sw", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
812 { "addi", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_addi, 0, 0, 0 },
813 { "slti", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
814 { "sltiu", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_sltiu, 0, 0, 0 },
815 { "xori", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_xori, 0, 0, 0 },
816 { "ori", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
817 { "andi", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
818 { "slli", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
819 { "srli", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
820 { "srai", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
821 { "add", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
822 { "sub", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_sub, 0, 0, 0 },
823 { "sll", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
824 { "slt", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_slt, 0, 0, 0 },
825 { "sltu", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_sltu, 0, 0, 0 },
826 { "xor", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
827 { "srl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
828 { "sra", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
829 { "or", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
830 { "and", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
831 { "fence", rv_codec_r_f, rv_fmt_pred_succ, NULL, 0, 0, 0 },
832 { "fence.i", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
833 { "lwu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
834 { "ld", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
835 { "sd", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
836 { "addiw", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_addiw, 0, 0, 0 },
837 { "slliw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
838 { "srliw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
839 { "sraiw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
840 { "addw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
841 { "subw", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_subw, 0, 0, 0 },
842 { "sllw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
843 { "srlw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
844 { "sraw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
845 { "ldu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
846 { "lq", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
847 { "sq", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
848 { "addid", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
849 { "sllid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
850 { "srlid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
851 { "sraid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
852 { "addd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
853 { "subd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
854 { "slld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
855 { "srld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
856 { "srad", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
857 { "mul", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
858 { "mulh", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
859 { "mulhsu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
860 { "mulhu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
861 { "div", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
862 { "divu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
863 { "rem", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
864 { "remu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
865 { "mulw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
866 { "divw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
867 { "divuw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
868 { "remw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
869 { "remuw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
870 { "muld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
871 { "divd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
872 { "divud", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
873 { "remd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
874 { "remud", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
875 { "lr.w", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 },
876 { "sc.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
877 { "amoswap.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
878 { "amoadd.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
879 { "amoxor.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
880 { "amoor.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
881 { "amoand.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
882 { "amomin.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
883 { "amomax.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
884 { "amominu.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
885 { "amomaxu.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
886 { "lr.d", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 },
887 { "sc.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
888 { "amoswap.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
889 { "amoadd.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
890 { "amoxor.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
891 { "amoor.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
892 { "amoand.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
893 { "amomin.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
894 { "amomax.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
895 { "amominu.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
896 { "amomaxu.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
897 { "lr.q", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 },
898 { "sc.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
899 { "amoswap.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
900 { "amoadd.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
901 { "amoxor.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
902 { "amoor.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
903 { "amoand.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
904 { "amomin.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
905 { "amomax.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
906 { "amominu.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
907 { "amomaxu.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
908 { "ecall", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
909 { "ebreak", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
910 { "uret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
911 { "sret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
912 { "hret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
913 { "mret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
914 { "dret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
915 { "sfence.vm", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
916 { "sfence.vma", rv_codec_r, rv_fmt_rs1_rs2, NULL, 0, 0, 0 },
917 { "wfi", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
918 { "csrrw", rv_codec_i_csr, rv_fmt_rd_csr_rs1, rvcp_csrrw, 0, 0, 0 },
919 { "csrrs", rv_codec_i_csr, rv_fmt_rd_csr_rs1, rvcp_csrrs, 0, 0, 0 },
920 { "csrrc", rv_codec_i_csr, rv_fmt_rd_csr_rs1, NULL, 0, 0, 0 },
921 { "csrrwi", rv_codec_i_csr, rv_fmt_rd_csr_zimm, rvcp_csrrwi, 0, 0, 0 },
922 { "csrrsi", rv_codec_i_csr, rv_fmt_rd_csr_zimm, NULL, 0, 0, 0 },
923 { "csrrci", rv_codec_i_csr, rv_fmt_rd_csr_zimm, NULL, 0, 0, 0 },
924 { "flw", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 },
925 { "fsw", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 },
926 { "fmadd.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
927 { "fmsub.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
928 { "fnmsub.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
929 { "fnmadd.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
930 { "fadd.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
931 { "fsub.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
932 { "fmul.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
933 { "fdiv.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
934 { "fsgnj.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_s, 0, 0, 0 },
935 { "fsgnjn.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_s, 0, 0, 0 },
936 { "fsgnjx.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_s, 0, 0, 0 },
937 { "fmin.s", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
938 { "fmax.s", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
939 { "fsqrt.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
940 { "fle.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
941 { "flt.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
942 { "feq.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
943 { "fcvt.w.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
944 { "fcvt.wu.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
945 { "fcvt.s.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
946 { "fcvt.s.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
947 { "fmv.x.s", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
948 { "fclass.s", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
949 { "fmv.s.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 },
950 { "fcvt.l.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
951 { "fcvt.lu.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
952 { "fcvt.s.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
953 { "fcvt.s.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
954 { "fld", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 },
955 { "fsd", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 },
956 { "fmadd.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
957 { "fmsub.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
958 { "fnmsub.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
959 { "fnmadd.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
960 { "fadd.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
961 { "fsub.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
962 { "fmul.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
963 { "fdiv.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
964 { "fsgnj.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_d, 0, 0, 0 },
965 { "fsgnjn.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_d, 0, 0, 0 },
966 { "fsgnjx.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_d, 0, 0, 0 },
967 { "fmin.d", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
968 { "fmax.d", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
969 { "fcvt.s.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
970 { "fcvt.d.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
971 { "fsqrt.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
972 { "fle.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
973 { "flt.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
974 { "feq.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
975 { "fcvt.w.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
976 { "fcvt.wu.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
977 { "fcvt.d.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
978 { "fcvt.d.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
979 { "fclass.d", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
980 { "fcvt.l.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
981 { "fcvt.lu.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
982 { "fmv.x.d", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
983 { "fcvt.d.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
984 { "fcvt.d.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
985 { "fmv.d.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 },
986 { "flq", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 },
987 { "fsq", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 },
988 { "fmadd.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
989 { "fmsub.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
990 { "fnmsub.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
991 { "fnmadd.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
992 { "fadd.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
993 { "fsub.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
994 { "fmul.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
995 { "fdiv.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
996 { "fsgnj.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_q, 0, 0, 0 },
997 { "fsgnjn.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_q, 0, 0, 0 },
998 { "fsgnjx.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_q, 0, 0, 0 },
999 { "fmin.q", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
1000 { "fmax.q", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
1001 { "fcvt.s.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1002 { "fcvt.q.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1003 { "fcvt.d.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1004 { "fcvt.q.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1005 { "fsqrt.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1006 { "fle.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
1007 { "flt.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
1008 { "feq.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
1009 { "fcvt.w.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1010 { "fcvt.wu.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1011 { "fcvt.q.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1012 { "fcvt.q.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1013 { "fclass.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
1014 { "fcvt.l.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1015 { "fcvt.lu.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1016 { "fcvt.q.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1017 { "fcvt.q.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1018 { "fmv.x.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
1019 { "fmv.q.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 },
1020 { "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi,
1021 rv_op_addi, rv_op_addi, rvcd_imm_nz },
1022 { "c.fld", rv_codec_cl_ld, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, 0 },
1023 { "c.lw", rv_codec_cl_lw, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw },
1024 { "c.flw", rv_codec_cl_lw, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 },
1025 { "c.fsd", rv_codec_cs_sd, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, rv_op_fsd, 0 },
1026 { "c.sw", rv_codec_cs_sw, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw },
1027 { "c.fsw", rv_codec_cs_sw, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 },
1028 { "c.nop", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1029 { "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi,
1030 rv_op_addi, rvcd_imm_nz },
1031 { "c.jal", rv_codec_cj_jal, rv_fmt_rd_offset, NULL, rv_op_jal, 0, 0 },
1032 { "c.li", rv_codec_ci_li, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1033 { "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi,
1034 rv_op_addi, rv_op_addi, rvcd_imm_nz },
1035 { "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui,
1036 rv_op_lui, rvcd_imm_nz },
1037 { "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli,
1038 rv_op_srli, rv_op_srli, rvcd_imm_nz },
1039 { "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai,
1040 rv_op_srai, rv_op_srai, rvcd_imm_nz },
1041 { "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi,
1042 rv_op_andi, rv_op_andi },
1043 { "c.sub", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_sub, rv_op_sub, rv_op_sub },
1044 { "c.xor", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_xor, rv_op_xor, rv_op_xor },
1045 { "c.or", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_or, rv_op_or, rv_op_or },
1046 { "c.and", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_and, rv_op_and, rv_op_and },
1047 { "c.subw", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_subw, rv_op_subw, rv_op_subw },
1048 { "c.addw", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_addw, rv_op_addw, rv_op_addw },
1049 { "c.j", rv_codec_cj, rv_fmt_rd_offset, NULL, rv_op_jal, rv_op_jal, rv_op_jal },
1050 { "c.beqz", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_beq, rv_op_beq, rv_op_beq },
1051 { "c.bnez", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_bne, rv_op_bne, rv_op_bne },
1052 { "c.slli", rv_codec_ci_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_slli,
1053 rv_op_slli, rv_op_slli, rvcd_imm_nz },
1054 { "c.fldsp", rv_codec_ci_ldsp, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, rv_op_fld },
1055 { "c.lwsp", rv_codec_ci_lwsp, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw },
1056 { "c.flwsp", rv_codec_ci_lwsp, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 },
1057 { "c.jr", rv_codec_cr_jr, rv_fmt_rd_rs1_offset, NULL, rv_op_jalr, rv_op_jalr, rv_op_jalr },
1058 { "c.mv", rv_codec_cr_mv, rv_fmt_rd_rs1_rs2, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1059 { "c.ebreak", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_ebreak, rv_op_ebreak, rv_op_ebreak },
1060 { "c.jalr", rv_codec_cr_jalr, rv_fmt_rd_rs1_offset, NULL, rv_op_jalr, rv_op_jalr, rv_op_jalr },
1061 { "c.add", rv_codec_cr, rv_fmt_rd_rs1_rs2, NULL, rv_op_add, rv_op_add, rv_op_add },
1062 { "c.fsdsp", rv_codec_css_sdsp, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, rv_op_fsd, rv_op_fsd },
1063 { "c.swsp", rv_codec_css_swsp, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw },
1064 { "c.fswsp", rv_codec_css_swsp, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 },
1065 { "c.ld", rv_codec_cl_ld, rv_fmt_rd_offset_rs1, NULL, 0, rv_op_ld, rv_op_ld },
1066 { "c.sd", rv_codec_cs_sd, rv_fmt_rs2_offset_rs1, NULL, 0, rv_op_sd, rv_op_sd },
1067 { "c.addiw", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, 0, rv_op_addiw, rv_op_addiw },
1068 { "c.ldsp", rv_codec_ci_ldsp, rv_fmt_rd_offset_rs1, NULL, 0, rv_op_ld, rv_op_ld },
1069 { "c.sdsp", rv_codec_css_sdsp, rv_fmt_rs2_offset_rs1, NULL, 0, rv_op_sd, rv_op_sd },
1070 { "c.lq", rv_codec_cl_lq, rv_fmt_rd_offset_rs1, NULL, 0, 0, rv_op_lq },
1071 { "c.sq", rv_codec_cs_sq, rv_fmt_rs2_offset_rs1, NULL, 0, 0, rv_op_sq },
1072 { "c.lqsp", rv_codec_ci_lqsp, rv_fmt_rd_offset_rs1, NULL, 0, 0, rv_op_lq },
1073 { "c.sqsp", rv_codec_css_sqsp, rv_fmt_rs2_offset_rs1, NULL, 0, 0, rv_op_sq },
1074 { "nop", rv_codec_i, rv_fmt_none, NULL, 0, 0, 0 },
1075 { "mv", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1076 { "not", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1077 { "neg", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1078 { "negw", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1079 { "sext.w", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1080 { "seqz", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1081 { "snez", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1082 { "sltz", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1083 { "sgtz", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1084 { "fmv.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1085 { "fabs.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1086 { "fneg.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1087 { "fmv.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1088 { "fabs.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1089 { "fneg.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1090 { "fmv.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1091 { "fabs.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1092 { "fneg.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1093 { "beqz", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1094 { "bnez", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1095 { "blez", rv_codec_sb, rv_fmt_rs2_offset, NULL, 0, 0, 0 },
1096 { "bgez", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1097 { "bltz", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1098 { "bgtz", rv_codec_sb, rv_fmt_rs2_offset, NULL, 0, 0, 0 },
1099 { "ble", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1100 { "bleu", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1101 { "bgt", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1102 { "bgtu", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1103 { "j", rv_codec_uj, rv_fmt_offset, NULL, 0, 0, 0 },
1104 { "ret", rv_codec_i, rv_fmt_none, NULL, 0, 0, 0 },
1105 { "jr", rv_codec_i, rv_fmt_rs1, NULL, 0, 0, 0 },
1106 { "rdcycle", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1107 { "rdtime", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1108 { "rdinstret", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1109 { "rdcycleh", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1110 { "rdtimeh", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1111 { "rdinstreth", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1112 { "frcsr", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1113 { "frrm", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1114 { "frflags", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1115 { "fscsr", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1116 { "fsrm", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1117 { "fsflags", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1118 { "fsrmi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 },
1119 { "fsflagsi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 },
1122 /* CSR names */
1124 static const char *csr_name(int csrno)
1126 switch (csrno) {
1127 case 0x0000: return "ustatus";
1128 case 0x0001: return "fflags";
1129 case 0x0002: return "frm";
1130 case 0x0003: return "fcsr";
1131 case 0x0004: return "uie";
1132 case 0x0005: return "utvec";
1133 case 0x0040: return "uscratch";
1134 case 0x0041: return "uepc";
1135 case 0x0042: return "ucause";
1136 case 0x0043: return "utval";
1137 case 0x0044: return "uip";
1138 case 0x0100: return "sstatus";
1139 case 0x0102: return "sedeleg";
1140 case 0x0103: return "sideleg";
1141 case 0x0104: return "sie";
1142 case 0x0105: return "stvec";
1143 case 0x0106: return "scounteren";
1144 case 0x0140: return "sscratch";
1145 case 0x0141: return "sepc";
1146 case 0x0142: return "scause";
1147 case 0x0143: return "stval";
1148 case 0x0144: return "sip";
1149 case 0x0180: return "satp";
1150 case 0x0200: return "hstatus";
1151 case 0x0202: return "hedeleg";
1152 case 0x0203: return "hideleg";
1153 case 0x0204: return "hie";
1154 case 0x0205: return "htvec";
1155 case 0x0240: return "hscratch";
1156 case 0x0241: return "hepc";
1157 case 0x0242: return "hcause";
1158 case 0x0243: return "hbadaddr";
1159 case 0x0244: return "hip";
1160 case 0x0300: return "mstatus";
1161 case 0x0301: return "misa";
1162 case 0x0302: return "medeleg";
1163 case 0x0303: return "mideleg";
1164 case 0x0304: return "mie";
1165 case 0x0305: return "mtvec";
1166 case 0x0306: return "mcounteren";
1167 case 0x0320: return "mucounteren";
1168 case 0x0321: return "mscounteren";
1169 case 0x0322: return "mhcounteren";
1170 case 0x0323: return "mhpmevent3";
1171 case 0x0324: return "mhpmevent4";
1172 case 0x0325: return "mhpmevent5";
1173 case 0x0326: return "mhpmevent6";
1174 case 0x0327: return "mhpmevent7";
1175 case 0x0328: return "mhpmevent8";
1176 case 0x0329: return "mhpmevent9";
1177 case 0x032a: return "mhpmevent10";
1178 case 0x032b: return "mhpmevent11";
1179 case 0x032c: return "mhpmevent12";
1180 case 0x032d: return "mhpmevent13";
1181 case 0x032e: return "mhpmevent14";
1182 case 0x032f: return "mhpmevent15";
1183 case 0x0330: return "mhpmevent16";
1184 case 0x0331: return "mhpmevent17";
1185 case 0x0332: return "mhpmevent18";
1186 case 0x0333: return "mhpmevent19";
1187 case 0x0334: return "mhpmevent20";
1188 case 0x0335: return "mhpmevent21";
1189 case 0x0336: return "mhpmevent22";
1190 case 0x0337: return "mhpmevent23";
1191 case 0x0338: return "mhpmevent24";
1192 case 0x0339: return "mhpmevent25";
1193 case 0x033a: return "mhpmevent26";
1194 case 0x033b: return "mhpmevent27";
1195 case 0x033c: return "mhpmevent28";
1196 case 0x033d: return "mhpmevent29";
1197 case 0x033e: return "mhpmevent30";
1198 case 0x033f: return "mhpmevent31";
1199 case 0x0340: return "mscratch";
1200 case 0x0341: return "mepc";
1201 case 0x0342: return "mcause";
1202 case 0x0343: return "mtval";
1203 case 0x0344: return "mip";
1204 case 0x0380: return "mbase";
1205 case 0x0381: return "mbound";
1206 case 0x0382: return "mibase";
1207 case 0x0383: return "mibound";
1208 case 0x0384: return "mdbase";
1209 case 0x0385: return "mdbound";
1210 case 0x03a0: return "pmpcfg3";
1211 case 0x03b0: return "pmpaddr0";
1212 case 0x03b1: return "pmpaddr1";
1213 case 0x03b2: return "pmpaddr2";
1214 case 0x03b3: return "pmpaddr3";
1215 case 0x03b4: return "pmpaddr4";
1216 case 0x03b5: return "pmpaddr5";
1217 case 0x03b6: return "pmpaddr6";
1218 case 0x03b7: return "pmpaddr7";
1219 case 0x03b8: return "pmpaddr8";
1220 case 0x03b9: return "pmpaddr9";
1221 case 0x03ba: return "pmpaddr10";
1222 case 0x03bb: return "pmpaddr11";
1223 case 0x03bc: return "pmpaddr12";
1224 case 0x03bd: return "pmpaddr14";
1225 case 0x03be: return "pmpaddr13";
1226 case 0x03bf: return "pmpaddr15";
1227 case 0x0780: return "mtohost";
1228 case 0x0781: return "mfromhost";
1229 case 0x0782: return "mreset";
1230 case 0x0783: return "mipi";
1231 case 0x0784: return "miobase";
1232 case 0x07a0: return "tselect";
1233 case 0x07a1: return "tdata1";
1234 case 0x07a2: return "tdata2";
1235 case 0x07a3: return "tdata3";
1236 case 0x07b0: return "dcsr";
1237 case 0x07b1: return "dpc";
1238 case 0x07b2: return "dscratch";
1239 case 0x0b00: return "mcycle";
1240 case 0x0b01: return "mtime";
1241 case 0x0b02: return "minstret";
1242 case 0x0b03: return "mhpmcounter3";
1243 case 0x0b04: return "mhpmcounter4";
1244 case 0x0b05: return "mhpmcounter5";
1245 case 0x0b06: return "mhpmcounter6";
1246 case 0x0b07: return "mhpmcounter7";
1247 case 0x0b08: return "mhpmcounter8";
1248 case 0x0b09: return "mhpmcounter9";
1249 case 0x0b0a: return "mhpmcounter10";
1250 case 0x0b0b: return "mhpmcounter11";
1251 case 0x0b0c: return "mhpmcounter12";
1252 case 0x0b0d: return "mhpmcounter13";
1253 case 0x0b0e: return "mhpmcounter14";
1254 case 0x0b0f: return "mhpmcounter15";
1255 case 0x0b10: return "mhpmcounter16";
1256 case 0x0b11: return "mhpmcounter17";
1257 case 0x0b12: return "mhpmcounter18";
1258 case 0x0b13: return "mhpmcounter19";
1259 case 0x0b14: return "mhpmcounter20";
1260 case 0x0b15: return "mhpmcounter21";
1261 case 0x0b16: return "mhpmcounter22";
1262 case 0x0b17: return "mhpmcounter23";
1263 case 0x0b18: return "mhpmcounter24";
1264 case 0x0b19: return "mhpmcounter25";
1265 case 0x0b1a: return "mhpmcounter26";
1266 case 0x0b1b: return "mhpmcounter27";
1267 case 0x0b1c: return "mhpmcounter28";
1268 case 0x0b1d: return "mhpmcounter29";
1269 case 0x0b1e: return "mhpmcounter30";
1270 case 0x0b1f: return "mhpmcounter31";
1271 case 0x0b80: return "mcycleh";
1272 case 0x0b81: return "mtimeh";
1273 case 0x0b82: return "minstreth";
1274 case 0x0b83: return "mhpmcounter3h";
1275 case 0x0b84: return "mhpmcounter4h";
1276 case 0x0b85: return "mhpmcounter5h";
1277 case 0x0b86: return "mhpmcounter6h";
1278 case 0x0b87: return "mhpmcounter7h";
1279 case 0x0b88: return "mhpmcounter8h";
1280 case 0x0b89: return "mhpmcounter9h";
1281 case 0x0b8a: return "mhpmcounter10h";
1282 case 0x0b8b: return "mhpmcounter11h";
1283 case 0x0b8c: return "mhpmcounter12h";
1284 case 0x0b8d: return "mhpmcounter13h";
1285 case 0x0b8e: return "mhpmcounter14h";
1286 case 0x0b8f: return "mhpmcounter15h";
1287 case 0x0b90: return "mhpmcounter16h";
1288 case 0x0b91: return "mhpmcounter17h";
1289 case 0x0b92: return "mhpmcounter18h";
1290 case 0x0b93: return "mhpmcounter19h";
1291 case 0x0b94: return "mhpmcounter20h";
1292 case 0x0b95: return "mhpmcounter21h";
1293 case 0x0b96: return "mhpmcounter22h";
1294 case 0x0b97: return "mhpmcounter23h";
1295 case 0x0b98: return "mhpmcounter24h";
1296 case 0x0b99: return "mhpmcounter25h";
1297 case 0x0b9a: return "mhpmcounter26h";
1298 case 0x0b9b: return "mhpmcounter27h";
1299 case 0x0b9c: return "mhpmcounter28h";
1300 case 0x0b9d: return "mhpmcounter29h";
1301 case 0x0b9e: return "mhpmcounter30h";
1302 case 0x0b9f: return "mhpmcounter31h";
1303 case 0x0c00: return "cycle";
1304 case 0x0c01: return "time";
1305 case 0x0c02: return "instret";
1306 case 0x0c80: return "cycleh";
1307 case 0x0c81: return "timeh";
1308 case 0x0c82: return "instreth";
1309 case 0x0d00: return "scycle";
1310 case 0x0d01: return "stime";
1311 case 0x0d02: return "sinstret";
1312 case 0x0d80: return "scycleh";
1313 case 0x0d81: return "stimeh";
1314 case 0x0d82: return "sinstreth";
1315 case 0x0e00: return "hcycle";
1316 case 0x0e01: return "htime";
1317 case 0x0e02: return "hinstret";
1318 case 0x0e80: return "hcycleh";
1319 case 0x0e81: return "htimeh";
1320 case 0x0e82: return "hinstreth";
1321 case 0x0f11: return "mvendorid";
1322 case 0x0f12: return "marchid";
1323 case 0x0f13: return "mimpid";
1324 case 0x0f14: return "mhartid";
1325 default: return NULL;
1329 /* decode opcode */
1331 static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
1333 rv_inst inst = dec->inst;
1334 rv_opcode op = rv_op_illegal;
1335 switch (((inst >> 0) & 0b11)) {
1336 case 0:
1337 switch (((inst >> 13) & 0b111)) {
1338 case 0: op = rv_op_c_addi4spn; break;
1339 case 1:
1340 if (isa == rv128) {
1341 op = rv_op_c_lq;
1342 } else {
1343 op = rv_op_c_fld;
1345 break;
1346 case 2: op = rv_op_c_lw; break;
1347 case 3:
1348 if (isa == rv32) {
1349 op = rv_op_c_flw;
1350 } else {
1351 op = rv_op_c_ld;
1353 break;
1354 case 5:
1355 if (isa == rv128) {
1356 op = rv_op_c_sq;
1357 } else {
1358 op = rv_op_c_fsd;
1360 break;
1361 case 6: op = rv_op_c_sw; break;
1362 case 7:
1363 if (isa == rv32) {
1364 op = rv_op_c_fsw;
1365 } else {
1366 op = rv_op_c_sd;
1368 break;
1370 break;
1371 case 1:
1372 switch (((inst >> 13) & 0b111)) {
1373 case 0:
1374 switch (((inst >> 2) & 0b11111111111)) {
1375 case 0: op = rv_op_c_nop; break;
1376 default: op = rv_op_c_addi; break;
1378 break;
1379 case 1:
1380 if (isa == rv32) {
1381 op = rv_op_c_jal;
1382 } else {
1383 op = rv_op_c_addiw;
1385 break;
1386 case 2: op = rv_op_c_li; break;
1387 case 3:
1388 switch (((inst >> 7) & 0b11111)) {
1389 case 2: op = rv_op_c_addi16sp; break;
1390 default: op = rv_op_c_lui; break;
1392 break;
1393 case 4:
1394 switch (((inst >> 10) & 0b11)) {
1395 case 0:
1396 op = rv_op_c_srli;
1397 break;
1398 case 1:
1399 op = rv_op_c_srai;
1400 break;
1401 case 2: op = rv_op_c_andi; break;
1402 case 3:
1403 switch (((inst >> 10) & 0b100) | ((inst >> 5) & 0b011)) {
1404 case 0: op = rv_op_c_sub; break;
1405 case 1: op = rv_op_c_xor; break;
1406 case 2: op = rv_op_c_or; break;
1407 case 3: op = rv_op_c_and; break;
1408 case 4: op = rv_op_c_subw; break;
1409 case 5: op = rv_op_c_addw; break;
1411 break;
1413 break;
1414 case 5: op = rv_op_c_j; break;
1415 case 6: op = rv_op_c_beqz; break;
1416 case 7: op = rv_op_c_bnez; break;
1418 break;
1419 case 2:
1420 switch (((inst >> 13) & 0b111)) {
1421 case 0:
1422 op = rv_op_c_slli;
1423 break;
1424 case 1:
1425 if (isa == rv128) {
1426 op = rv_op_c_lqsp;
1427 } else {
1428 op = rv_op_c_fldsp;
1430 break;
1431 case 2: op = rv_op_c_lwsp; break;
1432 case 3:
1433 if (isa == rv32) {
1434 op = rv_op_c_flwsp;
1435 } else {
1436 op = rv_op_c_ldsp;
1438 break;
1439 case 4:
1440 switch (((inst >> 12) & 0b1)) {
1441 case 0:
1442 switch (((inst >> 2) & 0b11111)) {
1443 case 0: op = rv_op_c_jr; break;
1444 default: op = rv_op_c_mv; break;
1446 break;
1447 case 1:
1448 switch (((inst >> 2) & 0b11111)) {
1449 case 0:
1450 switch (((inst >> 7) & 0b11111)) {
1451 case 0: op = rv_op_c_ebreak; break;
1452 default: op = rv_op_c_jalr; break;
1454 break;
1455 default: op = rv_op_c_add; break;
1457 break;
1459 break;
1460 case 5:
1461 if (isa == rv128) {
1462 op = rv_op_c_sqsp;
1463 } else {
1464 op = rv_op_c_fsdsp;
1466 break;
1467 case 6: op = rv_op_c_swsp; break;
1468 case 7:
1469 if (isa == rv32) {
1470 op = rv_op_c_fswsp;
1471 } else {
1472 op = rv_op_c_sdsp;
1474 break;
1476 break;
1477 case 3:
1478 switch (((inst >> 2) & 0b11111)) {
1479 case 0:
1480 switch (((inst >> 12) & 0b111)) {
1481 case 0: op = rv_op_lb; break;
1482 case 1: op = rv_op_lh; break;
1483 case 2: op = rv_op_lw; break;
1484 case 3: op = rv_op_ld; break;
1485 case 4: op = rv_op_lbu; break;
1486 case 5: op = rv_op_lhu; break;
1487 case 6: op = rv_op_lwu; break;
1488 case 7: op = rv_op_ldu; break;
1490 break;
1491 case 1:
1492 switch (((inst >> 12) & 0b111)) {
1493 case 2: op = rv_op_flw; break;
1494 case 3: op = rv_op_fld; break;
1495 case 4: op = rv_op_flq; break;
1497 break;
1498 case 3:
1499 switch (((inst >> 12) & 0b111)) {
1500 case 0: op = rv_op_fence; break;
1501 case 1: op = rv_op_fence_i; break;
1502 case 2: op = rv_op_lq; break;
1504 break;
1505 case 4:
1506 switch (((inst >> 12) & 0b111)) {
1507 case 0: op = rv_op_addi; break;
1508 case 1:
1509 switch (((inst >> 27) & 0b11111)) {
1510 case 0: op = rv_op_slli; break;
1512 break;
1513 case 2: op = rv_op_slti; break;
1514 case 3: op = rv_op_sltiu; break;
1515 case 4: op = rv_op_xori; break;
1516 case 5:
1517 switch (((inst >> 27) & 0b11111)) {
1518 case 0: op = rv_op_srli; break;
1519 case 8: op = rv_op_srai; break;
1521 break;
1522 case 6: op = rv_op_ori; break;
1523 case 7: op = rv_op_andi; break;
1525 break;
1526 case 5: op = rv_op_auipc; break;
1527 case 6:
1528 switch (((inst >> 12) & 0b111)) {
1529 case 0: op = rv_op_addiw; break;
1530 case 1:
1531 switch (((inst >> 25) & 0b1111111)) {
1532 case 0: op = rv_op_slliw; break;
1534 break;
1535 case 5:
1536 switch (((inst >> 25) & 0b1111111)) {
1537 case 0: op = rv_op_srliw; break;
1538 case 32: op = rv_op_sraiw; break;
1540 break;
1542 break;
1543 case 8:
1544 switch (((inst >> 12) & 0b111)) {
1545 case 0: op = rv_op_sb; break;
1546 case 1: op = rv_op_sh; break;
1547 case 2: op = rv_op_sw; break;
1548 case 3: op = rv_op_sd; break;
1549 case 4: op = rv_op_sq; break;
1551 break;
1552 case 9:
1553 switch (((inst >> 12) & 0b111)) {
1554 case 2: op = rv_op_fsw; break;
1555 case 3: op = rv_op_fsd; break;
1556 case 4: op = rv_op_fsq; break;
1558 break;
1559 case 11:
1560 switch (((inst >> 24) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1561 case 2: op = rv_op_amoadd_w; break;
1562 case 3: op = rv_op_amoadd_d; break;
1563 case 4: op = rv_op_amoadd_q; break;
1564 case 10: op = rv_op_amoswap_w; break;
1565 case 11: op = rv_op_amoswap_d; break;
1566 case 12: op = rv_op_amoswap_q; break;
1567 case 18:
1568 switch (((inst >> 20) & 0b11111)) {
1569 case 0: op = rv_op_lr_w; break;
1571 break;
1572 case 19:
1573 switch (((inst >> 20) & 0b11111)) {
1574 case 0: op = rv_op_lr_d; break;
1576 break;
1577 case 20:
1578 switch (((inst >> 20) & 0b11111)) {
1579 case 0: op = rv_op_lr_q; break;
1581 break;
1582 case 26: op = rv_op_sc_w; break;
1583 case 27: op = rv_op_sc_d; break;
1584 case 28: op = rv_op_sc_q; break;
1585 case 34: op = rv_op_amoxor_w; break;
1586 case 35: op = rv_op_amoxor_d; break;
1587 case 36: op = rv_op_amoxor_q; break;
1588 case 66: op = rv_op_amoor_w; break;
1589 case 67: op = rv_op_amoor_d; break;
1590 case 68: op = rv_op_amoor_q; break;
1591 case 98: op = rv_op_amoand_w; break;
1592 case 99: op = rv_op_amoand_d; break;
1593 case 100: op = rv_op_amoand_q; break;
1594 case 130: op = rv_op_amomin_w; break;
1595 case 131: op = rv_op_amomin_d; break;
1596 case 132: op = rv_op_amomin_q; break;
1597 case 162: op = rv_op_amomax_w; break;
1598 case 163: op = rv_op_amomax_d; break;
1599 case 164: op = rv_op_amomax_q; break;
1600 case 194: op = rv_op_amominu_w; break;
1601 case 195: op = rv_op_amominu_d; break;
1602 case 196: op = rv_op_amominu_q; break;
1603 case 226: op = rv_op_amomaxu_w; break;
1604 case 227: op = rv_op_amomaxu_d; break;
1605 case 228: op = rv_op_amomaxu_q; break;
1607 break;
1608 case 12:
1609 switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) {
1610 case 0: op = rv_op_add; break;
1611 case 1: op = rv_op_sll; break;
1612 case 2: op = rv_op_slt; break;
1613 case 3: op = rv_op_sltu; break;
1614 case 4: op = rv_op_xor; break;
1615 case 5: op = rv_op_srl; break;
1616 case 6: op = rv_op_or; break;
1617 case 7: op = rv_op_and; break;
1618 case 8: op = rv_op_mul; break;
1619 case 9: op = rv_op_mulh; break;
1620 case 10: op = rv_op_mulhsu; break;
1621 case 11: op = rv_op_mulhu; break;
1622 case 12: op = rv_op_div; break;
1623 case 13: op = rv_op_divu; break;
1624 case 14: op = rv_op_rem; break;
1625 case 15: op = rv_op_remu; break;
1626 case 256: op = rv_op_sub; break;
1627 case 261: op = rv_op_sra; break;
1629 break;
1630 case 13: op = rv_op_lui; break;
1631 case 14:
1632 switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) {
1633 case 0: op = rv_op_addw; break;
1634 case 1: op = rv_op_sllw; break;
1635 case 5: op = rv_op_srlw; break;
1636 case 8: op = rv_op_mulw; break;
1637 case 12: op = rv_op_divw; break;
1638 case 13: op = rv_op_divuw; break;
1639 case 14: op = rv_op_remw; break;
1640 case 15: op = rv_op_remuw; break;
1641 case 256: op = rv_op_subw; break;
1642 case 261: op = rv_op_sraw; break;
1644 break;
1645 case 16:
1646 switch (((inst >> 25) & 0b11)) {
1647 case 0: op = rv_op_fmadd_s; break;
1648 case 1: op = rv_op_fmadd_d; break;
1649 case 3: op = rv_op_fmadd_q; break;
1651 break;
1652 case 17:
1653 switch (((inst >> 25) & 0b11)) {
1654 case 0: op = rv_op_fmsub_s; break;
1655 case 1: op = rv_op_fmsub_d; break;
1656 case 3: op = rv_op_fmsub_q; break;
1658 break;
1659 case 18:
1660 switch (((inst >> 25) & 0b11)) {
1661 case 0: op = rv_op_fnmsub_s; break;
1662 case 1: op = rv_op_fnmsub_d; break;
1663 case 3: op = rv_op_fnmsub_q; break;
1665 break;
1666 case 19:
1667 switch (((inst >> 25) & 0b11)) {
1668 case 0: op = rv_op_fnmadd_s; break;
1669 case 1: op = rv_op_fnmadd_d; break;
1670 case 3: op = rv_op_fnmadd_q; break;
1672 break;
1673 case 20:
1674 switch (((inst >> 25) & 0b1111111)) {
1675 case 0: op = rv_op_fadd_s; break;
1676 case 1: op = rv_op_fadd_d; break;
1677 case 3: op = rv_op_fadd_q; break;
1678 case 4: op = rv_op_fsub_s; break;
1679 case 5: op = rv_op_fsub_d; break;
1680 case 7: op = rv_op_fsub_q; break;
1681 case 8: op = rv_op_fmul_s; break;
1682 case 9: op = rv_op_fmul_d; break;
1683 case 11: op = rv_op_fmul_q; break;
1684 case 12: op = rv_op_fdiv_s; break;
1685 case 13: op = rv_op_fdiv_d; break;
1686 case 15: op = rv_op_fdiv_q; break;
1687 case 16:
1688 switch (((inst >> 12) & 0b111)) {
1689 case 0: op = rv_op_fsgnj_s; break;
1690 case 1: op = rv_op_fsgnjn_s; break;
1691 case 2: op = rv_op_fsgnjx_s; break;
1693 break;
1694 case 17:
1695 switch (((inst >> 12) & 0b111)) {
1696 case 0: op = rv_op_fsgnj_d; break;
1697 case 1: op = rv_op_fsgnjn_d; break;
1698 case 2: op = rv_op_fsgnjx_d; break;
1700 break;
1701 case 19:
1702 switch (((inst >> 12) & 0b111)) {
1703 case 0: op = rv_op_fsgnj_q; break;
1704 case 1: op = rv_op_fsgnjn_q; break;
1705 case 2: op = rv_op_fsgnjx_q; break;
1707 break;
1708 case 20:
1709 switch (((inst >> 12) & 0b111)) {
1710 case 0: op = rv_op_fmin_s; break;
1711 case 1: op = rv_op_fmax_s; break;
1713 break;
1714 case 21:
1715 switch (((inst >> 12) & 0b111)) {
1716 case 0: op = rv_op_fmin_d; break;
1717 case 1: op = rv_op_fmax_d; break;
1719 break;
1720 case 23:
1721 switch (((inst >> 12) & 0b111)) {
1722 case 0: op = rv_op_fmin_q; break;
1723 case 1: op = rv_op_fmax_q; break;
1725 break;
1726 case 32:
1727 switch (((inst >> 20) & 0b11111)) {
1728 case 1: op = rv_op_fcvt_s_d; break;
1729 case 3: op = rv_op_fcvt_s_q; break;
1731 break;
1732 case 33:
1733 switch (((inst >> 20) & 0b11111)) {
1734 case 0: op = rv_op_fcvt_d_s; break;
1735 case 3: op = rv_op_fcvt_d_q; break;
1737 break;
1738 case 35:
1739 switch (((inst >> 20) & 0b11111)) {
1740 case 0: op = rv_op_fcvt_q_s; break;
1741 case 1: op = rv_op_fcvt_q_d; break;
1743 break;
1744 case 44:
1745 switch (((inst >> 20) & 0b11111)) {
1746 case 0: op = rv_op_fsqrt_s; break;
1748 break;
1749 case 45:
1750 switch (((inst >> 20) & 0b11111)) {
1751 case 0: op = rv_op_fsqrt_d; break;
1753 break;
1754 case 47:
1755 switch (((inst >> 20) & 0b11111)) {
1756 case 0: op = rv_op_fsqrt_q; break;
1758 break;
1759 case 80:
1760 switch (((inst >> 12) & 0b111)) {
1761 case 0: op = rv_op_fle_s; break;
1762 case 1: op = rv_op_flt_s; break;
1763 case 2: op = rv_op_feq_s; break;
1765 break;
1766 case 81:
1767 switch (((inst >> 12) & 0b111)) {
1768 case 0: op = rv_op_fle_d; break;
1769 case 1: op = rv_op_flt_d; break;
1770 case 2: op = rv_op_feq_d; break;
1772 break;
1773 case 83:
1774 switch (((inst >> 12) & 0b111)) {
1775 case 0: op = rv_op_fle_q; break;
1776 case 1: op = rv_op_flt_q; break;
1777 case 2: op = rv_op_feq_q; break;
1779 break;
1780 case 96:
1781 switch (((inst >> 20) & 0b11111)) {
1782 case 0: op = rv_op_fcvt_w_s; break;
1783 case 1: op = rv_op_fcvt_wu_s; break;
1784 case 2: op = rv_op_fcvt_l_s; break;
1785 case 3: op = rv_op_fcvt_lu_s; break;
1787 break;
1788 case 97:
1789 switch (((inst >> 20) & 0b11111)) {
1790 case 0: op = rv_op_fcvt_w_d; break;
1791 case 1: op = rv_op_fcvt_wu_d; break;
1792 case 2: op = rv_op_fcvt_l_d; break;
1793 case 3: op = rv_op_fcvt_lu_d; break;
1795 break;
1796 case 99:
1797 switch (((inst >> 20) & 0b11111)) {
1798 case 0: op = rv_op_fcvt_w_q; break;
1799 case 1: op = rv_op_fcvt_wu_q; break;
1800 case 2: op = rv_op_fcvt_l_q; break;
1801 case 3: op = rv_op_fcvt_lu_q; break;
1803 break;
1804 case 104:
1805 switch (((inst >> 20) & 0b11111)) {
1806 case 0: op = rv_op_fcvt_s_w; break;
1807 case 1: op = rv_op_fcvt_s_wu; break;
1808 case 2: op = rv_op_fcvt_s_l; break;
1809 case 3: op = rv_op_fcvt_s_lu; break;
1811 break;
1812 case 105:
1813 switch (((inst >> 20) & 0b11111)) {
1814 case 0: op = rv_op_fcvt_d_w; break;
1815 case 1: op = rv_op_fcvt_d_wu; break;
1816 case 2: op = rv_op_fcvt_d_l; break;
1817 case 3: op = rv_op_fcvt_d_lu; break;
1819 break;
1820 case 107:
1821 switch (((inst >> 20) & 0b11111)) {
1822 case 0: op = rv_op_fcvt_q_w; break;
1823 case 1: op = rv_op_fcvt_q_wu; break;
1824 case 2: op = rv_op_fcvt_q_l; break;
1825 case 3: op = rv_op_fcvt_q_lu; break;
1827 break;
1828 case 112:
1829 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1830 case 0: op = rv_op_fmv_x_s; break;
1831 case 1: op = rv_op_fclass_s; break;
1833 break;
1834 case 113:
1835 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1836 case 0: op = rv_op_fmv_x_d; break;
1837 case 1: op = rv_op_fclass_d; break;
1839 break;
1840 case 115:
1841 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1842 case 0: op = rv_op_fmv_x_q; break;
1843 case 1: op = rv_op_fclass_q; break;
1845 break;
1846 case 120:
1847 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1848 case 0: op = rv_op_fmv_s_x; break;
1850 break;
1851 case 121:
1852 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1853 case 0: op = rv_op_fmv_d_x; break;
1855 break;
1856 case 123:
1857 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1858 case 0: op = rv_op_fmv_q_x; break;
1860 break;
1862 break;
1863 case 22:
1864 switch (((inst >> 12) & 0b111)) {
1865 case 0: op = rv_op_addid; break;
1866 case 1:
1867 switch (((inst >> 26) & 0b111111)) {
1868 case 0: op = rv_op_sllid; break;
1870 break;
1871 case 5:
1872 switch (((inst >> 26) & 0b111111)) {
1873 case 0: op = rv_op_srlid; break;
1874 case 16: op = rv_op_sraid; break;
1876 break;
1878 break;
1879 case 24:
1880 switch (((inst >> 12) & 0b111)) {
1881 case 0: op = rv_op_beq; break;
1882 case 1: op = rv_op_bne; break;
1883 case 4: op = rv_op_blt; break;
1884 case 5: op = rv_op_bge; break;
1885 case 6: op = rv_op_bltu; break;
1886 case 7: op = rv_op_bgeu; break;
1888 break;
1889 case 25:
1890 switch (((inst >> 12) & 0b111)) {
1891 case 0: op = rv_op_jalr; break;
1893 break;
1894 case 27: op = rv_op_jal; break;
1895 case 28:
1896 switch (((inst >> 12) & 0b111)) {
1897 case 0:
1898 switch (((inst >> 20) & 0b111111100000) | ((inst >> 7) & 0b000000011111)) {
1899 case 0:
1900 switch (((inst >> 15) & 0b1111111111)) {
1901 case 0: op = rv_op_ecall; break;
1902 case 32: op = rv_op_ebreak; break;
1903 case 64: op = rv_op_uret; break;
1905 break;
1906 case 256:
1907 switch (((inst >> 20) & 0b11111)) {
1908 case 2:
1909 switch (((inst >> 15) & 0b11111)) {
1910 case 0: op = rv_op_sret; break;
1912 break;
1913 case 4: op = rv_op_sfence_vm; break;
1914 case 5:
1915 switch (((inst >> 15) & 0b11111)) {
1916 case 0: op = rv_op_wfi; break;
1918 break;
1920 break;
1921 case 288: op = rv_op_sfence_vma; break;
1922 case 512:
1923 switch (((inst >> 15) & 0b1111111111)) {
1924 case 64: op = rv_op_hret; break;
1926 break;
1927 case 768:
1928 switch (((inst >> 15) & 0b1111111111)) {
1929 case 64: op = rv_op_mret; break;
1931 break;
1932 case 1952:
1933 switch (((inst >> 15) & 0b1111111111)) {
1934 case 576: op = rv_op_dret; break;
1936 break;
1938 break;
1939 case 1: op = rv_op_csrrw; break;
1940 case 2: op = rv_op_csrrs; break;
1941 case 3: op = rv_op_csrrc; break;
1942 case 5: op = rv_op_csrrwi; break;
1943 case 6: op = rv_op_csrrsi; break;
1944 case 7: op = rv_op_csrrci; break;
1946 break;
1947 case 30:
1948 switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) {
1949 case 0: op = rv_op_addd; break;
1950 case 1: op = rv_op_slld; break;
1951 case 5: op = rv_op_srld; break;
1952 case 8: op = rv_op_muld; break;
1953 case 12: op = rv_op_divd; break;
1954 case 13: op = rv_op_divud; break;
1955 case 14: op = rv_op_remd; break;
1956 case 15: op = rv_op_remud; break;
1957 case 256: op = rv_op_subd; break;
1958 case 261: op = rv_op_srad; break;
1960 break;
1962 break;
1964 dec->op = op;
1967 /* operand extractors */
1969 static uint32_t operand_rd(rv_inst inst)
1971 return (inst << 52) >> 59;
1974 static uint32_t operand_rs1(rv_inst inst)
1976 return (inst << 44) >> 59;
1979 static uint32_t operand_rs2(rv_inst inst)
1981 return (inst << 39) >> 59;
1984 static uint32_t operand_rs3(rv_inst inst)
1986 return (inst << 32) >> 59;
1989 static uint32_t operand_aq(rv_inst inst)
1991 return (inst << 37) >> 63;
1994 static uint32_t operand_rl(rv_inst inst)
1996 return (inst << 38) >> 63;
1999 static uint32_t operand_pred(rv_inst inst)
2001 return (inst << 36) >> 60;
2004 static uint32_t operand_succ(rv_inst inst)
2006 return (inst << 40) >> 60;
2009 static uint32_t operand_rm(rv_inst inst)
2011 return (inst << 49) >> 61;
2014 static uint32_t operand_shamt5(rv_inst inst)
2016 return (inst << 39) >> 59;
2019 static uint32_t operand_shamt6(rv_inst inst)
2021 return (inst << 38) >> 58;
2024 static uint32_t operand_shamt7(rv_inst inst)
2026 return (inst << 37) >> 57;
2029 static uint32_t operand_crdq(rv_inst inst)
2031 return (inst << 59) >> 61;
2034 static uint32_t operand_crs1q(rv_inst inst)
2036 return (inst << 54) >> 61;
2039 static uint32_t operand_crs1rdq(rv_inst inst)
2041 return (inst << 54) >> 61;
2044 static uint32_t operand_crs2q(rv_inst inst)
2046 return (inst << 59) >> 61;
2049 static uint32_t operand_crd(rv_inst inst)
2051 return (inst << 52) >> 59;
2054 static uint32_t operand_crs1(rv_inst inst)
2056 return (inst << 52) >> 59;
2059 static uint32_t operand_crs1rd(rv_inst inst)
2061 return (inst << 52) >> 59;
2064 static uint32_t operand_crs2(rv_inst inst)
2066 return (inst << 57) >> 59;
2069 static uint32_t operand_cimmsh5(rv_inst inst)
2071 return (inst << 57) >> 59;
2074 static uint32_t operand_csr12(rv_inst inst)
2076 return (inst << 32) >> 52;
2079 static int32_t operand_imm12(rv_inst inst)
2081 return ((int64_t)inst << 32) >> 52;
2084 static int32_t operand_imm20(rv_inst inst)
2086 return (((int64_t)inst << 32) >> 44) << 12;
2089 static int32_t operand_jimm20(rv_inst inst)
2091 return (((int64_t)inst << 32) >> 63) << 20 |
2092 ((inst << 33) >> 54) << 1 |
2093 ((inst << 43) >> 63) << 11 |
2094 ((inst << 44) >> 56) << 12;
2097 static int32_t operand_simm12(rv_inst inst)
2099 return (((int64_t)inst << 32) >> 57) << 5 |
2100 (inst << 52) >> 59;
2103 static int32_t operand_sbimm12(rv_inst inst)
2105 return (((int64_t)inst << 32) >> 63) << 12 |
2106 ((inst << 33) >> 58) << 5 |
2107 ((inst << 52) >> 60) << 1 |
2108 ((inst << 56) >> 63) << 11;
2111 static uint32_t operand_cimmsh6(rv_inst inst)
2113 return ((inst << 51) >> 63) << 5 |
2114 (inst << 57) >> 59;
2117 static int32_t operand_cimmi(rv_inst inst)
2119 return (((int64_t)inst << 51) >> 63) << 5 |
2120 (inst << 57) >> 59;
2123 static int32_t operand_cimmui(rv_inst inst)
2125 return (((int64_t)inst << 51) >> 63) << 17 |
2126 ((inst << 57) >> 59) << 12;
2129 static uint32_t operand_cimmlwsp(rv_inst inst)
2131 return ((inst << 51) >> 63) << 5 |
2132 ((inst << 57) >> 61) << 2 |
2133 ((inst << 60) >> 62) << 6;
2136 static uint32_t operand_cimmldsp(rv_inst inst)
2138 return ((inst << 51) >> 63) << 5 |
2139 ((inst << 57) >> 62) << 3 |
2140 ((inst << 59) >> 61) << 6;
2143 static uint32_t operand_cimmlqsp(rv_inst inst)
2145 return ((inst << 51) >> 63) << 5 |
2146 ((inst << 57) >> 63) << 4 |
2147 ((inst << 58) >> 60) << 6;
2150 static int32_t operand_cimm16sp(rv_inst inst)
2152 return (((int64_t)inst << 51) >> 63) << 9 |
2153 ((inst << 57) >> 63) << 4 |
2154 ((inst << 58) >> 63) << 6 |
2155 ((inst << 59) >> 62) << 7 |
2156 ((inst << 61) >> 63) << 5;
2159 static int32_t operand_cimmj(rv_inst inst)
2161 return (((int64_t)inst << 51) >> 63) << 11 |
2162 ((inst << 52) >> 63) << 4 |
2163 ((inst << 53) >> 62) << 8 |
2164 ((inst << 55) >> 63) << 10 |
2165 ((inst << 56) >> 63) << 6 |
2166 ((inst << 57) >> 63) << 7 |
2167 ((inst << 58) >> 61) << 1 |
2168 ((inst << 61) >> 63) << 5;
2171 static int32_t operand_cimmb(rv_inst inst)
2173 return (((int64_t)inst << 51) >> 63) << 8 |
2174 ((inst << 52) >> 62) << 3 |
2175 ((inst << 57) >> 62) << 6 |
2176 ((inst << 59) >> 62) << 1 |
2177 ((inst << 61) >> 63) << 5;
2180 static uint32_t operand_cimmswsp(rv_inst inst)
2182 return ((inst << 51) >> 60) << 2 |
2183 ((inst << 55) >> 62) << 6;
2186 static uint32_t operand_cimmsdsp(rv_inst inst)
2188 return ((inst << 51) >> 61) << 3 |
2189 ((inst << 54) >> 61) << 6;
2192 static uint32_t operand_cimmsqsp(rv_inst inst)
2194 return ((inst << 51) >> 62) << 4 |
2195 ((inst << 53) >> 60) << 6;
2198 static uint32_t operand_cimm4spn(rv_inst inst)
2200 return ((inst << 51) >> 62) << 4 |
2201 ((inst << 53) >> 60) << 6 |
2202 ((inst << 57) >> 63) << 2 |
2203 ((inst << 58) >> 63) << 3;
2206 static uint32_t operand_cimmw(rv_inst inst)
2208 return ((inst << 51) >> 61) << 3 |
2209 ((inst << 57) >> 63) << 2 |
2210 ((inst << 58) >> 63) << 6;
2213 static uint32_t operand_cimmd(rv_inst inst)
2215 return ((inst << 51) >> 61) << 3 |
2216 ((inst << 57) >> 62) << 6;
2219 static uint32_t operand_cimmq(rv_inst inst)
2221 return ((inst << 51) >> 62) << 4 |
2222 ((inst << 53) >> 63) << 8 |
2223 ((inst << 57) >> 62) << 6;
2226 /* decode operands */
2228 static void decode_inst_operands(rv_decode *dec)
2230 rv_inst inst = dec->inst;
2231 dec->codec = opcode_data[dec->op].codec;
2232 switch (dec->codec) {
2233 case rv_codec_none:
2234 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2235 dec->imm = 0;
2236 break;
2237 case rv_codec_u:
2238 dec->rd = operand_rd(inst);
2239 dec->rs1 = dec->rs2 = rv_ireg_zero;
2240 dec->imm = operand_imm20(inst);
2241 break;
2242 case rv_codec_uj:
2243 dec->rd = operand_rd(inst);
2244 dec->rs1 = dec->rs2 = rv_ireg_zero;
2245 dec->imm = operand_jimm20(inst);
2246 break;
2247 case rv_codec_i:
2248 dec->rd = operand_rd(inst);
2249 dec->rs1 = operand_rs1(inst);
2250 dec->rs2 = rv_ireg_zero;
2251 dec->imm = operand_imm12(inst);
2252 break;
2253 case rv_codec_i_sh5:
2254 dec->rd = operand_rd(inst);
2255 dec->rs1 = operand_rs1(inst);
2256 dec->rs2 = rv_ireg_zero;
2257 dec->imm = operand_shamt5(inst);
2258 break;
2259 case rv_codec_i_sh6:
2260 dec->rd = operand_rd(inst);
2261 dec->rs1 = operand_rs1(inst);
2262 dec->rs2 = rv_ireg_zero;
2263 dec->imm = operand_shamt6(inst);
2264 break;
2265 case rv_codec_i_sh7:
2266 dec->rd = operand_rd(inst);
2267 dec->rs1 = operand_rs1(inst);
2268 dec->rs2 = rv_ireg_zero;
2269 dec->imm = operand_shamt7(inst);
2270 break;
2271 case rv_codec_i_csr:
2272 dec->rd = operand_rd(inst);
2273 dec->rs1 = operand_rs1(inst);
2274 dec->rs2 = rv_ireg_zero;
2275 dec->imm = operand_csr12(inst);
2276 break;
2277 case rv_codec_s:
2278 dec->rd = rv_ireg_zero;
2279 dec->rs1 = operand_rs1(inst);
2280 dec->rs2 = operand_rs2(inst);
2281 dec->imm = operand_simm12(inst);
2282 break;
2283 case rv_codec_sb:
2284 dec->rd = rv_ireg_zero;
2285 dec->rs1 = operand_rs1(inst);
2286 dec->rs2 = operand_rs2(inst);
2287 dec->imm = operand_sbimm12(inst);
2288 break;
2289 case rv_codec_r:
2290 dec->rd = operand_rd(inst);
2291 dec->rs1 = operand_rs1(inst);
2292 dec->rs2 = operand_rs2(inst);
2293 dec->imm = 0;
2294 break;
2295 case rv_codec_r_m:
2296 dec->rd = operand_rd(inst);
2297 dec->rs1 = operand_rs1(inst);
2298 dec->rs2 = operand_rs2(inst);
2299 dec->imm = 0;
2300 dec->rm = operand_rm(inst);
2301 break;
2302 case rv_codec_r4_m:
2303 dec->rd = operand_rd(inst);
2304 dec->rs1 = operand_rs1(inst);
2305 dec->rs2 = operand_rs2(inst);
2306 dec->rs3 = operand_rs3(inst);
2307 dec->imm = 0;
2308 dec->rm = operand_rm(inst);
2309 break;
2310 case rv_codec_r_a:
2311 dec->rd = operand_rd(inst);
2312 dec->rs1 = operand_rs1(inst);
2313 dec->rs2 = operand_rs2(inst);
2314 dec->imm = 0;
2315 dec->aq = operand_aq(inst);
2316 dec->rl = operand_rl(inst);
2317 break;
2318 case rv_codec_r_l:
2319 dec->rd = operand_rd(inst);
2320 dec->rs1 = operand_rs1(inst);
2321 dec->rs2 = rv_ireg_zero;
2322 dec->imm = 0;
2323 dec->aq = operand_aq(inst);
2324 dec->rl = operand_rl(inst);
2325 break;
2326 case rv_codec_r_f:
2327 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2328 dec->pred = operand_pred(inst);
2329 dec->succ = operand_succ(inst);
2330 dec->imm = 0;
2331 break;
2332 case rv_codec_cb:
2333 dec->rd = rv_ireg_zero;
2334 dec->rs1 = operand_crs1q(inst) + 8;
2335 dec->rs2 = rv_ireg_zero;
2336 dec->imm = operand_cimmb(inst);
2337 break;
2338 case rv_codec_cb_imm:
2339 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2340 dec->rs2 = rv_ireg_zero;
2341 dec->imm = operand_cimmi(inst);
2342 break;
2343 case rv_codec_cb_sh5:
2344 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2345 dec->rs2 = rv_ireg_zero;
2346 dec->imm = operand_cimmsh5(inst);
2347 break;
2348 case rv_codec_cb_sh6:
2349 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2350 dec->rs2 = rv_ireg_zero;
2351 dec->imm = operand_cimmsh6(inst);
2352 break;
2353 case rv_codec_ci:
2354 dec->rd = dec->rs1 = operand_crs1rd(inst);
2355 dec->rs2 = rv_ireg_zero;
2356 dec->imm = operand_cimmi(inst);
2357 break;
2358 case rv_codec_ci_sh5:
2359 dec->rd = dec->rs1 = operand_crs1rd(inst);
2360 dec->rs2 = rv_ireg_zero;
2361 dec->imm = operand_cimmsh5(inst);
2362 break;
2363 case rv_codec_ci_sh6:
2364 dec->rd = dec->rs1 = operand_crs1rd(inst);
2365 dec->rs2 = rv_ireg_zero;
2366 dec->imm = operand_cimmsh6(inst);
2367 break;
2368 case rv_codec_ci_16sp:
2369 dec->rd = rv_ireg_sp;
2370 dec->rs1 = rv_ireg_sp;
2371 dec->rs2 = rv_ireg_zero;
2372 dec->imm = operand_cimm16sp(inst);
2373 break;
2374 case rv_codec_ci_lwsp:
2375 dec->rd = operand_crd(inst);
2376 dec->rs1 = rv_ireg_sp;
2377 dec->rs2 = rv_ireg_zero;
2378 dec->imm = operand_cimmlwsp(inst);
2379 break;
2380 case rv_codec_ci_ldsp:
2381 dec->rd = operand_crd(inst);
2382 dec->rs1 = rv_ireg_sp;
2383 dec->rs2 = rv_ireg_zero;
2384 dec->imm = operand_cimmldsp(inst);
2385 break;
2386 case rv_codec_ci_lqsp:
2387 dec->rd = operand_crd(inst);
2388 dec->rs1 = rv_ireg_sp;
2389 dec->rs2 = rv_ireg_zero;
2390 dec->imm = operand_cimmlqsp(inst);
2391 break;
2392 case rv_codec_ci_li:
2393 dec->rd = operand_crd(inst);
2394 dec->rs1 = rv_ireg_zero;
2395 dec->rs2 = rv_ireg_zero;
2396 dec->imm = operand_cimmi(inst);
2397 break;
2398 case rv_codec_ci_lui:
2399 dec->rd = operand_crd(inst);
2400 dec->rs1 = rv_ireg_zero;
2401 dec->rs2 = rv_ireg_zero;
2402 dec->imm = operand_cimmui(inst);
2403 break;
2404 case rv_codec_ci_none:
2405 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2406 dec->imm = 0;
2407 break;
2408 case rv_codec_ciw_4spn:
2409 dec->rd = operand_crdq(inst) + 8;
2410 dec->rs1 = rv_ireg_sp;
2411 dec->rs2 = rv_ireg_zero;
2412 dec->imm = operand_cimm4spn(inst);
2413 break;
2414 case rv_codec_cj:
2415 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2416 dec->imm = operand_cimmj(inst);
2417 break;
2418 case rv_codec_cj_jal:
2419 dec->rd = rv_ireg_ra;
2420 dec->rs1 = dec->rs2 = rv_ireg_zero;
2421 dec->imm = operand_cimmj(inst);
2422 break;
2423 case rv_codec_cl_lw:
2424 dec->rd = operand_crdq(inst) + 8;
2425 dec->rs1 = operand_crs1q(inst) + 8;
2426 dec->rs2 = rv_ireg_zero;
2427 dec->imm = operand_cimmw(inst);
2428 break;
2429 case rv_codec_cl_ld:
2430 dec->rd = operand_crdq(inst) + 8;
2431 dec->rs1 = operand_crs1q(inst) + 8;
2432 dec->rs2 = rv_ireg_zero;
2433 dec->imm = operand_cimmd(inst);
2434 break;
2435 case rv_codec_cl_lq:
2436 dec->rd = operand_crdq(inst) + 8;
2437 dec->rs1 = operand_crs1q(inst) + 8;
2438 dec->rs2 = rv_ireg_zero;
2439 dec->imm = operand_cimmq(inst);
2440 break;
2441 case rv_codec_cr:
2442 dec->rd = dec->rs1 = operand_crs1rd(inst);
2443 dec->rs2 = operand_crs2(inst);
2444 dec->imm = 0;
2445 break;
2446 case rv_codec_cr_mv:
2447 dec->rd = operand_crd(inst);
2448 dec->rs1 = operand_crs2(inst);
2449 dec->rs2 = rv_ireg_zero;
2450 dec->imm = 0;
2451 break;
2452 case rv_codec_cr_jalr:
2453 dec->rd = rv_ireg_ra;
2454 dec->rs1 = operand_crs1(inst);
2455 dec->rs2 = rv_ireg_zero;
2456 dec->imm = 0;
2457 break;
2458 case rv_codec_cr_jr:
2459 dec->rd = rv_ireg_zero;
2460 dec->rs1 = operand_crs1(inst);
2461 dec->rs2 = rv_ireg_zero;
2462 dec->imm = 0;
2463 break;
2464 case rv_codec_cs:
2465 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2466 dec->rs2 = operand_crs2q(inst) + 8;
2467 dec->imm = 0;
2468 break;
2469 case rv_codec_cs_sw:
2470 dec->rd = rv_ireg_zero;
2471 dec->rs1 = operand_crs1q(inst) + 8;
2472 dec->rs2 = operand_crs2q(inst) + 8;
2473 dec->imm = operand_cimmw(inst);
2474 break;
2475 case rv_codec_cs_sd:
2476 dec->rd = rv_ireg_zero;
2477 dec->rs1 = operand_crs1q(inst) + 8;
2478 dec->rs2 = operand_crs2q(inst) + 8;
2479 dec->imm = operand_cimmd(inst);
2480 break;
2481 case rv_codec_cs_sq:
2482 dec->rd = rv_ireg_zero;
2483 dec->rs1 = operand_crs1q(inst) + 8;
2484 dec->rs2 = operand_crs2q(inst) + 8;
2485 dec->imm = operand_cimmq(inst);
2486 break;
2487 case rv_codec_css_swsp:
2488 dec->rd = rv_ireg_zero;
2489 dec->rs1 = rv_ireg_sp;
2490 dec->rs2 = operand_crs2(inst);
2491 dec->imm = operand_cimmswsp(inst);
2492 break;
2493 case rv_codec_css_sdsp:
2494 dec->rd = rv_ireg_zero;
2495 dec->rs1 = rv_ireg_sp;
2496 dec->rs2 = operand_crs2(inst);
2497 dec->imm = operand_cimmsdsp(inst);
2498 break;
2499 case rv_codec_css_sqsp:
2500 dec->rd = rv_ireg_zero;
2501 dec->rs1 = rv_ireg_sp;
2502 dec->rs2 = operand_crs2(inst);
2503 dec->imm = operand_cimmsqsp(inst);
2504 break;
2508 /* check constraint */
2510 static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
2512 int32_t imm = dec->imm;
2513 uint8_t rd = dec->rd, rs1 = dec->rs1, rs2 = dec->rs2;
2514 while (*c != rvc_end) {
2515 switch (*c) {
2516 case rvc_rd_eq_ra:
2517 if (!(rd == 1)) {
2518 return false;
2520 break;
2521 case rvc_rd_eq_x0:
2522 if (!(rd == 0)) {
2523 return false;
2525 break;
2526 case rvc_rs1_eq_x0:
2527 if (!(rs1 == 0)) {
2528 return false;
2530 break;
2531 case rvc_rs2_eq_x0:
2532 if (!(rs2 == 0)) {
2533 return false;
2535 break;
2536 case rvc_rs2_eq_rs1:
2537 if (!(rs2 == rs1)) {
2538 return false;
2540 break;
2541 case rvc_rs1_eq_ra:
2542 if (!(rs1 == 1)) {
2543 return false;
2545 break;
2546 case rvc_imm_eq_zero:
2547 if (!(imm == 0)) {
2548 return false;
2550 break;
2551 case rvc_imm_eq_n1:
2552 if (!(imm == -1)) {
2553 return false;
2555 break;
2556 case rvc_imm_eq_p1:
2557 if (!(imm == 1)) {
2558 return false;
2560 break;
2561 case rvc_csr_eq_0x001:
2562 if (!(imm == 0x001)) {
2563 return false;
2565 break;
2566 case rvc_csr_eq_0x002:
2567 if (!(imm == 0x002)) {
2568 return false;
2570 break;
2571 case rvc_csr_eq_0x003:
2572 if (!(imm == 0x003)) {
2573 return false;
2575 break;
2576 case rvc_csr_eq_0xc00:
2577 if (!(imm == 0xc00)) {
2578 return false;
2580 break;
2581 case rvc_csr_eq_0xc01:
2582 if (!(imm == 0xc01)) {
2583 return false;
2585 break;
2586 case rvc_csr_eq_0xc02:
2587 if (!(imm == 0xc02)) {
2588 return false;
2590 break;
2591 case rvc_csr_eq_0xc80:
2592 if (!(imm == 0xc80)) {
2593 return false;
2595 break;
2596 case rvc_csr_eq_0xc81:
2597 if (!(imm == 0xc81)) {
2598 return false;
2600 break;
2601 case rvc_csr_eq_0xc82:
2602 if (!(imm == 0xc82)) {
2603 return false;
2605 break;
2606 default: break;
2608 c++;
2610 return true;
2613 /* instruction length */
2615 static size_t inst_length(rv_inst inst)
2617 /* NOTE: supports maximum instruction size of 64-bits */
2619 /* instruction length coding
2621 * aa - 16 bit aa != 11
2622 * bbb11 - 32 bit bbb != 111
2623 * 011111 - 48 bit
2624 * 0111111 - 64 bit
2627 return (inst & 0b11) != 0b11 ? 2
2628 : (inst & 0b11100) != 0b11100 ? 4
2629 : (inst & 0b111111) == 0b011111 ? 6
2630 : (inst & 0b1111111) == 0b0111111 ? 8
2631 : 0;
2634 /* format instruction */
2636 static void append(char *s1, const char *s2, size_t n)
2638 size_t l1 = strlen(s1);
2639 if (n - l1 - 1 > 0) {
2640 strncat(s1, s2, n - l1);
2644 static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
2646 char tmp[64];
2647 const char *fmt;
2649 fmt = opcode_data[dec->op].format;
2650 while (*fmt) {
2651 switch (*fmt) {
2652 case 'O':
2653 append(buf, opcode_data[dec->op].name, buflen);
2654 break;
2655 case '(':
2656 append(buf, "(", buflen);
2657 break;
2658 case ',':
2659 append(buf, ",", buflen);
2660 break;
2661 case ')':
2662 append(buf, ")", buflen);
2663 break;
2664 case '0':
2665 append(buf, rv_ireg_name_sym[dec->rd], buflen);
2666 break;
2667 case '1':
2668 append(buf, rv_ireg_name_sym[dec->rs1], buflen);
2669 break;
2670 case '2':
2671 append(buf, rv_ireg_name_sym[dec->rs2], buflen);
2672 break;
2673 case '3':
2674 append(buf, rv_freg_name_sym[dec->rd], buflen);
2675 break;
2676 case '4':
2677 append(buf, rv_freg_name_sym[dec->rs1], buflen);
2678 break;
2679 case '5':
2680 append(buf, rv_freg_name_sym[dec->rs2], buflen);
2681 break;
2682 case '6':
2683 append(buf, rv_freg_name_sym[dec->rs3], buflen);
2684 break;
2685 case '7':
2686 snprintf(tmp, sizeof(tmp), "%d", dec->rs1);
2687 append(buf, tmp, buflen);
2688 break;
2689 case 'i':
2690 snprintf(tmp, sizeof(tmp), "%d", dec->imm);
2691 append(buf, tmp, buflen);
2692 break;
2693 case 'o':
2694 snprintf(tmp, sizeof(tmp), "%d", dec->imm);
2695 append(buf, tmp, buflen);
2696 while (strlen(buf) < tab * 2) {
2697 append(buf, " ", buflen);
2699 snprintf(tmp, sizeof(tmp), "# 0x%" PRIx64,
2700 dec->pc + dec->imm);
2701 append(buf, tmp, buflen);
2702 break;
2703 case 'c': {
2704 const char *name = csr_name(dec->imm & 0xfff);
2705 if (name) {
2706 append(buf, name, buflen);
2707 } else {
2708 snprintf(tmp, sizeof(tmp), "0x%03x", dec->imm & 0xfff);
2709 append(buf, tmp, buflen);
2711 break;
2713 case 'r':
2714 switch (dec->rm) {
2715 case rv_rm_rne:
2716 append(buf, "rne", buflen);
2717 break;
2718 case rv_rm_rtz:
2719 append(buf, "rtz", buflen);
2720 break;
2721 case rv_rm_rdn:
2722 append(buf, "rdn", buflen);
2723 break;
2724 case rv_rm_rup:
2725 append(buf, "rup", buflen);
2726 break;
2727 case rv_rm_rmm:
2728 append(buf, "rmm", buflen);
2729 break;
2730 case rv_rm_dyn:
2731 append(buf, "dyn", buflen);
2732 break;
2733 default:
2734 append(buf, "inv", buflen);
2735 break;
2737 break;
2738 case 'p':
2739 if (dec->pred & rv_fence_i) {
2740 append(buf, "i", buflen);
2742 if (dec->pred & rv_fence_o) {
2743 append(buf, "o", buflen);
2745 if (dec->pred & rv_fence_r) {
2746 append(buf, "r", buflen);
2748 if (dec->pred & rv_fence_w) {
2749 append(buf, "w", buflen);
2751 break;
2752 case 's':
2753 if (dec->succ & rv_fence_i) {
2754 append(buf, "i", buflen);
2756 if (dec->succ & rv_fence_o) {
2757 append(buf, "o", buflen);
2759 if (dec->succ & rv_fence_r) {
2760 append(buf, "r", buflen);
2762 if (dec->succ & rv_fence_w) {
2763 append(buf, "w", buflen);
2765 break;
2766 case '\t':
2767 while (strlen(buf) < tab) {
2768 append(buf, " ", buflen);
2770 break;
2771 case 'A':
2772 if (dec->aq) {
2773 append(buf, ".aq", buflen);
2775 break;
2776 case 'R':
2777 if (dec->rl) {
2778 append(buf, ".rl", buflen);
2780 break;
2781 default:
2782 break;
2784 fmt++;
2788 /* lift instruction to pseudo-instruction */
2790 static void decode_inst_lift_pseudo(rv_decode *dec)
2792 const rv_comp_data *comp_data = opcode_data[dec->op].pseudo;
2793 if (!comp_data) {
2794 return;
2796 while (comp_data->constraints) {
2797 if (check_constraints(dec, comp_data->constraints)) {
2798 dec->op = comp_data->op;
2799 dec->codec = opcode_data[dec->op].codec;
2800 return;
2802 comp_data++;
2806 /* decompress instruction */
2808 static void decode_inst_decompress_rv32(rv_decode *dec)
2810 int decomp_op = opcode_data[dec->op].decomp_rv32;
2811 if (decomp_op != rv_op_illegal) {
2812 if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz)
2813 && dec->imm == 0) {
2814 dec->op = rv_op_illegal;
2815 } else {
2816 dec->op = decomp_op;
2817 dec->codec = opcode_data[decomp_op].codec;
2822 static void decode_inst_decompress_rv64(rv_decode *dec)
2824 int decomp_op = opcode_data[dec->op].decomp_rv64;
2825 if (decomp_op != rv_op_illegal) {
2826 if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz)
2827 && dec->imm == 0) {
2828 dec->op = rv_op_illegal;
2829 } else {
2830 dec->op = decomp_op;
2831 dec->codec = opcode_data[decomp_op].codec;
2836 static void decode_inst_decompress_rv128(rv_decode *dec)
2838 int decomp_op = opcode_data[dec->op].decomp_rv128;
2839 if (decomp_op != rv_op_illegal) {
2840 if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz)
2841 && dec->imm == 0) {
2842 dec->op = rv_op_illegal;
2843 } else {
2844 dec->op = decomp_op;
2845 dec->codec = opcode_data[decomp_op].codec;
2850 static void decode_inst_decompress(rv_decode *dec, rv_isa isa)
2852 switch (isa) {
2853 case rv32:
2854 decode_inst_decompress_rv32(dec);
2855 break;
2856 case rv64:
2857 decode_inst_decompress_rv64(dec);
2858 break;
2859 case rv128:
2860 decode_inst_decompress_rv128(dec);
2861 break;
2865 /* disassemble instruction */
2867 static void
2868 disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst)
2870 rv_decode dec = { 0 };
2871 dec.pc = pc;
2872 dec.inst = inst;
2873 decode_inst_opcode(&dec, isa);
2874 decode_inst_operands(&dec);
2875 decode_inst_decompress(&dec, isa);
2876 decode_inst_lift_pseudo(&dec);
2877 format_inst(buf, buflen, 16, &dec);
2880 #define INST_FMT_2 "%04" PRIx64 " "
2881 #define INST_FMT_4 "%08" PRIx64 " "
2882 #define INST_FMT_6 "%012" PRIx64 " "
2883 #define INST_FMT_8 "%016" PRIx64 " "
2885 static int
2886 print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa)
2888 char buf[128] = { 0 };
2889 bfd_byte packet[2];
2890 rv_inst inst = 0;
2891 size_t len = 2;
2892 bfd_vma n;
2893 int status;
2895 /* Instructions are made of 2-byte packets in little-endian order */
2896 for (n = 0; n < len; n += 2) {
2897 status = (*info->read_memory_func)(memaddr + n, packet, 2, info);
2898 if (status != 0) {
2899 /* Don't fail just because we fell off the end. */
2900 if (n > 0) {
2901 break;
2903 (*info->memory_error_func)(status, memaddr, info);
2904 return status;
2906 inst |= ((rv_inst) bfd_getl16(packet)) << (8 * n);
2907 if (n == 0) {
2908 len = inst_length(inst);
2912 switch (len) {
2913 case 2:
2914 (*info->fprintf_func)(info->stream, INST_FMT_2, inst);
2915 break;
2916 case 4:
2917 (*info->fprintf_func)(info->stream, INST_FMT_4, inst);
2918 break;
2919 case 6:
2920 (*info->fprintf_func)(info->stream, INST_FMT_6, inst);
2921 break;
2922 default:
2923 (*info->fprintf_func)(info->stream, INST_FMT_8, inst);
2924 break;
2927 disasm_inst(buf, sizeof(buf), isa, memaddr, inst);
2928 (*info->fprintf_func)(info->stream, "%s", buf);
2930 return len;
2933 int print_insn_riscv32(bfd_vma memaddr, struct disassemble_info *info)
2935 return print_insn_riscv(memaddr, info, rv32);
2938 int print_insn_riscv64(bfd_vma memaddr, struct disassemble_info *info)
2940 return print_insn_riscv(memaddr, info, rv64);