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
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/bfd.h"
26 typedef uint64_t rv_inst;
27 typedef uint16_t rv_opcode;
269 rv_op_amoswap_w = 84,
276 rv_op_amominu_w = 91,
277 rv_op_amomaxu_w = 92,
280 rv_op_amoswap_d = 95,
285 rv_op_amomin_d = 100,
286 rv_op_amomax_d = 101,
287 rv_op_amominu_d = 102,
288 rv_op_amomaxu_d = 103,
291 rv_op_amoswap_q = 106,
292 rv_op_amoadd_q = 107,
293 rv_op_amoxor_q = 108,
295 rv_op_amoand_q = 110,
296 rv_op_amomin_q = 111,
297 rv_op_amomax_q = 112,
298 rv_op_amominu_q = 113,
299 rv_op_amomaxu_q = 114,
307 rv_op_sfence_vm = 122,
308 rv_op_sfence_vma = 123,
320 rv_op_fnmsub_s = 135,
321 rv_op_fnmadd_s = 136,
327 rv_op_fsgnjn_s = 142,
328 rv_op_fsgnjx_s = 143,
335 rv_op_fcvt_w_s = 150,
336 rv_op_fcvt_wu_s = 151,
337 rv_op_fcvt_s_w = 152,
338 rv_op_fcvt_s_wu = 153,
340 rv_op_fclass_s = 155,
342 rv_op_fcvt_l_s = 157,
343 rv_op_fcvt_lu_s = 158,
344 rv_op_fcvt_s_l = 159,
345 rv_op_fcvt_s_lu = 160,
350 rv_op_fnmsub_d = 165,
351 rv_op_fnmadd_d = 166,
357 rv_op_fsgnjn_d = 172,
358 rv_op_fsgnjx_d = 173,
361 rv_op_fcvt_s_d = 176,
362 rv_op_fcvt_d_s = 177,
367 rv_op_fcvt_w_d = 182,
368 rv_op_fcvt_wu_d = 183,
369 rv_op_fcvt_d_w = 184,
370 rv_op_fcvt_d_wu = 185,
371 rv_op_fclass_d = 186,
372 rv_op_fcvt_l_d = 187,
373 rv_op_fcvt_lu_d = 188,
375 rv_op_fcvt_d_l = 190,
376 rv_op_fcvt_d_lu = 191,
382 rv_op_fnmsub_q = 197,
383 rv_op_fnmadd_q = 198,
389 rv_op_fsgnjn_q = 204,
390 rv_op_fsgnjx_q = 205,
393 rv_op_fcvt_s_q = 208,
394 rv_op_fcvt_q_s = 209,
395 rv_op_fcvt_d_q = 210,
396 rv_op_fcvt_q_d = 211,
401 rv_op_fcvt_w_q = 216,
402 rv_op_fcvt_wu_q = 217,
403 rv_op_fcvt_q_w = 218,
404 rv_op_fcvt_q_wu = 219,
405 rv_op_fclass_q = 220,
406 rv_op_fcvt_l_q = 221,
407 rv_op_fcvt_lu_q = 222,
408 rv_op_fcvt_q_l = 223,
409 rv_op_fcvt_q_lu = 224,
412 rv_op_c_addi4spn = 227,
423 rv_op_c_addi16sp = 238,
443 rv_op_c_ebreak = 258,
492 rv_op_rdinstret = 307,
493 rv_op_rdcycleh = 308,
495 rv_op_rdinstreth = 310,
503 rv_op_fsflagsi = 318,
527 const rvc_constraint *constraints;
531 const char * const name;
532 const rv_codec codec;
533 const char * const format;
534 const rv_comp_data *pseudo;
535 const int decomp_rv32;
536 const int decomp_rv64;
537 const int decomp_rv128;
542 static const char rv_ireg_name_sym[32][5] = {
543 "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
544 "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
545 "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
546 "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6",
549 static const char rv_freg_name_sym[32][5] = {
550 "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
551 "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
552 "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
553 "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
556 /* instruction formats */
558 #define rv_fmt_none "O\t"
559 #define rv_fmt_rs1 "O\t1"
560 #define rv_fmt_offset "O\to"
561 #define rv_fmt_pred_succ "O\tp,s"
562 #define rv_fmt_rs1_rs2 "O\t1,2"
563 #define rv_fmt_rd_imm "O\t0,i"
564 #define rv_fmt_rd_offset "O\t0,o"
565 #define rv_fmt_rd_rs1_rs2 "O\t0,1,2"
566 #define rv_fmt_frd_rs1 "O\t3,1"
567 #define rv_fmt_rd_frs1 "O\t0,4"
568 #define rv_fmt_rd_frs1_frs2 "O\t0,4,5"
569 #define rv_fmt_frd_frs1_frs2 "O\t3,4,5"
570 #define rv_fmt_rm_frd_frs1 "O\tr,3,4"
571 #define rv_fmt_rm_frd_rs1 "O\tr,3,1"
572 #define rv_fmt_rm_rd_frs1 "O\tr,0,4"
573 #define rv_fmt_rm_frd_frs1_frs2 "O\tr,3,4,5"
574 #define rv_fmt_rm_frd_frs1_frs2_frs3 "O\tr,3,4,5,6"
575 #define rv_fmt_rd_rs1_imm "O\t0,1,i"
576 #define rv_fmt_rd_rs1_offset "O\t0,1,i"
577 #define rv_fmt_rd_offset_rs1 "O\t0,i(1)"
578 #define rv_fmt_frd_offset_rs1 "O\t3,i(1)"
579 #define rv_fmt_rd_csr_rs1 "O\t0,c,1"
580 #define rv_fmt_rd_csr_zimm "O\t0,c,7"
581 #define rv_fmt_rs2_offset_rs1 "O\t2,i(1)"
582 #define rv_fmt_frs2_offset_rs1 "O\t5,i(1)"
583 #define rv_fmt_rs1_rs2_offset "O\t1,2,o"
584 #define rv_fmt_rs2_rs1_offset "O\t2,1,o"
585 #define rv_fmt_aqrl_rd_rs2_rs1 "OAR\t0,2,(1)"
586 #define rv_fmt_aqrl_rd_rs1 "OAR\t0,(1)"
587 #define rv_fmt_rd "O\t0"
588 #define rv_fmt_rd_zimm "O\t0,7"
589 #define rv_fmt_rd_rs1 "O\t0,1"
590 #define rv_fmt_rd_rs2 "O\t0,2"
591 #define rv_fmt_rs1_offset "O\t1,o"
592 #define rv_fmt_rs2_offset "O\t2,o"
594 /* pseudo-instruction constraints */
596 static const rvc_constraint rvcc_jal[] = { rvc_rd_eq_ra, rvc_end };
597 static const rvc_constraint rvcc_jalr[] = { rvc_rd_eq_ra, rvc_imm_eq_zero, rvc_end };
598 static const rvc_constraint rvcc_nop[] = { rvc_rd_eq_x0, rvc_rs1_eq_x0, rvc_imm_eq_zero, rvc_end };
599 static const rvc_constraint rvcc_mv[] = { rvc_imm_eq_zero, rvc_end };
600 static const rvc_constraint rvcc_not[] = { rvc_imm_eq_n1, rvc_end };
601 static const rvc_constraint rvcc_neg[] = { rvc_rs1_eq_x0, rvc_end };
602 static const rvc_constraint rvcc_negw[] = { rvc_rs1_eq_x0, rvc_end };
603 static const rvc_constraint rvcc_sext_w[] = { rvc_rs2_eq_x0, rvc_end };
604 static const rvc_constraint rvcc_seqz[] = { rvc_imm_eq_p1, rvc_end };
605 static const rvc_constraint rvcc_snez[] = { rvc_rs1_eq_x0, rvc_end };
606 static const rvc_constraint rvcc_sltz[] = { rvc_rs2_eq_x0, rvc_end };
607 static const rvc_constraint rvcc_sgtz[] = { rvc_rs1_eq_x0, rvc_end };
608 static const rvc_constraint rvcc_fmv_s[] = { rvc_rs2_eq_rs1, rvc_end };
609 static const rvc_constraint rvcc_fabs_s[] = { rvc_rs2_eq_rs1, rvc_end };
610 static const rvc_constraint rvcc_fneg_s[] = { rvc_rs2_eq_rs1, rvc_end };
611 static const rvc_constraint rvcc_fmv_d[] = { rvc_rs2_eq_rs1, rvc_end };
612 static const rvc_constraint rvcc_fabs_d[] = { rvc_rs2_eq_rs1, rvc_end };
613 static const rvc_constraint rvcc_fneg_d[] = { rvc_rs2_eq_rs1, rvc_end };
614 static const rvc_constraint rvcc_fmv_q[] = { rvc_rs2_eq_rs1, rvc_end };
615 static const rvc_constraint rvcc_fabs_q[] = { rvc_rs2_eq_rs1, rvc_end };
616 static const rvc_constraint rvcc_fneg_q[] = { rvc_rs2_eq_rs1, rvc_end };
617 static const rvc_constraint rvcc_beqz[] = { rvc_rs2_eq_x0, rvc_end };
618 static const rvc_constraint rvcc_bnez[] = { rvc_rs2_eq_x0, rvc_end };
619 static const rvc_constraint rvcc_blez[] = { rvc_rs1_eq_x0, rvc_end };
620 static const rvc_constraint rvcc_bgez[] = { rvc_rs2_eq_x0, rvc_end };
621 static const rvc_constraint rvcc_bltz[] = { rvc_rs2_eq_x0, rvc_end };
622 static const rvc_constraint rvcc_bgtz[] = { rvc_rs1_eq_x0, rvc_end };
623 static const rvc_constraint rvcc_ble[] = { rvc_end };
624 static const rvc_constraint rvcc_bleu[] = { rvc_end };
625 static const rvc_constraint rvcc_bgt[] = { rvc_end };
626 static const rvc_constraint rvcc_bgtu[] = { rvc_end };
627 static const rvc_constraint rvcc_j[] = { rvc_rd_eq_x0, rvc_end };
628 static const rvc_constraint rvcc_ret[] = { rvc_rd_eq_x0, rvc_rs1_eq_ra, rvc_end };
629 static const rvc_constraint rvcc_jr[] = { rvc_rd_eq_x0, rvc_imm_eq_zero, rvc_end };
630 static const rvc_constraint rvcc_rdcycle[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc00, rvc_end };
631 static const rvc_constraint rvcc_rdtime[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc01, rvc_end };
632 static const rvc_constraint rvcc_rdinstret[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc02, rvc_end };
633 static const rvc_constraint rvcc_rdcycleh[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc80, rvc_end };
634 static const rvc_constraint rvcc_rdtimeh[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc81, rvc_end };
635 static const rvc_constraint rvcc_rdinstreth[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc80, rvc_end };
636 static const rvc_constraint rvcc_frcsr[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x003, rvc_end };
637 static const rvc_constraint rvcc_frrm[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x002, rvc_end };
638 static const rvc_constraint rvcc_frflags[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x001, rvc_end };
639 static const rvc_constraint rvcc_fscsr[] = { rvc_csr_eq_0x003, rvc_end };
640 static const rvc_constraint rvcc_fsrm[] = { rvc_csr_eq_0x002, rvc_end };
641 static const rvc_constraint rvcc_fsflags[] = { rvc_csr_eq_0x001, rvc_end };
642 static const rvc_constraint rvcc_fsrmi[] = { rvc_csr_eq_0x002, rvc_end };
643 static const rvc_constraint rvcc_fsflagsi[] = { rvc_csr_eq_0x001, rvc_end };
645 /* pseudo-instruction metadata */
647 static const rv_comp_data rvcp_jal[] = {
649 { rv_op_jal, rvcc_jal },
650 { rv_op_illegal, NULL }
653 static const rv_comp_data rvcp_jalr[] = {
654 { rv_op_ret, rvcc_ret },
655 { rv_op_jr, rvcc_jr },
656 { rv_op_jalr, rvcc_jalr },
657 { rv_op_illegal, NULL }
660 static const rv_comp_data rvcp_beq[] = {
661 { rv_op_beqz, rvcc_beqz },
662 { rv_op_illegal, NULL }
665 static const rv_comp_data rvcp_bne[] = {
666 { rv_op_bnez, rvcc_bnez },
667 { rv_op_illegal, NULL }
670 static const rv_comp_data rvcp_blt[] = {
671 { rv_op_bltz, rvcc_bltz },
672 { rv_op_bgtz, rvcc_bgtz },
673 { rv_op_bgt, rvcc_bgt },
674 { rv_op_illegal, NULL }
677 static const rv_comp_data rvcp_bge[] = {
678 { rv_op_blez, rvcc_blez },
679 { rv_op_bgez, rvcc_bgez },
680 { rv_op_ble, rvcc_ble },
681 { rv_op_illegal, NULL }
684 static const rv_comp_data rvcp_bltu[] = {
685 { rv_op_bgtu, rvcc_bgtu },
686 { rv_op_illegal, NULL }
689 static const rv_comp_data rvcp_bgeu[] = {
690 { rv_op_bleu, rvcc_bleu },
691 { rv_op_illegal, NULL }
694 static const rv_comp_data rvcp_addi[] = {
695 { rv_op_nop, rvcc_nop },
696 { rv_op_mv, rvcc_mv },
697 { rv_op_illegal, NULL }
700 static const rv_comp_data rvcp_sltiu[] = {
701 { rv_op_seqz, rvcc_seqz },
702 { rv_op_illegal, NULL }
705 static const rv_comp_data rvcp_xori[] = {
706 { rv_op_not, rvcc_not },
707 { rv_op_illegal, NULL }
710 static const rv_comp_data rvcp_sub[] = {
711 { rv_op_neg, rvcc_neg },
712 { rv_op_illegal, NULL }
715 static const rv_comp_data rvcp_slt[] = {
716 { rv_op_sltz, rvcc_sltz },
717 { rv_op_sgtz, rvcc_sgtz },
718 { rv_op_illegal, NULL }
721 static const rv_comp_data rvcp_sltu[] = {
722 { rv_op_snez, rvcc_snez },
723 { rv_op_illegal, NULL }
726 static const rv_comp_data rvcp_addiw[] = {
727 { rv_op_sext_w, rvcc_sext_w },
728 { rv_op_illegal, NULL }
731 static const rv_comp_data rvcp_subw[] = {
732 { rv_op_negw, rvcc_negw },
733 { rv_op_illegal, NULL }
736 static const rv_comp_data rvcp_csrrw[] = {
737 { rv_op_fscsr, rvcc_fscsr },
738 { rv_op_fsrm, rvcc_fsrm },
739 { rv_op_fsflags, rvcc_fsflags },
740 { rv_op_illegal, NULL }
743 static const rv_comp_data rvcp_csrrs[] = {
744 { rv_op_rdcycle, rvcc_rdcycle },
745 { rv_op_rdtime, rvcc_rdtime },
746 { rv_op_rdinstret, rvcc_rdinstret },
747 { rv_op_rdcycleh, rvcc_rdcycleh },
748 { rv_op_rdtimeh, rvcc_rdtimeh },
749 { rv_op_rdinstreth, rvcc_rdinstreth },
750 { rv_op_frcsr, rvcc_frcsr },
751 { rv_op_frrm, rvcc_frrm },
752 { rv_op_frflags, rvcc_frflags },
753 { rv_op_illegal, NULL }
756 static const rv_comp_data rvcp_csrrwi[] = {
757 { rv_op_fsrmi, rvcc_fsrmi },
758 { rv_op_fsflagsi, rvcc_fsflagsi },
759 { rv_op_illegal, NULL }
762 static const rv_comp_data rvcp_fsgnj_s[] = {
763 { rv_op_fmv_s, rvcc_fmv_s },
764 { rv_op_illegal, NULL }
767 static const rv_comp_data rvcp_fsgnjn_s[] = {
768 { rv_op_fneg_s, rvcc_fneg_s },
769 { rv_op_illegal, NULL }
772 static const rv_comp_data rvcp_fsgnjx_s[] = {
773 { rv_op_fabs_s, rvcc_fabs_s },
774 { rv_op_illegal, NULL }
777 static const rv_comp_data rvcp_fsgnj_d[] = {
778 { rv_op_fmv_d, rvcc_fmv_d },
779 { rv_op_illegal, NULL }
782 static const rv_comp_data rvcp_fsgnjn_d[] = {
783 { rv_op_fneg_d, rvcc_fneg_d },
784 { rv_op_illegal, NULL }
787 static const rv_comp_data rvcp_fsgnjx_d[] = {
788 { rv_op_fabs_d, rvcc_fabs_d },
789 { rv_op_illegal, NULL }
792 static const rv_comp_data rvcp_fsgnj_q[] = {
793 { rv_op_fmv_q, rvcc_fmv_q },
794 { rv_op_illegal, NULL }
797 static const rv_comp_data rvcp_fsgnjn_q[] = {
798 { rv_op_fneg_q, rvcc_fneg_q },
799 { rv_op_illegal, NULL }
802 static const rv_comp_data rvcp_fsgnjx_q[] = {
803 { rv_op_fabs_q, rvcc_fabs_q },
804 { rv_op_illegal, NULL }
807 /* instruction metadata */
809 const rv_opcode_data opcode_data[] = {
810 { "illegal", rv_codec_illegal, rv_fmt_none, NULL, 0, 0, 0 },
811 { "lui", rv_codec_u, rv_fmt_rd_imm, NULL, 0, 0, 0 },
812 { "auipc", rv_codec_u, rv_fmt_rd_offset, NULL, 0, 0, 0 },
813 { "jal", rv_codec_uj, rv_fmt_rd_offset, rvcp_jal, 0, 0, 0 },
814 { "jalr", rv_codec_i, rv_fmt_rd_rs1_offset, rvcp_jalr, 0, 0, 0 },
815 { "beq", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_beq, 0, 0, 0 },
816 { "bne", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bne, 0, 0, 0 },
817 { "blt", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_blt, 0, 0, 0 },
818 { "bge", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bge, 0, 0, 0 },
819 { "bltu", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bltu, 0, 0, 0 },
820 { "bgeu", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bgeu, 0, 0, 0 },
821 { "lb", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
822 { "lh", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
823 { "lw", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
824 { "lbu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
825 { "lhu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
826 { "sb", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
827 { "sh", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
828 { "sw", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
829 { "addi", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_addi, 0, 0, 0 },
830 { "slti", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
831 { "sltiu", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_sltiu, 0, 0, 0 },
832 { "xori", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_xori, 0, 0, 0 },
833 { "ori", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
834 { "andi", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
835 { "slli", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
836 { "srli", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
837 { "srai", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
838 { "add", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
839 { "sub", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_sub, 0, 0, 0 },
840 { "sll", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
841 { "slt", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_slt, 0, 0, 0 },
842 { "sltu", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_sltu, 0, 0, 0 },
843 { "xor", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
844 { "srl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
845 { "sra", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
846 { "or", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
847 { "and", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
848 { "fence", rv_codec_r_f, rv_fmt_pred_succ, NULL, 0, 0, 0 },
849 { "fence.i", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
850 { "lwu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
851 { "ld", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
852 { "sd", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
853 { "addiw", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_addiw, 0, 0, 0 },
854 { "slliw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
855 { "srliw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
856 { "sraiw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
857 { "addw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
858 { "subw", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_subw, 0, 0, 0 },
859 { "sllw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
860 { "srlw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
861 { "sraw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
862 { "ldu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
863 { "lq", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 },
864 { "sq", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 },
865 { "addid", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
866 { "sllid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
867 { "srlid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
868 { "sraid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 },
869 { "addd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
870 { "subd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
871 { "slld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
872 { "srld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
873 { "srad", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
874 { "mul", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
875 { "mulh", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
876 { "mulhsu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
877 { "mulhu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
878 { "div", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
879 { "divu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
880 { "rem", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
881 { "remu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
882 { "mulw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
883 { "divw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
884 { "divuw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
885 { "remw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
886 { "remuw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
887 { "muld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
888 { "divd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
889 { "divud", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
890 { "remd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
891 { "remud", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
892 { "lr.w", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 },
893 { "sc.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
894 { "amoswap.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
895 { "amoadd.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
896 { "amoxor.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
897 { "amoor.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
898 { "amoand.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
899 { "amomin.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
900 { "amomax.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
901 { "amominu.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
902 { "amomaxu.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
903 { "lr.d", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 },
904 { "sc.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
905 { "amoswap.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
906 { "amoadd.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
907 { "amoxor.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
908 { "amoor.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
909 { "amoand.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
910 { "amomin.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
911 { "amomax.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
912 { "amominu.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
913 { "amomaxu.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
914 { "lr.q", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 },
915 { "sc.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
916 { "amoswap.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
917 { "amoadd.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
918 { "amoxor.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
919 { "amoor.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
920 { "amoand.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
921 { "amomin.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
922 { "amomax.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
923 { "amominu.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
924 { "amomaxu.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
925 { "ecall", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
926 { "ebreak", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
927 { "uret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
928 { "sret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
929 { "hret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
930 { "mret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
931 { "dret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
932 { "sfence.vm", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 },
933 { "sfence.vma", rv_codec_r, rv_fmt_rs1_rs2, NULL, 0, 0, 0 },
934 { "wfi", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
935 { "csrrw", rv_codec_i_csr, rv_fmt_rd_csr_rs1, rvcp_csrrw, 0, 0, 0 },
936 { "csrrs", rv_codec_i_csr, rv_fmt_rd_csr_rs1, rvcp_csrrs, 0, 0, 0 },
937 { "csrrc", rv_codec_i_csr, rv_fmt_rd_csr_rs1, NULL, 0, 0, 0 },
938 { "csrrwi", rv_codec_i_csr, rv_fmt_rd_csr_zimm, rvcp_csrrwi, 0, 0, 0 },
939 { "csrrsi", rv_codec_i_csr, rv_fmt_rd_csr_zimm, NULL, 0, 0, 0 },
940 { "csrrci", rv_codec_i_csr, rv_fmt_rd_csr_zimm, NULL, 0, 0, 0 },
941 { "flw", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 },
942 { "fsw", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 },
943 { "fmadd.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
944 { "fmsub.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
945 { "fnmsub.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
946 { "fnmadd.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
947 { "fadd.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
948 { "fsub.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
949 { "fmul.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
950 { "fdiv.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
951 { "fsgnj.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_s, 0, 0, 0 },
952 { "fsgnjn.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_s, 0, 0, 0 },
953 { "fsgnjx.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_s, 0, 0, 0 },
954 { "fmin.s", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
955 { "fmax.s", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
956 { "fsqrt.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
957 { "fle.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
958 { "flt.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
959 { "feq.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
960 { "fcvt.w.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
961 { "fcvt.wu.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
962 { "fcvt.s.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
963 { "fcvt.s.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
964 { "fmv.x.s", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
965 { "fclass.s", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
966 { "fmv.s.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 },
967 { "fcvt.l.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
968 { "fcvt.lu.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
969 { "fcvt.s.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
970 { "fcvt.s.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
971 { "fld", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 },
972 { "fsd", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 },
973 { "fmadd.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
974 { "fmsub.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
975 { "fnmsub.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
976 { "fnmadd.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
977 { "fadd.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
978 { "fsub.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
979 { "fmul.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
980 { "fdiv.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
981 { "fsgnj.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_d, 0, 0, 0 },
982 { "fsgnjn.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_d, 0, 0, 0 },
983 { "fsgnjx.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_d, 0, 0, 0 },
984 { "fmin.d", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
985 { "fmax.d", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
986 { "fcvt.s.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
987 { "fcvt.d.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
988 { "fsqrt.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
989 { "fle.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
990 { "flt.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
991 { "feq.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
992 { "fcvt.w.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
993 { "fcvt.wu.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
994 { "fcvt.d.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
995 { "fcvt.d.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
996 { "fclass.d", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
997 { "fcvt.l.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
998 { "fcvt.lu.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
999 { "fmv.x.d", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
1000 { "fcvt.d.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1001 { "fcvt.d.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1002 { "fmv.d.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 },
1003 { "flq", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 },
1004 { "fsq", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 },
1005 { "fmadd.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
1006 { "fmsub.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
1007 { "fnmsub.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
1008 { "fnmadd.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 },
1009 { "fadd.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
1010 { "fsub.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
1011 { "fmul.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
1012 { "fdiv.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 },
1013 { "fsgnj.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_q, 0, 0, 0 },
1014 { "fsgnjn.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_q, 0, 0, 0 },
1015 { "fsgnjx.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_q, 0, 0, 0 },
1016 { "fmin.q", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
1017 { "fmax.q", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 },
1018 { "fcvt.s.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1019 { "fcvt.q.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1020 { "fcvt.d.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1021 { "fcvt.q.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1022 { "fsqrt.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 },
1023 { "fle.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
1024 { "flt.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
1025 { "feq.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 },
1026 { "fcvt.w.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1027 { "fcvt.wu.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1028 { "fcvt.q.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1029 { "fcvt.q.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1030 { "fclass.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
1031 { "fcvt.l.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1032 { "fcvt.lu.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 },
1033 { "fcvt.q.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1034 { "fcvt.q.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 },
1035 { "fmv.x.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 },
1036 { "fmv.q.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 },
1037 { "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1038 { "c.fld", rv_codec_cl_ld, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, 0 },
1039 { "c.lw", rv_codec_cl_lw, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw },
1040 { "c.flw", rv_codec_cl_lw, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 },
1041 { "c.fsd", rv_codec_cs_sd, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, rv_op_fsd, 0 },
1042 { "c.sw", rv_codec_cs_sw, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw },
1043 { "c.fsw", rv_codec_cs_sw, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 },
1044 { "c.nop", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1045 { "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1046 { "c.jal", rv_codec_cj_jal, rv_fmt_rd_offset, NULL, rv_op_jal, 0, 0 },
1047 { "c.li", rv_codec_ci_li, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1048 { "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1049 { "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui, rv_op_lui },
1050 { "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli, rv_op_srli, rv_op_srli },
1051 { "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai, rv_op_srai, rv_op_srai },
1052 { "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi, rv_op_andi, rv_op_andi },
1053 { "c.sub", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_sub, rv_op_sub, rv_op_sub },
1054 { "c.xor", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_xor, rv_op_xor, rv_op_xor },
1055 { "c.or", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_or, rv_op_or, rv_op_or },
1056 { "c.and", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_and, rv_op_and, rv_op_and },
1057 { "c.subw", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_subw, rv_op_subw, rv_op_subw },
1058 { "c.addw", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_addw, rv_op_addw, rv_op_addw },
1059 { "c.j", rv_codec_cj, rv_fmt_rd_offset, NULL, rv_op_jal, rv_op_jal, rv_op_jal },
1060 { "c.beqz", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_beq, rv_op_beq, rv_op_beq },
1061 { "c.bnez", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_bne, rv_op_bne, rv_op_bne },
1062 { "c.slli", rv_codec_ci_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_slli, rv_op_slli, rv_op_slli },
1063 { "c.fldsp", rv_codec_ci_ldsp, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, rv_op_fld },
1064 { "c.lwsp", rv_codec_ci_lwsp, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw },
1065 { "c.flwsp", rv_codec_ci_lwsp, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 },
1066 { "c.jr", rv_codec_cr_jr, rv_fmt_rd_rs1_offset, NULL, rv_op_jalr, rv_op_jalr, rv_op_jalr },
1067 { "c.mv", rv_codec_cr_mv, rv_fmt_rd_rs1_rs2, NULL, rv_op_addi, rv_op_addi, rv_op_addi },
1068 { "c.ebreak", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_ebreak, rv_op_ebreak, rv_op_ebreak },
1069 { "c.jalr", rv_codec_cr_jalr, rv_fmt_rd_rs1_offset, NULL, rv_op_jalr, rv_op_jalr, rv_op_jalr },
1070 { "c.add", rv_codec_cr, rv_fmt_rd_rs1_rs2, NULL, rv_op_add, rv_op_add, rv_op_add },
1071 { "c.fsdsp", rv_codec_css_sdsp, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, rv_op_fsd, rv_op_fsd },
1072 { "c.swsp", rv_codec_css_swsp, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw },
1073 { "c.fswsp", rv_codec_css_swsp, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 },
1074 { "c.ld", rv_codec_cl_ld, rv_fmt_rd_offset_rs1, NULL, 0, rv_op_ld, rv_op_ld },
1075 { "c.sd", rv_codec_cs_sd, rv_fmt_rs2_offset_rs1, NULL, 0, rv_op_sd, rv_op_sd },
1076 { "c.addiw", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, 0, rv_op_addiw, rv_op_addiw },
1077 { "c.ldsp", rv_codec_ci_ldsp, rv_fmt_rd_offset_rs1, NULL, 0, rv_op_ld, rv_op_ld },
1078 { "c.sdsp", rv_codec_css_sdsp, rv_fmt_rs2_offset_rs1, NULL, 0, rv_op_sd, rv_op_sd },
1079 { "c.lq", rv_codec_cl_lq, rv_fmt_rd_offset_rs1, NULL, 0, 0, rv_op_lq },
1080 { "c.sq", rv_codec_cs_sq, rv_fmt_rs2_offset_rs1, NULL, 0, 0, rv_op_sq },
1081 { "c.lqsp", rv_codec_ci_lqsp, rv_fmt_rd_offset_rs1, NULL, 0, 0, rv_op_lq },
1082 { "c.sqsp", rv_codec_css_sqsp, rv_fmt_rs2_offset_rs1, NULL, 0, 0, rv_op_sq },
1083 { "nop", rv_codec_i, rv_fmt_none, NULL, 0, 0, 0 },
1084 { "mv", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1085 { "not", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1086 { "neg", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1087 { "negw", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1088 { "sext.w", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1089 { "seqz", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1090 { "snez", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1091 { "sltz", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1092 { "sgtz", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 },
1093 { "fmv.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1094 { "fabs.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1095 { "fneg.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1096 { "fmv.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1097 { "fabs.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1098 { "fneg.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1099 { "fmv.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1100 { "fabs.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1101 { "fneg.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1102 { "beqz", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1103 { "bnez", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1104 { "blez", rv_codec_sb, rv_fmt_rs2_offset, NULL, 0, 0, 0 },
1105 { "bgez", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1106 { "bltz", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 },
1107 { "bgtz", rv_codec_sb, rv_fmt_rs2_offset, NULL, 0, 0, 0 },
1108 { "ble", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1109 { "bleu", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1110 { "bgt", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1111 { "bgtu", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 },
1112 { "j", rv_codec_uj, rv_fmt_offset, NULL, 0, 0, 0 },
1113 { "ret", rv_codec_i, rv_fmt_none, NULL, 0, 0, 0 },
1114 { "jr", rv_codec_i, rv_fmt_rs1, NULL, 0, 0, 0 },
1115 { "rdcycle", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1116 { "rdtime", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1117 { "rdinstret", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1118 { "rdcycleh", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1119 { "rdtimeh", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1120 { "rdinstreth", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1121 { "frcsr", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1122 { "frrm", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1123 { "frflags", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 },
1124 { "fscsr", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1125 { "fsrm", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1126 { "fsflags", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 },
1127 { "fsrmi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 },
1128 { "fsflagsi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 },
1133 static const char *csr_name(int csrno)
1136 case 0x0000: return "ustatus";
1137 case 0x0001: return "fflags";
1138 case 0x0002: return "frm";
1139 case 0x0003: return "fcsr";
1140 case 0x0004: return "uie";
1141 case 0x0005: return "utvec";
1142 case 0x0040: return "uscratch";
1143 case 0x0041: return "uepc";
1144 case 0x0042: return "ucause";
1145 case 0x0043: return "utval";
1146 case 0x0044: return "uip";
1147 case 0x0100: return "sstatus";
1148 case 0x0102: return "sedeleg";
1149 case 0x0103: return "sideleg";
1150 case 0x0104: return "sie";
1151 case 0x0105: return "stvec";
1152 case 0x0106: return "scounteren";
1153 case 0x0140: return "sscratch";
1154 case 0x0141: return "sepc";
1155 case 0x0142: return "scause";
1156 case 0x0143: return "stval";
1157 case 0x0144: return "sip";
1158 case 0x0180: return "satp";
1159 case 0x0200: return "hstatus";
1160 case 0x0202: return "hedeleg";
1161 case 0x0203: return "hideleg";
1162 case 0x0204: return "hie";
1163 case 0x0205: return "htvec";
1164 case 0x0240: return "hscratch";
1165 case 0x0241: return "hepc";
1166 case 0x0242: return "hcause";
1167 case 0x0243: return "hbadaddr";
1168 case 0x0244: return "hip";
1169 case 0x0300: return "mstatus";
1170 case 0x0301: return "misa";
1171 case 0x0302: return "medeleg";
1172 case 0x0303: return "mideleg";
1173 case 0x0304: return "mie";
1174 case 0x0305: return "mtvec";
1175 case 0x0306: return "mcounteren";
1176 case 0x0320: return "mucounteren";
1177 case 0x0321: return "mscounteren";
1178 case 0x0322: return "mhcounteren";
1179 case 0x0323: return "mhpmevent3";
1180 case 0x0324: return "mhpmevent4";
1181 case 0x0325: return "mhpmevent5";
1182 case 0x0326: return "mhpmevent6";
1183 case 0x0327: return "mhpmevent7";
1184 case 0x0328: return "mhpmevent8";
1185 case 0x0329: return "mhpmevent9";
1186 case 0x032a: return "mhpmevent10";
1187 case 0x032b: return "mhpmevent11";
1188 case 0x032c: return "mhpmevent12";
1189 case 0x032d: return "mhpmevent13";
1190 case 0x032e: return "mhpmevent14";
1191 case 0x032f: return "mhpmevent15";
1192 case 0x0330: return "mhpmevent16";
1193 case 0x0331: return "mhpmevent17";
1194 case 0x0332: return "mhpmevent18";
1195 case 0x0333: return "mhpmevent19";
1196 case 0x0334: return "mhpmevent20";
1197 case 0x0335: return "mhpmevent21";
1198 case 0x0336: return "mhpmevent22";
1199 case 0x0337: return "mhpmevent23";
1200 case 0x0338: return "mhpmevent24";
1201 case 0x0339: return "mhpmevent25";
1202 case 0x033a: return "mhpmevent26";
1203 case 0x033b: return "mhpmevent27";
1204 case 0x033c: return "mhpmevent28";
1205 case 0x033d: return "mhpmevent29";
1206 case 0x033e: return "mhpmevent30";
1207 case 0x033f: return "mhpmevent31";
1208 case 0x0340: return "mscratch";
1209 case 0x0341: return "mepc";
1210 case 0x0342: return "mcause";
1211 case 0x0343: return "mtval";
1212 case 0x0344: return "mip";
1213 case 0x0380: return "mbase";
1214 case 0x0381: return "mbound";
1215 case 0x0382: return "mibase";
1216 case 0x0383: return "mibound";
1217 case 0x0384: return "mdbase";
1218 case 0x0385: return "mdbound";
1219 case 0x03a0: return "pmpcfg3";
1220 case 0x03b0: return "pmpaddr0";
1221 case 0x03b1: return "pmpaddr1";
1222 case 0x03b2: return "pmpaddr2";
1223 case 0x03b3: return "pmpaddr3";
1224 case 0x03b4: return "pmpaddr4";
1225 case 0x03b5: return "pmpaddr5";
1226 case 0x03b6: return "pmpaddr6";
1227 case 0x03b7: return "pmpaddr7";
1228 case 0x03b8: return "pmpaddr8";
1229 case 0x03b9: return "pmpaddr9";
1230 case 0x03ba: return "pmpaddr10";
1231 case 0x03bb: return "pmpaddr11";
1232 case 0x03bc: return "pmpaddr12";
1233 case 0x03bd: return "pmpaddr14";
1234 case 0x03be: return "pmpaddr13";
1235 case 0x03bf: return "pmpaddr15";
1236 case 0x0780: return "mtohost";
1237 case 0x0781: return "mfromhost";
1238 case 0x0782: return "mreset";
1239 case 0x0783: return "mipi";
1240 case 0x0784: return "miobase";
1241 case 0x07a0: return "tselect";
1242 case 0x07a1: return "tdata1";
1243 case 0x07a2: return "tdata2";
1244 case 0x07a3: return "tdata3";
1245 case 0x07b0: return "dcsr";
1246 case 0x07b1: return "dpc";
1247 case 0x07b2: return "dscratch";
1248 case 0x0b00: return "mcycle";
1249 case 0x0b01: return "mtime";
1250 case 0x0b02: return "minstret";
1251 case 0x0b03: return "mhpmcounter3";
1252 case 0x0b04: return "mhpmcounter4";
1253 case 0x0b05: return "mhpmcounter5";
1254 case 0x0b06: return "mhpmcounter6";
1255 case 0x0b07: return "mhpmcounter7";
1256 case 0x0b08: return "mhpmcounter8";
1257 case 0x0b09: return "mhpmcounter9";
1258 case 0x0b0a: return "mhpmcounter10";
1259 case 0x0b0b: return "mhpmcounter11";
1260 case 0x0b0c: return "mhpmcounter12";
1261 case 0x0b0d: return "mhpmcounter13";
1262 case 0x0b0e: return "mhpmcounter14";
1263 case 0x0b0f: return "mhpmcounter15";
1264 case 0x0b10: return "mhpmcounter16";
1265 case 0x0b11: return "mhpmcounter17";
1266 case 0x0b12: return "mhpmcounter18";
1267 case 0x0b13: return "mhpmcounter19";
1268 case 0x0b14: return "mhpmcounter20";
1269 case 0x0b15: return "mhpmcounter21";
1270 case 0x0b16: return "mhpmcounter22";
1271 case 0x0b17: return "mhpmcounter23";
1272 case 0x0b18: return "mhpmcounter24";
1273 case 0x0b19: return "mhpmcounter25";
1274 case 0x0b1a: return "mhpmcounter26";
1275 case 0x0b1b: return "mhpmcounter27";
1276 case 0x0b1c: return "mhpmcounter28";
1277 case 0x0b1d: return "mhpmcounter29";
1278 case 0x0b1e: return "mhpmcounter30";
1279 case 0x0b1f: return "mhpmcounter31";
1280 case 0x0b80: return "mcycleh";
1281 case 0x0b81: return "mtimeh";
1282 case 0x0b82: return "minstreth";
1283 case 0x0b83: return "mhpmcounter3h";
1284 case 0x0b84: return "mhpmcounter4h";
1285 case 0x0b85: return "mhpmcounter5h";
1286 case 0x0b86: return "mhpmcounter6h";
1287 case 0x0b87: return "mhpmcounter7h";
1288 case 0x0b88: return "mhpmcounter8h";
1289 case 0x0b89: return "mhpmcounter9h";
1290 case 0x0b8a: return "mhpmcounter10h";
1291 case 0x0b8b: return "mhpmcounter11h";
1292 case 0x0b8c: return "mhpmcounter12h";
1293 case 0x0b8d: return "mhpmcounter13h";
1294 case 0x0b8e: return "mhpmcounter14h";
1295 case 0x0b8f: return "mhpmcounter15h";
1296 case 0x0b90: return "mhpmcounter16h";
1297 case 0x0b91: return "mhpmcounter17h";
1298 case 0x0b92: return "mhpmcounter18h";
1299 case 0x0b93: return "mhpmcounter19h";
1300 case 0x0b94: return "mhpmcounter20h";
1301 case 0x0b95: return "mhpmcounter21h";
1302 case 0x0b96: return "mhpmcounter22h";
1303 case 0x0b97: return "mhpmcounter23h";
1304 case 0x0b98: return "mhpmcounter24h";
1305 case 0x0b99: return "mhpmcounter25h";
1306 case 0x0b9a: return "mhpmcounter26h";
1307 case 0x0b9b: return "mhpmcounter27h";
1308 case 0x0b9c: return "mhpmcounter28h";
1309 case 0x0b9d: return "mhpmcounter29h";
1310 case 0x0b9e: return "mhpmcounter30h";
1311 case 0x0b9f: return "mhpmcounter31h";
1312 case 0x0c00: return "cycle";
1313 case 0x0c01: return "time";
1314 case 0x0c02: return "instret";
1315 case 0x0c80: return "cycleh";
1316 case 0x0c81: return "timeh";
1317 case 0x0c82: return "instreth";
1318 case 0x0d00: return "scycle";
1319 case 0x0d01: return "stime";
1320 case 0x0d02: return "sinstret";
1321 case 0x0d80: return "scycleh";
1322 case 0x0d81: return "stimeh";
1323 case 0x0d82: return "sinstreth";
1324 case 0x0e00: return "hcycle";
1325 case 0x0e01: return "htime";
1326 case 0x0e02: return "hinstret";
1327 case 0x0e80: return "hcycleh";
1328 case 0x0e81: return "htimeh";
1329 case 0x0e82: return "hinstreth";
1330 case 0x0f11: return "mvendorid";
1331 case 0x0f12: return "marchid";
1332 case 0x0f13: return "mimpid";
1333 case 0x0f14: return "mhartid";
1334 default: return NULL;
1340 static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
1342 rv_inst inst = dec->inst;
1343 rv_opcode op = rv_op_illegal;
1344 switch (((inst >> 0) & 0b11)) {
1346 switch (((inst >> 13) & 0b111)) {
1347 case 0: op = rv_op_c_addi4spn; break;
1355 case 2: op = rv_op_c_lw; break;
1370 case 6: op = rv_op_c_sw; break;
1381 switch (((inst >> 13) & 0b111)) {
1383 switch (((inst >> 2) & 0b11111111111)) {
1384 case 0: op = rv_op_c_nop; break;
1385 default: op = rv_op_c_addi; break;
1395 case 2: op = rv_op_c_li; break;
1397 switch (((inst >> 7) & 0b11111)) {
1398 case 2: op = rv_op_c_addi16sp; break;
1399 default: op = rv_op_c_lui; break;
1403 switch (((inst >> 10) & 0b11)) {
1410 case 2: op = rv_op_c_andi; break;
1412 switch (((inst >> 10) & 0b100) | ((inst >> 5) & 0b011)) {
1413 case 0: op = rv_op_c_sub; break;
1414 case 1: op = rv_op_c_xor; break;
1415 case 2: op = rv_op_c_or; break;
1416 case 3: op = rv_op_c_and; break;
1417 case 4: op = rv_op_c_subw; break;
1418 case 5: op = rv_op_c_addw; break;
1423 case 5: op = rv_op_c_j; break;
1424 case 6: op = rv_op_c_beqz; break;
1425 case 7: op = rv_op_c_bnez; break;
1429 switch (((inst >> 13) & 0b111)) {
1440 case 2: op = rv_op_c_lwsp; break;
1449 switch (((inst >> 12) & 0b1)) {
1451 switch (((inst >> 2) & 0b11111)) {
1452 case 0: op = rv_op_c_jr; break;
1453 default: op = rv_op_c_mv; break;
1457 switch (((inst >> 2) & 0b11111)) {
1459 switch (((inst >> 7) & 0b11111)) {
1460 case 0: op = rv_op_c_ebreak; break;
1461 default: op = rv_op_c_jalr; break;
1464 default: op = rv_op_c_add; break;
1473 op = rv_op_c_fsdsp; break;
1475 case 6: op = rv_op_c_swsp; break;
1486 switch (((inst >> 2) & 0b11111)) {
1488 switch (((inst >> 12) & 0b111)) {
1489 case 0: op = rv_op_lb; break;
1490 case 1: op = rv_op_lh; break;
1491 case 2: op = rv_op_lw; break;
1492 case 3: op = rv_op_ld; break;
1493 case 4: op = rv_op_lbu; break;
1494 case 5: op = rv_op_lhu; break;
1495 case 6: op = rv_op_lwu; break;
1496 case 7: op = rv_op_ldu; break;
1500 switch (((inst >> 12) & 0b111)) {
1501 case 2: op = rv_op_flw; break;
1502 case 3: op = rv_op_fld; break;
1503 case 4: op = rv_op_flq; break;
1507 switch (((inst >> 12) & 0b111)) {
1508 case 0: op = rv_op_fence; break;
1509 case 1: op = rv_op_fence_i; break;
1510 case 2: op = rv_op_lq; break;
1514 switch (((inst >> 12) & 0b111)) {
1515 case 0: op = rv_op_addi; break;
1517 switch (((inst >> 27) & 0b11111)) {
1518 case 0: op = rv_op_slli; break;
1521 case 2: op = rv_op_slti; break;
1522 case 3: op = rv_op_sltiu; break;
1523 case 4: op = rv_op_xori; break;
1525 switch (((inst >> 27) & 0b11111)) {
1526 case 0: op = rv_op_srli; break;
1527 case 8: op = rv_op_srai; break;
1530 case 6: op = rv_op_ori; break;
1531 case 7: op = rv_op_andi; break;
1534 case 5: op = rv_op_auipc; break;
1536 switch (((inst >> 12) & 0b111)) {
1537 case 0: op = rv_op_addiw; break;
1539 switch (((inst >> 25) & 0b1111111)) {
1540 case 0: op = rv_op_slliw; break;
1544 switch (((inst >> 25) & 0b1111111)) {
1545 case 0: op = rv_op_srliw; break;
1546 case 32: op = rv_op_sraiw; break;
1552 switch (((inst >> 12) & 0b111)) {
1553 case 0: op = rv_op_sb; break;
1554 case 1: op = rv_op_sh; break;
1555 case 2: op = rv_op_sw; break;
1556 case 3: op = rv_op_sd; break;
1557 case 4: op = rv_op_sq; break;
1561 switch (((inst >> 12) & 0b111)) {
1562 case 2: op = rv_op_fsw; break;
1563 case 3: op = rv_op_fsd; break;
1564 case 4: op = rv_op_fsq; break;
1568 switch (((inst >> 24) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1569 case 2: op = rv_op_amoadd_w; break;
1570 case 3: op = rv_op_amoadd_d; break;
1571 case 4: op = rv_op_amoadd_q; break;
1572 case 10: op = rv_op_amoswap_w; break;
1573 case 11: op = rv_op_amoswap_d; break;
1574 case 12: op = rv_op_amoswap_q; break;
1576 switch (((inst >> 20) & 0b11111)) {
1577 case 0: op = rv_op_lr_w; break;
1581 switch (((inst >> 20) & 0b11111)) {
1582 case 0: op = rv_op_lr_d; break;
1586 switch (((inst >> 20) & 0b11111)) {
1587 case 0: op = rv_op_lr_q; break;
1590 case 26: op = rv_op_sc_w; break;
1591 case 27: op = rv_op_sc_d; break;
1592 case 28: op = rv_op_sc_q; break;
1593 case 34: op = rv_op_amoxor_w; break;
1594 case 35: op = rv_op_amoxor_d; break;
1595 case 36: op = rv_op_amoxor_q; break;
1596 case 66: op = rv_op_amoor_w; break;
1597 case 67: op = rv_op_amoor_d; break;
1598 case 68: op = rv_op_amoor_q; break;
1599 case 98: op = rv_op_amoand_w; break;
1600 case 99: op = rv_op_amoand_d; break;
1601 case 100: op = rv_op_amoand_q; break;
1602 case 130: op = rv_op_amomin_w; break;
1603 case 131: op = rv_op_amomin_d; break;
1604 case 132: op = rv_op_amomin_q; break;
1605 case 162: op = rv_op_amomax_w; break;
1606 case 163: op = rv_op_amomax_d; break;
1607 case 164: op = rv_op_amomax_q; break;
1608 case 194: op = rv_op_amominu_w; break;
1609 case 195: op = rv_op_amominu_d; break;
1610 case 196: op = rv_op_amominu_q; break;
1611 case 226: op = rv_op_amomaxu_w; break;
1612 case 227: op = rv_op_amomaxu_d; break;
1613 case 228: op = rv_op_amomaxu_q; break;
1617 switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) {
1618 case 0: op = rv_op_add; break;
1619 case 1: op = rv_op_sll; break;
1620 case 2: op = rv_op_slt; break;
1621 case 3: op = rv_op_sltu; break;
1622 case 4: op = rv_op_xor; break;
1623 case 5: op = rv_op_srl; break;
1624 case 6: op = rv_op_or; break;
1625 case 7: op = rv_op_and; break;
1626 case 8: op = rv_op_mul; break;
1627 case 9: op = rv_op_mulh; break;
1628 case 10: op = rv_op_mulhsu; break;
1629 case 11: op = rv_op_mulhu; break;
1630 case 12: op = rv_op_div; break;
1631 case 13: op = rv_op_divu; break;
1632 case 14: op = rv_op_rem; break;
1633 case 15: op = rv_op_remu; break;
1634 case 256: op = rv_op_sub; break;
1635 case 261: op = rv_op_sra; break;
1638 case 13: op = rv_op_lui; break;
1640 switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) {
1641 case 0: op = rv_op_addw; break;
1642 case 1: op = rv_op_sllw; break;
1643 case 5: op = rv_op_srlw; break;
1644 case 8: op = rv_op_mulw; break;
1645 case 12: op = rv_op_divw; break;
1646 case 13: op = rv_op_divuw; break;
1647 case 14: op = rv_op_remw; break;
1648 case 15: op = rv_op_remuw; break;
1649 case 256: op = rv_op_subw; break;
1650 case 261: op = rv_op_sraw; break;
1654 switch (((inst >> 25) & 0b11)) {
1655 case 0: op = rv_op_fmadd_s; break;
1656 case 1: op = rv_op_fmadd_d; break;
1657 case 3: op = rv_op_fmadd_q; break;
1661 switch (((inst >> 25) & 0b11)) {
1662 case 0: op = rv_op_fmsub_s; break;
1663 case 1: op = rv_op_fmsub_d; break;
1664 case 3: op = rv_op_fmsub_q; break;
1668 switch (((inst >> 25) & 0b11)) {
1669 case 0: op = rv_op_fnmsub_s; break;
1670 case 1: op = rv_op_fnmsub_d; break;
1671 case 3: op = rv_op_fnmsub_q; break;
1675 switch (((inst >> 25) & 0b11)) {
1676 case 0: op = rv_op_fnmadd_s; break;
1677 case 1: op = rv_op_fnmadd_d; break;
1678 case 3: op = rv_op_fnmadd_q; break;
1682 switch (((inst >> 25) & 0b1111111)) {
1683 case 0: op = rv_op_fadd_s; break;
1684 case 1: op = rv_op_fadd_d; break;
1685 case 3: op = rv_op_fadd_q; break;
1686 case 4: op = rv_op_fsub_s; break;
1687 case 5: op = rv_op_fsub_d; break;
1688 case 7: op = rv_op_fsub_q; break;
1689 case 8: op = rv_op_fmul_s; break;
1690 case 9: op = rv_op_fmul_d; break;
1691 case 11: op = rv_op_fmul_q; break;
1692 case 12: op = rv_op_fdiv_s; break;
1693 case 13: op = rv_op_fdiv_d; break;
1694 case 15: op = rv_op_fdiv_q; break;
1696 switch (((inst >> 12) & 0b111)) {
1697 case 0: op = rv_op_fsgnj_s; break;
1698 case 1: op = rv_op_fsgnjn_s; break;
1699 case 2: op = rv_op_fsgnjx_s; break;
1703 switch (((inst >> 12) & 0b111)) {
1704 case 0: op = rv_op_fsgnj_d; break;
1705 case 1: op = rv_op_fsgnjn_d; break;
1706 case 2: op = rv_op_fsgnjx_d; break;
1710 switch (((inst >> 12) & 0b111)) {
1711 case 0: op = rv_op_fsgnj_q; break;
1712 case 1: op = rv_op_fsgnjn_q; break;
1713 case 2: op = rv_op_fsgnjx_q; break;
1717 switch (((inst >> 12) & 0b111)) {
1718 case 0: op = rv_op_fmin_s; break;
1719 case 1: op = rv_op_fmax_s; break;
1723 switch (((inst >> 12) & 0b111)) {
1724 case 0: op = rv_op_fmin_d; break;
1725 case 1: op = rv_op_fmax_d; break;
1729 switch (((inst >> 12) & 0b111)) {
1730 case 0: op = rv_op_fmin_q; break;
1731 case 1: op = rv_op_fmax_q; break;
1735 switch (((inst >> 20) & 0b11111)) {
1736 case 1: op = rv_op_fcvt_s_d; break;
1737 case 3: op = rv_op_fcvt_s_q; break;
1741 switch (((inst >> 20) & 0b11111)) {
1742 case 0: op = rv_op_fcvt_d_s; break;
1743 case 3: op = rv_op_fcvt_d_q; break;
1747 switch (((inst >> 20) & 0b11111)) {
1748 case 0: op = rv_op_fcvt_q_s; break;
1749 case 1: op = rv_op_fcvt_q_d; break;
1753 switch (((inst >> 20) & 0b11111)) {
1754 case 0: op = rv_op_fsqrt_s; break;
1758 switch (((inst >> 20) & 0b11111)) {
1759 case 0: op = rv_op_fsqrt_d; break;
1763 switch (((inst >> 20) & 0b11111)) {
1764 case 0: op = rv_op_fsqrt_q; break;
1768 switch (((inst >> 12) & 0b111)) {
1769 case 0: op = rv_op_fle_s; break;
1770 case 1: op = rv_op_flt_s; break;
1771 case 2: op = rv_op_feq_s; break;
1775 switch (((inst >> 12) & 0b111)) {
1776 case 0: op = rv_op_fle_d; break;
1777 case 1: op = rv_op_flt_d; break;
1778 case 2: op = rv_op_feq_d; break;
1782 switch (((inst >> 12) & 0b111)) {
1783 case 0: op = rv_op_fle_q; break;
1784 case 1: op = rv_op_flt_q; break;
1785 case 2: op = rv_op_feq_q; break;
1789 switch (((inst >> 20) & 0b11111)) {
1790 case 0: op = rv_op_fcvt_w_s; break;
1791 case 1: op = rv_op_fcvt_wu_s; break;
1792 case 2: op = rv_op_fcvt_l_s; break;
1793 case 3: op = rv_op_fcvt_lu_s; break;
1797 switch (((inst >> 20) & 0b11111)) {
1798 case 0: op = rv_op_fcvt_w_d; break;
1799 case 1: op = rv_op_fcvt_wu_d; break;
1800 case 2: op = rv_op_fcvt_l_d; break;
1801 case 3: op = rv_op_fcvt_lu_d; break;
1805 switch (((inst >> 20) & 0b11111)) {
1806 case 0: op = rv_op_fcvt_w_q; break;
1807 case 1: op = rv_op_fcvt_wu_q; break;
1808 case 2: op = rv_op_fcvt_l_q; break;
1809 case 3: op = rv_op_fcvt_lu_q; break;
1813 switch (((inst >> 20) & 0b11111)) {
1814 case 0: op = rv_op_fcvt_s_w; break;
1815 case 1: op = rv_op_fcvt_s_wu; break;
1816 case 2: op = rv_op_fcvt_s_l; break;
1817 case 3: op = rv_op_fcvt_s_lu; break;
1821 switch (((inst >> 20) & 0b11111)) {
1822 case 0: op = rv_op_fcvt_d_w; break;
1823 case 1: op = rv_op_fcvt_d_wu; break;
1824 case 2: op = rv_op_fcvt_d_l; break;
1825 case 3: op = rv_op_fcvt_d_lu; break;
1829 switch (((inst >> 20) & 0b11111)) {
1830 case 0: op = rv_op_fcvt_q_w; break;
1831 case 1: op = rv_op_fcvt_q_wu; break;
1832 case 2: op = rv_op_fcvt_q_l; break;
1833 case 3: op = rv_op_fcvt_q_lu; break;
1837 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1838 case 0: op = rv_op_fmv_x_s; break;
1839 case 1: op = rv_op_fclass_s; break;
1843 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1844 case 0: op = rv_op_fmv_x_d; break;
1845 case 1: op = rv_op_fclass_d; break;
1849 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1850 case 0: op = rv_op_fmv_x_q; break;
1851 case 1: op = rv_op_fclass_q; break;
1855 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1856 case 0: op = rv_op_fmv_s_x; break;
1860 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1861 case 0: op = rv_op_fmv_d_x; break;
1865 switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) {
1866 case 0: op = rv_op_fmv_q_x; break;
1872 switch (((inst >> 12) & 0b111)) {
1873 case 0: op = rv_op_addid; break;
1875 switch (((inst >> 26) & 0b111111)) {
1876 case 0: op = rv_op_sllid; break;
1880 switch (((inst >> 26) & 0b111111)) {
1881 case 0: op = rv_op_srlid; break;
1882 case 16: op = rv_op_sraid; break;
1888 switch (((inst >> 12) & 0b111)) {
1889 case 0: op = rv_op_beq; break;
1890 case 1: op = rv_op_bne; break;
1891 case 4: op = rv_op_blt; break;
1892 case 5: op = rv_op_bge; break;
1893 case 6: op = rv_op_bltu; break;
1894 case 7: op = rv_op_bgeu; break;
1898 switch (((inst >> 12) & 0b111)) {
1899 case 0: op = rv_op_jalr; break;
1902 case 27: op = rv_op_jal; break;
1904 switch (((inst >> 12) & 0b111)) {
1906 switch (((inst >> 20) & 0b111111100000) | ((inst >> 7) & 0b000000011111)) {
1908 switch (((inst >> 15) & 0b1111111111)) {
1909 case 0: op = rv_op_ecall; break;
1910 case 32: op = rv_op_ebreak; break;
1911 case 64: op = rv_op_uret; break;
1915 switch (((inst >> 20) & 0b11111)) {
1917 switch (((inst >> 15) & 0b11111)) {
1918 case 0: op = rv_op_sret; break;
1921 case 4: op = rv_op_sfence_vm; break;
1923 switch (((inst >> 15) & 0b11111)) {
1924 case 0: op = rv_op_wfi; break;
1929 case 288: op = rv_op_sfence_vma; break;
1931 switch (((inst >> 15) & 0b1111111111)) {
1932 case 64: op = rv_op_hret; break;
1936 switch (((inst >> 15) & 0b1111111111)) {
1937 case 64: op = rv_op_mret; break;
1941 switch (((inst >> 15) & 0b1111111111)) {
1942 case 576: op = rv_op_dret; break;
1947 case 1: op = rv_op_csrrw; break;
1948 case 2: op = rv_op_csrrs; break;
1949 case 3: op = rv_op_csrrc; break;
1950 case 5: op = rv_op_csrrwi; break;
1951 case 6: op = rv_op_csrrsi; break;
1952 case 7: op = rv_op_csrrci; break;
1956 switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) {
1957 case 0: op = rv_op_addd; break;
1958 case 1: op = rv_op_slld; break;
1959 case 5: op = rv_op_srld; break;
1960 case 8: op = rv_op_muld; break;
1961 case 12: op = rv_op_divd; break;
1962 case 13: op = rv_op_divud; break;
1963 case 14: op = rv_op_remd; break;
1964 case 15: op = rv_op_remud; break;
1965 case 256: op = rv_op_subd; break;
1966 case 261: op = rv_op_srad; break;
1975 /* operand extractors */
1977 static uint32_t operand_rd(rv_inst inst)
1979 return (inst << 52) >> 59;
1982 static uint32_t operand_rs1(rv_inst inst)
1984 return (inst << 44) >> 59;
1987 static uint32_t operand_rs2(rv_inst inst)
1989 return (inst << 39) >> 59;
1992 static uint32_t operand_rs3(rv_inst inst)
1994 return (inst << 32) >> 59;
1997 static uint32_t operand_aq(rv_inst inst)
1999 return (inst << 37) >> 63;
2002 static uint32_t operand_rl(rv_inst inst)
2004 return (inst << 38) >> 63;
2007 static uint32_t operand_pred(rv_inst inst)
2009 return (inst << 36) >> 60;
2012 static uint32_t operand_succ(rv_inst inst)
2014 return (inst << 40) >> 60;
2017 static uint32_t operand_rm(rv_inst inst)
2019 return (inst << 49) >> 61;
2022 static uint32_t operand_shamt5(rv_inst inst)
2024 return (inst << 39) >> 59;
2027 static uint32_t operand_shamt6(rv_inst inst)
2029 return (inst << 38) >> 58;
2032 static uint32_t operand_shamt7(rv_inst inst)
2034 return (inst << 37) >> 57;
2037 static uint32_t operand_crdq(rv_inst inst)
2039 return (inst << 59) >> 61;
2042 static uint32_t operand_crs1q(rv_inst inst)
2044 return (inst << 54) >> 61;
2047 static uint32_t operand_crs1rdq(rv_inst inst)
2049 return (inst << 54) >> 61;
2052 static uint32_t operand_crs2q(rv_inst inst)
2054 return (inst << 59) >> 61;
2057 static uint32_t operand_crd(rv_inst inst)
2059 return (inst << 52) >> 59;
2062 static uint32_t operand_crs1(rv_inst inst)
2064 return (inst << 52) >> 59;
2067 static uint32_t operand_crs1rd(rv_inst inst)
2069 return (inst << 52) >> 59;
2072 static uint32_t operand_crs2(rv_inst inst)
2074 return (inst << 57) >> 59;
2077 static uint32_t operand_cimmsh5(rv_inst inst)
2079 return (inst << 57) >> 59;
2082 static uint32_t operand_csr12(rv_inst inst)
2084 return (inst << 32) >> 52;
2087 static int32_t operand_imm12(rv_inst inst)
2089 return ((int64_t)inst << 32) >> 52;
2092 static int32_t operand_imm20(rv_inst inst)
2094 return (((int64_t)inst << 32) >> 44) << 12;
2097 static int32_t operand_jimm20(rv_inst inst)
2099 return (((int64_t)inst << 32) >> 63) << 20 |
2100 ((inst << 33) >> 54) << 1 |
2101 ((inst << 43) >> 63) << 11 |
2102 ((inst << 44) >> 56) << 12;
2105 static int32_t operand_simm12(rv_inst inst)
2107 return (((int64_t)inst << 32) >> 57) << 5 |
2111 static int32_t operand_sbimm12(rv_inst inst)
2113 return (((int64_t)inst << 32) >> 63) << 12 |
2114 ((inst << 33) >> 58) << 5 |
2115 ((inst << 52) >> 60) << 1 |
2116 ((inst << 56) >> 63) << 11;
2119 static uint32_t operand_cimmsh6(rv_inst inst)
2121 return ((inst << 51) >> 63) << 5 |
2125 static int32_t operand_cimmi(rv_inst inst)
2127 return (((int64_t)inst << 51) >> 63) << 5 |
2131 static int32_t operand_cimmui(rv_inst inst)
2133 return (((int64_t)inst << 51) >> 63) << 17 |
2134 ((inst << 57) >> 59) << 12;
2137 static uint32_t operand_cimmlwsp(rv_inst inst)
2139 return ((inst << 51) >> 63) << 5 |
2140 ((inst << 57) >> 61) << 2 |
2141 ((inst << 60) >> 62) << 6;
2144 static uint32_t operand_cimmldsp(rv_inst inst)
2146 return ((inst << 51) >> 63) << 5 |
2147 ((inst << 57) >> 62) << 3 |
2148 ((inst << 59) >> 61) << 6;
2151 static uint32_t operand_cimmlqsp(rv_inst inst)
2153 return ((inst << 51) >> 63) << 5 |
2154 ((inst << 57) >> 63) << 4 |
2155 ((inst << 58) >> 60) << 6;
2158 static int32_t operand_cimm16sp(rv_inst inst)
2160 return (((int64_t)inst << 51) >> 63) << 9 |
2161 ((inst << 57) >> 63) << 4 |
2162 ((inst << 58) >> 63) << 6 |
2163 ((inst << 59) >> 62) << 7 |
2164 ((inst << 61) >> 63) << 5;
2167 static int32_t operand_cimmj(rv_inst inst)
2169 return (((int64_t)inst << 51) >> 63) << 11 |
2170 ((inst << 52) >> 63) << 4 |
2171 ((inst << 53) >> 62) << 8 |
2172 ((inst << 55) >> 63) << 10 |
2173 ((inst << 56) >> 63) << 6 |
2174 ((inst << 57) >> 63) << 7 |
2175 ((inst << 58) >> 61) << 1 |
2176 ((inst << 61) >> 63) << 5;
2179 static int32_t operand_cimmb(rv_inst inst)
2181 return (((int64_t)inst << 51) >> 63) << 8 |
2182 ((inst << 52) >> 62) << 3 |
2183 ((inst << 57) >> 62) << 6 |
2184 ((inst << 59) >> 62) << 1 |
2185 ((inst << 61) >> 63) << 5;
2188 static uint32_t operand_cimmswsp(rv_inst inst)
2190 return ((inst << 51) >> 60) << 2 |
2191 ((inst << 55) >> 62) << 6;
2194 static uint32_t operand_cimmsdsp(rv_inst inst)
2196 return ((inst << 51) >> 61) << 3 |
2197 ((inst << 54) >> 61) << 6;
2200 static uint32_t operand_cimmsqsp(rv_inst inst)
2202 return ((inst << 51) >> 62) << 4 |
2203 ((inst << 53) >> 60) << 6;
2206 static uint32_t operand_cimm4spn(rv_inst inst)
2208 return ((inst << 51) >> 62) << 4 |
2209 ((inst << 53) >> 60) << 6 |
2210 ((inst << 57) >> 63) << 2 |
2211 ((inst << 58) >> 63) << 3;
2214 static uint32_t operand_cimmw(rv_inst inst)
2216 return ((inst << 51) >> 61) << 3 |
2217 ((inst << 57) >> 63) << 2 |
2218 ((inst << 58) >> 63) << 6;
2221 static uint32_t operand_cimmd(rv_inst inst)
2223 return ((inst << 51) >> 61) << 3 |
2224 ((inst << 57) >> 62) << 6;
2227 static uint32_t operand_cimmq(rv_inst inst)
2229 return ((inst << 51) >> 62) << 4 |
2230 ((inst << 53) >> 63) << 8 |
2231 ((inst << 57) >> 62) << 6;
2234 /* decode operands */
2236 static void decode_inst_operands(rv_decode *dec)
2238 rv_inst inst = dec->inst;
2239 dec->codec = opcode_data[dec->op].codec;
2240 switch (dec->codec) {
2242 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2246 dec->rd = operand_rd(inst);
2247 dec->rs1 = dec->rs2 = rv_ireg_zero;
2248 dec->imm = operand_imm20(inst);
2251 dec->rd = operand_rd(inst);
2252 dec->rs1 = dec->rs2 = rv_ireg_zero;
2253 dec->imm = operand_jimm20(inst);
2256 dec->rd = operand_rd(inst);
2257 dec->rs1 = operand_rs1(inst);
2258 dec->rs2 = rv_ireg_zero;
2259 dec->imm = operand_imm12(inst);
2261 case rv_codec_i_sh5:
2262 dec->rd = operand_rd(inst);
2263 dec->rs1 = operand_rs1(inst);
2264 dec->rs2 = rv_ireg_zero;
2265 dec->imm = operand_shamt5(inst);
2267 case rv_codec_i_sh6:
2268 dec->rd = operand_rd(inst);
2269 dec->rs1 = operand_rs1(inst);
2270 dec->rs2 = rv_ireg_zero;
2271 dec->imm = operand_shamt6(inst);
2273 case rv_codec_i_sh7:
2274 dec->rd = operand_rd(inst);
2275 dec->rs1 = operand_rs1(inst);
2276 dec->rs2 = rv_ireg_zero;
2277 dec->imm = operand_shamt7(inst);
2279 case rv_codec_i_csr:
2280 dec->rd = operand_rd(inst);
2281 dec->rs1 = operand_rs1(inst);
2282 dec->rs2 = rv_ireg_zero;
2283 dec->imm = operand_csr12(inst);
2286 dec->rd = rv_ireg_zero;
2287 dec->rs1 = operand_rs1(inst);
2288 dec->rs2 = operand_rs2(inst);
2289 dec->imm = operand_simm12(inst);
2292 dec->rd = rv_ireg_zero;
2293 dec->rs1 = operand_rs1(inst);
2294 dec->rs2 = operand_rs2(inst);
2295 dec->imm = operand_sbimm12(inst);
2298 dec->rd = operand_rd(inst);
2299 dec->rs1 = operand_rs1(inst);
2300 dec->rs2 = operand_rs2(inst);
2304 dec->rd = operand_rd(inst);
2305 dec->rs1 = operand_rs1(inst);
2306 dec->rs2 = operand_rs2(inst);
2308 dec->rm = operand_rm(inst);
2311 dec->rd = operand_rd(inst);
2312 dec->rs1 = operand_rs1(inst);
2313 dec->rs2 = operand_rs2(inst);
2314 dec->rs3 = operand_rs3(inst);
2316 dec->rm = operand_rm(inst);
2319 dec->rd = operand_rd(inst);
2320 dec->rs1 = operand_rs1(inst);
2321 dec->rs2 = operand_rs2(inst);
2323 dec->aq = operand_aq(inst);
2324 dec->rl = operand_rl(inst);
2327 dec->rd = operand_rd(inst);
2328 dec->rs1 = operand_rs1(inst);
2329 dec->rs2 = rv_ireg_zero;
2331 dec->aq = operand_aq(inst);
2332 dec->rl = operand_rl(inst);
2335 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2336 dec->pred = operand_pred(inst);
2337 dec->succ = operand_succ(inst);
2341 dec->rd = rv_ireg_zero;
2342 dec->rs1 = operand_crs1q(inst) + 8;
2343 dec->rs2 = rv_ireg_zero;
2344 dec->imm = operand_cimmb(inst);
2346 case rv_codec_cb_imm:
2347 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2348 dec->rs2 = rv_ireg_zero;
2349 dec->imm = operand_cimmi(inst);
2351 case rv_codec_cb_sh5:
2352 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2353 dec->rs2 = rv_ireg_zero;
2354 dec->imm = operand_cimmsh5(inst);
2356 case rv_codec_cb_sh6:
2357 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2358 dec->rs2 = rv_ireg_zero;
2359 dec->imm = operand_cimmsh6(inst);
2362 dec->rd = dec->rs1 = operand_crs1rd(inst);
2363 dec->rs2 = rv_ireg_zero;
2364 dec->imm = operand_cimmi(inst);
2366 case rv_codec_ci_sh5:
2367 dec->rd = dec->rs1 = operand_crs1rd(inst);
2368 dec->rs2 = rv_ireg_zero;
2369 dec->imm = operand_cimmsh5(inst);
2371 case rv_codec_ci_sh6:
2372 dec->rd = dec->rs1 = operand_crs1rd(inst);
2373 dec->rs2 = rv_ireg_zero;
2374 dec->imm = operand_cimmsh6(inst);
2376 case rv_codec_ci_16sp:
2377 dec->rd = rv_ireg_sp;
2378 dec->rs1 = rv_ireg_sp;
2379 dec->rs2 = rv_ireg_zero;
2380 dec->imm = operand_cimm16sp(inst);
2382 case rv_codec_ci_lwsp:
2383 dec->rd = operand_crd(inst);
2384 dec->rs1 = rv_ireg_sp;
2385 dec->rs2 = rv_ireg_zero;
2386 dec->imm = operand_cimmlwsp(inst);
2388 case rv_codec_ci_ldsp:
2389 dec->rd = operand_crd(inst);
2390 dec->rs1 = rv_ireg_sp;
2391 dec->rs2 = rv_ireg_zero;
2392 dec->imm = operand_cimmldsp(inst);
2394 case rv_codec_ci_lqsp:
2395 dec->rd = operand_crd(inst);
2396 dec->rs1 = rv_ireg_sp;
2397 dec->rs2 = rv_ireg_zero;
2398 dec->imm = operand_cimmlqsp(inst);
2400 case rv_codec_ci_li:
2401 dec->rd = operand_crd(inst);
2402 dec->rs1 = rv_ireg_zero;
2403 dec->rs2 = rv_ireg_zero;
2404 dec->imm = operand_cimmi(inst);
2406 case rv_codec_ci_lui:
2407 dec->rd = operand_crd(inst);
2408 dec->rs1 = rv_ireg_zero;
2409 dec->rs2 = rv_ireg_zero;
2410 dec->imm = operand_cimmui(inst);
2412 case rv_codec_ci_none:
2413 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2416 case rv_codec_ciw_4spn:
2417 dec->rd = operand_crdq(inst) + 8;
2418 dec->rs1 = rv_ireg_sp;
2419 dec->rs2 = rv_ireg_zero;
2420 dec->imm = operand_cimm4spn(inst);
2423 dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero;
2424 dec->imm = operand_cimmj(inst);
2426 case rv_codec_cj_jal:
2427 dec->rd = rv_ireg_ra;
2428 dec->rs1 = dec->rs2 = rv_ireg_zero;
2429 dec->imm = operand_cimmj(inst);
2431 case rv_codec_cl_lw:
2432 dec->rd = operand_crdq(inst) + 8;
2433 dec->rs1 = operand_crs1q(inst) + 8;
2434 dec->rs2 = rv_ireg_zero;
2435 dec->imm = operand_cimmw(inst);
2437 case rv_codec_cl_ld:
2438 dec->rd = operand_crdq(inst) + 8;
2439 dec->rs1 = operand_crs1q(inst) + 8;
2440 dec->rs2 = rv_ireg_zero;
2441 dec->imm = operand_cimmd(inst);
2443 case rv_codec_cl_lq:
2444 dec->rd = operand_crdq(inst) + 8;
2445 dec->rs1 = operand_crs1q(inst) + 8;
2446 dec->rs2 = rv_ireg_zero;
2447 dec->imm = operand_cimmq(inst);
2450 dec->rd = dec->rs1 = operand_crs1rd(inst);
2451 dec->rs2 = operand_crs2(inst);
2454 case rv_codec_cr_mv:
2455 dec->rd = operand_crd(inst);
2456 dec->rs1 = operand_crs2(inst);
2457 dec->rs2 = rv_ireg_zero;
2460 case rv_codec_cr_jalr:
2461 dec->rd = rv_ireg_ra;
2462 dec->rs1 = operand_crs1(inst);
2463 dec->rs2 = rv_ireg_zero;
2466 case rv_codec_cr_jr:
2467 dec->rd = rv_ireg_zero;
2468 dec->rs1 = operand_crs1(inst);
2469 dec->rs2 = rv_ireg_zero;
2473 dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8;
2474 dec->rs2 = operand_crs2q(inst) + 8;
2477 case rv_codec_cs_sw:
2478 dec->rd = rv_ireg_zero;
2479 dec->rs1 = operand_crs1q(inst) + 8;
2480 dec->rs2 = operand_crs2q(inst) + 8;
2481 dec->imm = operand_cimmw(inst);
2483 case rv_codec_cs_sd:
2484 dec->rd = rv_ireg_zero;
2485 dec->rs1 = operand_crs1q(inst) + 8;
2486 dec->rs2 = operand_crs2q(inst) + 8;
2487 dec->imm = operand_cimmd(inst);
2489 case rv_codec_cs_sq:
2490 dec->rd = rv_ireg_zero;
2491 dec->rs1 = operand_crs1q(inst) + 8;
2492 dec->rs2 = operand_crs2q(inst) + 8;
2493 dec->imm = operand_cimmq(inst);
2495 case rv_codec_css_swsp:
2496 dec->rd = rv_ireg_zero;
2497 dec->rs1 = rv_ireg_sp;
2498 dec->rs2 = operand_crs2(inst);
2499 dec->imm = operand_cimmswsp(inst);
2501 case rv_codec_css_sdsp:
2502 dec->rd = rv_ireg_zero;
2503 dec->rs1 = rv_ireg_sp;
2504 dec->rs2 = operand_crs2(inst);
2505 dec->imm = operand_cimmsdsp(inst);
2507 case rv_codec_css_sqsp:
2508 dec->rd = rv_ireg_zero;
2509 dec->rs1 = rv_ireg_sp;
2510 dec->rs2 = operand_crs2(inst);
2511 dec->imm = operand_cimmsqsp(inst);
2516 /* check constraint */
2518 static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
2520 int32_t imm = dec->imm;
2521 uint8_t rd = dec->rd, rs1 = dec->rs1, rs2 = dec->rs2;
2522 while (*c != rvc_end) {
2525 if (!(imm >= -32 && imm < 32)) {
2535 if (!(imm <= 127)) {
2540 if (!(imm <= 255)) {
2545 if (!(imm <= 511)) {
2550 if (!(imm <= 1023)) {
2555 if (!(imm <= 4095)) {
2560 if (!(imm <= 262143)) {
2570 if (!((imm & 0b1) == 0)) {
2575 if (!((imm & 0b11) == 0)) {
2580 if (!((imm & 0b111) == 0)) {
2585 if (!((imm & 0b1111) == 0)) {
2590 if (!(rd >= 8 && rd <= 15)) {
2595 if (!(rs1 >= 8 && rs1 <= 15)) {
2600 if (!(rs2 >= 8 && rs2 <= 15)) {
2639 case rvc_rd_ne_x0_x2:
2640 if (!(rd != 0 && rd != 2)) {
2659 case rvc_rs2_eq_rs1:
2660 if (!(rs2 == rs1)) {
2669 case rvc_imm_eq_zero:
2684 case rvc_csr_eq_0x001:
2685 if (!(imm == 0x001)) {
2689 case rvc_csr_eq_0x002:
2690 if (!(imm == 0x002)) {
2694 case rvc_csr_eq_0x003:
2695 if (!(imm == 0x003)) {
2699 case rvc_csr_eq_0xc00:
2700 if (!(imm == 0xc00)) {
2704 case rvc_csr_eq_0xc01:
2705 if (!(imm == 0xc01)) {
2709 case rvc_csr_eq_0xc02:
2710 if (!(imm == 0xc02)) {
2714 case rvc_csr_eq_0xc80:
2715 if (!(imm == 0xc80)) {
2719 case rvc_csr_eq_0xc81:
2720 if (!(imm == 0xc81)) {
2724 case rvc_csr_eq_0xc82:
2725 if (!(imm == 0xc82)) {
2736 /* instruction length */
2738 static size_t inst_length(rv_inst inst)
2740 /* NOTE: supports maximum instruction size of 64-bits */
2742 /* instruction length coding
2744 * aa - 16 bit aa != 11
2745 * bbb11 - 32 bit bbb != 111
2750 return (inst & 0b11) != 0b11 ? 2
2751 : (inst & 0b11100) != 0b11100 ? 4
2752 : (inst & 0b111111) == 0b011111 ? 6
2753 : (inst & 0b1111111) == 0b0111111 ? 8
2757 /* format instruction */
2759 static void append(char *s1, const char *s2, size_t n)
2761 size_t l1 = strlen(s1);
2762 if (n - l1 - 1 > 0) {
2763 strncat(s1, s2, n - l1);
2767 static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec)
2772 if (dec->op == rv_op_illegal) {
2773 size_t len = inst_length(dec->inst);
2776 snprintf(buf, buflen, "(0x%04" PRIx64 ")", dec->inst);
2779 snprintf(buf, buflen, "(0x%08" PRIx64 ")", dec->inst);
2782 snprintf(buf, buflen, "(0x%012" PRIx64 ")", dec->inst);
2785 snprintf(buf, buflen, "(0x%016" PRIx64 ")", dec->inst);
2791 fmt = opcode_data[dec->op].format;
2795 append(buf, opcode_data[dec->op].name, buflen);
2798 append(buf, "(", buflen);
2801 append(buf, ",", buflen);
2804 append(buf, ")", buflen);
2807 append(buf, rv_ireg_name_sym[dec->rd], buflen);
2810 append(buf, rv_ireg_name_sym[dec->rs1], buflen);
2813 append(buf, rv_ireg_name_sym[dec->rs2], buflen);
2816 append(buf, rv_freg_name_sym[dec->rd], buflen);
2819 append(buf, rv_freg_name_sym[dec->rs1], buflen);
2822 append(buf, rv_freg_name_sym[dec->rs2], buflen);
2825 append(buf, rv_freg_name_sym[dec->rs3], buflen);
2828 snprintf(tmp, sizeof(tmp), "%d", dec->rs1);
2829 append(buf, tmp, buflen);
2832 snprintf(tmp, sizeof(tmp), "%d", dec->imm);
2833 append(buf, tmp, buflen);
2836 snprintf(tmp, sizeof(tmp), "%d", dec->imm);
2837 append(buf, tmp, buflen);
2838 while (strlen(buf) < tab * 2) {
2839 append(buf, " ", buflen);
2841 snprintf(tmp, sizeof(tmp), "# 0x%" PRIx64,
2842 dec->pc + dec->imm);
2843 append(buf, tmp, buflen);
2846 const char *name = csr_name(dec->imm & 0xfff);
2848 append(buf, name, buflen);
2850 snprintf(tmp, sizeof(tmp), "0x%03x", dec->imm & 0xfff);
2851 append(buf, tmp, buflen);
2858 append(buf, "rne", buflen);
2861 append(buf, "rtz", buflen);
2864 append(buf, "rdn", buflen);
2867 append(buf, "rup", buflen);
2870 append(buf, "rmm", buflen);
2873 append(buf, "dyn", buflen);
2876 append(buf, "inv", buflen);
2881 if (dec->pred & rv_fence_i) {
2882 append(buf, "i", buflen);
2884 if (dec->pred & rv_fence_o) {
2885 append(buf, "o", buflen);
2887 if (dec->pred & rv_fence_r) {
2888 append(buf, "r", buflen);
2890 if (dec->pred & rv_fence_w) {
2891 append(buf, "w", buflen);
2895 if (dec->succ & rv_fence_i) {
2896 append(buf, "i", buflen);
2898 if (dec->succ & rv_fence_o) {
2899 append(buf, "o", buflen);
2901 if (dec->succ & rv_fence_r) {
2902 append(buf, "r", buflen);
2904 if (dec->succ & rv_fence_w) {
2905 append(buf, "w", buflen);
2909 while (strlen(buf) < tab) {
2910 append(buf, " ", buflen);
2915 append(buf, ".aq", buflen);
2920 append(buf, ".rl", buflen);
2930 /* lift instruction to pseudo-instruction */
2932 static void decode_inst_lift_pseudo(rv_decode *dec)
2934 const rv_comp_data *comp_data = opcode_data[dec->op].pseudo;
2938 while (comp_data->constraints) {
2939 if (check_constraints(dec, comp_data->constraints)) {
2940 dec->op = comp_data->op;
2941 dec->codec = opcode_data[dec->op].codec;
2948 /* decompress instruction */
2950 static void decode_inst_decompress_rv32(rv_decode *dec)
2952 int decomp_op = opcode_data[dec->op].decomp_rv32;
2953 if (decomp_op != rv_op_illegal) {
2954 dec->op = decomp_op;
2955 dec->codec = opcode_data[decomp_op].codec;
2959 static void decode_inst_decompress_rv64(rv_decode *dec)
2961 int decomp_op = opcode_data[dec->op].decomp_rv64;
2962 if (decomp_op != rv_op_illegal) {
2963 dec->op = decomp_op;
2964 dec->codec = opcode_data[decomp_op].codec;
2968 static void decode_inst_decompress_rv128(rv_decode *dec)
2970 int decomp_op = opcode_data[dec->op].decomp_rv128;
2971 if (decomp_op != rv_op_illegal) {
2972 dec->op = decomp_op;
2973 dec->codec = opcode_data[decomp_op].codec;
2977 static void decode_inst_decompress(rv_decode *dec, rv_isa isa)
2981 decode_inst_decompress_rv32(dec);
2984 decode_inst_decompress_rv64(dec);
2987 decode_inst_decompress_rv128(dec);
2992 /* disassemble instruction */
2995 disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst)
2997 rv_decode dec = { 0 };
3000 decode_inst_opcode(&dec, isa);
3001 decode_inst_operands(&dec);
3002 decode_inst_decompress(&dec, isa);
3003 decode_inst_lift_pseudo(&dec);
3004 format_inst(buf, buflen, 16, &dec);
3008 print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa)
3010 char buf[128] = { 0 };
3017 /* Instructions are made of 2-byte packets in little-endian order */
3018 for (n = 0; n < len; n += 2) {
3019 status = (*info->read_memory_func)(memaddr + n, packet, 2, info);
3021 /* Don't fail just because we fell off the end. */
3025 (*info->memory_error_func)(status, memaddr, info);
3028 inst |= ((rv_inst) bfd_getl16(packet)) << (8 * n);
3030 len = inst_length(inst);
3034 disasm_inst(buf, sizeof(buf), isa, memaddr, inst);
3035 (*info->fprintf_func)(info->stream, "%s", buf);
3040 int print_insn_riscv32(bfd_vma memaddr, struct disassemble_info *info)
3042 return print_insn_riscv(memaddr, info, rv32);
3045 int print_insn_riscv64(bfd_vma memaddr, struct disassemble_info *info)
3047 return print_insn_riscv(memaddr, info, rv64);