riscv-disas.c (88189B)
1 /* 2 * RISC-V Disassembler 3 * 4 * Copyright (c) 2016-2017 Michael Clark <michaeljclark@mac.com> 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 }