├── .gitignore ├── CMakeLists.txt ├── README.md ├── src ├── riscv-disas.c └── riscv-disas.h └── tests ├── t1.c └── t2.c /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.12) 2 | project(riscv-disassembler VERSION 0.0.1) 3 | enable_testing() 4 | 5 | include_directories(src) 6 | add_library(rvasm src/riscv-disas.c) 7 | 8 | foreach(test t1 t2) 9 | add_executable(${test} tests/${test}.c) 10 | target_link_libraries(${test} rvasm) 11 | add_test(TEST-DECODE ${test}) 12 | endforeach() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RISC-V Disassembler 2 | 3 | RISC-V Disassembler with support for RV32/RV64/RV128 IMAFDC 4 | 5 | ## Build instructions 6 | 7 | ``` 8 | cmake -B build 9 | cmake --build build 10 | ``` 11 | -------------------------------------------------------------------------------- /src/riscv-disas.c: -------------------------------------------------------------------------------- 1 | /* 2 | * RISC-V Disassembler 3 | * 4 | * Copyright (c) 2016-2017 Michael Clark 5 | * Copyright (c) 2017-2018 SiFive, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #include "riscv-disas.h" 27 | 28 | typedef struct { 29 | const int op; 30 | const rvc_constraint *constraints; 31 | } rv_comp_data; 32 | 33 | enum { 34 | rvcd_imm_nz = 0x1, 35 | rvcd_imm_nz_hint = 0x2 36 | }; 37 | 38 | typedef struct { 39 | const char * const name; 40 | const rv_codec codec; 41 | const char * const format; 42 | const rv_comp_data *pseudo; 43 | const short decomp_rv32; 44 | const short decomp_rv64; 45 | const short decomp_rv128; 46 | const short decomp_data; 47 | } rv_opcode_data; 48 | 49 | /* register names */ 50 | 51 | static const char rv_ireg_name_sym[32][5] = { 52 | "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", 53 | "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", 54 | "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", 55 | "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", 56 | }; 57 | 58 | static const char rv_freg_name_sym[32][5] = { 59 | "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", 60 | "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", 61 | "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", 62 | "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11", 63 | }; 64 | 65 | /* instruction formats */ 66 | 67 | static const char rv_fmt_none[] = "O\t"; 68 | static const char rv_fmt_rs1[] = "O\t1"; 69 | static const char rv_fmt_offset[] = "O\to"; 70 | static const char rv_fmt_pred_succ[] = "O\tp,s"; 71 | static const char rv_fmt_rs1_rs2[] = "O\t1,2"; 72 | static const char rv_fmt_rd_imm[] = "O\t0,i"; 73 | static const char rv_fmt_rd_offset[] = "O\t0,o"; 74 | static const char rv_fmt_rd_rs1_rs2[] = "O\t0,1,2"; 75 | static const char rv_fmt_frd_rs1[] = "O\t3,1"; 76 | static const char rv_fmt_rd_frs1[] = "O\t0,4"; 77 | static const char rv_fmt_rd_frs1_frs2[] = "O\t0,4,5"; 78 | static const char rv_fmt_frd_frs1_frs2[] = "O\t3,4,5"; 79 | static const char rv_fmt_rm_frd_frs1[] = "O\tr,3,4"; 80 | static const char rv_fmt_rm_frd_rs1[] = "O\tr,3,1"; 81 | static const char rv_fmt_rm_rd_frs1[] = "O\tr,0,4"; 82 | static const char rv_fmt_rm_frd_frs1_frs2[] = "O\tr,3,4,5"; 83 | static const char rv_fmt_rm_frd_frs1_frs2_frs3[] = "O\tr,3,4,5,6"; 84 | static const char rv_fmt_rd_rs1_imm[] = "O\t0,1,i"; 85 | static const char rv_fmt_rd_rs1_offset[] = "O\t0,1,i"; 86 | static const char rv_fmt_rd_offset_rs1[] = "O\t0,i(1)"; 87 | static const char rv_fmt_frd_offset_rs1[] = "O\t3,i(1)"; 88 | static const char rv_fmt_rd_csr_rs1[] = "O\t0,c,1"; 89 | static const char rv_fmt_rd_csr_zimm[] = "O\t0,c,7"; 90 | static const char rv_fmt_rs2_offset_rs1[] = "O\t2,i(1)"; 91 | static const char rv_fmt_frs2_offset_rs1[] = "O\t5,i(1)"; 92 | static const char rv_fmt_rs1_rs2_offset[] = "O\t1,2,o"; 93 | static const char rv_fmt_rs2_rs1_offset[] = "O\t2,1,o"; 94 | static const char rv_fmt_aqrl_rd_rs2_rs1[] = "OAR\t0,2,(1)"; 95 | static const char rv_fmt_aqrl_rd_rs1[] = "OAR\t0,(1)"; 96 | static const char rv_fmt_rd[] = "O\t0"; 97 | static const char rv_fmt_rd_zimm[] = "O\t0,7"; 98 | static const char rv_fmt_rd_rs1[] = "O\t0,1"; 99 | static const char rv_fmt_rd_rs2[] = "O\t0,2"; 100 | static const char rv_fmt_rs1_offset[] = "O\t1,o"; 101 | static const char rv_fmt_rs2_offset[] = "O\t2,o"; 102 | 103 | /* pseudo-instruction constraints */ 104 | 105 | static const rvc_constraint rvcc_last[] = { rvc_end }; 106 | static const rvc_constraint rvcc_imm_eq_zero[] = { rvc_imm_eq_zero, rvc_end }; 107 | static const rvc_constraint rvcc_imm_eq_n1[] = { rvc_imm_eq_n1, rvc_end }; 108 | static const rvc_constraint rvcc_imm_eq_p1[] = { rvc_imm_eq_p1, rvc_end }; 109 | static const rvc_constraint rvcc_rs1_eq_x0[] = { rvc_rs1_eq_x0, rvc_end }; 110 | static const rvc_constraint rvcc_rs2_eq_x0[] = { rvc_rs2_eq_x0, rvc_end }; 111 | static const rvc_constraint rvcc_rs2_eq_rs1[] = { rvc_rs2_eq_rs1, rvc_end }; 112 | static const rvc_constraint rvcc_jal_j[] = { rvc_rd_eq_x0, rvc_end }; 113 | static const rvc_constraint rvcc_jal_jal[] = { rvc_rd_eq_ra, rvc_end }; 114 | static const rvc_constraint rvcc_jalr_jr[] = { rvc_rd_eq_x0, rvc_imm_eq_zero, rvc_end }; 115 | static const rvc_constraint rvcc_jalr_jalr[] = { rvc_rd_eq_ra, rvc_imm_eq_zero, rvc_end }; 116 | static const rvc_constraint rvcc_jalr_ret[] = { rvc_rd_eq_x0, rvc_rs1_eq_ra, rvc_end }; 117 | static const rvc_constraint rvcc_addi_nop[] = { rvc_rd_eq_x0, rvc_rs1_eq_x0, rvc_imm_eq_zero, rvc_end }; 118 | static const rvc_constraint rvcc_rdcycle[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc00, rvc_end }; 119 | static const rvc_constraint rvcc_rdtime[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc01, rvc_end }; 120 | static const rvc_constraint rvcc_rdinstret[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc02, rvc_end }; 121 | static const rvc_constraint rvcc_rdcycleh[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc80, rvc_end }; 122 | static const rvc_constraint rvcc_rdtimeh[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc81, rvc_end }; 123 | static const rvc_constraint rvcc_rdinstreth[] = { rvc_rs1_eq_x0, rvc_csr_eq_0xc82, rvc_end }; 124 | static const rvc_constraint rvcc_frcsr[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x003, rvc_end }; 125 | static const rvc_constraint rvcc_frrm[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x002, rvc_end }; 126 | static const rvc_constraint rvcc_frflags[] = { rvc_rs1_eq_x0, rvc_csr_eq_0x001, rvc_end }; 127 | static const rvc_constraint rvcc_fscsr[] = { rvc_csr_eq_0x003, rvc_end }; 128 | static const rvc_constraint rvcc_fsrm[] = { rvc_csr_eq_0x002, rvc_end }; 129 | static const rvc_constraint rvcc_fsflags[] = { rvc_csr_eq_0x001, rvc_end }; 130 | static const rvc_constraint rvcc_fsrmi[] = { rvc_csr_eq_0x002, rvc_end }; 131 | static const rvc_constraint rvcc_fsflagsi[] = { rvc_csr_eq_0x001, rvc_end }; 132 | 133 | /* pseudo-instruction metadata */ 134 | 135 | static const rv_comp_data rvcp_jal[] = { 136 | { rv_op_j, rvcc_jal_j }, 137 | { rv_op_jal, rvcc_jal_jal }, 138 | { rv_op_illegal, NULL } 139 | }; 140 | 141 | static const rv_comp_data rvcp_jalr[] = { 142 | { rv_op_ret, rvcc_jalr_ret }, 143 | { rv_op_jr, rvcc_jalr_jr }, 144 | { rv_op_jalr, rvcc_jalr_jalr }, 145 | { rv_op_illegal, NULL } 146 | }; 147 | 148 | static const rv_comp_data rvcp_beq[] = { 149 | { rv_op_beqz, rvcc_rs2_eq_x0 }, 150 | { rv_op_illegal, NULL } 151 | }; 152 | 153 | static const rv_comp_data rvcp_bne[] = { 154 | { rv_op_bnez, rvcc_rs2_eq_x0 }, 155 | { rv_op_illegal, NULL } 156 | }; 157 | 158 | static const rv_comp_data rvcp_blt[] = { 159 | { rv_op_bltz, rvcc_rs2_eq_x0 }, 160 | { rv_op_bgtz, rvcc_rs1_eq_x0 }, 161 | { rv_op_bgt, rvcc_last }, 162 | { rv_op_illegal, NULL } 163 | }; 164 | 165 | static const rv_comp_data rvcp_bge[] = { 166 | { rv_op_blez, rvcc_rs1_eq_x0 }, 167 | { rv_op_bgez, rvcc_rs2_eq_x0 }, 168 | { rv_op_ble, rvcc_last }, 169 | { rv_op_illegal, NULL } 170 | }; 171 | 172 | static const rv_comp_data rvcp_bltu[] = { 173 | { rv_op_bgtu, rvcc_last }, 174 | { rv_op_illegal, NULL } 175 | }; 176 | 177 | static const rv_comp_data rvcp_bgeu[] = { 178 | { rv_op_bleu, rvcc_last }, 179 | { rv_op_illegal, NULL } 180 | }; 181 | 182 | static const rv_comp_data rvcp_addi[] = { 183 | { rv_op_nop, rvcc_addi_nop }, 184 | { rv_op_mv, rvcc_imm_eq_zero }, 185 | { rv_op_illegal, NULL } 186 | }; 187 | 188 | static const rv_comp_data rvcp_sltiu[] = { 189 | { rv_op_seqz, rvcc_imm_eq_p1 }, 190 | { rv_op_illegal, NULL } 191 | }; 192 | 193 | static const rv_comp_data rvcp_xori[] = { 194 | { rv_op_not, rvcc_imm_eq_n1 }, 195 | { rv_op_illegal, NULL } 196 | }; 197 | 198 | static const rv_comp_data rvcp_sub[] = { 199 | { rv_op_neg, rvcc_rs1_eq_x0 }, 200 | { rv_op_illegal, NULL } 201 | }; 202 | 203 | static const rv_comp_data rvcp_slt[] = { 204 | { rv_op_sltz, rvcc_rs2_eq_x0 }, 205 | { rv_op_sgtz, rvcc_rs1_eq_x0 }, 206 | { rv_op_illegal, NULL } 207 | }; 208 | 209 | static const rv_comp_data rvcp_sltu[] = { 210 | { rv_op_snez, rvcc_rs1_eq_x0 }, 211 | { rv_op_illegal, NULL } 212 | }; 213 | 214 | static const rv_comp_data rvcp_addiw[] = { 215 | { rv_op_sext_w, rvcc_imm_eq_zero }, 216 | { rv_op_illegal, NULL } 217 | }; 218 | 219 | static const rv_comp_data rvcp_subw[] = { 220 | { rv_op_negw, rvcc_rs1_eq_x0 }, 221 | { rv_op_illegal, NULL } 222 | }; 223 | 224 | static const rv_comp_data rvcp_csrrw[] = { 225 | { rv_op_fscsr, rvcc_fscsr }, 226 | { rv_op_fsrm, rvcc_fsrm }, 227 | { rv_op_fsflags, rvcc_fsflags }, 228 | { rv_op_illegal, NULL } 229 | }; 230 | 231 | static const rv_comp_data rvcp_csrrs[] = { 232 | { rv_op_rdcycle, rvcc_rdcycle }, 233 | { rv_op_rdtime, rvcc_rdtime }, 234 | { rv_op_rdinstret, rvcc_rdinstret }, 235 | { rv_op_rdcycleh, rvcc_rdcycleh }, 236 | { rv_op_rdtimeh, rvcc_rdtimeh }, 237 | { rv_op_rdinstreth, rvcc_rdinstreth }, 238 | { rv_op_frcsr, rvcc_frcsr }, 239 | { rv_op_frrm, rvcc_frrm }, 240 | { rv_op_frflags, rvcc_frflags }, 241 | { rv_op_illegal, NULL } 242 | }; 243 | 244 | static const rv_comp_data rvcp_csrrwi[] = { 245 | { rv_op_fsrmi, rvcc_fsrmi }, 246 | { rv_op_fsflagsi, rvcc_fsflagsi }, 247 | { rv_op_illegal, NULL } 248 | }; 249 | 250 | static const rv_comp_data rvcp_fsgnj_s[] = { 251 | { rv_op_fmv_s, rvcc_rs2_eq_rs1 }, 252 | { rv_op_illegal, NULL } 253 | }; 254 | 255 | static const rv_comp_data rvcp_fsgnjn_s[] = { 256 | { rv_op_fneg_s, rvcc_rs2_eq_rs1 }, 257 | { rv_op_illegal, NULL } 258 | }; 259 | 260 | static const rv_comp_data rvcp_fsgnjx_s[] = { 261 | { rv_op_fabs_s, rvcc_rs2_eq_rs1 }, 262 | { rv_op_illegal, NULL } 263 | }; 264 | 265 | static const rv_comp_data rvcp_fsgnj_d[] = { 266 | { rv_op_fmv_d, rvcc_rs2_eq_rs1 }, 267 | { rv_op_illegal, NULL } 268 | }; 269 | 270 | static const rv_comp_data rvcp_fsgnjn_d[] = { 271 | { rv_op_fneg_d, rvcc_rs2_eq_rs1 }, 272 | { rv_op_illegal, NULL } 273 | }; 274 | 275 | static const rv_comp_data rvcp_fsgnjx_d[] = { 276 | { rv_op_fabs_d, rvcc_rs2_eq_rs1 }, 277 | { rv_op_illegal, NULL } 278 | }; 279 | 280 | static const rv_comp_data rvcp_fsgnj_q[] = { 281 | { rv_op_fmv_q, rvcc_rs2_eq_rs1 }, 282 | { rv_op_illegal, NULL } 283 | }; 284 | 285 | static const rv_comp_data rvcp_fsgnjn_q[] = { 286 | { rv_op_fneg_q, rvcc_rs2_eq_rs1 }, 287 | { rv_op_illegal, NULL } 288 | }; 289 | 290 | static const rv_comp_data rvcp_fsgnjx_q[] = { 291 | { rv_op_fabs_q, rvcc_rs2_eq_rs1 }, 292 | { rv_op_illegal, NULL } 293 | }; 294 | 295 | /* instruction metadata */ 296 | 297 | const rv_opcode_data opcode_data[] = { 298 | { "illegal", rv_codec_illegal, rv_fmt_none, NULL, 0, 0, 0 }, 299 | { "lui", rv_codec_u, rv_fmt_rd_imm, NULL, 0, 0, 0 }, 300 | { "auipc", rv_codec_u, rv_fmt_rd_offset, NULL, 0, 0, 0 }, 301 | { "jal", rv_codec_uj, rv_fmt_rd_offset, rvcp_jal, 0, 0, 0 }, 302 | { "jalr", rv_codec_i, rv_fmt_rd_rs1_offset, rvcp_jalr, 0, 0, 0 }, 303 | { "beq", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_beq, 0, 0, 0 }, 304 | { "bne", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bne, 0, 0, 0 }, 305 | { "blt", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_blt, 0, 0, 0 }, 306 | { "bge", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bge, 0, 0, 0 }, 307 | { "bltu", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bltu, 0, 0, 0 }, 308 | { "bgeu", rv_codec_sb, rv_fmt_rs1_rs2_offset, rvcp_bgeu, 0, 0, 0 }, 309 | { "lb", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 }, 310 | { "lh", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 }, 311 | { "lw", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 }, 312 | { "lbu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 }, 313 | { "lhu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 }, 314 | { "sb", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 }, 315 | { "sh", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 }, 316 | { "sw", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 }, 317 | { "addi", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_addi, 0, 0, 0 }, 318 | { "slti", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 319 | { "sltiu", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_sltiu, 0, 0, 0 }, 320 | { "xori", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_xori, 0, 0, 0 }, 321 | { "ori", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 322 | { "andi", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 323 | { "slli", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 324 | { "srli", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 325 | { "srai", rv_codec_i_sh7, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 326 | { "add", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 327 | { "sub", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_sub, 0, 0, 0 }, 328 | { "sll", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 329 | { "slt", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_slt, 0, 0, 0 }, 330 | { "sltu", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_sltu, 0, 0, 0 }, 331 | { "xor", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 332 | { "srl", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 333 | { "sra", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 334 | { "or", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 335 | { "and", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 336 | { "fence", rv_codec_r_f, rv_fmt_pred_succ, NULL, 0, 0, 0 }, 337 | { "fence.i", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, 338 | { "lwu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 }, 339 | { "ld", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 }, 340 | { "sd", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 }, 341 | { "addiw", rv_codec_i, rv_fmt_rd_rs1_imm, rvcp_addiw, 0, 0, 0 }, 342 | { "slliw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 343 | { "srliw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 344 | { "sraiw", rv_codec_i_sh5, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 345 | { "addw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 346 | { "subw", rv_codec_r, rv_fmt_rd_rs1_rs2, rvcp_subw, 0, 0, 0 }, 347 | { "sllw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 348 | { "srlw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 349 | { "sraw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 350 | { "ldu", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 }, 351 | { "lq", rv_codec_i, rv_fmt_rd_offset_rs1, NULL, 0, 0, 0 }, 352 | { "sq", rv_codec_s, rv_fmt_rs2_offset_rs1, NULL, 0, 0, 0 }, 353 | { "addid", rv_codec_i, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 354 | { "sllid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 355 | { "srlid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 356 | { "sraid", rv_codec_i_sh6, rv_fmt_rd_rs1_imm, NULL, 0, 0, 0 }, 357 | { "addd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 358 | { "subd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 359 | { "slld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 360 | { "srld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 361 | { "srad", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 362 | { "mul", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 363 | { "mulh", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 364 | { "mulhsu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 365 | { "mulhu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 366 | { "div", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 367 | { "divu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 368 | { "rem", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 369 | { "remu", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 370 | { "mulw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 371 | { "divw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 372 | { "divuw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 373 | { "remw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 374 | { "remuw", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 375 | { "muld", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 376 | { "divd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 377 | { "divud", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 378 | { "remd", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 379 | { "remud", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, 380 | { "lr.w", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 }, 381 | { "sc.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 382 | { "amoswap.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 383 | { "amoadd.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 384 | { "amoxor.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 385 | { "amoor.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 386 | { "amoand.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 387 | { "amomin.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 388 | { "amomax.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 389 | { "amominu.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 390 | { "amomaxu.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 391 | { "lr.d", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 }, 392 | { "sc.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 393 | { "amoswap.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 394 | { "amoadd.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 395 | { "amoxor.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 396 | { "amoor.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 397 | { "amoand.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 398 | { "amomin.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 399 | { "amomax.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 400 | { "amominu.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 401 | { "amomaxu.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 402 | { "lr.q", rv_codec_r_l, rv_fmt_aqrl_rd_rs1, NULL, 0, 0, 0 }, 403 | { "sc.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 404 | { "amoswap.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 405 | { "amoadd.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 406 | { "amoxor.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 407 | { "amoor.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 408 | { "amoand.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 409 | { "amomin.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 410 | { "amomax.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 411 | { "amominu.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 412 | { "amomaxu.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, 413 | { "ecall", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, 414 | { "ebreak", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, 415 | { "uret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, 416 | { "sret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, 417 | { "hret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, 418 | { "mret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, 419 | { "dret", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, 420 | { "sfence.vm", rv_codec_r, rv_fmt_rs1, NULL, 0, 0, 0 }, 421 | { "sfence.vma", rv_codec_r, rv_fmt_rs1_rs2, NULL, 0, 0, 0 }, 422 | { "wfi", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, 423 | { "csrrw", rv_codec_i_csr, rv_fmt_rd_csr_rs1, rvcp_csrrw, 0, 0, 0 }, 424 | { "csrrs", rv_codec_i_csr, rv_fmt_rd_csr_rs1, rvcp_csrrs, 0, 0, 0 }, 425 | { "csrrc", rv_codec_i_csr, rv_fmt_rd_csr_rs1, NULL, 0, 0, 0 }, 426 | { "csrrwi", rv_codec_i_csr, rv_fmt_rd_csr_zimm, rvcp_csrrwi, 0, 0, 0 }, 427 | { "csrrsi", rv_codec_i_csr, rv_fmt_rd_csr_zimm, NULL, 0, 0, 0 }, 428 | { "csrrci", rv_codec_i_csr, rv_fmt_rd_csr_zimm, NULL, 0, 0, 0 }, 429 | { "flw", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 }, 430 | { "fsw", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 }, 431 | { "fmadd.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 432 | { "fmsub.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 433 | { "fnmsub.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 434 | { "fnmadd.s", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 435 | { "fadd.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 436 | { "fsub.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 437 | { "fmul.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 438 | { "fdiv.s", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 439 | { "fsgnj.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_s, 0, 0, 0 }, 440 | { "fsgnjn.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_s, 0, 0, 0 }, 441 | { "fsgnjx.s", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_s, 0, 0, 0 }, 442 | { "fmin.s", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 }, 443 | { "fmax.s", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 }, 444 | { "fsqrt.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 }, 445 | { "fle.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, 446 | { "flt.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, 447 | { "feq.s", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, 448 | { "fcvt.w.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 449 | { "fcvt.wu.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 450 | { "fcvt.s.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 451 | { "fcvt.s.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 452 | { "fmv.x.s", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 }, 453 | { "fclass.s", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 }, 454 | { "fmv.s.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 }, 455 | { "fcvt.l.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 456 | { "fcvt.lu.s", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 457 | { "fcvt.s.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 458 | { "fcvt.s.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 459 | { "fld", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 }, 460 | { "fsd", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 }, 461 | { "fmadd.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 462 | { "fmsub.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 463 | { "fnmsub.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 464 | { "fnmadd.d", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 465 | { "fadd.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 466 | { "fsub.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 467 | { "fmul.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 468 | { "fdiv.d", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 469 | { "fsgnj.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_d, 0, 0, 0 }, 470 | { "fsgnjn.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_d, 0, 0, 0 }, 471 | { "fsgnjx.d", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_d, 0, 0, 0 }, 472 | { "fmin.d", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 }, 473 | { "fmax.d", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 }, 474 | { "fcvt.s.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 }, 475 | { "fcvt.d.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 }, 476 | { "fsqrt.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 }, 477 | { "fle.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, 478 | { "flt.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, 479 | { "feq.d", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, 480 | { "fcvt.w.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 481 | { "fcvt.wu.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 482 | { "fcvt.d.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 483 | { "fcvt.d.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 484 | { "fclass.d", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 }, 485 | { "fcvt.l.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 486 | { "fcvt.lu.d", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 487 | { "fmv.x.d", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 }, 488 | { "fcvt.d.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 489 | { "fcvt.d.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 490 | { "fmv.d.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 }, 491 | { "flq", rv_codec_i, rv_fmt_frd_offset_rs1, NULL, 0, 0, 0 }, 492 | { "fsq", rv_codec_s, rv_fmt_frs2_offset_rs1, NULL, 0, 0, 0 }, 493 | { "fmadd.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 494 | { "fmsub.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 495 | { "fnmsub.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 496 | { "fnmadd.q", rv_codec_r4_m, rv_fmt_rm_frd_frs1_frs2_frs3, NULL, 0, 0, 0 }, 497 | { "fadd.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 498 | { "fsub.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 499 | { "fmul.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 500 | { "fdiv.q", rv_codec_r_m, rv_fmt_rm_frd_frs1_frs2, NULL, 0, 0, 0 }, 501 | { "fsgnj.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnj_q, 0, 0, 0 }, 502 | { "fsgnjn.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjn_q, 0, 0, 0 }, 503 | { "fsgnjx.q", rv_codec_r, rv_fmt_frd_frs1_frs2, rvcp_fsgnjx_q, 0, 0, 0 }, 504 | { "fmin.q", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 }, 505 | { "fmax.q", rv_codec_r, rv_fmt_frd_frs1_frs2, NULL, 0, 0, 0 }, 506 | { "fcvt.s.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 }, 507 | { "fcvt.q.s", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 }, 508 | { "fcvt.d.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 }, 509 | { "fcvt.q.d", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 }, 510 | { "fsqrt.q", rv_codec_r_m, rv_fmt_rm_frd_frs1, NULL, 0, 0, 0 }, 511 | { "fle.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, 512 | { "flt.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, 513 | { "feq.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, 514 | { "fcvt.w.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 515 | { "fcvt.wu.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 516 | { "fcvt.q.w", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 517 | { "fcvt.q.wu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 518 | { "fclass.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 }, 519 | { "fcvt.l.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 520 | { "fcvt.lu.q", rv_codec_r_m, rv_fmt_rm_rd_frs1, NULL, 0, 0, 0 }, 521 | { "fcvt.q.l", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 522 | { "fcvt.q.lu", rv_codec_r_m, rv_fmt_rm_frd_rs1, NULL, 0, 0, 0 }, 523 | { "fmv.x.q", rv_codec_r, rv_fmt_rd_frs1, NULL, 0, 0, 0 }, 524 | { "fmv.q.x", rv_codec_r, rv_fmt_frd_rs1, NULL, 0, 0, 0 }, 525 | { "c.addi4spn", rv_codec_ciw_4spn, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi, rvcd_imm_nz }, 526 | { "c.fld", rv_codec_cl_ld, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, 0 }, 527 | { "c.lw", rv_codec_cl_lw, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw }, 528 | { "c.flw", rv_codec_cl_lw, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 }, 529 | { "c.fsd", rv_codec_cs_sd, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, rv_op_fsd, 0 }, 530 | { "c.sw", rv_codec_cs_sw, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw }, 531 | { "c.fsw", rv_codec_cs_sw, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 }, 532 | { "c.nop", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, 533 | { "c.addi", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi, rvcd_imm_nz_hint }, 534 | { "c.jal", rv_codec_cj_jal, rv_fmt_rd_offset, NULL, rv_op_jal, 0, 0 }, 535 | { "c.li", rv_codec_ci_li, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, 536 | { "c.addi16sp", rv_codec_ci_16sp, rv_fmt_rd_rs1_imm, NULL, rv_op_addi, rv_op_addi, rv_op_addi, rvcd_imm_nz }, 537 | { "c.lui", rv_codec_ci_lui, rv_fmt_rd_imm, NULL, rv_op_lui, rv_op_lui, rv_op_lui, rvcd_imm_nz }, 538 | { "c.srli", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srli, rv_op_srli, rv_op_srli, rvcd_imm_nz }, 539 | { "c.srai", rv_codec_cb_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_srai, rv_op_srai, rv_op_srai, rvcd_imm_nz }, 540 | { "c.andi", rv_codec_cb_imm, rv_fmt_rd_rs1_imm, NULL, rv_op_andi, rv_op_andi, rv_op_andi, rvcd_imm_nz }, 541 | { "c.sub", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_sub, rv_op_sub, rv_op_sub }, 542 | { "c.xor", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_xor, rv_op_xor, rv_op_xor }, 543 | { "c.or", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_or, rv_op_or, rv_op_or }, 544 | { "c.and", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_and, rv_op_and, rv_op_and }, 545 | { "c.subw", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_subw, rv_op_subw, rv_op_subw }, 546 | { "c.addw", rv_codec_cs, rv_fmt_rd_rs1_rs2, NULL, rv_op_addw, rv_op_addw, rv_op_addw }, 547 | { "c.j", rv_codec_cj, rv_fmt_rd_offset, NULL, rv_op_jal, rv_op_jal, rv_op_jal }, 548 | { "c.beqz", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_beq, rv_op_beq, rv_op_beq }, 549 | { "c.bnez", rv_codec_cb, rv_fmt_rs1_rs2_offset, NULL, rv_op_bne, rv_op_bne, rv_op_bne }, 550 | { "c.slli", rv_codec_ci_sh6, rv_fmt_rd_rs1_imm, NULL, rv_op_slli, rv_op_slli, rv_op_slli, rvcd_imm_nz }, 551 | { "c.fldsp", rv_codec_ci_ldsp, rv_fmt_frd_offset_rs1, NULL, rv_op_fld, rv_op_fld, rv_op_fld }, 552 | { "c.lwsp", rv_codec_ci_lwsp, rv_fmt_rd_offset_rs1, NULL, rv_op_lw, rv_op_lw, rv_op_lw }, 553 | { "c.flwsp", rv_codec_ci_lwsp, rv_fmt_frd_offset_rs1, NULL, rv_op_flw, 0, 0 }, 554 | { "c.jr", rv_codec_cr_jr, rv_fmt_rd_rs1_offset, NULL, rv_op_jalr, rv_op_jalr, rv_op_jalr }, 555 | { "c.mv", rv_codec_cr_mv, rv_fmt_rd_rs1_rs2, NULL, rv_op_addi, rv_op_addi, rv_op_addi }, 556 | { "c.ebreak", rv_codec_ci_none, rv_fmt_none, NULL, rv_op_ebreak, rv_op_ebreak, rv_op_ebreak }, 557 | { "c.jalr", rv_codec_cr_jalr, rv_fmt_rd_rs1_offset, NULL, rv_op_jalr, rv_op_jalr, rv_op_jalr }, 558 | { "c.add", rv_codec_cr, rv_fmt_rd_rs1_rs2, NULL, rv_op_add, rv_op_add, rv_op_add }, 559 | { "c.fsdsp", rv_codec_css_sdsp, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsd, rv_op_fsd, rv_op_fsd }, 560 | { "c.swsp", rv_codec_css_swsp, rv_fmt_rs2_offset_rs1, NULL, rv_op_sw, rv_op_sw, rv_op_sw }, 561 | { "c.fswsp", rv_codec_css_swsp, rv_fmt_frs2_offset_rs1, NULL, rv_op_fsw, 0, 0 }, 562 | { "c.ld", rv_codec_cl_ld, rv_fmt_rd_offset_rs1, NULL, 0, rv_op_ld, rv_op_ld }, 563 | { "c.sd", rv_codec_cs_sd, rv_fmt_rs2_offset_rs1, NULL, 0, rv_op_sd, rv_op_sd }, 564 | { "c.addiw", rv_codec_ci, rv_fmt_rd_rs1_imm, NULL, 0, rv_op_addiw, rv_op_addiw }, 565 | { "c.ldsp", rv_codec_ci_ldsp, rv_fmt_rd_offset_rs1, NULL, 0, rv_op_ld, rv_op_ld }, 566 | { "c.sdsp", rv_codec_css_sdsp, rv_fmt_rs2_offset_rs1, NULL, 0, rv_op_sd, rv_op_sd }, 567 | { "c.lq", rv_codec_cl_lq, rv_fmt_rd_offset_rs1, NULL, 0, 0, rv_op_lq }, 568 | { "c.sq", rv_codec_cs_sq, rv_fmt_rs2_offset_rs1, NULL, 0, 0, rv_op_sq }, 569 | { "c.lqsp", rv_codec_ci_lqsp, rv_fmt_rd_offset_rs1, NULL, 0, 0, rv_op_lq }, 570 | { "c.sqsp", rv_codec_css_sqsp, rv_fmt_rs2_offset_rs1, NULL, 0, 0, rv_op_sq }, 571 | { "nop", rv_codec_i, rv_fmt_none, NULL, 0, 0, 0 }, 572 | { "mv", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 573 | { "not", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 574 | { "neg", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 }, 575 | { "negw", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 }, 576 | { "sext.w", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 577 | { "seqz", rv_codec_i, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 578 | { "snez", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 }, 579 | { "sltz", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 580 | { "sgtz", rv_codec_r, rv_fmt_rd_rs2, NULL, 0, 0, 0 }, 581 | { "fmv.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 582 | { "fabs.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 583 | { "fneg.s", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 584 | { "fmv.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 585 | { "fabs.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 586 | { "fneg.d", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 587 | { "fmv.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 588 | { "fabs.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 589 | { "fneg.q", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 590 | { "beqz", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 }, 591 | { "bnez", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 }, 592 | { "blez", rv_codec_sb, rv_fmt_rs2_offset, NULL, 0, 0, 0 }, 593 | { "bgez", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 }, 594 | { "bltz", rv_codec_sb, rv_fmt_rs1_offset, NULL, 0, 0, 0 }, 595 | { "bgtz", rv_codec_sb, rv_fmt_rs2_offset, NULL, 0, 0, 0 }, 596 | { "ble", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 }, 597 | { "bleu", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 }, 598 | { "bgt", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 }, 599 | { "bgtu", rv_codec_sb, rv_fmt_rs2_rs1_offset, NULL, 0, 0, 0 }, 600 | { "j", rv_codec_uj, rv_fmt_offset, NULL, 0, 0, 0 }, 601 | { "ret", rv_codec_i, rv_fmt_none, NULL, 0, 0, 0 }, 602 | { "jr", rv_codec_i, rv_fmt_rs1, NULL, 0, 0, 0 }, 603 | { "rdcycle", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 }, 604 | { "rdtime", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 }, 605 | { "rdinstret", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 }, 606 | { "rdcycleh", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 }, 607 | { "rdtimeh", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 }, 608 | { "rdinstreth", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 }, 609 | { "frcsr", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 }, 610 | { "frrm", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 }, 611 | { "frflags", rv_codec_i_csr, rv_fmt_rd, NULL, 0, 0, 0 }, 612 | { "fscsr", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 613 | { "fsrm", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 614 | { "fsflags", rv_codec_i_csr, rv_fmt_rd_rs1, NULL, 0, 0, 0 }, 615 | { "fsrmi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 }, 616 | { "fsflagsi", rv_codec_i_csr, rv_fmt_rd_zimm, NULL, 0, 0, 0 }, 617 | }; 618 | 619 | /* CSR names */ 620 | 621 | static const char *csr_name(int csrno) 622 | { 623 | switch (csrno) { 624 | case 0x0000: return "ustatus"; 625 | case 0x0001: return "fflags"; 626 | case 0x0002: return "frm"; 627 | case 0x0003: return "fcsr"; 628 | case 0x0004: return "uie"; 629 | case 0x0005: return "utvec"; 630 | case 0x0007: return "utvt"; 631 | case 0x0008: return "vstart"; 632 | case 0x0009: return "vxsat"; 633 | case 0x000a: return "vxrm"; 634 | case 0x000f: return "vcsr"; 635 | case 0x0040: return "uscratch"; 636 | case 0x0041: return "uepc"; 637 | case 0x0042: return "ucause"; 638 | case 0x0043: return "utval"; 639 | case 0x0044: return "uip"; 640 | case 0x0045: return "unxti"; 641 | case 0x0046: return "uintstatus"; 642 | case 0x0048: return "uscratchcsw"; 643 | case 0x0049: return "uscratchcswl"; 644 | case 0x0100: return "sstatus"; 645 | case 0x0102: return "sedeleg"; 646 | case 0x0103: return "sideleg"; 647 | case 0x0104: return "sie"; 648 | case 0x0105: return "stvec"; 649 | case 0x0106: return "scounteren"; 650 | case 0x0107: return "stvt"; 651 | case 0x0140: return "sscratch"; 652 | case 0x0141: return "sepc"; 653 | case 0x0142: return "scause"; 654 | case 0x0143: return "stval"; 655 | case 0x0144: return "sip"; 656 | case 0x0145: return "snxti"; 657 | case 0x0146: return "sintstatus"; 658 | case 0x0148: return "sscratchcsw"; 659 | case 0x0149: return "sscratchcswl"; 660 | case 0x0180: return "satp"; 661 | case 0x0200: return "vsstatus"; 662 | case 0x0204: return "vsie"; 663 | case 0x0205: return "vstvec"; 664 | case 0x0240: return "vsscratch"; 665 | case 0x0241: return "vsepc"; 666 | case 0x0242: return "vscause"; 667 | case 0x0243: return "vstval"; 668 | case 0x0244: return "vsip"; 669 | case 0x0280: return "vsatp"; 670 | case 0x0300: return "mstatus"; 671 | case 0x0301: return "misa"; 672 | case 0x0302: return "medeleg"; 673 | case 0x0303: return "mideleg"; 674 | case 0x0304: return "mie"; 675 | case 0x0305: return "mtvec"; 676 | case 0x0306: return "mcounteren"; 677 | case 0x0307: return "mtvt"; 678 | case 0x0310: return "mstatush"; 679 | case 0x0320: return "mcountinhibit"; 680 | case 0x0323: return "mhpmevent3"; 681 | case 0x0324: return "mhpmevent4"; 682 | case 0x0325: return "mhpmevent5"; 683 | case 0x0326: return "mhpmevent6"; 684 | case 0x0327: return "mhpmevent7"; 685 | case 0x0328: return "mhpmevent8"; 686 | case 0x0329: return "mhpmevent9"; 687 | case 0x032a: return "mhpmevent10"; 688 | case 0x032b: return "mhpmevent11"; 689 | case 0x032c: return "mhpmevent12"; 690 | case 0x032d: return "mhpmevent13"; 691 | case 0x032e: return "mhpmevent14"; 692 | case 0x032f: return "mhpmevent15"; 693 | case 0x0330: return "mhpmevent16"; 694 | case 0x0331: return "mhpmevent17"; 695 | case 0x0332: return "mhpmevent18"; 696 | case 0x0333: return "mhpmevent19"; 697 | case 0x0334: return "mhpmevent20"; 698 | case 0x0335: return "mhpmevent21"; 699 | case 0x0336: return "mhpmevent22"; 700 | case 0x0337: return "mhpmevent23"; 701 | case 0x0338: return "mhpmevent24"; 702 | case 0x0339: return "mhpmevent25"; 703 | case 0x033a: return "mhpmevent26"; 704 | case 0x033b: return "mhpmevent27"; 705 | case 0x033c: return "mhpmevent28"; 706 | case 0x033d: return "mhpmevent29"; 707 | case 0x033e: return "mhpmevent30"; 708 | case 0x033f: return "mhpmevent31"; 709 | case 0x0340: return "mscratch"; 710 | case 0x0341: return "mepc"; 711 | case 0x0342: return "mcause"; 712 | case 0x0343: return "mtval"; 713 | case 0x0344: return "mip"; 714 | case 0x0345: return "mnxti"; 715 | case 0x0346: return "mintstatus"; 716 | case 0x0348: return "mscratchcsw"; 717 | case 0x0349: return "mscratchcswl"; 718 | case 0x034a: return "mtinst"; 719 | case 0x034b: return "mtval2"; 720 | case 0x03a0: return "pmpcfg0"; 721 | case 0x03a1: return "pmpcfg1"; 722 | case 0x03a2: return "pmpcfg2"; 723 | case 0x03a3: return "pmpcfg3"; 724 | case 0x03b0: return "pmpaddr0"; 725 | case 0x03b1: return "pmpaddr1"; 726 | case 0x03b2: return "pmpaddr2"; 727 | case 0x03b3: return "pmpaddr3"; 728 | case 0x03b4: return "pmpaddr4"; 729 | case 0x03b5: return "pmpaddr5"; 730 | case 0x03b6: return "pmpaddr6"; 731 | case 0x03b7: return "pmpaddr7"; 732 | case 0x03b8: return "pmpaddr8"; 733 | case 0x03b9: return "pmpaddr9"; 734 | case 0x03ba: return "pmpaddr10"; 735 | case 0x03bb: return "pmpaddr11"; 736 | case 0x03bc: return "pmpaddr12"; 737 | case 0x03bd: return "pmpaddr13"; 738 | case 0x03be: return "pmpaddr14"; 739 | case 0x03bf: return "pmpaddr15"; 740 | case 0x0600: return "hstatus"; 741 | case 0x0602: return "hedeleg"; 742 | case 0x0603: return "hideleg"; 743 | case 0x0604: return "hie"; 744 | case 0x0605: return "htimedelta"; 745 | case 0x0606: return "hcounteren"; 746 | case 0x0607: return "hgeie"; 747 | case 0x0615: return "htimedeltah"; 748 | case 0x0643: return "htval"; 749 | case 0x0644: return "hip"; 750 | case 0x0645: return "hvip"; 751 | case 0x064a: return "htinst"; 752 | case 0x0680: return "hgatp"; 753 | case 0x07a0: return "tselect"; 754 | case 0x07a1: return "tdata1"; 755 | case 0x07a2: return "tdata2"; 756 | case 0x07a3: return "tdata3"; 757 | case 0x07a4: return "tinfo"; 758 | case 0x07a5: return "tcontrol"; 759 | case 0x07a8: return "mcontext"; 760 | case 0x07a9: return "mnoise"; 761 | case 0x07aa: return "scontext"; 762 | case 0x07b0: return "dcsr"; 763 | case 0x07b1: return "dpc"; 764 | case 0x07b2: return "dscratch0"; 765 | case 0x07b3: return "dscratch1"; 766 | case 0x0b00: return "mcycle"; 767 | case 0x0b02: return "minstret"; 768 | case 0x0b03: return "mhpmcounter3"; 769 | case 0x0b04: return "mhpmcounter4"; 770 | case 0x0b05: return "mhpmcounter5"; 771 | case 0x0b06: return "mhpmcounter6"; 772 | case 0x0b07: return "mhpmcounter7"; 773 | case 0x0b08: return "mhpmcounter8"; 774 | case 0x0b09: return "mhpmcounter9"; 775 | case 0x0b0a: return "mhpmcounter10"; 776 | case 0x0b0b: return "mhpmcounter11"; 777 | case 0x0b0c: return "mhpmcounter12"; 778 | case 0x0b0d: return "mhpmcounter13"; 779 | case 0x0b0e: return "mhpmcounter14"; 780 | case 0x0b0f: return "mhpmcounter15"; 781 | case 0x0b10: return "mhpmcounter16"; 782 | case 0x0b11: return "mhpmcounter17"; 783 | case 0x0b12: return "mhpmcounter18"; 784 | case 0x0b13: return "mhpmcounter19"; 785 | case 0x0b14: return "mhpmcounter20"; 786 | case 0x0b15: return "mhpmcounter21"; 787 | case 0x0b16: return "mhpmcounter22"; 788 | case 0x0b17: return "mhpmcounter23"; 789 | case 0x0b18: return "mhpmcounter24"; 790 | case 0x0b19: return "mhpmcounter25"; 791 | case 0x0b1a: return "mhpmcounter26"; 792 | case 0x0b1b: return "mhpmcounter27"; 793 | case 0x0b1c: return "mhpmcounter28"; 794 | case 0x0b1d: return "mhpmcounter29"; 795 | case 0x0b1e: return "mhpmcounter30"; 796 | case 0x0b1f: return "mhpmcounter31"; 797 | case 0x0b80: return "mcycleh"; 798 | case 0x0b82: return "minstreth"; 799 | case 0x0b83: return "mhpmcounter3h"; 800 | case 0x0b84: return "mhpmcounter4h"; 801 | case 0x0b85: return "mhpmcounter5h"; 802 | case 0x0b86: return "mhpmcounter6h"; 803 | case 0x0b87: return "mhpmcounter7h"; 804 | case 0x0b88: return "mhpmcounter8h"; 805 | case 0x0b89: return "mhpmcounter9h"; 806 | case 0x0b8a: return "mhpmcounter10h"; 807 | case 0x0b8b: return "mhpmcounter11h"; 808 | case 0x0b8c: return "mhpmcounter12h"; 809 | case 0x0b8d: return "mhpmcounter13h"; 810 | case 0x0b8e: return "mhpmcounter14h"; 811 | case 0x0b8f: return "mhpmcounter15h"; 812 | case 0x0b90: return "mhpmcounter16h"; 813 | case 0x0b91: return "mhpmcounter17h"; 814 | case 0x0b92: return "mhpmcounter18h"; 815 | case 0x0b93: return "mhpmcounter19h"; 816 | case 0x0b94: return "mhpmcounter20h"; 817 | case 0x0b95: return "mhpmcounter21h"; 818 | case 0x0b96: return "mhpmcounter22h"; 819 | case 0x0b97: return "mhpmcounter23h"; 820 | case 0x0b98: return "mhpmcounter24h"; 821 | case 0x0b99: return "mhpmcounter25h"; 822 | case 0x0b9a: return "mhpmcounter26h"; 823 | case 0x0b9b: return "mhpmcounter27h"; 824 | case 0x0b9c: return "mhpmcounter28h"; 825 | case 0x0b9d: return "mhpmcounter29h"; 826 | case 0x0b9e: return "mhpmcounter30h"; 827 | case 0x0b9f: return "mhpmcounter31h"; 828 | case 0x0c00: return "cycle"; 829 | case 0x0c01: return "time"; 830 | case 0x0c02: return "instret"; 831 | case 0x0c03: return "hpmcounter3"; 832 | case 0x0c04: return "hpmcounter4"; 833 | case 0x0c05: return "hpmcounter5"; 834 | case 0x0c06: return "hpmcounter6"; 835 | case 0x0c07: return "hpmcounter7"; 836 | case 0x0c08: return "hpmcounter8"; 837 | case 0x0c09: return "hpmcounter9"; 838 | case 0x0c0a: return "hpmcounter10"; 839 | case 0x0c0b: return "hpmcounter11"; 840 | case 0x0c0c: return "hpmcounter12"; 841 | case 0x0c0d: return "hpmcounter13"; 842 | case 0x0c0e: return "hpmcounter14"; 843 | case 0x0c0f: return "hpmcounter15"; 844 | case 0x0c10: return "hpmcounter16"; 845 | case 0x0c11: return "hpmcounter17"; 846 | case 0x0c12: return "hpmcounter18"; 847 | case 0x0c13: return "hpmcounter19"; 848 | case 0x0c14: return "hpmcounter20"; 849 | case 0x0c15: return "hpmcounter21"; 850 | case 0x0c16: return "hpmcounter22"; 851 | case 0x0c17: return "hpmcounter23"; 852 | case 0x0c18: return "hpmcounter24"; 853 | case 0x0c19: return "hpmcounter25"; 854 | case 0x0c1a: return "hpmcounter26"; 855 | case 0x0c1b: return "hpmcounter27"; 856 | case 0x0c1c: return "hpmcounter28"; 857 | case 0x0c1d: return "hpmcounter29"; 858 | case 0x0c1e: return "hpmcounter30"; 859 | case 0x0c1f: return "hpmcounter31"; 860 | case 0x0c20: return "vl"; 861 | case 0x0c21: return "vtype"; 862 | case 0x0c22: return "vlenb"; 863 | case 0x0c80: return "cycleh"; 864 | case 0x0c81: return "timeh"; 865 | case 0x0c82: return "instreth"; 866 | case 0x0c83: return "hpmcounter3h"; 867 | case 0x0c84: return "hpmcounter4h"; 868 | case 0x0c85: return "hpmcounter5h"; 869 | case 0x0c86: return "hpmcounter6h"; 870 | case 0x0c87: return "hpmcounter7h"; 871 | case 0x0c88: return "hpmcounter8h"; 872 | case 0x0c89: return "hpmcounter9h"; 873 | case 0x0c8a: return "hpmcounter10h"; 874 | case 0x0c8b: return "hpmcounter11h"; 875 | case 0x0c8c: return "hpmcounter12h"; 876 | case 0x0c8d: return "hpmcounter13h"; 877 | case 0x0c8e: return "hpmcounter14h"; 878 | case 0x0c8f: return "hpmcounter15h"; 879 | case 0x0c90: return "hpmcounter16h"; 880 | case 0x0c91: return "hpmcounter17h"; 881 | case 0x0c92: return "hpmcounter18h"; 882 | case 0x0c93: return "hpmcounter19h"; 883 | case 0x0c94: return "hpmcounter20h"; 884 | case 0x0c95: return "hpmcounter21h"; 885 | case 0x0c96: return "hpmcounter22h"; 886 | case 0x0c97: return "hpmcounter23h"; 887 | case 0x0c98: return "hpmcounter24h"; 888 | case 0x0c99: return "hpmcounter25h"; 889 | case 0x0c9a: return "hpmcounter26h"; 890 | case 0x0c9b: return "hpmcounter27h"; 891 | case 0x0c9c: return "hpmcounter28h"; 892 | case 0x0c9d: return "hpmcounter29h"; 893 | case 0x0c9e: return "hpmcounter30h"; 894 | case 0x0c9f: return "hpmcounter31h"; 895 | case 0x0e12: return "hgeip"; 896 | case 0x0f11: return "mvendorid"; 897 | case 0x0f12: return "marchid"; 898 | case 0x0f13: return "mimpid"; 899 | case 0x0f14: return "mhartid"; 900 | case 0x0f15: return "mentropy"; 901 | default: return NULL; 902 | } 903 | } 904 | 905 | /* decode opcode */ 906 | 907 | static void decode_inst_opcode(rv_decode *dec, rv_isa isa) 908 | { 909 | rv_inst inst = dec->inst; 910 | rv_opcode op = rv_op_illegal; 911 | switch (((inst >> 0) & 0b11)) { 912 | case 0: 913 | switch (((inst >> 13) & 0b111)) { 914 | case 0: op = rv_op_c_addi4spn; break; 915 | case 1: op = (isa == rv128) ? rv_op_c_lq : rv_op_c_fld; break; 916 | case 2: op = rv_op_c_lw; break; 917 | case 3: op = (isa == rv32) ? rv_op_c_flw : rv_op_c_ld; break; 918 | case 5: op = (isa == rv128) ? rv_op_c_sq : rv_op_c_fsd; break; 919 | case 6: op = rv_op_c_sw; break; 920 | case 7: op = (isa == rv32) ? rv_op_c_fsw : rv_op_c_sd; break; 921 | } 922 | break; 923 | case 1: 924 | switch (((inst >> 13) & 0b111)) { 925 | case 0: 926 | switch (((inst >> 2) & 0b11111111111)) { 927 | case 0: op = rv_op_c_nop; break; 928 | default: op = rv_op_c_addi; break; 929 | } 930 | break; 931 | case 1: op = (isa == rv32) ? rv_op_c_jal : rv_op_c_addiw; break; 932 | case 2: op = rv_op_c_li; break; 933 | case 3: 934 | switch (((inst >> 7) & 0b11111)) { 935 | case 2: op = rv_op_c_addi16sp; break; 936 | default: op = rv_op_c_lui; break; 937 | } 938 | break; 939 | case 4: 940 | switch (((inst >> 10) & 0b11)) { 941 | case 0: 942 | op = rv_op_c_srli; 943 | break; 944 | case 1: 945 | op = rv_op_c_srai; 946 | break; 947 | case 2: op = rv_op_c_andi; break; 948 | case 3: 949 | switch (((inst >> 10) & 0b100) | ((inst >> 5) & 0b011)) { 950 | case 0: op = rv_op_c_sub; break; 951 | case 1: op = rv_op_c_xor; break; 952 | case 2: op = rv_op_c_or; break; 953 | case 3: op = rv_op_c_and; break; 954 | case 4: op = rv_op_c_subw; break; 955 | case 5: op = rv_op_c_addw; break; 956 | } 957 | break; 958 | } 959 | break; 960 | case 5: op = rv_op_c_j; break; 961 | case 6: op = rv_op_c_beqz; break; 962 | case 7: op = rv_op_c_bnez; break; 963 | } 964 | break; 965 | case 2: 966 | switch (((inst >> 13) & 0b111)) { 967 | case 0: 968 | op = rv_op_c_slli; 969 | break; 970 | case 1: op = (isa == rv128) ? rv_op_c_lqsp : rv_op_c_fldsp; break; 971 | case 2: op = rv_op_c_lwsp; break; 972 | case 3: op = (isa == rv32) ? rv_op_c_flwsp : rv_op_c_ldsp; break; 973 | case 4: 974 | switch (((inst >> 12) & 0b1)) { 975 | case 0: 976 | switch (((inst >> 2) & 0b11111)) { 977 | case 0: op = rv_op_c_jr; break; 978 | default: op = rv_op_c_mv; break; 979 | } 980 | break; 981 | case 1: 982 | switch (((inst >> 2) & 0b11111)) { 983 | case 0: 984 | switch (((inst >> 7) & 0b11111)) { 985 | case 0: op = rv_op_c_ebreak; break; 986 | default: op = rv_op_c_jalr; break; 987 | } 988 | break; 989 | default: op = rv_op_c_add; break; 990 | } 991 | break; 992 | } 993 | break; 994 | case 5: op = (isa == rv128) ? rv_op_c_sqsp : rv_op_c_fsdsp; break; 995 | case 6: op = rv_op_c_swsp; break; 996 | case 7: op = (isa == rv32) ? rv_op_c_fswsp : rv_op_c_sdsp; break; 997 | } 998 | break; 999 | case 3: 1000 | switch (((inst >> 2) & 0b11111)) { 1001 | case 0: 1002 | switch (((inst >> 12) & 0b111)) { 1003 | case 0: op = rv_op_lb; break; 1004 | case 1: op = rv_op_lh; break; 1005 | case 2: op = rv_op_lw; break; 1006 | case 3: op = rv_op_ld; break; 1007 | case 4: op = rv_op_lbu; break; 1008 | case 5: op = rv_op_lhu; break; 1009 | case 6: op = rv_op_lwu; break; 1010 | case 7: op = rv_op_ldu; break; 1011 | } 1012 | break; 1013 | case 1: 1014 | switch (((inst >> 12) & 0b111)) { 1015 | case 2: op = rv_op_flw; break; 1016 | case 3: op = rv_op_fld; break; 1017 | case 4: op = rv_op_flq; break; 1018 | } 1019 | break; 1020 | case 3: 1021 | switch (((inst >> 12) & 0b111)) { 1022 | case 0: op = rv_op_fence; break; 1023 | case 1: op = rv_op_fence_i; break; 1024 | case 2: op = rv_op_lq; break; 1025 | } 1026 | break; 1027 | case 4: 1028 | switch (((inst >> 12) & 0b111)) { 1029 | case 0: op = rv_op_addi; break; 1030 | case 1: 1031 | switch (((inst >> 27) & 0b11111)) { 1032 | case 0: op = rv_op_slli; break; 1033 | } 1034 | break; 1035 | case 2: op = rv_op_slti; break; 1036 | case 3: op = rv_op_sltiu; break; 1037 | case 4: op = rv_op_xori; break; 1038 | case 5: 1039 | switch (((inst >> 27) & 0b11111)) { 1040 | case 0: op = rv_op_srli; break; 1041 | case 8: op = rv_op_srai; break; 1042 | } 1043 | break; 1044 | case 6: op = rv_op_ori; break; 1045 | case 7: op = rv_op_andi; break; 1046 | } 1047 | break; 1048 | case 5: op = rv_op_auipc; break; 1049 | case 6: 1050 | switch (((inst >> 12) & 0b111)) { 1051 | case 0: op = rv_op_addiw; break; 1052 | case 1: 1053 | switch (((inst >> 25) & 0b1111111)) { 1054 | case 0: op = rv_op_slliw; break; 1055 | } 1056 | break; 1057 | case 5: 1058 | switch (((inst >> 25) & 0b1111111)) { 1059 | case 0: op = rv_op_srliw; break; 1060 | case 32: op = rv_op_sraiw; break; 1061 | } 1062 | break; 1063 | } 1064 | break; 1065 | case 8: 1066 | switch (((inst >> 12) & 0b111)) { 1067 | case 0: op = rv_op_sb; break; 1068 | case 1: op = rv_op_sh; break; 1069 | case 2: op = rv_op_sw; break; 1070 | case 3: op = rv_op_sd; break; 1071 | case 4: op = rv_op_sq; break; 1072 | } 1073 | break; 1074 | case 9: 1075 | switch (((inst >> 12) & 0b111)) { 1076 | case 2: op = rv_op_fsw; break; 1077 | case 3: op = rv_op_fsd; break; 1078 | case 4: op = rv_op_fsq; break; 1079 | } 1080 | break; 1081 | case 11: 1082 | switch (((inst >> 24) & 0b11111000) | ((inst >> 12) & 0b00000111)) { 1083 | case 2: op = rv_op_amoadd_w; break; 1084 | case 3: op = rv_op_amoadd_d; break; 1085 | case 4: op = rv_op_amoadd_q; break; 1086 | case 10: op = rv_op_amoswap_w; break; 1087 | case 11: op = rv_op_amoswap_d; break; 1088 | case 12: op = rv_op_amoswap_q; break; 1089 | case 18: 1090 | switch (((inst >> 20) & 0b11111)) { 1091 | case 0: op = rv_op_lr_w; break; 1092 | } 1093 | break; 1094 | case 19: 1095 | switch (((inst >> 20) & 0b11111)) { 1096 | case 0: op = rv_op_lr_d; break; 1097 | } 1098 | break; 1099 | case 20: 1100 | switch (((inst >> 20) & 0b11111)) { 1101 | case 0: op = rv_op_lr_q; break; 1102 | } 1103 | break; 1104 | case 26: op = rv_op_sc_w; break; 1105 | case 27: op = rv_op_sc_d; break; 1106 | case 28: op = rv_op_sc_q; break; 1107 | case 34: op = rv_op_amoxor_w; break; 1108 | case 35: op = rv_op_amoxor_d; break; 1109 | case 36: op = rv_op_amoxor_q; break; 1110 | case 66: op = rv_op_amoor_w; break; 1111 | case 67: op = rv_op_amoor_d; break; 1112 | case 68: op = rv_op_amoor_q; break; 1113 | case 98: op = rv_op_amoand_w; break; 1114 | case 99: op = rv_op_amoand_d; break; 1115 | case 100: op = rv_op_amoand_q; break; 1116 | case 130: op = rv_op_amomin_w; break; 1117 | case 131: op = rv_op_amomin_d; break; 1118 | case 132: op = rv_op_amomin_q; break; 1119 | case 162: op = rv_op_amomax_w; break; 1120 | case 163: op = rv_op_amomax_d; break; 1121 | case 164: op = rv_op_amomax_q; break; 1122 | case 194: op = rv_op_amominu_w; break; 1123 | case 195: op = rv_op_amominu_d; break; 1124 | case 196: op = rv_op_amominu_q; break; 1125 | case 226: op = rv_op_amomaxu_w; break; 1126 | case 227: op = rv_op_amomaxu_d; break; 1127 | case 228: op = rv_op_amomaxu_q; break; 1128 | } 1129 | break; 1130 | case 12: 1131 | switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) { 1132 | case 0: op = rv_op_add; break; 1133 | case 1: op = rv_op_sll; break; 1134 | case 2: op = rv_op_slt; break; 1135 | case 3: op = rv_op_sltu; break; 1136 | case 4: op = rv_op_xor; break; 1137 | case 5: op = rv_op_srl; break; 1138 | case 6: op = rv_op_or; break; 1139 | case 7: op = rv_op_and; break; 1140 | case 8: op = rv_op_mul; break; 1141 | case 9: op = rv_op_mulh; break; 1142 | case 10: op = rv_op_mulhsu; break; 1143 | case 11: op = rv_op_mulhu; break; 1144 | case 12: op = rv_op_div; break; 1145 | case 13: op = rv_op_divu; break; 1146 | case 14: op = rv_op_rem; break; 1147 | case 15: op = rv_op_remu; break; 1148 | case 256: op = rv_op_sub; break; 1149 | case 261: op = rv_op_sra; break; 1150 | } 1151 | break; 1152 | case 13: op = rv_op_lui; break; 1153 | case 14: 1154 | switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) { 1155 | case 0: op = rv_op_addw; break; 1156 | case 1: op = rv_op_sllw; break; 1157 | case 5: op = rv_op_srlw; break; 1158 | case 8: op = rv_op_mulw; break; 1159 | case 12: op = rv_op_divw; break; 1160 | case 13: op = rv_op_divuw; break; 1161 | case 14: op = rv_op_remw; break; 1162 | case 15: op = rv_op_remuw; break; 1163 | case 256: op = rv_op_subw; break; 1164 | case 261: op = rv_op_sraw; break; 1165 | } 1166 | break; 1167 | case 16: 1168 | switch (((inst >> 25) & 0b11)) { 1169 | case 0: op = rv_op_fmadd_s; break; 1170 | case 1: op = rv_op_fmadd_d; break; 1171 | case 3: op = rv_op_fmadd_q; break; 1172 | } 1173 | break; 1174 | case 17: 1175 | switch (((inst >> 25) & 0b11)) { 1176 | case 0: op = rv_op_fmsub_s; break; 1177 | case 1: op = rv_op_fmsub_d; break; 1178 | case 3: op = rv_op_fmsub_q; break; 1179 | } 1180 | break; 1181 | case 18: 1182 | switch (((inst >> 25) & 0b11)) { 1183 | case 0: op = rv_op_fnmsub_s; break; 1184 | case 1: op = rv_op_fnmsub_d; break; 1185 | case 3: op = rv_op_fnmsub_q; break; 1186 | } 1187 | break; 1188 | case 19: 1189 | switch (((inst >> 25) & 0b11)) { 1190 | case 0: op = rv_op_fnmadd_s; break; 1191 | case 1: op = rv_op_fnmadd_d; break; 1192 | case 3: op = rv_op_fnmadd_q; break; 1193 | } 1194 | break; 1195 | case 20: 1196 | switch (((inst >> 25) & 0b1111111)) { 1197 | case 0: op = rv_op_fadd_s; break; 1198 | case 1: op = rv_op_fadd_d; break; 1199 | case 3: op = rv_op_fadd_q; break; 1200 | case 4: op = rv_op_fsub_s; break; 1201 | case 5: op = rv_op_fsub_d; break; 1202 | case 7: op = rv_op_fsub_q; break; 1203 | case 8: op = rv_op_fmul_s; break; 1204 | case 9: op = rv_op_fmul_d; break; 1205 | case 11: op = rv_op_fmul_q; break; 1206 | case 12: op = rv_op_fdiv_s; break; 1207 | case 13: op = rv_op_fdiv_d; break; 1208 | case 15: op = rv_op_fdiv_q; break; 1209 | case 16: 1210 | switch (((inst >> 12) & 0b111)) { 1211 | case 0: op = rv_op_fsgnj_s; break; 1212 | case 1: op = rv_op_fsgnjn_s; break; 1213 | case 2: op = rv_op_fsgnjx_s; break; 1214 | } 1215 | break; 1216 | case 17: 1217 | switch (((inst >> 12) & 0b111)) { 1218 | case 0: op = rv_op_fsgnj_d; break; 1219 | case 1: op = rv_op_fsgnjn_d; break; 1220 | case 2: op = rv_op_fsgnjx_d; break; 1221 | } 1222 | break; 1223 | case 19: 1224 | switch (((inst >> 12) & 0b111)) { 1225 | case 0: op = rv_op_fsgnj_q; break; 1226 | case 1: op = rv_op_fsgnjn_q; break; 1227 | case 2: op = rv_op_fsgnjx_q; break; 1228 | } 1229 | break; 1230 | case 20: 1231 | switch (((inst >> 12) & 0b111)) { 1232 | case 0: op = rv_op_fmin_s; break; 1233 | case 1: op = rv_op_fmax_s; break; 1234 | } 1235 | break; 1236 | case 21: 1237 | switch (((inst >> 12) & 0b111)) { 1238 | case 0: op = rv_op_fmin_d; break; 1239 | case 1: op = rv_op_fmax_d; break; 1240 | } 1241 | break; 1242 | case 23: 1243 | switch (((inst >> 12) & 0b111)) { 1244 | case 0: op = rv_op_fmin_q; break; 1245 | case 1: op = rv_op_fmax_q; break; 1246 | } 1247 | break; 1248 | case 32: 1249 | switch (((inst >> 20) & 0b11111)) { 1250 | case 1: op = rv_op_fcvt_s_d; break; 1251 | case 3: op = rv_op_fcvt_s_q; break; 1252 | } 1253 | break; 1254 | case 33: 1255 | switch (((inst >> 20) & 0b11111)) { 1256 | case 0: op = rv_op_fcvt_d_s; break; 1257 | case 3: op = rv_op_fcvt_d_q; break; 1258 | } 1259 | break; 1260 | case 35: 1261 | switch (((inst >> 20) & 0b11111)) { 1262 | case 0: op = rv_op_fcvt_q_s; break; 1263 | case 1: op = rv_op_fcvt_q_d; break; 1264 | } 1265 | break; 1266 | case 44: 1267 | switch (((inst >> 20) & 0b11111)) { 1268 | case 0: op = rv_op_fsqrt_s; break; 1269 | } 1270 | break; 1271 | case 45: 1272 | switch (((inst >> 20) & 0b11111)) { 1273 | case 0: op = rv_op_fsqrt_d; break; 1274 | } 1275 | break; 1276 | case 47: 1277 | switch (((inst >> 20) & 0b11111)) { 1278 | case 0: op = rv_op_fsqrt_q; break; 1279 | } 1280 | break; 1281 | case 80: 1282 | switch (((inst >> 12) & 0b111)) { 1283 | case 0: op = rv_op_fle_s; break; 1284 | case 1: op = rv_op_flt_s; break; 1285 | case 2: op = rv_op_feq_s; break; 1286 | } 1287 | break; 1288 | case 81: 1289 | switch (((inst >> 12) & 0b111)) { 1290 | case 0: op = rv_op_fle_d; break; 1291 | case 1: op = rv_op_flt_d; break; 1292 | case 2: op = rv_op_feq_d; break; 1293 | } 1294 | break; 1295 | case 83: 1296 | switch (((inst >> 12) & 0b111)) { 1297 | case 0: op = rv_op_fle_q; break; 1298 | case 1: op = rv_op_flt_q; break; 1299 | case 2: op = rv_op_feq_q; break; 1300 | } 1301 | break; 1302 | case 96: 1303 | switch (((inst >> 20) & 0b11111)) { 1304 | case 0: op = rv_op_fcvt_w_s; break; 1305 | case 1: op = rv_op_fcvt_wu_s; break; 1306 | case 2: op = rv_op_fcvt_l_s; break; 1307 | case 3: op = rv_op_fcvt_lu_s; break; 1308 | } 1309 | break; 1310 | case 97: 1311 | switch (((inst >> 20) & 0b11111)) { 1312 | case 0: op = rv_op_fcvt_w_d; break; 1313 | case 1: op = rv_op_fcvt_wu_d; break; 1314 | case 2: op = rv_op_fcvt_l_d; break; 1315 | case 3: op = rv_op_fcvt_lu_d; break; 1316 | } 1317 | break; 1318 | case 99: 1319 | switch (((inst >> 20) & 0b11111)) { 1320 | case 0: op = rv_op_fcvt_w_q; break; 1321 | case 1: op = rv_op_fcvt_wu_q; break; 1322 | case 2: op = rv_op_fcvt_l_q; break; 1323 | case 3: op = rv_op_fcvt_lu_q; break; 1324 | } 1325 | break; 1326 | case 104: 1327 | switch (((inst >> 20) & 0b11111)) { 1328 | case 0: op = rv_op_fcvt_s_w; break; 1329 | case 1: op = rv_op_fcvt_s_wu; break; 1330 | case 2: op = rv_op_fcvt_s_l; break; 1331 | case 3: op = rv_op_fcvt_s_lu; break; 1332 | } 1333 | break; 1334 | case 105: 1335 | switch (((inst >> 20) & 0b11111)) { 1336 | case 0: op = rv_op_fcvt_d_w; break; 1337 | case 1: op = rv_op_fcvt_d_wu; break; 1338 | case 2: op = rv_op_fcvt_d_l; break; 1339 | case 3: op = rv_op_fcvt_d_lu; break; 1340 | } 1341 | break; 1342 | case 107: 1343 | switch (((inst >> 20) & 0b11111)) { 1344 | case 0: op = rv_op_fcvt_q_w; break; 1345 | case 1: op = rv_op_fcvt_q_wu; break; 1346 | case 2: op = rv_op_fcvt_q_l; break; 1347 | case 3: op = rv_op_fcvt_q_lu; break; 1348 | } 1349 | break; 1350 | case 112: 1351 | switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) { 1352 | case 0: op = rv_op_fmv_x_s; break; 1353 | case 1: op = rv_op_fclass_s; break; 1354 | } 1355 | break; 1356 | case 113: 1357 | switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) { 1358 | case 0: op = rv_op_fmv_x_d; break; 1359 | case 1: op = rv_op_fclass_d; break; 1360 | } 1361 | break; 1362 | case 115: 1363 | switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) { 1364 | case 0: op = rv_op_fmv_x_q; break; 1365 | case 1: op = rv_op_fclass_q; break; 1366 | } 1367 | break; 1368 | case 120: 1369 | switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) { 1370 | case 0: op = rv_op_fmv_s_x; break; 1371 | } 1372 | break; 1373 | case 121: 1374 | switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) { 1375 | case 0: op = rv_op_fmv_d_x; break; 1376 | } 1377 | break; 1378 | case 123: 1379 | switch (((inst >> 17) & 0b11111000) | ((inst >> 12) & 0b00000111)) { 1380 | case 0: op = rv_op_fmv_q_x; break; 1381 | } 1382 | break; 1383 | } 1384 | break; 1385 | case 22: 1386 | switch (((inst >> 12) & 0b111)) { 1387 | case 0: op = rv_op_addid; break; 1388 | case 1: 1389 | switch (((inst >> 26) & 0b111111)) { 1390 | case 0: op = rv_op_sllid; break; 1391 | } 1392 | break; 1393 | case 5: 1394 | switch (((inst >> 26) & 0b111111)) { 1395 | case 0: op = rv_op_srlid; break; 1396 | case 16: op = rv_op_sraid; break; 1397 | } 1398 | break; 1399 | } 1400 | break; 1401 | case 24: 1402 | switch (((inst >> 12) & 0b111)) { 1403 | case 0: op = rv_op_beq; break; 1404 | case 1: op = rv_op_bne; break; 1405 | case 4: op = rv_op_blt; break; 1406 | case 5: op = rv_op_bge; break; 1407 | case 6: op = rv_op_bltu; break; 1408 | case 7: op = rv_op_bgeu; break; 1409 | } 1410 | break; 1411 | case 25: 1412 | switch (((inst >> 12) & 0b111)) { 1413 | case 0: op = rv_op_jalr; break; 1414 | } 1415 | break; 1416 | case 27: op = rv_op_jal; break; 1417 | case 28: 1418 | switch (((inst >> 12) & 0b111)) { 1419 | case 0: 1420 | switch (((inst >> 20) & 0b111111100000) | ((inst >> 7) & 0b000000011111)) { 1421 | case 0: 1422 | switch (((inst >> 15) & 0b1111111111)) { 1423 | case 0: op = rv_op_ecall; break; 1424 | case 32: op = rv_op_ebreak; break; 1425 | case 64: op = rv_op_uret; break; 1426 | } 1427 | break; 1428 | case 256: 1429 | switch (((inst >> 20) & 0b11111)) { 1430 | case 2: 1431 | switch (((inst >> 15) & 0b11111)) { 1432 | case 0: op = rv_op_sret; break; 1433 | } 1434 | break; 1435 | case 4: op = rv_op_sfence_vm; break; 1436 | case 5: 1437 | switch (((inst >> 15) & 0b11111)) { 1438 | case 0: op = rv_op_wfi; break; 1439 | } 1440 | break; 1441 | } 1442 | break; 1443 | case 288: op = rv_op_sfence_vma; break; 1444 | case 512: 1445 | switch (((inst >> 15) & 0b1111111111)) { 1446 | case 64: op = rv_op_hret; break; 1447 | } 1448 | break; 1449 | case 768: 1450 | switch (((inst >> 15) & 0b1111111111)) { 1451 | case 64: op = rv_op_mret; break; 1452 | } 1453 | break; 1454 | case 1952: 1455 | switch (((inst >> 15) & 0b1111111111)) { 1456 | case 576: op = rv_op_dret; break; 1457 | } 1458 | break; 1459 | } 1460 | break; 1461 | case 1: op = rv_op_csrrw; break; 1462 | case 2: op = rv_op_csrrs; break; 1463 | case 3: op = rv_op_csrrc; break; 1464 | case 5: op = rv_op_csrrwi; break; 1465 | case 6: op = rv_op_csrrsi; break; 1466 | case 7: op = rv_op_csrrci; break; 1467 | } 1468 | break; 1469 | case 30: 1470 | switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) { 1471 | case 0: op = rv_op_addd; break; 1472 | case 1: op = rv_op_slld; break; 1473 | case 5: op = rv_op_srld; break; 1474 | case 8: op = rv_op_muld; break; 1475 | case 12: op = rv_op_divd; break; 1476 | case 13: op = rv_op_divud; break; 1477 | case 14: op = rv_op_remd; break; 1478 | case 15: op = rv_op_remud; break; 1479 | case 256: op = rv_op_subd; break; 1480 | case 261: op = rv_op_srad; break; 1481 | } 1482 | break; 1483 | } 1484 | break; 1485 | } 1486 | dec->op = op; 1487 | } 1488 | 1489 | /* operand extractors */ 1490 | 1491 | static uint32_t operand_rd(rv_inst inst) { 1492 | return (inst << 52) >> 59; 1493 | } 1494 | 1495 | static uint32_t operand_rs1(rv_inst inst) { 1496 | return (inst << 44) >> 59; 1497 | } 1498 | 1499 | static uint32_t operand_rs2(rv_inst inst) { 1500 | return (inst << 39) >> 59; 1501 | } 1502 | 1503 | static uint32_t operand_rs3(rv_inst inst) { 1504 | return (inst << 32) >> 59; 1505 | } 1506 | 1507 | static uint32_t operand_aq(rv_inst inst) { 1508 | return (inst << 37) >> 63; 1509 | } 1510 | 1511 | static uint32_t operand_rl(rv_inst inst) { 1512 | return (inst << 38) >> 63; 1513 | } 1514 | 1515 | static uint32_t operand_pred(rv_inst inst) { 1516 | return (inst << 36) >> 60; 1517 | } 1518 | 1519 | static uint32_t operand_succ(rv_inst inst) { 1520 | return (inst << 40) >> 60; 1521 | } 1522 | 1523 | static uint32_t operand_rm(rv_inst inst) { 1524 | return (inst << 49) >> 61; 1525 | } 1526 | 1527 | static uint32_t operand_shamt5(rv_inst inst) { 1528 | return (inst << 39) >> 59; 1529 | } 1530 | 1531 | static uint32_t operand_shamt6(rv_inst inst) { 1532 | return (inst << 38) >> 58; 1533 | } 1534 | 1535 | static uint32_t operand_shamt7(rv_inst inst) { 1536 | return (inst << 37) >> 57; 1537 | } 1538 | 1539 | static uint32_t operand_crdq(rv_inst inst) { 1540 | return (inst << 59) >> 61; 1541 | } 1542 | 1543 | static uint32_t operand_crs1q(rv_inst inst) { 1544 | return (inst << 54) >> 61; 1545 | } 1546 | 1547 | static uint32_t operand_crs1rdq(rv_inst inst) { 1548 | return (inst << 54) >> 61; 1549 | } 1550 | 1551 | static uint32_t operand_crs2q(rv_inst inst) { 1552 | return (inst << 59) >> 61; 1553 | } 1554 | 1555 | static uint32_t operand_crd(rv_inst inst) { 1556 | return (inst << 52) >> 59; 1557 | } 1558 | 1559 | static uint32_t operand_crs1(rv_inst inst) { 1560 | return (inst << 52) >> 59; 1561 | } 1562 | 1563 | static uint32_t operand_crs1rd(rv_inst inst) { 1564 | return (inst << 52) >> 59; 1565 | } 1566 | 1567 | static uint32_t operand_crs2(rv_inst inst) { 1568 | return (inst << 57) >> 59; 1569 | } 1570 | 1571 | static uint32_t operand_cimmsh5(rv_inst inst) { 1572 | return (inst << 57) >> 59; 1573 | } 1574 | 1575 | static uint32_t operand_csr12(rv_inst inst) { 1576 | return (inst << 32) >> 52; 1577 | } 1578 | 1579 | static int32_t operand_imm12(rv_inst inst) { 1580 | return ((int64_t)inst << 32) >> 52; 1581 | } 1582 | 1583 | static int32_t operand_imm20(rv_inst inst) { 1584 | return (((int64_t)inst << 32) >> 44) << 12; 1585 | } 1586 | 1587 | static int32_t operand_jimm20(rv_inst inst) { 1588 | return (((int64_t)inst << 32) >> 63) << 20 | 1589 | ((inst << 33) >> 54) << 1 | 1590 | ((inst << 43) >> 63) << 11 | 1591 | ((inst << 44) >> 56) << 12; 1592 | } 1593 | 1594 | static int32_t operand_simm12(rv_inst inst) { 1595 | return (((int64_t)inst << 32) >> 57) << 5 | 1596 | (inst << 52) >> 59; 1597 | } 1598 | 1599 | static int32_t operand_sbimm12(rv_inst inst) { 1600 | return (((int64_t)inst << 32) >> 63) << 12 | 1601 | ((inst << 33) >> 58) << 5 | 1602 | ((inst << 52) >> 60) << 1 | 1603 | ((inst << 56) >> 63) << 11; 1604 | } 1605 | 1606 | static uint32_t operand_cimmsh6(rv_inst inst) { 1607 | return ((inst << 51) >> 63) << 5 | 1608 | (inst << 57) >> 59; 1609 | } 1610 | 1611 | static int32_t operand_cimmi(rv_inst inst) { 1612 | return (((int64_t)inst << 51) >> 63) << 5 | 1613 | (inst << 57) >> 59; 1614 | } 1615 | 1616 | static int32_t operand_cimmui(rv_inst inst) { 1617 | return (((int64_t)inst << 51) >> 63) << 17 | 1618 | ((inst << 57) >> 59) << 12; 1619 | } 1620 | 1621 | static uint32_t operand_cimmlwsp(rv_inst inst) { 1622 | return ((inst << 51) >> 63) << 5 | 1623 | ((inst << 57) >> 61) << 2 | 1624 | ((inst << 60) >> 62) << 6; 1625 | } 1626 | 1627 | static uint32_t operand_cimmldsp(rv_inst inst) { 1628 | return ((inst << 51) >> 63) << 5 | 1629 | ((inst << 57) >> 62) << 3 | 1630 | ((inst << 59) >> 61) << 6; 1631 | } 1632 | 1633 | static uint32_t operand_cimmlqsp(rv_inst inst) { 1634 | return ((inst << 51) >> 63) << 5 | 1635 | ((inst << 57) >> 63) << 4 | 1636 | ((inst << 58) >> 60) << 6; 1637 | } 1638 | 1639 | static int32_t operand_cimm16sp(rv_inst inst) { 1640 | return (((int64_t)inst << 51) >> 63) << 9 | 1641 | ((inst << 57) >> 63) << 4 | 1642 | ((inst << 58) >> 63) << 6 | 1643 | ((inst << 59) >> 62) << 7 | 1644 | ((inst << 61) >> 63) << 5; 1645 | } 1646 | 1647 | static int32_t operand_cimmj(rv_inst inst) { 1648 | return (((int64_t)inst << 51) >> 63) << 11 | 1649 | ((inst << 52) >> 63) << 4 | 1650 | ((inst << 53) >> 62) << 8 | 1651 | ((inst << 55) >> 63) << 10 | 1652 | ((inst << 56) >> 63) << 6 | 1653 | ((inst << 57) >> 63) << 7 | 1654 | ((inst << 58) >> 61) << 1 | 1655 | ((inst << 61) >> 63) << 5; 1656 | } 1657 | 1658 | static int32_t operand_cimmb(rv_inst inst) { 1659 | return (((int64_t)inst << 51) >> 63) << 8 | 1660 | ((inst << 52) >> 62) << 3 | 1661 | ((inst << 57) >> 62) << 6 | 1662 | ((inst << 59) >> 62) << 1 | 1663 | ((inst << 61) >> 63) << 5; 1664 | } 1665 | 1666 | static uint32_t operand_cimmswsp(rv_inst inst) { 1667 | return ((inst << 51) >> 60) << 2 | 1668 | ((inst << 55) >> 62) << 6; 1669 | } 1670 | 1671 | static uint32_t operand_cimmsdsp(rv_inst inst) { 1672 | return ((inst << 51) >> 61) << 3 | 1673 | ((inst << 54) >> 61) << 6; 1674 | } 1675 | 1676 | static uint32_t operand_cimmsqsp(rv_inst inst) { 1677 | return ((inst << 51) >> 62) << 4 | 1678 | ((inst << 53) >> 60) << 6; 1679 | } 1680 | 1681 | static uint32_t operand_cimm4spn(rv_inst inst) { 1682 | return ((inst << 51) >> 62) << 4 | 1683 | ((inst << 53) >> 60) << 6 | 1684 | ((inst << 57) >> 63) << 2 | 1685 | ((inst << 58) >> 63) << 3; 1686 | } 1687 | 1688 | static uint32_t operand_cimmw(rv_inst inst) { 1689 | return ((inst << 51) >> 61) << 3 | 1690 | ((inst << 57) >> 63) << 2 | 1691 | ((inst << 58) >> 63) << 6; 1692 | } 1693 | 1694 | static uint32_t operand_cimmd(rv_inst inst) { 1695 | return ((inst << 51) >> 61) << 3 | 1696 | ((inst << 57) >> 62) << 6; 1697 | } 1698 | 1699 | static uint32_t operand_cimmq(rv_inst inst) { 1700 | return ((inst << 51) >> 62) << 4 | 1701 | ((inst << 53) >> 63) << 8 | 1702 | ((inst << 57) >> 62) << 6; 1703 | } 1704 | 1705 | /* decode operands */ 1706 | 1707 | static void decode_inst_operands(rv_decode *dec) 1708 | { 1709 | rv_inst inst = dec->inst; 1710 | dec->codec = opcode_data[dec->op].codec; 1711 | switch (dec->codec) { 1712 | case rv_codec_none: 1713 | dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero; 1714 | dec->imm = 0; 1715 | break; 1716 | case rv_codec_u: 1717 | dec->rd = operand_rd(inst); 1718 | dec->rs1 = dec->rs2 = rv_ireg_zero; 1719 | dec->imm = operand_imm20(inst); 1720 | break; 1721 | case rv_codec_uj: 1722 | dec->rd = operand_rd(inst); 1723 | dec->rs1 = dec->rs2 = rv_ireg_zero; 1724 | dec->imm = operand_jimm20(inst); 1725 | break; 1726 | case rv_codec_i: 1727 | dec->rd = operand_rd(inst); 1728 | dec->rs1 = operand_rs1(inst); 1729 | dec->rs2 = rv_ireg_zero; 1730 | dec->imm = operand_imm12(inst); 1731 | break; 1732 | case rv_codec_i_sh5: 1733 | dec->rd = operand_rd(inst); 1734 | dec->rs1 = operand_rs1(inst); 1735 | dec->rs2 = rv_ireg_zero; 1736 | dec->imm = operand_shamt5(inst); 1737 | break; 1738 | case rv_codec_i_sh6: 1739 | dec->rd = operand_rd(inst); 1740 | dec->rs1 = operand_rs1(inst); 1741 | dec->rs2 = rv_ireg_zero; 1742 | dec->imm = operand_shamt6(inst); 1743 | break; 1744 | case rv_codec_i_sh7: 1745 | dec->rd = operand_rd(inst); 1746 | dec->rs1 = operand_rs1(inst); 1747 | dec->rs2 = rv_ireg_zero; 1748 | dec->imm = operand_shamt7(inst); 1749 | break; 1750 | case rv_codec_i_csr: 1751 | dec->rd = operand_rd(inst); 1752 | dec->rs1 = operand_rs1(inst); 1753 | dec->rs2 = rv_ireg_zero; 1754 | dec->imm = operand_csr12(inst); 1755 | break; 1756 | case rv_codec_s: 1757 | dec->rd = rv_ireg_zero; 1758 | dec->rs1 = operand_rs1(inst); 1759 | dec->rs2 = operand_rs2(inst); 1760 | dec->imm = operand_simm12(inst); 1761 | break; 1762 | case rv_codec_sb: 1763 | dec->rd = rv_ireg_zero; 1764 | dec->rs1 = operand_rs1(inst); 1765 | dec->rs2 = operand_rs2(inst); 1766 | dec->imm = operand_sbimm12(inst); 1767 | break; 1768 | case rv_codec_r: 1769 | dec->rd = operand_rd(inst); 1770 | dec->rs1 = operand_rs1(inst); 1771 | dec->rs2 = operand_rs2(inst); 1772 | dec->imm = 0; 1773 | break; 1774 | case rv_codec_r_m: 1775 | dec->rd = operand_rd(inst); 1776 | dec->rs1 = operand_rs1(inst); 1777 | dec->rs2 = operand_rs2(inst); 1778 | dec->imm = 0; 1779 | dec->rm = operand_rm(inst); 1780 | break; 1781 | case rv_codec_r4_m: 1782 | dec->rd = operand_rd(inst); 1783 | dec->rs1 = operand_rs1(inst); 1784 | dec->rs2 = operand_rs2(inst); 1785 | dec->rs3 = operand_rs3(inst); 1786 | dec->imm = 0; 1787 | dec->rm = operand_rm(inst); 1788 | break; 1789 | case rv_codec_r_a: 1790 | dec->rd = operand_rd(inst); 1791 | dec->rs1 = operand_rs1(inst); 1792 | dec->rs2 = operand_rs2(inst); 1793 | dec->imm = 0; 1794 | dec->aq = operand_aq(inst); 1795 | dec->rl = operand_rl(inst); 1796 | break; 1797 | case rv_codec_r_l: 1798 | dec->rd = operand_rd(inst); 1799 | dec->rs1 = operand_rs1(inst); 1800 | dec->rs2 = rv_ireg_zero; 1801 | dec->imm = 0; 1802 | dec->aq = operand_aq(inst); 1803 | dec->rl = operand_rl(inst); 1804 | break; 1805 | case rv_codec_r_f: 1806 | dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero; 1807 | dec->pred = operand_pred(inst); 1808 | dec->succ = operand_succ(inst); 1809 | dec->imm = 0; 1810 | break; 1811 | case rv_codec_cb: 1812 | dec->rd = rv_ireg_zero; 1813 | dec->rs1 = operand_crs1q(inst) + 8; 1814 | dec->rs2 = rv_ireg_zero; 1815 | dec->imm = operand_cimmb(inst); 1816 | break; 1817 | case rv_codec_cb_imm: 1818 | dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8; 1819 | dec->rs2 = rv_ireg_zero; 1820 | dec->imm = operand_cimmi(inst); 1821 | break; 1822 | case rv_codec_cb_sh5: 1823 | dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8; 1824 | dec->rs2 = rv_ireg_zero; 1825 | dec->imm = operand_cimmsh5(inst); 1826 | break; 1827 | case rv_codec_cb_sh6: 1828 | dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8; 1829 | dec->rs2 = rv_ireg_zero; 1830 | dec->imm = operand_cimmsh6(inst); 1831 | break; 1832 | case rv_codec_ci: 1833 | dec->rd = dec->rs1 = operand_crs1rd(inst); 1834 | dec->rs2 = rv_ireg_zero; 1835 | dec->imm = operand_cimmi(inst); 1836 | break; 1837 | case rv_codec_ci_sh5: 1838 | dec->rd = dec->rs1 = operand_crs1rd(inst); 1839 | dec->rs2 = rv_ireg_zero; 1840 | dec->imm = operand_cimmsh5(inst); 1841 | break; 1842 | case rv_codec_ci_sh6: 1843 | dec->rd = dec->rs1 = operand_crs1rd(inst); 1844 | dec->rs2 = rv_ireg_zero; 1845 | dec->imm = operand_cimmsh6(inst); 1846 | break; 1847 | case rv_codec_ci_16sp: 1848 | dec->rd = rv_ireg_sp; 1849 | dec->rs1 = rv_ireg_sp; 1850 | dec->rs2 = rv_ireg_zero; 1851 | dec->imm = operand_cimm16sp(inst); 1852 | break; 1853 | case rv_codec_ci_lwsp: 1854 | dec->rd = operand_crd(inst); 1855 | dec->rs1 = rv_ireg_sp; 1856 | dec->rs2 = rv_ireg_zero; 1857 | dec->imm = operand_cimmlwsp(inst); 1858 | break; 1859 | case rv_codec_ci_ldsp: 1860 | dec->rd = operand_crd(inst); 1861 | dec->rs1 = rv_ireg_sp; 1862 | dec->rs2 = rv_ireg_zero; 1863 | dec->imm = operand_cimmldsp(inst); 1864 | break; 1865 | case rv_codec_ci_lqsp: 1866 | dec->rd = operand_crd(inst); 1867 | dec->rs1 = rv_ireg_sp; 1868 | dec->rs2 = rv_ireg_zero; 1869 | dec->imm = operand_cimmlqsp(inst); 1870 | break; 1871 | case rv_codec_ci_li: 1872 | dec->rd = operand_crd(inst); 1873 | dec->rs1 = rv_ireg_zero; 1874 | dec->rs2 = rv_ireg_zero; 1875 | dec->imm = operand_cimmi(inst); 1876 | break; 1877 | case rv_codec_ci_lui: 1878 | dec->rd = operand_crd(inst); 1879 | dec->rs1 = rv_ireg_zero; 1880 | dec->rs2 = rv_ireg_zero; 1881 | dec->imm = operand_cimmui(inst); 1882 | break; 1883 | case rv_codec_ci_none: 1884 | dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero; 1885 | dec->imm = 0; 1886 | break; 1887 | case rv_codec_ciw_4spn: 1888 | dec->rd = operand_crdq(inst) + 8; 1889 | dec->rs1 = rv_ireg_sp; 1890 | dec->rs2 = rv_ireg_zero; 1891 | dec->imm = operand_cimm4spn(inst); 1892 | break; 1893 | case rv_codec_cj: 1894 | dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero; 1895 | dec->imm = operand_cimmj(inst); 1896 | break; 1897 | case rv_codec_cj_jal: 1898 | dec->rd = rv_ireg_ra; 1899 | dec->rs1 = dec->rs2 = rv_ireg_zero; 1900 | dec->imm = operand_cimmj(inst); 1901 | break; 1902 | case rv_codec_cl_lw: 1903 | dec->rd = operand_crdq(inst) + 8; 1904 | dec->rs1 = operand_crs1q(inst) + 8; 1905 | dec->rs2 = rv_ireg_zero; 1906 | dec->imm = operand_cimmw(inst); 1907 | break; 1908 | case rv_codec_cl_ld: 1909 | dec->rd = operand_crdq(inst) + 8; 1910 | dec->rs1 = operand_crs1q(inst) + 8; 1911 | dec->rs2 = rv_ireg_zero; 1912 | dec->imm = operand_cimmd(inst); 1913 | break; 1914 | case rv_codec_cl_lq: 1915 | dec->rd = operand_crdq(inst) + 8; 1916 | dec->rs1 = operand_crs1q(inst) + 8; 1917 | dec->rs2 = rv_ireg_zero; 1918 | dec->imm = operand_cimmq(inst); 1919 | break; 1920 | case rv_codec_cr: 1921 | dec->rd = dec->rs1 = operand_crs1rd(inst); 1922 | dec->rs2 = operand_crs2(inst); 1923 | dec->imm = 0; 1924 | break; 1925 | case rv_codec_cr_mv: 1926 | dec->rd = operand_crd(inst); 1927 | dec->rs1 = operand_crs2(inst); 1928 | dec->rs2 = rv_ireg_zero; 1929 | dec->imm = 0; 1930 | break; 1931 | case rv_codec_cr_jalr: 1932 | dec->rd = rv_ireg_ra; 1933 | dec->rs1 = operand_crs1(inst); 1934 | dec->rs2 = rv_ireg_zero; 1935 | dec->imm = 0; 1936 | break; 1937 | case rv_codec_cr_jr: 1938 | dec->rd = rv_ireg_zero; 1939 | dec->rs1 = operand_crs1(inst); 1940 | dec->rs2 = rv_ireg_zero; 1941 | dec->imm = 0; 1942 | break; 1943 | case rv_codec_cs: 1944 | dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8; 1945 | dec->rs2 = operand_crs2q(inst) + 8; 1946 | dec->imm = 0; 1947 | break; 1948 | case rv_codec_cs_sw: 1949 | dec->rd = rv_ireg_zero; 1950 | dec->rs1 = operand_crs1q(inst) + 8; 1951 | dec->rs2 = operand_crs2q(inst) + 8; 1952 | dec->imm = operand_cimmw(inst); 1953 | break; 1954 | case rv_codec_cs_sd: 1955 | dec->rd = rv_ireg_zero; 1956 | dec->rs1 = operand_crs1q(inst) + 8; 1957 | dec->rs2 = operand_crs2q(inst) + 8; 1958 | dec->imm = operand_cimmd(inst); 1959 | break; 1960 | case rv_codec_cs_sq: 1961 | dec->rd = rv_ireg_zero; 1962 | dec->rs1 = operand_crs1q(inst) + 8; 1963 | dec->rs2 = operand_crs2q(inst) + 8; 1964 | dec->imm = operand_cimmq(inst); 1965 | break; 1966 | case rv_codec_css_swsp: 1967 | dec->rd = rv_ireg_zero; 1968 | dec->rs1 = rv_ireg_sp; 1969 | dec->rs2 = operand_crs2(inst); 1970 | dec->imm = operand_cimmswsp(inst); 1971 | break; 1972 | case rv_codec_css_sdsp: 1973 | dec->rd = rv_ireg_zero; 1974 | dec->rs1 = rv_ireg_sp; 1975 | dec->rs2 = operand_crs2(inst); 1976 | dec->imm = operand_cimmsdsp(inst); 1977 | break; 1978 | case rv_codec_css_sqsp: 1979 | dec->rd = rv_ireg_zero; 1980 | dec->rs1 = rv_ireg_sp; 1981 | dec->rs2 = operand_crs2(inst); 1982 | dec->imm = operand_cimmsqsp(inst); 1983 | break; 1984 | }; 1985 | } 1986 | 1987 | /* decompress instruction */ 1988 | 1989 | static void decode_inst_decompress(rv_decode *dec, rv_isa isa) 1990 | { 1991 | int decomp_op; 1992 | switch (isa) { 1993 | case rv32: decomp_op = opcode_data[dec->op].decomp_rv32; break; 1994 | case rv64: decomp_op = opcode_data[dec->op].decomp_rv64; break; 1995 | case rv128: decomp_op = opcode_data[dec->op].decomp_rv128; break; 1996 | } 1997 | if (decomp_op != rv_op_illegal) { 1998 | if ((opcode_data[dec->op].decomp_data & rvcd_imm_nz) && dec->imm == 0) { 1999 | dec->op = rv_op_illegal; 2000 | } else { 2001 | dec->op = decomp_op; 2002 | dec->codec = opcode_data[decomp_op].codec; 2003 | } 2004 | } 2005 | } 2006 | 2007 | /* check constraint */ 2008 | 2009 | static bool check_constraints(rv_decode *dec, const rvc_constraint *c) 2010 | { 2011 | int32_t imm = dec->imm; 2012 | uint8_t rd = dec->rd, rs1 = dec->rs1, rs2 = dec->rs2; 2013 | while (*c != rvc_end) { 2014 | switch (*c) { 2015 | case rvc_rd_eq_ra: if (!(rd == 1)) return false; break; 2016 | case rvc_rd_eq_x0: if (!(rd == 0)) return false; break; 2017 | case rvc_rs1_eq_x0: if (!(rs1 == 0)) return false; break; 2018 | case rvc_rs2_eq_x0: if (!(rs2 == 0)) return false; break; 2019 | case rvc_rs2_eq_rs1: if (!(rs2 == rs1)) return false; break; 2020 | case rvc_rs1_eq_ra: if (!(rs1 == 1)) return false; break; 2021 | case rvc_imm_eq_zero: if (!(imm == 0)) return false; break; 2022 | case rvc_imm_eq_n1: if (!(imm == -1)) return false; break; 2023 | case rvc_imm_eq_p1: if (!(imm == 1)) return false; break; 2024 | case rvc_csr_eq_0x001: if (!(imm == 0x001)) return false; break; 2025 | case rvc_csr_eq_0x002: if (!(imm == 0x002)) return false; break; 2026 | case rvc_csr_eq_0x003: if (!(imm == 0x003)) return false; break; 2027 | case rvc_csr_eq_0xc00: if (!(imm == 0xc00)) return false; break; 2028 | case rvc_csr_eq_0xc01: if (!(imm == 0xc01)) return false; break; 2029 | case rvc_csr_eq_0xc02: if (!(imm == 0xc02)) return false; break; 2030 | case rvc_csr_eq_0xc80: if (!(imm == 0xc80)) return false; break; 2031 | case rvc_csr_eq_0xc81: if (!(imm == 0xc81)) return false; break; 2032 | case rvc_csr_eq_0xc82: if (!(imm == 0xc82)) return false; break; 2033 | default: break; 2034 | } 2035 | c++; 2036 | } 2037 | return true; 2038 | } 2039 | 2040 | /* lift instruction to pseudo-instruction */ 2041 | 2042 | static void decode_inst_lift_pseudo(rv_decode *dec) 2043 | { 2044 | const rv_comp_data *comp_data = opcode_data[dec->op].pseudo; 2045 | if (!comp_data) { 2046 | return; 2047 | } 2048 | while (comp_data->constraints) { 2049 | if (check_constraints(dec, comp_data->constraints)) { 2050 | dec->op = comp_data->op; 2051 | dec->codec = opcode_data[dec->op].codec; 2052 | return; 2053 | } 2054 | comp_data++; 2055 | } 2056 | } 2057 | 2058 | /* format instruction */ 2059 | 2060 | static void append(char *s1, const char *s2, ssize_t n) 2061 | { 2062 | ssize_t l1 = strlen(s1); 2063 | if (n - l1 - 1 > 0) { 2064 | strncat(s1, s2, n - l1); 2065 | } 2066 | } 2067 | 2068 | #define INST_FMT_2 "%04" PRIx64 " " 2069 | #define INST_FMT_4 "%08" PRIx64 " " 2070 | #define INST_FMT_6 "%012" PRIx64 " " 2071 | #define INST_FMT_8 "%016" PRIx64 " " 2072 | 2073 | static void decode_inst_format(char *buf, size_t buflen, size_t tab, rv_decode *dec) 2074 | { 2075 | char tmp[64]; 2076 | const char *fmt; 2077 | 2078 | size_t len = inst_length(dec->inst); 2079 | switch (len) { 2080 | case 2: 2081 | snprintf(buf, buflen, INST_FMT_2, dec->inst); 2082 | break; 2083 | case 4: 2084 | snprintf(buf, buflen, INST_FMT_4, dec->inst); 2085 | break; 2086 | case 6: 2087 | snprintf(buf, buflen, INST_FMT_6, dec->inst); 2088 | break; 2089 | default: 2090 | snprintf(buf, buflen, INST_FMT_8, dec->inst); 2091 | break; 2092 | } 2093 | 2094 | fmt = opcode_data[dec->op].format; 2095 | while (*fmt) { 2096 | switch (*fmt) { 2097 | case 'O': 2098 | append(buf, opcode_data[dec->op].name, buflen); 2099 | break; 2100 | case '(': 2101 | append(buf, "(", buflen); 2102 | break; 2103 | case ',': 2104 | append(buf, ",", buflen); 2105 | break; 2106 | case ')': 2107 | append(buf, ")", buflen); 2108 | break; 2109 | case '0': 2110 | append(buf, rv_ireg_name_sym[dec->rd], buflen); 2111 | break; 2112 | case '1': 2113 | append(buf, rv_ireg_name_sym[dec->rs1], buflen); 2114 | break; 2115 | case '2': 2116 | append(buf, rv_ireg_name_sym[dec->rs2], buflen); 2117 | break; 2118 | case '3': 2119 | append(buf, rv_freg_name_sym[dec->rd], buflen); 2120 | break; 2121 | case '4': 2122 | append(buf, rv_freg_name_sym[dec->rs1], buflen); 2123 | break; 2124 | case '5': 2125 | append(buf, rv_freg_name_sym[dec->rs2], buflen); 2126 | break; 2127 | case '6': 2128 | append(buf, rv_freg_name_sym[dec->rs3], buflen); 2129 | break; 2130 | case '7': 2131 | snprintf(tmp, sizeof(tmp), "%d", dec->rs1); 2132 | append(buf, tmp, buflen); 2133 | break; 2134 | case 'i': 2135 | snprintf(tmp, sizeof(tmp), "%d", dec->imm); 2136 | append(buf, tmp, buflen); 2137 | break; 2138 | case 'o': 2139 | snprintf(tmp, sizeof(tmp), "%d", dec->imm); 2140 | append(buf, tmp, buflen); 2141 | while (strlen(buf) < tab * 2) { 2142 | append(buf, " ", buflen); 2143 | } 2144 | snprintf(tmp, sizeof(tmp), "# 0x%" PRIx64, 2145 | dec->pc + dec->imm); 2146 | append(buf, tmp, buflen); 2147 | break; 2148 | case 'c': { 2149 | const char *name = csr_name(dec->imm & 0xfff); 2150 | if (name) { 2151 | append(buf, name, buflen); 2152 | } else { 2153 | snprintf(tmp, sizeof(tmp), "0x%03x", dec->imm & 0xfff); 2154 | append(buf, tmp, buflen); 2155 | } 2156 | break; 2157 | } 2158 | case 'r': 2159 | switch (dec->rm) { 2160 | case rv_rm_rne: 2161 | append(buf, "rne", buflen); 2162 | break; 2163 | case rv_rm_rtz: 2164 | append(buf, "rtz", buflen); 2165 | break; 2166 | case rv_rm_rdn: 2167 | append(buf, "rdn", buflen); 2168 | break; 2169 | case rv_rm_rup: 2170 | append(buf, "rup", buflen); 2171 | break; 2172 | case rv_rm_rmm: 2173 | append(buf, "rmm", buflen); 2174 | break; 2175 | case rv_rm_dyn: 2176 | append(buf, "dyn", buflen); 2177 | break; 2178 | default: 2179 | append(buf, "inv", buflen); 2180 | break; 2181 | } 2182 | break; 2183 | case 'p': 2184 | if (dec->pred & rv_fence_i) { 2185 | append(buf, "i", buflen); 2186 | } 2187 | if (dec->pred & rv_fence_o) { 2188 | append(buf, "o", buflen); 2189 | } 2190 | if (dec->pred & rv_fence_r) { 2191 | append(buf, "r", buflen); 2192 | } 2193 | if (dec->pred & rv_fence_w) { 2194 | append(buf, "w", buflen); 2195 | } 2196 | break; 2197 | case 's': 2198 | if (dec->succ & rv_fence_i) { 2199 | append(buf, "i", buflen); 2200 | } 2201 | if (dec->succ & rv_fence_o) { 2202 | append(buf, "o", buflen); 2203 | } 2204 | if (dec->succ & rv_fence_r) { 2205 | append(buf, "r", buflen); 2206 | } 2207 | if (dec->succ & rv_fence_w) { 2208 | append(buf, "w", buflen); 2209 | } 2210 | break; 2211 | case '\t': 2212 | while (strlen(buf) < tab) { 2213 | append(buf, " ", buflen); 2214 | } 2215 | break; 2216 | case 'A': 2217 | if (dec->aq) { 2218 | append(buf, ".aq", buflen); 2219 | } 2220 | break; 2221 | case 'R': 2222 | if (dec->rl) { 2223 | append(buf, ".rl", buflen); 2224 | } 2225 | break; 2226 | default: 2227 | break; 2228 | } 2229 | fmt++; 2230 | } 2231 | } 2232 | 2233 | /* instruction length */ 2234 | 2235 | size_t inst_length(rv_inst inst) 2236 | { 2237 | /* NOTE: supports maximum instruction size of 64-bits */ 2238 | 2239 | /* instruction length coding 2240 | * 2241 | * aa - 16 bit aa != 11 2242 | * bbb11 - 32 bit bbb != 111 2243 | * 011111 - 48 bit 2244 | * 0111111 - 64 bit 2245 | */ 2246 | 2247 | return (inst & 0b11) != 0b11 ? 2 2248 | : (inst & 0b11100) != 0b11100 ? 4 2249 | : (inst & 0b111111) == 0b011111 ? 6 2250 | : (inst & 0b1111111) == 0b0111111 ? 8 2251 | : 0; 2252 | } 2253 | 2254 | /* instruction fetch */ 2255 | 2256 | void inst_fetch(const uint8_t *data, rv_inst *instp, size_t *length) 2257 | { 2258 | rv_inst inst = ((rv_inst)data[1] << 8) | ((rv_inst)data[0]); 2259 | size_t len = *length = inst_length(inst); 2260 | if (len >= 8) inst |= ((rv_inst)data[7] << 56) | ((rv_inst)data[6] << 48); 2261 | if (len >= 6) inst |= ((rv_inst)data[5] << 40) | ((rv_inst)data[4] << 32); 2262 | if (len >= 4) inst |= ((rv_inst)data[3] << 24) | ((rv_inst)data[2] << 16); 2263 | *instp = inst; 2264 | } 2265 | 2266 | /* disassemble instruction */ 2267 | 2268 | void disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst) 2269 | { 2270 | rv_decode dec = { .pc = pc, .inst = inst }; 2271 | decode_inst_opcode(&dec, isa); 2272 | decode_inst_operands(&dec); 2273 | decode_inst_decompress(&dec, isa); 2274 | decode_inst_lift_pseudo(&dec); 2275 | decode_inst_format(buf, buflen, 32, &dec); 2276 | } 2277 | -------------------------------------------------------------------------------- /src/riscv-disas.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RISC-V Disassembler 3 | * 4 | * Copyright (c) 2016-2017 Michael Clark 5 | * Copyright (c) 2017-2018 SiFive, Inc. 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in 15 | * all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | * THE SOFTWARE. 24 | */ 25 | 26 | #ifndef RISCV_DISASSEMBLER_H 27 | #define RISCV_DISASSEMBLER_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | /* types */ 37 | 38 | typedef uint64_t rv_inst; 39 | typedef uint16_t rv_opcode; 40 | 41 | /* enums */ 42 | 43 | typedef enum { 44 | rv32, 45 | rv64, 46 | rv128 47 | } rv_isa; 48 | 49 | typedef enum { 50 | rv_rm_rne = 0, 51 | rv_rm_rtz = 1, 52 | rv_rm_rdn = 2, 53 | rv_rm_rup = 3, 54 | rv_rm_rmm = 4, 55 | rv_rm_dyn = 7, 56 | } rv_rm; 57 | 58 | typedef enum { 59 | rv_fence_i = 8, 60 | rv_fence_o = 4, 61 | rv_fence_r = 2, 62 | rv_fence_w = 1, 63 | } rv_fence; 64 | 65 | typedef enum { 66 | rv_ireg_zero, 67 | rv_ireg_ra, 68 | rv_ireg_sp, 69 | rv_ireg_gp, 70 | rv_ireg_tp, 71 | rv_ireg_t0, 72 | rv_ireg_t1, 73 | rv_ireg_t2, 74 | rv_ireg_s0, 75 | rv_ireg_s1, 76 | rv_ireg_a0, 77 | rv_ireg_a1, 78 | rv_ireg_a2, 79 | rv_ireg_a3, 80 | rv_ireg_a4, 81 | rv_ireg_a5, 82 | rv_ireg_a6, 83 | rv_ireg_a7, 84 | rv_ireg_s2, 85 | rv_ireg_s3, 86 | rv_ireg_s4, 87 | rv_ireg_s5, 88 | rv_ireg_s6, 89 | rv_ireg_s7, 90 | rv_ireg_s8, 91 | rv_ireg_s9, 92 | rv_ireg_s10, 93 | rv_ireg_s11, 94 | rv_ireg_t3, 95 | rv_ireg_t4, 96 | rv_ireg_t5, 97 | rv_ireg_t6, 98 | } rv_ireg; 99 | 100 | typedef enum { 101 | rvc_end, 102 | rvc_rd_eq_ra, 103 | rvc_rd_eq_x0, 104 | rvc_rs1_eq_x0, 105 | rvc_rs2_eq_x0, 106 | rvc_rs2_eq_rs1, 107 | rvc_rs1_eq_ra, 108 | rvc_imm_eq_zero, 109 | rvc_imm_eq_n1, 110 | rvc_imm_eq_p1, 111 | rvc_csr_eq_0x001, 112 | rvc_csr_eq_0x002, 113 | rvc_csr_eq_0x003, 114 | rvc_csr_eq_0xc00, 115 | rvc_csr_eq_0xc01, 116 | rvc_csr_eq_0xc02, 117 | rvc_csr_eq_0xc80, 118 | rvc_csr_eq_0xc81, 119 | rvc_csr_eq_0xc82, 120 | } rvc_constraint; 121 | 122 | typedef enum { 123 | rv_codec_illegal, 124 | rv_codec_none, 125 | rv_codec_u, 126 | rv_codec_uj, 127 | rv_codec_i, 128 | rv_codec_i_sh5, 129 | rv_codec_i_sh6, 130 | rv_codec_i_sh7, 131 | rv_codec_i_csr, 132 | rv_codec_s, 133 | rv_codec_sb, 134 | rv_codec_r, 135 | rv_codec_r_m, 136 | rv_codec_r4_m, 137 | rv_codec_r_a, 138 | rv_codec_r_l, 139 | rv_codec_r_f, 140 | rv_codec_cb, 141 | rv_codec_cb_imm, 142 | rv_codec_cb_sh5, 143 | rv_codec_cb_sh6, 144 | rv_codec_ci, 145 | rv_codec_ci_sh5, 146 | rv_codec_ci_sh6, 147 | rv_codec_ci_16sp, 148 | rv_codec_ci_lwsp, 149 | rv_codec_ci_ldsp, 150 | rv_codec_ci_lqsp, 151 | rv_codec_ci_li, 152 | rv_codec_ci_lui, 153 | rv_codec_ci_none, 154 | rv_codec_ciw_4spn, 155 | rv_codec_cj, 156 | rv_codec_cj_jal, 157 | rv_codec_cl_lw, 158 | rv_codec_cl_ld, 159 | rv_codec_cl_lq, 160 | rv_codec_cr, 161 | rv_codec_cr_mv, 162 | rv_codec_cr_jalr, 163 | rv_codec_cr_jr, 164 | rv_codec_cs, 165 | rv_codec_cs_sw, 166 | rv_codec_cs_sd, 167 | rv_codec_cs_sq, 168 | rv_codec_css_swsp, 169 | rv_codec_css_sdsp, 170 | rv_codec_css_sqsp, 171 | } rv_codec; 172 | 173 | typedef enum { 174 | rv_op_illegal, 175 | rv_op_lui, 176 | rv_op_auipc, 177 | rv_op_jal, 178 | rv_op_jalr, 179 | rv_op_beq, 180 | rv_op_bne, 181 | rv_op_blt, 182 | rv_op_bge, 183 | rv_op_bltu, 184 | rv_op_bgeu, 185 | rv_op_lb, 186 | rv_op_lh, 187 | rv_op_lw, 188 | rv_op_lbu, 189 | rv_op_lhu, 190 | rv_op_sb, 191 | rv_op_sh, 192 | rv_op_sw, 193 | rv_op_addi, 194 | rv_op_slti, 195 | rv_op_sltiu, 196 | rv_op_xori, 197 | rv_op_ori, 198 | rv_op_andi, 199 | rv_op_slli, 200 | rv_op_srli, 201 | rv_op_srai, 202 | rv_op_add, 203 | rv_op_sub, 204 | rv_op_sll, 205 | rv_op_slt, 206 | rv_op_sltu, 207 | rv_op_xor, 208 | rv_op_srl, 209 | rv_op_sra, 210 | rv_op_or, 211 | rv_op_and, 212 | rv_op_fence, 213 | rv_op_fence_i, 214 | rv_op_lwu, 215 | rv_op_ld, 216 | rv_op_sd, 217 | rv_op_addiw, 218 | rv_op_slliw, 219 | rv_op_srliw, 220 | rv_op_sraiw, 221 | rv_op_addw, 222 | rv_op_subw, 223 | rv_op_sllw, 224 | rv_op_srlw, 225 | rv_op_sraw, 226 | rv_op_ldu, 227 | rv_op_lq, 228 | rv_op_sq, 229 | rv_op_addid, 230 | rv_op_sllid, 231 | rv_op_srlid, 232 | rv_op_sraid, 233 | rv_op_addd, 234 | rv_op_subd, 235 | rv_op_slld, 236 | rv_op_srld, 237 | rv_op_srad, 238 | rv_op_mul, 239 | rv_op_mulh, 240 | rv_op_mulhsu, 241 | rv_op_mulhu, 242 | rv_op_div, 243 | rv_op_divu, 244 | rv_op_rem, 245 | rv_op_remu, 246 | rv_op_mulw, 247 | rv_op_divw, 248 | rv_op_divuw, 249 | rv_op_remw, 250 | rv_op_remuw, 251 | rv_op_muld, 252 | rv_op_divd, 253 | rv_op_divud, 254 | rv_op_remd, 255 | rv_op_remud, 256 | rv_op_lr_w, 257 | rv_op_sc_w, 258 | rv_op_amoswap_w, 259 | rv_op_amoadd_w, 260 | rv_op_amoxor_w, 261 | rv_op_amoor_w, 262 | rv_op_amoand_w, 263 | rv_op_amomin_w, 264 | rv_op_amomax_w, 265 | rv_op_amominu_w, 266 | rv_op_amomaxu_w, 267 | rv_op_lr_d, 268 | rv_op_sc_d, 269 | rv_op_amoswap_d, 270 | rv_op_amoadd_d, 271 | rv_op_amoxor_d, 272 | rv_op_amoor_d, 273 | rv_op_amoand_d, 274 | rv_op_amomin_d, 275 | rv_op_amomax_d, 276 | rv_op_amominu_d, 277 | rv_op_amomaxu_d, 278 | rv_op_lr_q, 279 | rv_op_sc_q, 280 | rv_op_amoswap_q, 281 | rv_op_amoadd_q, 282 | rv_op_amoxor_q, 283 | rv_op_amoor_q, 284 | rv_op_amoand_q, 285 | rv_op_amomin_q, 286 | rv_op_amomax_q, 287 | rv_op_amominu_q, 288 | rv_op_amomaxu_q, 289 | rv_op_ecall, 290 | rv_op_ebreak, 291 | rv_op_uret, 292 | rv_op_sret, 293 | rv_op_hret, 294 | rv_op_mret, 295 | rv_op_dret, 296 | rv_op_sfence_vm, 297 | rv_op_sfence_vma, 298 | rv_op_wfi, 299 | rv_op_csrrw, 300 | rv_op_csrrs, 301 | rv_op_csrrc, 302 | rv_op_csrrwi, 303 | rv_op_csrrsi, 304 | rv_op_csrrci, 305 | rv_op_flw, 306 | rv_op_fsw, 307 | rv_op_fmadd_s, 308 | rv_op_fmsub_s, 309 | rv_op_fnmsub_s, 310 | rv_op_fnmadd_s, 311 | rv_op_fadd_s, 312 | rv_op_fsub_s, 313 | rv_op_fmul_s, 314 | rv_op_fdiv_s, 315 | rv_op_fsgnj_s, 316 | rv_op_fsgnjn_s, 317 | rv_op_fsgnjx_s, 318 | rv_op_fmin_s, 319 | rv_op_fmax_s, 320 | rv_op_fsqrt_s, 321 | rv_op_fle_s, 322 | rv_op_flt_s, 323 | rv_op_feq_s, 324 | rv_op_fcvt_w_s, 325 | rv_op_fcvt_wu_s, 326 | rv_op_fcvt_s_w, 327 | rv_op_fcvt_s_wu, 328 | rv_op_fmv_x_s, 329 | rv_op_fclass_s, 330 | rv_op_fmv_s_x, 331 | rv_op_fcvt_l_s, 332 | rv_op_fcvt_lu_s, 333 | rv_op_fcvt_s_l, 334 | rv_op_fcvt_s_lu, 335 | rv_op_fld, 336 | rv_op_fsd, 337 | rv_op_fmadd_d, 338 | rv_op_fmsub_d, 339 | rv_op_fnmsub_d, 340 | rv_op_fnmadd_d, 341 | rv_op_fadd_d, 342 | rv_op_fsub_d, 343 | rv_op_fmul_d, 344 | rv_op_fdiv_d, 345 | rv_op_fsgnj_d, 346 | rv_op_fsgnjn_d, 347 | rv_op_fsgnjx_d, 348 | rv_op_fmin_d, 349 | rv_op_fmax_d, 350 | rv_op_fcvt_s_d, 351 | rv_op_fcvt_d_s, 352 | rv_op_fsqrt_d, 353 | rv_op_fle_d, 354 | rv_op_flt_d, 355 | rv_op_feq_d, 356 | rv_op_fcvt_w_d, 357 | rv_op_fcvt_wu_d, 358 | rv_op_fcvt_d_w, 359 | rv_op_fcvt_d_wu, 360 | rv_op_fclass_d, 361 | rv_op_fcvt_l_d, 362 | rv_op_fcvt_lu_d, 363 | rv_op_fmv_x_d, 364 | rv_op_fcvt_d_l, 365 | rv_op_fcvt_d_lu, 366 | rv_op_fmv_d_x, 367 | rv_op_flq, 368 | rv_op_fsq, 369 | rv_op_fmadd_q, 370 | rv_op_fmsub_q, 371 | rv_op_fnmsub_q, 372 | rv_op_fnmadd_q, 373 | rv_op_fadd_q, 374 | rv_op_fsub_q, 375 | rv_op_fmul_q, 376 | rv_op_fdiv_q, 377 | rv_op_fsgnj_q, 378 | rv_op_fsgnjn_q, 379 | rv_op_fsgnjx_q, 380 | rv_op_fmin_q, 381 | rv_op_fmax_q, 382 | rv_op_fcvt_s_q, 383 | rv_op_fcvt_q_s, 384 | rv_op_fcvt_d_q, 385 | rv_op_fcvt_q_d, 386 | rv_op_fsqrt_q, 387 | rv_op_fle_q, 388 | rv_op_flt_q, 389 | rv_op_feq_q, 390 | rv_op_fcvt_w_q, 391 | rv_op_fcvt_wu_q, 392 | rv_op_fcvt_q_w, 393 | rv_op_fcvt_q_wu, 394 | rv_op_fclass_q, 395 | rv_op_fcvt_l_q, 396 | rv_op_fcvt_lu_q, 397 | rv_op_fcvt_q_l, 398 | rv_op_fcvt_q_lu, 399 | rv_op_fmv_x_q, 400 | rv_op_fmv_q_x, 401 | rv_op_c_addi4spn, 402 | rv_op_c_fld, 403 | rv_op_c_lw, 404 | rv_op_c_flw, 405 | rv_op_c_fsd, 406 | rv_op_c_sw, 407 | rv_op_c_fsw, 408 | rv_op_c_nop, 409 | rv_op_c_addi, 410 | rv_op_c_jal, 411 | rv_op_c_li, 412 | rv_op_c_addi16sp, 413 | rv_op_c_lui, 414 | rv_op_c_srli, 415 | rv_op_c_srai, 416 | rv_op_c_andi, 417 | rv_op_c_sub, 418 | rv_op_c_xor, 419 | rv_op_c_or, 420 | rv_op_c_and, 421 | rv_op_c_subw, 422 | rv_op_c_addw, 423 | rv_op_c_j, 424 | rv_op_c_beqz, 425 | rv_op_c_bnez, 426 | rv_op_c_slli, 427 | rv_op_c_fldsp, 428 | rv_op_c_lwsp, 429 | rv_op_c_flwsp, 430 | rv_op_c_jr, 431 | rv_op_c_mv, 432 | rv_op_c_ebreak, 433 | rv_op_c_jalr, 434 | rv_op_c_add, 435 | rv_op_c_fsdsp, 436 | rv_op_c_swsp, 437 | rv_op_c_fswsp, 438 | rv_op_c_ld, 439 | rv_op_c_sd, 440 | rv_op_c_addiw, 441 | rv_op_c_ldsp, 442 | rv_op_c_sdsp, 443 | rv_op_c_lq, 444 | rv_op_c_sq, 445 | rv_op_c_lqsp, 446 | rv_op_c_sqsp, 447 | rv_op_nop, 448 | rv_op_mv, 449 | rv_op_not, 450 | rv_op_neg, 451 | rv_op_negw, 452 | rv_op_sext_w, 453 | rv_op_seqz, 454 | rv_op_snez, 455 | rv_op_sltz, 456 | rv_op_sgtz, 457 | rv_op_fmv_s, 458 | rv_op_fabs_s, 459 | rv_op_fneg_s, 460 | rv_op_fmv_d, 461 | rv_op_fabs_d, 462 | rv_op_fneg_d, 463 | rv_op_fmv_q, 464 | rv_op_fabs_q, 465 | rv_op_fneg_q, 466 | rv_op_beqz, 467 | rv_op_bnez, 468 | rv_op_blez, 469 | rv_op_bgez, 470 | rv_op_bltz, 471 | rv_op_bgtz, 472 | rv_op_ble, 473 | rv_op_bleu, 474 | rv_op_bgt, 475 | rv_op_bgtu, 476 | rv_op_j, 477 | rv_op_ret, 478 | rv_op_jr, 479 | rv_op_rdcycle, 480 | rv_op_rdtime, 481 | rv_op_rdinstret, 482 | rv_op_rdcycleh, 483 | rv_op_rdtimeh, 484 | rv_op_rdinstreth, 485 | rv_op_frcsr, 486 | rv_op_frrm, 487 | rv_op_frflags, 488 | rv_op_fscsr, 489 | rv_op_fsrm, 490 | rv_op_fsflags, 491 | rv_op_fsrmi, 492 | rv_op_fsflagsi, 493 | } rv_op; 494 | 495 | /* structures */ 496 | 497 | typedef struct { 498 | uint64_t pc; 499 | uint64_t inst; 500 | int32_t imm; 501 | uint16_t op; 502 | uint8_t codec; 503 | uint8_t rd; 504 | uint8_t rs1; 505 | uint8_t rs2; 506 | uint8_t rs3; 507 | uint8_t rm; 508 | uint8_t pred; 509 | uint8_t succ; 510 | uint8_t aq; 511 | uint8_t rl; 512 | } rv_decode; 513 | 514 | /* functions */ 515 | 516 | size_t inst_length(rv_inst inst); 517 | void inst_fetch(const uint8_t *data, rv_inst *instp, size_t *length); 518 | void disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst); 519 | 520 | #endif 521 | -------------------------------------------------------------------------------- /tests/t1.c: -------------------------------------------------------------------------------- 1 | #include "riscv-disas.h" 2 | 3 | enum { 4 | OPC_ADD = 0x33, 5 | OPC_ADDI = 0x13, 6 | OPC_ADDIW = 0x1b, 7 | OPC_ADDW = 0x3b, 8 | OPC_AND = 0x7033, 9 | OPC_ANDI = 0x7013, 10 | OPC_AUIPC = 0x17, 11 | OPC_BEQ = 0x63, 12 | OPC_BGE = 0x5063, 13 | OPC_BGEU = 0x7063, 14 | OPC_BLT = 0x4063, 15 | OPC_BLTU = 0x6063, 16 | OPC_BNE = 0x1063, 17 | OPC_DIV = 0x2004033, 18 | OPC_DIVU = 0x2005033, 19 | OPC_DIVUW = 0x200503b, 20 | OPC_DIVW = 0x200403b, 21 | OPC_JAL = 0x6f, 22 | OPC_JALR = 0x67, 23 | OPC_LB = 0x3, 24 | OPC_LBU = 0x4003, 25 | OPC_LD = 0x3003, 26 | OPC_LH = 0x1003, 27 | OPC_LHU = 0x5003, 28 | OPC_LUI = 0x37, 29 | OPC_LW = 0x2003, 30 | OPC_LWU = 0x6003, 31 | OPC_MUL = 0x2000033, 32 | OPC_MULH = 0x2001033, 33 | OPC_MULHSU = 0x2002033, 34 | OPC_MULHU = 0x2003033, 35 | OPC_MULW = 0x200003b, 36 | OPC_OR = 0x6033, 37 | OPC_ORI = 0x6013, 38 | OPC_REM = 0x2006033, 39 | OPC_REMU = 0x2007033, 40 | OPC_REMUW = 0x200703b, 41 | OPC_REMW = 0x200603b, 42 | OPC_SB = 0x23, 43 | OPC_SD = 0x3023, 44 | OPC_SH = 0x1023, 45 | OPC_SLL = 0x1033, 46 | OPC_SLLI = 0x1013, 47 | OPC_SLLIW = 0x101b, 48 | OPC_SLLW = 0x103b, 49 | OPC_SLT = 0x2033, 50 | OPC_SLTI = 0x2013, 51 | OPC_SLTIU = 0x3013, 52 | OPC_SLTU = 0x3033, 53 | OPC_SRA = 0x40005033, 54 | OPC_SRAI = 0x40005013, 55 | OPC_SRAIW = 0x4000501b, 56 | OPC_SRAW = 0x4000503b, 57 | OPC_SRL = 0x5033, 58 | OPC_SRLI = 0x5013, 59 | OPC_SRLIW = 0x501b, 60 | OPC_SRLW = 0x503b, 61 | OPC_SUB = 0x40000033, 62 | OPC_SUBW = 0x4000003b, 63 | OPC_SW = 0x2023, 64 | OPC_XOR = 0x4033, 65 | OPC_XORI = 0x4013, 66 | }; 67 | 68 | uint32_t encode_sbimm12(uint32_t imm) 69 | { 70 | return ((imm << 19) >> 31) << 31 | 71 | ((imm << 21) >> 26) << 25 | 72 | ((imm << 27) >> 28) << 8 | 73 | ((imm << 20) >> 31) << 7; 74 | } 75 | 76 | uint32_t encode_r_jimm20(uint32_t rd, uint32_t imm) 77 | { 78 | return (rd & 0x1f) << 7 | 79 | ((imm << 11) >> 31) << 31 | 80 | ((imm << 21) >> 22) << 21 | 81 | ((imm << 20) >> 31) << 20 | 82 | ((imm << 12) >> 24) << 12; 83 | } 84 | 85 | uint32_t encode_rr_simm12(uint32_t rd, uint32_t rs1, uint32_t imm) 86 | { 87 | return (rd & 0x1f) << 7 | 88 | (rs1 & 0x1f) << 15 | 89 | (imm & 0xfff) << 20; 90 | } 91 | 92 | void print_inst(uint64_t pc, uint32_t inst) 93 | { 94 | char buf[80] = { 0 }; 95 | disasm_inst(buf, sizeof(buf), rv64, pc, inst); 96 | printf("%016" PRIx64 ": %s\n", pc, buf); 97 | } 98 | 99 | int main() 100 | { 101 | print_inst(0x10000, OPC_BEQ | encode_sbimm12(-454)); 102 | print_inst(0x10004, OPC_BEQ | encode_sbimm12(-232)); 103 | print_inst(0x10008, OPC_BEQ | encode_sbimm12(232)); 104 | print_inst(0x1000c, OPC_BEQ | encode_sbimm12(454)); 105 | print_inst(0x10010, OPC_ADDI | encode_rr_simm12(8, 9, 0)); 106 | print_inst(0x10014, OPC_JAL | encode_r_jimm20(0, -4)); 107 | print_inst(0x10018, OPC_JAL | encode_r_jimm20(1, -12)); 108 | } 109 | -------------------------------------------------------------------------------- /tests/t2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "riscv-disas.h" 4 | 5 | #define array_size(arr) (sizeof(arr) / sizeof(arr[0])) 6 | 7 | void dissassemble(uint64_t pc, const uint8_t *data, size_t data_len) 8 | { 9 | char buf[128] = { 0 }; 10 | size_t offset = 0, inst_len; 11 | rv_inst inst; 12 | while (offset < data_len) 13 | { 14 | inst_fetch(data + offset, &inst, &inst_len); 15 | disasm_inst(buf, sizeof(buf), rv64, pc + offset, inst); 16 | printf("0x%" PRIx64 ": %s\n", pc + offset, buf); 17 | offset += inst_len; 18 | } 19 | } 20 | 21 | void t1() 22 | { 23 | static const uint8_t inst_arr[] = { 24 | 0x00, 0x00, // illegal 25 | 0x00, 0x01, // nop 26 | 0x00, 0x0d, // addi zero,zero,3 27 | 0x01, 0x04, // mv s0,s0 28 | 0x04, 0x04, // addi s1,sp,512 29 | 0x05, 0x40, // addi s0,s0,1 30 | 0x73, 0x25, 0x40, 0xf1, // csrrs a0,mhartid,zero 31 | 0x97, 0x05, 0x00, 0x00, // auipc a1,0 32 | 0xb7, 0x02, 0x40, 0x20, // lui t0,541065216 33 | 0x13, 0x00, 0x00, 0x00, // nop 34 | }; 35 | dissassemble(0x10078, inst_arr, array_size(inst_arr)); 36 | } 37 | 38 | int main() 39 | { 40 | t1(); 41 | } 42 | --------------------------------------------------------------------------------