| 1 | /* |
| 2 | * QEMU RISC-V Disassembler |
| 3 | * |
| 4 | * Copyright (c) 2016-2017 Michael Clark <michaeljclark@mac.com> |
| 5 | * Copyright (c) 2017-2018 SiFive, Inc. |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify it |
| 8 | * under the terms and conditions of the GNU General Public License, |
| 9 | * version 2 or later, as published by the Free Software Foundation. |
| 10 | * |
| 11 | * This program is distributed in the hope it will be useful, but WITHOUT |
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 14 | * more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License along with |
| 17 | * this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | */ |
| 19 | |
| 20 | #include "qemu/osdep.h" |
| 21 | #include "qemu/bitops.h" |
| 22 | #include "disas/dis-asm.h" |
| 23 | #include "target/riscv/cpu_cfg.h" |
| 24 | #include "disas/riscv.h" |
| 25 | |
| 26 | /* Vendor extensions */ |
| 27 | #include "disas/riscv-xthead.h" |
| 28 | #include "disas/riscv-xventana.h" |
| 29 | #include "disas/riscv-xlrbr.h" |
| 30 | |
| 31 | /* register names */ |
| 32 | |
| 33 | static const char rv_ireg_name_sym[32][5] = { |
| 34 | "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", |
| 35 | "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", |
| 36 | "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", |
| 37 | "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", |
| 38 | }; |
| 39 | |
| 40 | static const char rv_freg_name_sym[32][5] = { |
| 41 | "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7", |
| 42 | "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5", |
| 43 | "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7", |
| 44 | "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11", |
| 45 | }; |
| 46 | |
| 47 | static const char rv_vreg_name_sym[32][4] = { |
| 48 | "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", |
| 49 | "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", |
| 50 | "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", |
| 51 | "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31" |
| 52 | }; |
| 53 | |
| 54 | /* The FLI.[HSDQ] numeric constants (0.0 for symbolic constants). |
| 55 | * The constants use the hex floating-point literal representation |
| 56 | * that is printed when using the printf %a format specifier, |
| 57 | * which matches the output that is generated by the disassembler. |
| 58 | */ |
| 59 | static const char rv_fli_name_const[32][9] = |
| 60 | { |
| 61 | "0x1p+0", "min", "0x1p-16", "0x1p-15", |
| 62 | "0x1p-8", "0x1p-7", "0x1p-4", "0x1p-3", |
| 63 | "0x1p-2", "0x1.4p-2", "0x1.8p-2", "0x1.cp-2", |
| 64 | "0x1p-1", "0x1.4p-1", "0x1.8p-1", "0x1.cp-1", |
| 65 | "0x1p+0", "0x1.4p+0", "0x1.8p+0", "0x1.cp+0", |
| 66 | "0x1p+1", "0x1.4p+1", "0x1.8p+1", "0x1p+2", |
| 67 | "0x1p+3", "0x1p+4", "0x1p+7", "0x1p+8", |
| 68 | "0x1p+15", "0x1p+16", "inf", "nan" |
| 69 | }; |
| 70 | |
| 71 | /* pseudo-instruction constraints */ |
| 72 | |
| 73 | static const rvc_constraint rvcc_jal_ra[] = { rvc_rd_eq_ra, rvc_end }; |
| 74 | static const rvc_constraint rvcc_jalr_ra[] = { rvc_rd_eq_ra, rvc_imm_eq_zero, |
| 75 | rvc_end }; |
| 76 | static const rvc_constraint rvcc_nop[] = { rvc_rd_eq_x0, rvc_rs1_eq_x0, |
| 77 | rvc_end }; |
| 78 | static const rvc_constraint rvcc_mv[] = { rvc_imm_eq_zero, rvc_end }; |
| 79 | static const rvc_constraint rvcc_not[] = { rvc_imm_eq_n1, rvc_end }; |
| 80 | static const rvc_constraint rvcc_neg[] = { rvc_rs1_eq_x0, rvc_end }; |
| 81 | static const rvc_constraint rvcc_negw[] = { rvc_rs1_eq_x0, rvc_end }; |
| 82 | static const rvc_constraint rvcc_sext_w[] = { rvc_imm_eq_zero, rvc_end }; |
| 83 | static const rvc_constraint rvcc_seqz[] = { rvc_imm_eq_p1, rvc_end }; |
| 84 | static const rvc_constraint rvcc_snez[] = { rvc_rs1_eq_x0, rvc_end }; |
| 85 | static const rvc_constraint rvcc_sltz[] = { rvc_rs2_eq_x0, rvc_end }; |
| 86 | static const rvc_constraint rvcc_sgtz[] = { rvc_rs1_eq_x0, rvc_end }; |
| 87 | static const rvc_constraint rvcc_fmv_s[] = { rvc_rs2_eq_rs1, rvc_end }; |
| 88 | static const rvc_constraint rvcc_fabs_s[] = { rvc_rs2_eq_rs1, rvc_end }; |
| 89 | static const rvc_constraint rvcc_fneg_s[] = { rvc_rs2_eq_rs1, rvc_end }; |
| 90 | static const rvc_constraint rvcc_fmv_d[] = { rvc_rs2_eq_rs1, rvc_end }; |
| 91 | static const rvc_constraint rvcc_fabs_d[] = { rvc_rs2_eq_rs1, rvc_end }; |
| 92 | static const rvc_constraint rvcc_fneg_d[] = { rvc_rs2_eq_rs1, rvc_end }; |
| 93 | static const rvc_constraint rvcc_fmv_q[] = { rvc_rs2_eq_rs1, rvc_end }; |
| 94 | static const rvc_constraint rvcc_fabs_q[] = { rvc_rs2_eq_rs1, rvc_end }; |
| 95 | static const rvc_constraint rvcc_fneg_q[] = { rvc_rs2_eq_rs1, rvc_end }; |
| 96 | static const rvc_constraint rvcc_beqz[] = { rvc_rs2_eq_x0, rvc_end }; |
| 97 | static const rvc_constraint rvcc_bnez[] = { rvc_rs2_eq_x0, rvc_end }; |
| 98 | static const rvc_constraint rvcc_blez[] = { rvc_rs1_eq_x0, rvc_end }; |
| 99 | static const rvc_constraint rvcc_bgez[] = { rvc_rs2_eq_x0, rvc_end }; |
| 100 | static const rvc_constraint rvcc_bltz[] = { rvc_rs2_eq_x0, rvc_end }; |
| 101 | static const rvc_constraint rvcc_bgtz[] = { rvc_rs1_eq_x0, rvc_end }; |
| 102 | static const rvc_constraint rvcc_j[] = { rvc_rd_eq_x0, rvc_end }; |
| 103 | static const rvc_constraint rvcc_ret[] = { rvc_rs1_eq_ra, rvc_end }; |
| 104 | static const rvc_constraint rvcc_jr[] = { rvc_rd_eq_x0, rvc_imm_eq_zero, |
| 105 | rvc_end }; |
| 106 | static const rvc_constraint rvcc_true[] = { rvc_end }; |
| 107 | |
| 108 | /* pseudo-instruction metadata */ |
| 109 | |
| 110 | /* Forward declare the all the opcodes so that we may link them. */ |
| 111 | #define OP(N, ...) static const rv_opcode_data op_##N; |
| 112 | #include "riscv-op.c.inc" |
| 113 | #undef OP |
| 114 | |
| 115 | static const rv_comp_data rvcp_jal[] = { |
| 116 | { &op_j, rvcc_j }, |
| 117 | { &op_jal_ra, rvcc_jal_ra }, |
| 118 | { }, |
| 119 | }; |
| 120 | |
| 121 | static const rv_comp_data rvcp_jalr[] = { |
| 122 | { &op_jr, rvcc_jr }, |
| 123 | { &op_jalr_ra, rvcc_jalr_ra }, |
| 124 | { }, |
| 125 | }; |
| 126 | |
| 127 | static const rv_comp_data rvcp_jr[] = { |
| 128 | { &op_ret, rvcc_ret }, |
| 129 | { }, |
| 130 | }; |
| 131 | |
| 132 | static const rv_comp_data rvcp_beq[] = { |
| 133 | { &op_beqz, rvcc_beqz }, |
| 134 | { }, |
| 135 | }; |
| 136 | |
| 137 | static const rv_comp_data rvcp_bne[] = { |
| 138 | { &op_bnez, rvcc_bnez }, |
| 139 | { }, |
| 140 | }; |
| 141 | |
| 142 | static const rv_comp_data rvcp_blt[] = { |
| 143 | { &op_bltz, rvcc_bltz }, |
| 144 | { &op_bgtz, rvcc_bgtz }, |
| 145 | { }, |
| 146 | }; |
| 147 | |
| 148 | static const rv_comp_data rvcp_bge[] = { |
| 149 | { &op_blez, rvcc_blez }, |
| 150 | { &op_bgez, rvcc_bgez }, |
| 151 | { }, |
| 152 | }; |
| 153 | |
| 154 | static const rv_comp_data rvcp_addi[] = { |
| 155 | { &op_mv, rvcc_mv }, |
| 156 | { }, |
| 157 | }; |
| 158 | |
| 159 | static const rv_comp_data rvcp_mv[] = { |
| 160 | { &op_nop, rvcc_nop }, |
| 161 | { }, |
| 162 | }; |
| 163 | |
| 164 | static const rv_comp_data rvcp_sltiu[] = { |
| 165 | { &op_seqz, rvcc_seqz }, |
| 166 | { }, |
| 167 | }; |
| 168 | |
| 169 | static const rv_comp_data rvcp_xori[] = { |
| 170 | { &op_not, rvcc_not }, |
| 171 | { }, |
| 172 | }; |
| 173 | |
| 174 | static const rv_comp_data rvcp_sub[] = { |
| 175 | { &op_neg, rvcc_neg }, |
| 176 | { }, |
| 177 | }; |
| 178 | |
| 179 | static const rv_comp_data rvcp_slt[] = { |
| 180 | { &op_sltz, rvcc_sltz }, |
| 181 | { &op_sgtz, rvcc_sgtz }, |
| 182 | { }, |
| 183 | }; |
| 184 | |
| 185 | static const rv_comp_data rvcp_sltu[] = { |
| 186 | { &op_snez, rvcc_snez }, |
| 187 | { }, |
| 188 | }; |
| 189 | |
| 190 | static const rv_comp_data rvcp_addiw[] = { |
| 191 | { &op_sext_w, rvcc_sext_w }, |
| 192 | { }, |
| 193 | }; |
| 194 | |
| 195 | static const rv_comp_data rvcp_subw[] = { |
| 196 | { &op_negw, rvcc_negw }, |
| 197 | { }, |
| 198 | }; |
| 199 | |
| 200 | static const rv_comp_data rvcp_fsgnj_s[] = { |
| 201 | { &op_fmv_s, rvcc_fmv_s }, |
| 202 | { }, |
| 203 | }; |
| 204 | |
| 205 | static const rv_comp_data rvcp_fsgnjn_s[] = { |
| 206 | { &op_fneg_s, rvcc_fneg_s }, |
| 207 | { }, |
| 208 | }; |
| 209 | |
| 210 | static const rv_comp_data rvcp_fsgnjx_s[] = { |
| 211 | { &op_fabs_s, rvcc_fabs_s }, |
| 212 | { }, |
| 213 | }; |
| 214 | |
| 215 | static const rv_comp_data rvcp_fsgnj_d[] = { |
| 216 | { &op_fmv_d, rvcc_fmv_d }, |
| 217 | { }, |
| 218 | }; |
| 219 | |
| 220 | static const rv_comp_data rvcp_fsgnjn_d[] = { |
| 221 | { &op_fneg_d, rvcc_fneg_d }, |
| 222 | { }, |
| 223 | }; |
| 224 | |
| 225 | static const rv_comp_data rvcp_fsgnjx_d[] = { |
| 226 | { &op_fabs_d, rvcc_fabs_d }, |
| 227 | { }, |
| 228 | }; |
| 229 | |
| 230 | static const rv_comp_data rvcp_fsgnj_q[] = { |
| 231 | { &op_fmv_q, rvcc_fmv_q }, |
| 232 | { }, |
| 233 | }; |
| 234 | |
| 235 | static const rv_comp_data rvcp_fsgnjn_q[] = { |
| 236 | { &op_fneg_q, rvcc_fneg_q }, |
| 237 | { }, |
| 238 | }; |
| 239 | |
| 240 | static const rv_comp_data rvcp_fsgnjx_q[] = { |
| 241 | { &op_fabs_q, rvcc_fabs_q }, |
| 242 | { }, |
| 243 | }; |
| 244 | |
| 245 | /* Convert compressed insns into normal insns via pseudo expansion. */ |
| 246 | #define DECOMP(X) &(const rv_comp_data){ &X, rvcc_true } |
| 247 | |
| 248 | /* operand extractors */ |
| 249 | |
| 250 | static uint32_t operand_rd(rv_inst inst) |
| 251 | { |
| 252 | return extract32(inst, 7, 5); |
| 253 | } |
| 254 | |
| 255 | static uint32_t operand_rs1(rv_inst inst) |
| 256 | { |
| 257 | return extract32(inst, 15, 5); |
| 258 | } |
| 259 | |
| 260 | static uint32_t operand_rs2(rv_inst inst) |
| 261 | { |
| 262 | return extract32(inst, 20, 5); |
| 263 | } |
| 264 | |
| 265 | static uint32_t operand_rs3(rv_inst inst) |
| 266 | { |
| 267 | return extract32(inst, 27, 5); |
| 268 | } |
| 269 | |
| 270 | static uint32_t operand_aq(rv_inst inst) |
| 271 | { |
| 272 | return extract32(inst, 26, 1); |
| 273 | } |
| 274 | |
| 275 | static uint32_t operand_rl(rv_inst inst) |
| 276 | { |
| 277 | return extract32(inst, 25, 1); |
| 278 | } |
| 279 | |
| 280 | static uint32_t operand_pred(rv_inst inst) |
| 281 | { |
| 282 | return extract32(inst, 24, 4); |
| 283 | } |
| 284 | |
| 285 | static uint32_t operand_succ(rv_inst inst) |
| 286 | { |
| 287 | return extract32(inst, 20, 4); |
| 288 | } |
| 289 | |
| 290 | static uint32_t operand_rm(rv_inst inst) |
| 291 | { |
| 292 | return extract32(inst, 12, 3); |
| 293 | } |
| 294 | |
| 295 | static uint32_t operand_shamt5(rv_inst inst) |
| 296 | { |
| 297 | return extract32(inst, 20, 5); |
| 298 | } |
| 299 | |
| 300 | static uint32_t operand_shamt6(rv_inst inst) |
| 301 | { |
| 302 | return extract32(inst, 20, 6); |
| 303 | } |
| 304 | |
| 305 | static uint32_t operand_shamt7(rv_inst inst) |
| 306 | { |
| 307 | return extract32(inst, 20, 7); |
| 308 | } |
| 309 | |
| 310 | static uint32_t operand_crdq(rv_inst inst) |
| 311 | { |
| 312 | return extract32(inst, 2, 3); |
| 313 | } |
| 314 | |
| 315 | static uint32_t operand_crs1q(rv_inst inst) |
| 316 | { |
| 317 | return extract32(inst, 7, 3); |
| 318 | } |
| 319 | |
| 320 | static uint32_t operand_crs1rdq(rv_inst inst) |
| 321 | { |
| 322 | return extract32(inst, 7, 3); |
| 323 | } |
| 324 | |
| 325 | static uint32_t operand_crs2q(rv_inst inst) |
| 326 | { |
| 327 | return extract32(inst, 2, 3); |
| 328 | } |
| 329 | |
| 330 | static uint32_t calculate_xreg(uint32_t sreg) |
| 331 | { |
| 332 | return sreg < 2 ? sreg + 8 : sreg + 16; |
| 333 | } |
| 334 | |
| 335 | static uint32_t operand_sreg1(rv_inst inst) |
| 336 | { |
| 337 | return calculate_xreg(extract32(inst, 7, 3)); |
| 338 | } |
| 339 | |
| 340 | static uint32_t operand_sreg2(rv_inst inst) |
| 341 | { |
| 342 | return calculate_xreg(extract32(inst, 2, 3)); |
| 343 | } |
| 344 | |
| 345 | static uint32_t operand_crd(rv_inst inst) |
| 346 | { |
| 347 | return extract32(inst, 7, 5); |
| 348 | } |
| 349 | |
| 350 | static uint32_t operand_crs1(rv_inst inst) |
| 351 | { |
| 352 | return extract32(inst, 7, 5); |
| 353 | } |
| 354 | |
| 355 | static uint32_t operand_crs1rd(rv_inst inst) |
| 356 | { |
| 357 | return extract32(inst, 7, 5); |
| 358 | } |
| 359 | |
| 360 | static uint32_t operand_crs2(rv_inst inst) |
| 361 | { |
| 362 | return extract32(inst, 2, 5); |
| 363 | } |
| 364 | |
| 365 | static uint32_t operand_cimmsh5(rv_inst inst) |
| 366 | { |
| 367 | return extract32(inst, 2, 5); |
| 368 | } |
| 369 | |
| 370 | static uint32_t operand_csr12(rv_inst inst) |
| 371 | { |
| 372 | return extract32(inst, 20, 12); |
| 373 | } |
| 374 | |
| 375 | static int32_t operand_imm12(rv_inst inst) |
| 376 | { |
| 377 | return sextract32(inst, 20, 12); |
| 378 | } |
| 379 | |
| 380 | static int32_t operand_imm20(rv_inst inst) |
| 381 | { |
| 382 | return sextract32(inst, 12, 20) << 12; |
| 383 | } |
| 384 | |
| 385 | static int32_t operand_jimm20(rv_inst inst) |
| 386 | { |
| 387 | return sextract32(inst, 31, 1) << 20 | |
| 388 | extract32(inst, 21, 10) << 1 | |
| 389 | extract32(inst, 20, 1) << 11 | |
| 390 | extract32(inst, 12, 8) << 12; |
| 391 | } |
| 392 | |
| 393 | static int32_t operand_simm12(rv_inst inst) |
| 394 | { |
| 395 | return sextract32(inst, 25, 7) << 5 | |
| 396 | extract32(inst, 7, 5); |
| 397 | } |
| 398 | |
| 399 | static int32_t operand_sbimm12(rv_inst inst) |
| 400 | { |
| 401 | return sextract32(inst, 31, 1) << 12 | |
| 402 | extract32(inst, 25, 6) << 5 | |
| 403 | extract32(inst, 8, 4) << 1 | |
| 404 | extract32(inst, 7, 1) << 11; |
| 405 | } |
| 406 | |
| 407 | static uint32_t operand_cimmshl6(rv_inst inst, rv_isa isa) |
| 408 | { |
| 409 | int imm = extract32(inst, 12, 1) << 5 | |
| 410 | extract32(inst, 2, 5); |
| 411 | if (isa == rv128) { |
| 412 | imm = imm ? imm : 64; |
| 413 | } |
| 414 | return imm; |
| 415 | } |
| 416 | |
| 417 | static uint32_t operand_cimmshr6(rv_inst inst, rv_isa isa) |
| 418 | { |
| 419 | int imm = extract32(inst, 12, 1) << 5 | |
| 420 | extract32(inst, 2, 5); |
| 421 | if (isa == rv128) { |
| 422 | imm = imm | (imm & 32) << 1; |
| 423 | imm = imm ? imm : 64; |
| 424 | } |
| 425 | return imm; |
| 426 | } |
| 427 | |
| 428 | static int32_t operand_cimmi(rv_inst inst) |
| 429 | { |
| 430 | return sextract32(inst, 12, 1) << 5 | |
| 431 | extract32(inst, 2, 5); |
| 432 | } |
| 433 | |
| 434 | static int32_t operand_cimmui(rv_inst inst) |
| 435 | { |
| 436 | return sextract32(inst, 12, 1) << 17 | |
| 437 | extract32(inst, 2, 5) << 12; |
| 438 | } |
| 439 | |
| 440 | static uint32_t operand_cimmlwsp(rv_inst inst) |
| 441 | { |
| 442 | return extract32(inst, 12, 1) << 5 | |
| 443 | extract32(inst, 4, 3) << 2 | |
| 444 | extract32(inst, 2, 2) << 6; |
| 445 | } |
| 446 | |
| 447 | static uint32_t operand_cimmldsp(rv_inst inst) |
| 448 | { |
| 449 | return extract32(inst, 12, 1) << 5 | |
| 450 | extract32(inst, 5, 2) << 3 | |
| 451 | extract32(inst, 2, 3) << 6; |
| 452 | } |
| 453 | |
| 454 | static uint32_t operand_cimmlqsp(rv_inst inst) |
| 455 | { |
| 456 | return extract32(inst, 12, 1) << 5 | |
| 457 | extract32(inst, 6, 1) << 4 | |
| 458 | extract32(inst, 2, 4) << 6; |
| 459 | } |
| 460 | |
| 461 | static int32_t operand_cimm16sp(rv_inst inst) |
| 462 | { |
| 463 | return sextract32(inst, 12, 1) << 9 | |
| 464 | extract32(inst, 6, 1) << 4 | |
| 465 | extract32(inst, 5, 1) << 6 | |
| 466 | extract32(inst, 3, 2) << 7 | |
| 467 | extract32(inst, 2, 1) << 5; |
| 468 | } |
| 469 | |
| 470 | static int32_t operand_cimmj(rv_inst inst) |
| 471 | { |
| 472 | return sextract32(inst, 12, 1) << 11 | |
| 473 | extract32(inst, 11, 1) << 4 | |
| 474 | extract32(inst, 9, 2) << 8 | |
| 475 | extract32(inst, 8, 1) << 10 | |
| 476 | extract32(inst, 7, 1) << 6 | |
| 477 | extract32(inst, 6, 1) << 7 | |
| 478 | extract32(inst, 3, 3) << 1 | |
| 479 | extract32(inst, 2, 1) << 5; |
| 480 | } |
| 481 | |
| 482 | static int32_t operand_cimmb(rv_inst inst) |
| 483 | { |
| 484 | return sextract32(inst, 12, 1) << 8 | |
| 485 | extract32(inst, 10, 2) << 3 | |
| 486 | extract32(inst, 5, 2) << 6 | |
| 487 | extract32(inst, 3, 2) << 1 | |
| 488 | extract32(inst, 2, 1) << 5; |
| 489 | } |
| 490 | |
| 491 | static uint32_t operand_cimmswsp(rv_inst inst) |
| 492 | { |
| 493 | return extract32(inst, 9, 4) << 2 | |
| 494 | extract32(inst, 7, 2) << 6; |
| 495 | } |
| 496 | |
| 497 | static uint32_t operand_cimmsdsp(rv_inst inst) |
| 498 | { |
| 499 | return extract32(inst, 10, 3) << 3 | |
| 500 | extract32(inst, 7, 3) << 6; |
| 501 | } |
| 502 | |
| 503 | static uint32_t operand_cimmsqsp(rv_inst inst) |
| 504 | { |
| 505 | return extract32(inst, 11, 2) << 4 | |
| 506 | extract32(inst, 7, 4) << 6; |
| 507 | } |
| 508 | |
| 509 | static uint32_t operand_cimm4spn(rv_inst inst) |
| 510 | { |
| 511 | return extract32(inst, 11, 2) << 4 | |
| 512 | extract32(inst, 7, 4) << 6 | |
| 513 | extract32(inst, 6, 1) << 2 | |
| 514 | extract32(inst, 5, 1) << 3; |
| 515 | } |
| 516 | |
| 517 | static uint32_t operand_cimmw(rv_inst inst) |
| 518 | { |
| 519 | return extract32(inst, 10, 3) << 3 | |
| 520 | extract32(inst, 6, 1) << 2 | |
| 521 | extract32(inst, 5, 1) << 6; |
| 522 | } |
| 523 | |
| 524 | static uint32_t operand_cimmd(rv_inst inst) |
| 525 | { |
| 526 | return extract32(inst, 10, 3) << 3 | |
| 527 | extract32(inst, 5, 2) << 6; |
| 528 | } |
| 529 | |
| 530 | static uint32_t operand_cimmq(rv_inst inst) |
| 531 | { |
| 532 | return extract32(inst, 11, 2) << 4 | |
| 533 | extract32(inst, 10, 1) << 8 | |
| 534 | extract32(inst, 5, 2) << 6; |
| 535 | } |
| 536 | |
| 537 | static int32_t operand_vimm(rv_inst inst) |
| 538 | { |
| 539 | return sextract32(inst, 15, 5); |
| 540 | } |
| 541 | |
| 542 | static uint32_t operand_vuimm(rv_inst inst) |
| 543 | { |
| 544 | return extract32(inst, 15, 5); |
| 545 | } |
| 546 | |
| 547 | static uint32_t operand_vzimm11(rv_inst inst) |
| 548 | { |
| 549 | return extract32(inst, 20, 11); |
| 550 | } |
| 551 | |
| 552 | static uint32_t operand_vzimm10(rv_inst inst) |
| 553 | { |
| 554 | return extract32(inst, 20, 10); |
| 555 | } |
| 556 | |
| 557 | static uint32_t operand_vzimm6(rv_inst inst) |
| 558 | { |
| 559 | return extract32(inst, 26, 1) << 5 | |
| 560 | extract32(inst, 15, 5); |
| 561 | } |
| 562 | |
| 563 | static uint32_t operand_bs(rv_inst inst) |
| 564 | { |
| 565 | return extract32(inst, 30, 2); |
| 566 | } |
| 567 | |
| 568 | static uint32_t operand_rnum(rv_inst inst) |
| 569 | { |
| 570 | return extract32(inst, 20, 4); |
| 571 | } |
| 572 | |
| 573 | static uint32_t operand_vm(rv_inst inst) |
| 574 | { |
| 575 | return extract32(inst, 25, 1); |
| 576 | } |
| 577 | |
| 578 | static uint32_t operand_uimm_c_lb(rv_inst inst) |
| 579 | { |
| 580 | return extract32(inst, 5, 1) << 1 | |
| 581 | extract32(inst, 6, 1); |
| 582 | } |
| 583 | |
| 584 | static uint32_t operand_uimm_c_lh(rv_inst inst) |
| 585 | { |
| 586 | return extract32(inst, 5, 1) << 1; |
| 587 | } |
| 588 | |
| 589 | static uint32_t operand_zcmp_spimm(rv_inst inst) |
| 590 | { |
| 591 | return extract32(inst, 2, 2) << 4; |
| 592 | } |
| 593 | |
| 594 | static uint32_t operand_zcmp_rlist(rv_inst inst) |
| 595 | { |
| 596 | return extract32(inst, 4, 4); |
| 597 | } |
| 598 | |
| 599 | static uint32_t operand_imm6(rv_inst inst) |
| 600 | { |
| 601 | return extract32(inst, 20, 6); |
| 602 | } |
| 603 | |
| 604 | static uint32_t operand_imm2(rv_inst inst) |
| 605 | { |
| 606 | return extract32(inst, 25, 2); |
| 607 | } |
| 608 | |
| 609 | static uint32_t operand_immh(rv_inst inst) |
| 610 | { |
| 611 | return extract32(inst, 26, 6); |
| 612 | } |
| 613 | |
| 614 | static uint32_t operand_imml(rv_inst inst) |
| 615 | { |
| 616 | return extract32(inst, 20, 6); |
| 617 | } |
| 618 | |
| 619 | static uint32_t calculate_stack_adj(rv_isa isa, uint32_t rlist, uint32_t spimm) |
| 620 | { |
| 621 | int xlen_bytes_log2 = isa == rv64 ? 3 : 2; |
| 622 | int regs = rlist == 15 ? 13 : rlist - 3; |
| 623 | uint32_t stack_adj_base = ROUND_UP(regs << xlen_bytes_log2, 16); |
| 624 | return stack_adj_base + spimm; |
| 625 | } |
| 626 | |
| 627 | static uint32_t operand_zcmp_stack_adj(rv_inst inst, rv_isa isa) |
| 628 | { |
| 629 | return calculate_stack_adj(isa, operand_zcmp_rlist(inst), |
| 630 | operand_zcmp_spimm(inst)); |
| 631 | } |
| 632 | |
| 633 | static uint32_t operand_tbl_index(rv_inst inst) |
| 634 | { |
| 635 | return extract32(inst, 2, 8); |
| 636 | } |
| 637 | |
| 638 | static uint32_t operand_lpl(rv_inst inst) |
| 639 | { |
| 640 | return extract32(inst, 12, 20); |
| 641 | } |
| 642 | |
| 643 | static uint32_t operand_cmop_imm(rv_inst inst) |
| 644 | { |
| 645 | return extract32(inst, 8, 3) * 2 + 1; |
| 646 | } |
| 647 | |
| 648 | static uint32_t operand_mop_r_imm(rv_inst inst) |
| 649 | { |
| 650 | return (extract32(inst, 30, 1) << 4) | |
| 651 | (extract32(inst, 26, 2) << 2) | |
| 652 | extract32(inst, 20, 2); |
| 653 | } |
| 654 | |
| 655 | static uint32_t operand_mop_rr_imm(rv_inst inst) |
| 656 | { |
| 657 | return (extract32(inst, 30, 1) << 2) | extract32(inst, 26, 2); |
| 658 | } |
| 659 | |
| 660 | /* instruction metadata */ |
| 661 | |
| 662 | #define OP(N, ...) static const rv_opcode_data op_##N = { __VA_ARGS__ }; |
| 663 | #include "riscv-op.c.inc" |
| 664 | #undef OP |
| 665 | |
| 666 | /* CSR names */ |
| 667 | |
| 668 | static const char *csr_name(int csrno) |
| 669 | { |
| 670 | switch (csrno) { |
| 671 | case 0x0000: return "ustatus"; |
| 672 | case 0x0001: return "fflags"; |
| 673 | case 0x0002: return "frm"; |
| 674 | case 0x0003: return "fcsr"; |
| 675 | case 0x0004: return "uie"; |
| 676 | case 0x0005: return "utvec"; |
| 677 | case 0x0008: return "vstart"; |
| 678 | case 0x0009: return "vxsat"; |
| 679 | case 0x000a: return "vxrm"; |
| 680 | case 0x000f: return "vcsr"; |
| 681 | case 0x0011: return "ssp"; |
| 682 | case 0x0015: return "seed"; |
| 683 | case 0x0017: return "jvt"; |
| 684 | case 0x0040: return "uscratch"; |
| 685 | case 0x0041: return "uepc"; |
| 686 | case 0x0042: return "ucause"; |
| 687 | case 0x0043: return "utval"; |
| 688 | case 0x0044: return "uip"; |
| 689 | case 0x0100: return "sstatus"; |
| 690 | case 0x0104: return "sie"; |
| 691 | case 0x0105: return "stvec"; |
| 692 | case 0x0106: return "scounteren"; |
| 693 | case 0x0140: return "sscratch"; |
| 694 | case 0x0141: return "sepc"; |
| 695 | case 0x0142: return "scause"; |
| 696 | case 0x0143: return "stval"; |
| 697 | case 0x0144: return "sip"; |
| 698 | case 0x0180: return "satp"; |
| 699 | case 0x0200: return "hstatus"; |
| 700 | case 0x0202: return "hedeleg"; |
| 701 | case 0x0203: return "hideleg"; |
| 702 | case 0x0204: return "hie"; |
| 703 | case 0x0205: return "htvec"; |
| 704 | case 0x0240: return "hscratch"; |
| 705 | case 0x0241: return "hepc"; |
| 706 | case 0x0242: return "hcause"; |
| 707 | case 0x0243: return "hbadaddr"; |
| 708 | case 0x0244: return "hip"; |
| 709 | case 0x0300: return "mstatus"; |
| 710 | case 0x0301: return "misa"; |
| 711 | case 0x0302: return "medeleg"; |
| 712 | case 0x0303: return "mideleg"; |
| 713 | case 0x0304: return "mie"; |
| 714 | case 0x0305: return "mtvec"; |
| 715 | case 0x0306: return "mcounteren"; |
| 716 | case 0x0320: return "mucounteren"; |
| 717 | case 0x0321: return "mscounteren"; |
| 718 | case 0x0322: return "mhcounteren"; |
| 719 | case 0x0323: return "mhpmevent3"; |
| 720 | case 0x0324: return "mhpmevent4"; |
| 721 | case 0x0325: return "mhpmevent5"; |
| 722 | case 0x0326: return "mhpmevent6"; |
| 723 | case 0x0327: return "mhpmevent7"; |
| 724 | case 0x0328: return "mhpmevent8"; |
| 725 | case 0x0329: return "mhpmevent9"; |
| 726 | case 0x032a: return "mhpmevent10"; |
| 727 | case 0x032b: return "mhpmevent11"; |
| 728 | case 0x032c: return "mhpmevent12"; |
| 729 | case 0x032d: return "mhpmevent13"; |
| 730 | case 0x032e: return "mhpmevent14"; |
| 731 | case 0x032f: return "mhpmevent15"; |
| 732 | case 0x0330: return "mhpmevent16"; |
| 733 | case 0x0331: return "mhpmevent17"; |
| 734 | case 0x0332: return "mhpmevent18"; |
| 735 | case 0x0333: return "mhpmevent19"; |
| 736 | case 0x0334: return "mhpmevent20"; |
| 737 | case 0x0335: return "mhpmevent21"; |
| 738 | case 0x0336: return "mhpmevent22"; |
| 739 | case 0x0337: return "mhpmevent23"; |
| 740 | case 0x0338: return "mhpmevent24"; |
| 741 | case 0x0339: return "mhpmevent25"; |
| 742 | case 0x033a: return "mhpmevent26"; |
| 743 | case 0x033b: return "mhpmevent27"; |
| 744 | case 0x033c: return "mhpmevent28"; |
| 745 | case 0x033d: return "mhpmevent29"; |
| 746 | case 0x033e: return "mhpmevent30"; |
| 747 | case 0x033f: return "mhpmevent31"; |
| 748 | case 0x0340: return "mscratch"; |
| 749 | case 0x0341: return "mepc"; |
| 750 | case 0x0342: return "mcause"; |
| 751 | case 0x0343: return "mtval"; |
| 752 | case 0x0344: return "mip"; |
| 753 | case 0x0380: return "mbase"; |
| 754 | case 0x0381: return "mbound"; |
| 755 | case 0x0382: return "mibase"; |
| 756 | case 0x0383: return "mibound"; |
| 757 | case 0x0384: return "mdbase"; |
| 758 | case 0x0385: return "mdbound"; |
| 759 | case 0x03a0: return "pmpcfg0"; |
| 760 | case 0x03a1: return "pmpcfg1"; |
| 761 | case 0x03a2: return "pmpcfg2"; |
| 762 | case 0x03a3: return "pmpcfg3"; |
| 763 | case 0x03a4: return "pmpcfg4"; |
| 764 | case 0x03a5: return "pmpcfg5"; |
| 765 | case 0x03a6: return "pmpcfg6"; |
| 766 | case 0x03a7: return "pmpcfg7"; |
| 767 | case 0x03a8: return "pmpcfg8"; |
| 768 | case 0x03a9: return "pmpcfg9"; |
| 769 | case 0x03aa: return "pmpcfg10"; |
| 770 | case 0x03ab: return "pmpcfg11"; |
| 771 | case 0x03ac: return "pmpcfg12"; |
| 772 | case 0x03ad: return "pmpcfg13"; |
| 773 | case 0x03ae: return "pmpcfg14"; |
| 774 | case 0x03af: return "pmpcfg15"; |
| 775 | case 0x03b0: return "pmpaddr0"; |
| 776 | case 0x03b1: return "pmpaddr1"; |
| 777 | case 0x03b2: return "pmpaddr2"; |
| 778 | case 0x03b3: return "pmpaddr3"; |
| 779 | case 0x03b4: return "pmpaddr4"; |
| 780 | case 0x03b5: return "pmpaddr5"; |
| 781 | case 0x03b6: return "pmpaddr6"; |
| 782 | case 0x03b7: return "pmpaddr7"; |
| 783 | case 0x03b8: return "pmpaddr8"; |
| 784 | case 0x03b9: return "pmpaddr9"; |
| 785 | case 0x03ba: return "pmpaddr10"; |
| 786 | case 0x03bb: return "pmpaddr11"; |
| 787 | case 0x03bc: return "pmpaddr12"; |
| 788 | case 0x03bd: return "pmpaddr13"; |
| 789 | case 0x03be: return "pmpaddr14"; |
| 790 | case 0x03bf: return "pmpaddr15"; |
| 791 | case 0x03c0: return "pmpaddr16"; |
| 792 | case 0x03c1: return "pmpaddr17"; |
| 793 | case 0x03c2: return "pmpaddr18"; |
| 794 | case 0x03c3: return "pmpaddr19"; |
| 795 | case 0x03c4: return "pmpaddr20"; |
| 796 | case 0x03c5: return "pmpaddr21"; |
| 797 | case 0x03c6: return "pmpaddr22"; |
| 798 | case 0x03c7: return "pmpaddr23"; |
| 799 | case 0x03c8: return "pmpaddr24"; |
| 800 | case 0x03c9: return "pmpaddr25"; |
| 801 | case 0x03ca: return "pmpaddr26"; |
| 802 | case 0x03cb: return "pmpaddr27"; |
| 803 | case 0x03cc: return "pmpaddr28"; |
| 804 | case 0x03cd: return "pmpaddr29"; |
| 805 | case 0x03ce: return "pmpaddr30"; |
| 806 | case 0x03cf: return "pmpaddr31"; |
| 807 | case 0x03d0: return "pmpaddr32"; |
| 808 | case 0x03d1: return "pmpaddr33"; |
| 809 | case 0x03d2: return "pmpaddr34"; |
| 810 | case 0x03d3: return "pmpaddr35"; |
| 811 | case 0x03d4: return "pmpaddr36"; |
| 812 | case 0x03d5: return "pmpaddr37"; |
| 813 | case 0x03d6: return "pmpaddr38"; |
| 814 | case 0x03d7: return "pmpaddr39"; |
| 815 | case 0x03d8: return "pmpaddr40"; |
| 816 | case 0x03d9: return "pmpaddr41"; |
| 817 | case 0x03da: return "pmpaddr42"; |
| 818 | case 0x03db: return "pmpaddr43"; |
| 819 | case 0x03dc: return "pmpaddr44"; |
| 820 | case 0x03dd: return "pmpaddr45"; |
| 821 | case 0x03de: return "pmpaddr46"; |
| 822 | case 0x03df: return "pmpaddr47"; |
| 823 | case 0x03e0: return "pmpaddr48"; |
| 824 | case 0x03e1: return "pmpaddr49"; |
| 825 | case 0x03e2: return "pmpaddr50"; |
| 826 | case 0x03e3: return "pmpaddr51"; |
| 827 | case 0x03e4: return "pmpaddr52"; |
| 828 | case 0x03e5: return "pmpaddr53"; |
| 829 | case 0x03e6: return "pmpaddr54"; |
| 830 | case 0x03e7: return "pmpaddr55"; |
| 831 | case 0x03e8: return "pmpaddr56"; |
| 832 | case 0x03e9: return "pmpaddr57"; |
| 833 | case 0x03ea: return "pmpaddr58"; |
| 834 | case 0x03eb: return "pmpaddr59"; |
| 835 | case 0x03ec: return "pmpaddr60"; |
| 836 | case 0x03ed: return "pmpaddr61"; |
| 837 | case 0x03ee: return "pmpaddr62"; |
| 838 | case 0x03ef: return "pmpaddr63"; |
| 839 | case 0x0780: return "mtohost"; |
| 840 | case 0x0781: return "mfromhost"; |
| 841 | case 0x0782: return "mreset"; |
| 842 | case 0x0783: return "mipi"; |
| 843 | case 0x0784: return "miobase"; |
| 844 | case 0x07a0: return "tselect"; |
| 845 | case 0x07a1: return "tdata1"; |
| 846 | case 0x07a2: return "tdata2"; |
| 847 | case 0x07a3: return "tdata3"; |
| 848 | case 0x07a4: return "tinfo"; |
| 849 | case 0x07b0: return "dcsr"; |
| 850 | case 0x07b1: return "dpc"; |
| 851 | case 0x07b2: return "dscratch0"; |
| 852 | case 0x07b3: return "dscratch1"; |
| 853 | case 0x0b00: return "mcycle"; |
| 854 | case 0x0b01: return "mtime"; |
| 855 | case 0x0b02: return "minstret"; |
| 856 | case 0x0b03: return "mhpmcounter3"; |
| 857 | case 0x0b04: return "mhpmcounter4"; |
| 858 | case 0x0b05: return "mhpmcounter5"; |
| 859 | case 0x0b06: return "mhpmcounter6"; |
| 860 | case 0x0b07: return "mhpmcounter7"; |
| 861 | case 0x0b08: return "mhpmcounter8"; |
| 862 | case 0x0b09: return "mhpmcounter9"; |
| 863 | case 0x0b0a: return "mhpmcounter10"; |
| 864 | case 0x0b0b: return "mhpmcounter11"; |
| 865 | case 0x0b0c: return "mhpmcounter12"; |
| 866 | case 0x0b0d: return "mhpmcounter13"; |
| 867 | case 0x0b0e: return "mhpmcounter14"; |
| 868 | case 0x0b0f: return "mhpmcounter15"; |
| 869 | case 0x0b10: return "mhpmcounter16"; |
| 870 | case 0x0b11: return "mhpmcounter17"; |
| 871 | case 0x0b12: return "mhpmcounter18"; |
| 872 | case 0x0b13: return "mhpmcounter19"; |
| 873 | case 0x0b14: return "mhpmcounter20"; |
| 874 | case 0x0b15: return "mhpmcounter21"; |
| 875 | case 0x0b16: return "mhpmcounter22"; |
| 876 | case 0x0b17: return "mhpmcounter23"; |
| 877 | case 0x0b18: return "mhpmcounter24"; |
| 878 | case 0x0b19: return "mhpmcounter25"; |
| 879 | case 0x0b1a: return "mhpmcounter26"; |
| 880 | case 0x0b1b: return "mhpmcounter27"; |
| 881 | case 0x0b1c: return "mhpmcounter28"; |
| 882 | case 0x0b1d: return "mhpmcounter29"; |
| 883 | case 0x0b1e: return "mhpmcounter30"; |
| 884 | case 0x0b1f: return "mhpmcounter31"; |
| 885 | case 0x0b80: return "mcycleh"; |
| 886 | case 0x0b81: return "mtimeh"; |
| 887 | case 0x0b82: return "minstreth"; |
| 888 | case 0x0b83: return "mhpmcounter3h"; |
| 889 | case 0x0b84: return "mhpmcounter4h"; |
| 890 | case 0x0b85: return "mhpmcounter5h"; |
| 891 | case 0x0b86: return "mhpmcounter6h"; |
| 892 | case 0x0b87: return "mhpmcounter7h"; |
| 893 | case 0x0b88: return "mhpmcounter8h"; |
| 894 | case 0x0b89: return "mhpmcounter9h"; |
| 895 | case 0x0b8a: return "mhpmcounter10h"; |
| 896 | case 0x0b8b: return "mhpmcounter11h"; |
| 897 | case 0x0b8c: return "mhpmcounter12h"; |
| 898 | case 0x0b8d: return "mhpmcounter13h"; |
| 899 | case 0x0b8e: return "mhpmcounter14h"; |
| 900 | case 0x0b8f: return "mhpmcounter15h"; |
| 901 | case 0x0b90: return "mhpmcounter16h"; |
| 902 | case 0x0b91: return "mhpmcounter17h"; |
| 903 | case 0x0b92: return "mhpmcounter18h"; |
| 904 | case 0x0b93: return "mhpmcounter19h"; |
| 905 | case 0x0b94: return "mhpmcounter20h"; |
| 906 | case 0x0b95: return "mhpmcounter21h"; |
| 907 | case 0x0b96: return "mhpmcounter22h"; |
| 908 | case 0x0b97: return "mhpmcounter23h"; |
| 909 | case 0x0b98: return "mhpmcounter24h"; |
| 910 | case 0x0b99: return "mhpmcounter25h"; |
| 911 | case 0x0b9a: return "mhpmcounter26h"; |
| 912 | case 0x0b9b: return "mhpmcounter27h"; |
| 913 | case 0x0b9c: return "mhpmcounter28h"; |
| 914 | case 0x0b9d: return "mhpmcounter29h"; |
| 915 | case 0x0b9e: return "mhpmcounter30h"; |
| 916 | case 0x0b9f: return "mhpmcounter31h"; |
| 917 | case 0x0c00: return "cycle"; |
| 918 | case 0x0c01: return "time"; |
| 919 | case 0x0c02: return "instret"; |
| 920 | case 0x0c20: return "vl"; |
| 921 | case 0x0c21: return "vtype"; |
| 922 | case 0x0c22: return "vlenb"; |
| 923 | case 0x0c80: return "cycleh"; |
| 924 | case 0x0c81: return "timeh"; |
| 925 | case 0x0c82: return "instreth"; |
| 926 | case 0x0d00: return "scycle"; |
| 927 | case 0x0d01: return "stime"; |
| 928 | case 0x0d02: return "sinstret"; |
| 929 | case 0x0d80: return "scycleh"; |
| 930 | case 0x0d81: return "stimeh"; |
| 931 | case 0x0d82: return "sinstreth"; |
| 932 | case 0x0e00: return "hcycle"; |
| 933 | case 0x0e01: return "htime"; |
| 934 | case 0x0e02: return "hinstret"; |
| 935 | case 0x0e80: return "hcycleh"; |
| 936 | case 0x0e81: return "htimeh"; |
| 937 | case 0x0e82: return "hinstreth"; |
| 938 | case 0x0f11: return "mvendorid"; |
| 939 | case 0x0f12: return "marchid"; |
| 940 | case 0x0f13: return "mimpid"; |
| 941 | case 0x0f14: return "mhartid"; |
| 942 | default: return NULL; |
| 943 | } |
| 944 | } |
| 945 | |
| 946 | /* decode opcode */ |
| 947 | |
| 948 | static const rv_opcode_data *decode_inst_opcode(rv_decode *dec, rv_isa isa) |
| 949 | { |
| 950 | rv_inst inst = dec->inst; |
| 951 | |
| 952 | switch ((inst >> 0) & 0b11) { |
| 953 | case 0: |
| 954 | switch ((inst >> 13) & 0b111) { |
| 955 | case 0: |
| 956 | if ((inst >> 5) & 0xff) { |
| 957 | return &op_c_addi4spn; |
| 958 | } |
| 959 | break; |
| 960 | case 1: |
| 961 | if (isa == rv128) { |
| 962 | return &op_c_lq; |
| 963 | } |
| 964 | return &op_c_fld; |
| 965 | case 2: return &op_c_lw; |
| 966 | case 3: |
| 967 | if (isa == rv32) { |
| 968 | return &op_c_flw; |
| 969 | } |
| 970 | return &op_c_ld; |
| 971 | case 4: |
| 972 | switch ((inst >> 10) & 0b111) { |
| 973 | case 0: return &op_c_lbu; |
| 974 | case 1: |
| 975 | if (((inst >> 6) & 1) == 0) { |
| 976 | return &op_c_lhu; |
| 977 | } |
| 978 | return &op_c_lh; |
| 979 | case 2: return &op_c_sb; |
| 980 | case 3: |
| 981 | if (((inst >> 6) & 1) == 0) { |
| 982 | return &op_c_sh; |
| 983 | } |
| 984 | break; |
| 985 | } |
| 986 | break; |
| 987 | case 5: |
| 988 | if (isa == rv128) { |
| 989 | return &op_c_sq; |
| 990 | } |
| 991 | return &op_c_fsd; |
| 992 | case 6: return &op_c_sw; |
| 993 | case 7: |
| 994 | if (isa == rv32) { |
| 995 | return &op_c_fsw; |
| 996 | } |
| 997 | return &op_c_sd; |
| 998 | } |
| 999 | break; |
| 1000 | case 1: |
| 1001 | switch ((inst >> 13) & 0b111) { |
| 1002 | case 0: |
| 1003 | return &op_c_addi; /* or unspecified HINT */ |
| 1004 | case 1: |
| 1005 | if (isa == rv32) { |
| 1006 | return &op_c_jal; |
| 1007 | } |
| 1008 | return &op_c_addiw; |
| 1009 | case 2: return &op_c_li; |
| 1010 | case 3: |
| 1011 | if (dec->cfg |
| 1012 | && dec->cfg->ext_zcmop |
| 1013 | && ((inst >> 2) & 0b111111) == 0b100000 |
| 1014 | && ((inst >> 11) & 0b11) == 0) { |
| 1015 | if (dec->cfg->ext_zicfiss) { |
| 1016 | switch (operand_cmop_imm(inst)) { |
| 1017 | case 1: return &op_c_sspush; |
| 1018 | case 5: return &op_c_sspopchk; |
| 1019 | } |
| 1020 | } |
| 1021 | return &op_c_mop; |
| 1022 | } |
| 1023 | if (inst & ((1 << 12) | (0x1f << 2))) { |
| 1024 | switch ((inst >> 7) & 0b11111) { |
| 1025 | case 2: return &op_c_addi16sp; |
| 1026 | default: return &op_c_lui; |
| 1027 | } |
| 1028 | } |
| 1029 | break; |
| 1030 | case 4: |
| 1031 | switch ((inst >> 10) & 0b11) { |
| 1032 | case 0: |
| 1033 | /* For rv32, shamt[5]=1 is designated for custom extensions. */ |
| 1034 | if (isa != rv32 || (inst & 0x1000) == 0) { |
| 1035 | return &op_c_srli; /* or unspecified HINT */ |
| 1036 | } |
| 1037 | break; |
| 1038 | case 1: |
| 1039 | /* For rv32, shamt[5]=1 is designated for custom extensions. */ |
| 1040 | if (isa != rv32 || (inst & 0x1000) == 0) { |
| 1041 | return &op_c_srai; /* or unspecified HINT */ |
| 1042 | } |
| 1043 | break; |
| 1044 | case 2: return &op_c_andi; |
| 1045 | case 3: |
| 1046 | switch (((inst >> 10) & 0b100) | ((inst >> 5) & 0b011)) { |
| 1047 | case 0: return &op_c_sub; |
| 1048 | case 1: return &op_c_xor; |
| 1049 | case 2: return &op_c_or; |
| 1050 | case 3: return &op_c_and; |
| 1051 | case 4: |
| 1052 | if (isa != rv32) { |
| 1053 | return &op_c_subw; |
| 1054 | } |
| 1055 | break; |
| 1056 | case 5: |
| 1057 | if (isa != rv32) { |
| 1058 | return &op_c_addw; |
| 1059 | } |
| 1060 | break; |
| 1061 | case 6: return &op_c_mul; |
| 1062 | case 7: |
| 1063 | switch ((inst >> 2) & 0b111) { |
| 1064 | case 0: return &op_c_zext_b; |
| 1065 | case 1: return &op_c_sext_b; |
| 1066 | case 2: return &op_c_zext_h; |
| 1067 | case 3: return &op_c_sext_h; |
| 1068 | case 4: return &op_c_zext_w; |
| 1069 | case 5: return &op_c_not; |
| 1070 | } |
| 1071 | break; |
| 1072 | } |
| 1073 | break; |
| 1074 | } |
| 1075 | break; |
| 1076 | case 5: return &op_c_j; |
| 1077 | case 6: return &op_c_beqz; |
| 1078 | case 7: return &op_c_bnez; |
| 1079 | } |
| 1080 | break; |
| 1081 | case 2: |
| 1082 | switch ((inst >> 13) & 0b111) { |
| 1083 | case 0: |
| 1084 | if (isa != rv32 || (inst & 0x1000) == 0) { |
| 1085 | return &op_c_slli; /* or unspecified HINT */ |
| 1086 | } |
| 1087 | break; |
| 1088 | case 1: |
| 1089 | if (isa == rv128) { |
| 1090 | return &op_c_lqsp; |
| 1091 | } |
| 1092 | return &op_c_fldsp; |
| 1093 | case 2: return &op_c_lwsp; |
| 1094 | case 3: |
| 1095 | if (isa == rv32) { |
| 1096 | return &op_c_flwsp; |
| 1097 | } |
| 1098 | return &op_c_ldsp; |
| 1099 | case 4: |
| 1100 | switch ((inst >> 12) & 0b1) { |
| 1101 | case 0: |
| 1102 | switch ((inst >> 2) & 0b11111) { |
| 1103 | case 0: return &op_c_jr; |
| 1104 | default: return &op_c_mv; |
| 1105 | } |
| 1106 | break; |
| 1107 | case 1: |
| 1108 | switch ((inst >> 2) & 0b11111) { |
| 1109 | case 0: |
| 1110 | switch ((inst >> 7) & 0b11111) { |
| 1111 | case 0: return &op_c_ebreak; |
| 1112 | default: return &op_c_jalr; |
| 1113 | } |
| 1114 | break; |
| 1115 | default: return &op_c_add; |
| 1116 | } |
| 1117 | break; |
| 1118 | } |
| 1119 | break; |
| 1120 | case 5: |
| 1121 | if (isa == rv128) { |
| 1122 | return &op_c_sqsp; |
| 1123 | } |
| 1124 | if (dec->cfg) { |
| 1125 | if (dec->cfg->ext_zcmp && ((inst >> 12) & 0b01)) { |
| 1126 | switch ((inst >> 8) & 0b01111) { |
| 1127 | case 8: |
| 1128 | if (((inst >> 4) & 0b01111) >= 4) { |
| 1129 | return &op_cm_push; |
| 1130 | } |
| 1131 | break; |
| 1132 | case 10: |
| 1133 | if (((inst >> 4) & 0b01111) >= 4) { |
| 1134 | return &op_cm_pop; |
| 1135 | } |
| 1136 | break; |
| 1137 | case 12: |
| 1138 | if (((inst >> 4) & 0b01111) >= 4) { |
| 1139 | return &op_cm_popretz; |
| 1140 | } |
| 1141 | break; |
| 1142 | case 14: |
| 1143 | if (((inst >> 4) & 0b01111) >= 4) { |
| 1144 | return &op_cm_popret; |
| 1145 | } |
| 1146 | break; |
| 1147 | } |
| 1148 | } |
| 1149 | switch ((inst >> 10) & 0b011) { |
| 1150 | case 0: |
| 1151 | if (!dec->cfg->ext_zcmt) { |
| 1152 | break; |
| 1153 | } |
| 1154 | if (((inst >> 2) & 0xFF) >= 32) { |
| 1155 | return &op_cm_jalt; |
| 1156 | } |
| 1157 | return &op_cm_jt; |
| 1158 | case 3: |
| 1159 | if (!dec->cfg->ext_zcmp) { |
| 1160 | break; |
| 1161 | } |
| 1162 | switch ((inst >> 5) & 0b011) { |
| 1163 | case 1: return &op_cm_mvsa01; |
| 1164 | case 3: return &op_cm_mva01s; |
| 1165 | } |
| 1166 | break; |
| 1167 | } |
| 1168 | } |
| 1169 | return &op_c_fsdsp; |
| 1170 | case 6: return &op_c_swsp; |
| 1171 | case 7: |
| 1172 | if (isa == rv32) { |
| 1173 | return &op_c_fswsp; |
| 1174 | } |
| 1175 | return &op_c_sdsp; |
| 1176 | } |
| 1177 | break; |
| 1178 | case 3: |
| 1179 | switch ((inst >> 2) & 0b11111) { |
| 1180 | case 0: |
| 1181 | switch ((inst >> 12) & 0b111) { |
| 1182 | case 0: return &op_lb; |
| 1183 | case 1: return &op_lh; |
| 1184 | case 2: return &op_lw; |
| 1185 | case 3: return &op_ld; |
| 1186 | case 4: return &op_lbu; |
| 1187 | case 5: return &op_lhu; |
| 1188 | case 6: return &op_lwu; |
| 1189 | case 7: return &op_ldu; |
| 1190 | } |
| 1191 | break; |
| 1192 | case 1: |
| 1193 | switch ((inst >> 12) & 0b111) { |
| 1194 | case 0: |
| 1195 | switch ((inst >> 20) & 0b111111111111) { |
| 1196 | case 40: return &op_vl1re8_v; |
| 1197 | case 552: return &op_vl2re8_v; |
| 1198 | case 1576: return &op_vl4re8_v; |
| 1199 | case 3624: return &op_vl8re8_v; |
| 1200 | } |
| 1201 | switch ((inst >> 26) & 0b111) { |
| 1202 | case 0: |
| 1203 | switch ((inst >> 20) & 0b11111) { |
| 1204 | case 0: return &op_vle8_v; |
| 1205 | case 11: return &op_vlm_v; |
| 1206 | case 16: return &op_vle8ff_v; |
| 1207 | } |
| 1208 | break; |
| 1209 | case 1: return &op_vluxei8_v; |
| 1210 | case 2: return &op_vlse8_v; |
| 1211 | case 3: return &op_vloxei8_v; |
| 1212 | } |
| 1213 | break; |
| 1214 | case 1: return &op_flh; |
| 1215 | case 2: return &op_flw; |
| 1216 | case 3: return &op_fld; |
| 1217 | case 4: return &op_flq; |
| 1218 | case 5: |
| 1219 | switch ((inst >> 20) & 0b111111111111) { |
| 1220 | case 40: return &op_vl1re16_v; |
| 1221 | case 552: return &op_vl2re16_v; |
| 1222 | case 1576: return &op_vl4re16_v; |
| 1223 | case 3624: return &op_vl8re16_v; |
| 1224 | } |
| 1225 | switch ((inst >> 26) & 0b111) { |
| 1226 | case 0: |
| 1227 | switch ((inst >> 20) & 0b11111) { |
| 1228 | case 0: return &op_vle16_v; |
| 1229 | case 16: return &op_vle16ff_v; |
| 1230 | } |
| 1231 | break; |
| 1232 | case 1: return &op_vluxei16_v; |
| 1233 | case 2: return &op_vlse16_v; |
| 1234 | case 3: return &op_vloxei16_v; |
| 1235 | } |
| 1236 | break; |
| 1237 | case 6: |
| 1238 | switch ((inst >> 20) & 0b111111111111) { |
| 1239 | case 40: return &op_vl1re32_v; |
| 1240 | case 552: return &op_vl2re32_v; |
| 1241 | case 1576: return &op_vl4re32_v; |
| 1242 | case 3624: return &op_vl8re32_v; |
| 1243 | } |
| 1244 | switch ((inst >> 26) & 0b111) { |
| 1245 | case 0: |
| 1246 | switch ((inst >> 20) & 0b11111) { |
| 1247 | case 0: return &op_vle32_v; |
| 1248 | case 16: return &op_vle32ff_v; |
| 1249 | } |
| 1250 | break; |
| 1251 | case 1: return &op_vluxei32_v; |
| 1252 | case 2: return &op_vlse32_v; |
| 1253 | case 3: return &op_vloxei32_v; |
| 1254 | } |
| 1255 | break; |
| 1256 | case 7: |
| 1257 | switch ((inst >> 20) & 0b111111111111) { |
| 1258 | case 40: return &op_vl1re64_v; |
| 1259 | case 552: return &op_vl2re64_v; |
| 1260 | case 1576: return &op_vl4re64_v; |
| 1261 | case 3624: return &op_vl8re64_v; |
| 1262 | } |
| 1263 | switch ((inst >> 26) & 0b111) { |
| 1264 | case 0: |
| 1265 | switch ((inst >> 20) & 0b11111) { |
| 1266 | case 0: return &op_vle64_v; |
| 1267 | case 16: return &op_vle64ff_v; |
| 1268 | } |
| 1269 | break; |
| 1270 | case 1: return &op_vluxei64_v; |
| 1271 | case 2: return &op_vlse64_v; |
| 1272 | case 3: return &op_vloxei64_v; |
| 1273 | } |
| 1274 | break; |
| 1275 | } |
| 1276 | break; |
| 1277 | case 3: |
| 1278 | switch ((inst >> 12) & 0b111) { |
| 1279 | case 0: return &op_fence; |
| 1280 | case 1: return &op_fence_i; |
| 1281 | case 2: |
| 1282 | /* |
| 1283 | * 'lq' shares the "(...) 010 ..... 0001111" opcode space |
| 1284 | * with 'cbo' insns. Check the next 5 bits to select |
| 1285 | * what we want: |
| 1286 | * |
| 1287 | * cbo_inval 0000000 00000 ..... 010 00000 0001111 |
| 1288 | * cbo_clean 0000000 00001 ..... 010 00000 0001111 |
| 1289 | * cbo_flush 0000000 00010 ..... 010 00000 0001111 |
| 1290 | * cbo_zero 0000000 00100 ..... 010 00000 0001111 |
| 1291 | * |
| 1292 | * Anything that doesn't match these will default to 'lq'. |
| 1293 | */ |
| 1294 | switch ((inst >> 17) & 0b11111) { |
| 1295 | case 0: return &op_cbo_inval; |
| 1296 | case 1: return &op_cbo_clean; |
| 1297 | case 2: return &op_cbo_flush; |
| 1298 | case 4: return &op_cbo_zero; |
| 1299 | default: return &op_lq; |
| 1300 | } |
| 1301 | } |
| 1302 | break; |
| 1303 | case 4: |
| 1304 | switch ((inst >> 12) & 0b111) { |
| 1305 | case 0: return &op_addi; |
| 1306 | case 1: |
| 1307 | switch ((inst >> 27) & 0b11111) { |
| 1308 | case 0b00000: return &op_slli; |
| 1309 | case 0b00001: |
| 1310 | switch ((inst >> 20) & 0b1111111) { |
| 1311 | case 0b0001111: return &op_zip; |
| 1312 | } |
| 1313 | break; |
| 1314 | case 0b00010: |
| 1315 | switch ((inst >> 20) & 0b1111111) { |
| 1316 | case 0b0000000: return &op_sha256sum0; |
| 1317 | case 0b0000001: return &op_sha256sum1; |
| 1318 | case 0b0000010: return &op_sha256sig0; |
| 1319 | case 0b0000011: return &op_sha256sig1; |
| 1320 | case 0b0000100: return &op_sha512sum0; |
| 1321 | case 0b0000101: return &op_sha512sum1; |
| 1322 | case 0b0000110: return &op_sha512sig0; |
| 1323 | case 0b0000111: return &op_sha512sig1; |
| 1324 | case 0b0001000: return &op_sm3p0; |
| 1325 | case 0b0001001: return &op_sm3p1; |
| 1326 | } |
| 1327 | break; |
| 1328 | case 0b00101: return &op_bseti; |
| 1329 | case 0b00110: |
| 1330 | switch ((inst >> 20) & 0b1111111) { |
| 1331 | case 0b0000000: return &op_aes64im; |
| 1332 | default: |
| 1333 | if (((inst >> 24) & 0b0111) == 0b001) { |
| 1334 | return &op_aes64ks1i; |
| 1335 | } |
| 1336 | break; |
| 1337 | } |
| 1338 | break; |
| 1339 | case 0b01001: return &op_bclri; |
| 1340 | case 0b01101: return &op_binvi; |
| 1341 | case 0b01100: |
| 1342 | switch ((inst >> 20) & 0b1111111) { |
| 1343 | case 0b0000000: return &op_clz; |
| 1344 | case 0b0000001: return &op_ctz; |
| 1345 | case 0b0000010: return &op_cpop; |
| 1346 | /* 0b0000011 */ |
| 1347 | case 0b0000100: return &op_sext_b; |
| 1348 | case 0b0000101: return &op_sext_h; |
| 1349 | } |
| 1350 | break; |
| 1351 | } |
| 1352 | break; |
| 1353 | case 2: return &op_slti; |
| 1354 | case 3: return &op_sltiu; |
| 1355 | case 4: return &op_xori; |
| 1356 | case 5: |
| 1357 | switch ((inst >> 27) & 0b11111) { |
| 1358 | case 0b00000: return &op_srli; |
| 1359 | case 0b00001: |
| 1360 | switch ((inst >> 20) & 0b1111111) { |
| 1361 | case 0b0001111: return &op_unzip; |
| 1362 | } |
| 1363 | break; |
| 1364 | case 0b00101: return &op_orc_b; |
| 1365 | case 0b01000: return &op_srai; |
| 1366 | case 0b01001: return &op_bexti; |
| 1367 | case 0b01100: return &op_rori; |
| 1368 | case 0b01101: |
| 1369 | switch ((inst >> 20) & 0b1111111) { |
| 1370 | case 0b0011000: |
| 1371 | if (isa == rv32) { |
| 1372 | return &op_rev8; |
| 1373 | } |
| 1374 | break; |
| 1375 | case 0b0111000: |
| 1376 | if (isa == rv64) { |
| 1377 | return &op_rev8; |
| 1378 | } |
| 1379 | break; |
| 1380 | case 0b0000111: return &op_brev8; |
| 1381 | } |
| 1382 | break; |
| 1383 | } |
| 1384 | break; |
| 1385 | case 6: return &op_ori; |
| 1386 | case 7: return &op_andi; |
| 1387 | } |
| 1388 | break; |
| 1389 | case 5: |
| 1390 | if (dec->cfg && dec->cfg->ext_zicfilp && |
| 1391 | (((inst >> 7) & 0b11111) == 0b00000)) { |
| 1392 | return &op_lpad; |
| 1393 | } |
| 1394 | return &op_auipc; |
| 1395 | case 6: |
| 1396 | /* OP-IMM-32 */ |
| 1397 | if (isa == rv32) { |
| 1398 | break; |
| 1399 | } |
| 1400 | switch ((inst >> 12) & 0b111) { |
| 1401 | case 0: return &op_addiw; |
| 1402 | case 1: |
| 1403 | switch ((inst >> 26) & 0b111111) { |
| 1404 | case 0: return &op_slliw; |
| 1405 | case 2: return &op_slli_uw; |
| 1406 | case 24: |
| 1407 | switch ((inst >> 20) & 0b11111) { |
| 1408 | case 0b00000: return &op_clzw; |
| 1409 | case 0b00001: return &op_ctzw; |
| 1410 | case 0b00010: return &op_cpopw; |
| 1411 | } |
| 1412 | break; |
| 1413 | } |
| 1414 | break; |
| 1415 | case 5: |
| 1416 | switch ((inst >> 25) & 0b1111111) { |
| 1417 | case 0: return &op_srliw; |
| 1418 | case 32: return &op_sraiw; |
| 1419 | case 48: return &op_roriw; |
| 1420 | } |
| 1421 | break; |
| 1422 | } |
| 1423 | break; |
| 1424 | case 8: |
| 1425 | switch ((inst >> 12) & 0b111) { |
| 1426 | case 0: return &op_sb; |
| 1427 | case 1: return &op_sh; |
| 1428 | case 2: return &op_sw; |
| 1429 | case 3: return &op_sd; |
| 1430 | case 4: return &op_sq; |
| 1431 | } |
| 1432 | break; |
| 1433 | case 9: |
| 1434 | switch ((inst >> 12) & 0b111) { |
| 1435 | case 0: |
| 1436 | switch ((inst >> 20) & 0b111111111111) { |
| 1437 | case 40: return &op_vs1r_v; |
| 1438 | case 552: return &op_vs2r_v; |
| 1439 | case 1576: return &op_vs4r_v; |
| 1440 | case 3624: return &op_vs8r_v; |
| 1441 | } |
| 1442 | switch ((inst >> 26) & 0b111) { |
| 1443 | case 0: |
| 1444 | switch ((inst >> 20) & 0b11111) { |
| 1445 | case 0: return &op_vse8_v; |
| 1446 | case 11: return &op_vsm_v; |
| 1447 | } |
| 1448 | break; |
| 1449 | case 1: return &op_vsuxei8_v; |
| 1450 | case 2: return &op_vsse8_v; |
| 1451 | case 3: return &op_vsoxei8_v; |
| 1452 | } |
| 1453 | break; |
| 1454 | case 1: return &op_fsh; |
| 1455 | case 2: return &op_fsw; |
| 1456 | case 3: return &op_fsd; |
| 1457 | case 4: return &op_fsq; |
| 1458 | case 5: |
| 1459 | switch ((inst >> 26) & 0b111) { |
| 1460 | case 0: |
| 1461 | switch ((inst >> 20) & 0b11111) { |
| 1462 | case 0: return &op_vse16_v; |
| 1463 | } |
| 1464 | break; |
| 1465 | case 1: return &op_vsuxei16_v; |
| 1466 | case 2: return &op_vsse16_v; |
| 1467 | case 3: return &op_vsoxei16_v; |
| 1468 | } |
| 1469 | break; |
| 1470 | case 6: |
| 1471 | switch ((inst >> 26) & 0b111) { |
| 1472 | case 0: |
| 1473 | switch ((inst >> 20) & 0b11111) { |
| 1474 | case 0: return &op_vse32_v; |
| 1475 | } |
| 1476 | break; |
| 1477 | case 1: return &op_vsuxei32_v; |
| 1478 | case 2: return &op_vsse32_v; |
| 1479 | case 3: return &op_vsoxei32_v; |
| 1480 | } |
| 1481 | break; |
| 1482 | case 7: |
| 1483 | switch ((inst >> 26) & 0b111) { |
| 1484 | case 0: |
| 1485 | switch ((inst >> 20) & 0b11111) { |
| 1486 | case 0: return &op_vse64_v; |
| 1487 | } |
| 1488 | break; |
| 1489 | case 1: return &op_vsuxei64_v; |
| 1490 | case 2: return &op_vsse64_v; |
| 1491 | case 3: return &op_vsoxei64_v; |
| 1492 | } |
| 1493 | break; |
| 1494 | } |
| 1495 | break; |
| 1496 | case 11: |
| 1497 | switch (((inst >> 24) & 0b11111000) | |
| 1498 | ((inst >> 12) & 0b00000111)) { |
| 1499 | case 0: return &op_amoadd_b; |
| 1500 | case 1: return &op_amoadd_h; |
| 1501 | case 2: return &op_amoadd_w; |
| 1502 | case 3: return &op_amoadd_d; |
| 1503 | case 4: return &op_amoadd_q; |
| 1504 | case 8: return &op_amoswap_b; |
| 1505 | case 9: return &op_amoswap_h; |
| 1506 | case 10: return &op_amoswap_w; |
| 1507 | case 11: return &op_amoswap_d; |
| 1508 | case 12: return &op_amoswap_q; |
| 1509 | case 18: |
| 1510 | switch ((inst >> 20) & 0b11111) { |
| 1511 | case 0: return &op_lr_w; |
| 1512 | } |
| 1513 | break; |
| 1514 | case 19: |
| 1515 | switch ((inst >> 20) & 0b11111) { |
| 1516 | case 0: return &op_lr_d; |
| 1517 | } |
| 1518 | break; |
| 1519 | case 20: |
| 1520 | switch ((inst >> 20) & 0b11111) { |
| 1521 | case 0: return &op_lr_q; |
| 1522 | } |
| 1523 | break; |
| 1524 | case 26: return &op_sc_w; |
| 1525 | case 27: return &op_sc_d; |
| 1526 | case 28: return &op_sc_q; |
| 1527 | case 32: return &op_amoxor_b; |
| 1528 | case 33: return &op_amoxor_h; |
| 1529 | case 34: return &op_amoxor_w; |
| 1530 | case 35: return &op_amoxor_d; |
| 1531 | case 36: return &op_amoxor_q; |
| 1532 | case 40: return &op_amocas_b; |
| 1533 | case 41: return &op_amocas_h; |
| 1534 | case 42: return &op_amocas_w; |
| 1535 | case 43: return &op_amocas_d; |
| 1536 | case 44: return &op_amocas_q; |
| 1537 | case 64: return &op_amoor_b; |
| 1538 | case 65: return &op_amoor_h; |
| 1539 | case 66: return &op_amoor_w; |
| 1540 | case 67: return &op_amoor_d; |
| 1541 | case 68: return &op_amoor_q; |
| 1542 | case 74: return &op_ssamoswap_w; |
| 1543 | case 75: return &op_ssamoswap_d; |
| 1544 | case 96: return &op_amoand_b; |
| 1545 | case 97: return &op_amoand_h; |
| 1546 | case 98: return &op_amoand_w; |
| 1547 | case 99: return &op_amoand_d; |
| 1548 | case 100: return &op_amoand_q; |
| 1549 | case 128: return &op_amomin_b; |
| 1550 | case 129: return &op_amomin_h; |
| 1551 | case 130: return &op_amomin_w; |
| 1552 | case 131: return &op_amomin_d; |
| 1553 | case 132: return &op_amomin_q; |
| 1554 | case 160: return &op_amomax_b; |
| 1555 | case 161: return &op_amomax_h; |
| 1556 | case 162: return &op_amomax_w; |
| 1557 | case 163: return &op_amomax_d; |
| 1558 | case 164: return &op_amomax_q; |
| 1559 | case 192: return &op_amominu_b; |
| 1560 | case 193: return &op_amominu_h; |
| 1561 | case 194: return &op_amominu_w; |
| 1562 | case 195: return &op_amominu_d; |
| 1563 | case 196: return &op_amominu_q; |
| 1564 | case 224: return &op_amomaxu_b; |
| 1565 | case 225: return &op_amomaxu_h; |
| 1566 | case 226: return &op_amomaxu_w; |
| 1567 | case 227: return &op_amomaxu_d; |
| 1568 | case 228: return &op_amomaxu_q; |
| 1569 | } |
| 1570 | break; |
| 1571 | case 12: |
| 1572 | switch (((inst >> 22) & 0b1111111000) | |
| 1573 | ((inst >> 12) & 0b0000000111)) { |
| 1574 | case 0: return &op_add; |
| 1575 | case 1: return &op_sll; |
| 1576 | case 2: return &op_slt; |
| 1577 | case 3: return &op_sltu; |
| 1578 | case 4: return &op_xor; |
| 1579 | case 5: return &op_srl; |
| 1580 | case 6: return &op_or; |
| 1581 | case 7: return &op_and; |
| 1582 | case 8: return &op_mul; |
| 1583 | case 9: return &op_mulh; |
| 1584 | case 10: return &op_mulhsu; |
| 1585 | case 11: return &op_mulhu; |
| 1586 | case 12: return &op_div; |
| 1587 | case 13: return &op_divu; |
| 1588 | case 14: return &op_rem; |
| 1589 | case 15: return &op_remu; |
| 1590 | case 36: |
| 1591 | if (isa == rv32 && !((inst >> 20) & 0b11111)) { |
| 1592 | return &op_zext_h; |
| 1593 | } |
| 1594 | return &op_pack; |
| 1595 | case 39: return &op_packh; |
| 1596 | case 41: return &op_clmul; |
| 1597 | case 42: return &op_clmulr; |
| 1598 | case 43: return &op_clmulh; |
| 1599 | case 44: return &op_min; |
| 1600 | case 45: return &op_minu; |
| 1601 | case 46: return &op_max; |
| 1602 | case 47: return &op_maxu; |
| 1603 | case 075: return &op_czero_eqz; |
| 1604 | case 077: return &op_czero_nez; |
| 1605 | case 130: return &op_sh1add; |
| 1606 | case 132: return &op_sh2add; |
| 1607 | case 134: return &op_sh3add; |
| 1608 | case 161: return &op_bset; |
| 1609 | case 162: return &op_xperm4; |
| 1610 | case 164: return &op_xperm8; |
| 1611 | case 200: return &op_aes64es; |
| 1612 | case 216: return &op_aes64esm; |
| 1613 | case 232: return &op_aes64ds; |
| 1614 | case 248: return &op_aes64dsm; |
| 1615 | case 256: return &op_sub; |
| 1616 | case 260: return &op_xnor; |
| 1617 | case 261: return &op_sra; |
| 1618 | case 262: return &op_orn; |
| 1619 | case 263: return &op_andn; |
| 1620 | case 289: return &op_bclr; |
| 1621 | case 293: return &op_bext; |
| 1622 | case 320: return &op_sha512sum0r; |
| 1623 | case 328: return &op_sha512sum1r; |
| 1624 | case 336: return &op_sha512sig0l; |
| 1625 | case 344: return &op_sha512sig1l; |
| 1626 | case 368: return &op_sha512sig0h; |
| 1627 | case 376: return &op_sha512sig1h; |
| 1628 | case 385: return &op_rol; |
| 1629 | case 389: return &op_ror; |
| 1630 | case 417: return &op_binv; |
| 1631 | case 504: return &op_aes64ks2; |
| 1632 | } |
| 1633 | switch ((inst >> 25) & 0b0011111) { |
| 1634 | case 17: return &op_aes32esi; |
| 1635 | case 19: return &op_aes32esmi; |
| 1636 | case 21: return &op_aes32dsi; |
| 1637 | case 23: return &op_aes32dsmi; |
| 1638 | case 24: return &op_sm4ed; |
| 1639 | case 26: return &op_sm4ks; |
| 1640 | } |
| 1641 | break; |
| 1642 | case 13: return &op_lui; |
| 1643 | case 14: |
| 1644 | /* OP-32 */ |
| 1645 | if (isa == rv32) { |
| 1646 | break; |
| 1647 | } |
| 1648 | switch (((inst >> 22) & 0b1111111000) | |
| 1649 | ((inst >> 12) & 0b0000000111)) { |
| 1650 | case 0: return &op_addw; |
| 1651 | case 1: return &op_sllw; |
| 1652 | case 5: return &op_srlw; |
| 1653 | case 8: return &op_mulw; |
| 1654 | case 12: return &op_divw; |
| 1655 | case 13: return &op_divuw; |
| 1656 | case 14: return &op_remw; |
| 1657 | case 15: return &op_remuw; |
| 1658 | case 32: return &op_add_uw; |
| 1659 | case 36: |
| 1660 | switch ((inst >> 20) & 0b11111) { |
| 1661 | case 0: return &op_zext_h; |
| 1662 | default: return &op_packw; |
| 1663 | } |
| 1664 | break; |
| 1665 | case 130: return &op_sh1add_uw; |
| 1666 | case 132: return &op_sh2add_uw; |
| 1667 | case 134: return &op_sh3add_uw; |
| 1668 | case 256: return &op_subw; |
| 1669 | case 261: return &op_sraw; |
| 1670 | case 385: return &op_rolw; |
| 1671 | case 389: return &op_rorw; |
| 1672 | } |
| 1673 | break; |
| 1674 | case 16: |
| 1675 | switch ((inst >> 25) & 0b11) { |
| 1676 | case 0: return &op_fmadd_s; |
| 1677 | case 1: return &op_fmadd_d; |
| 1678 | case 3: return &op_fmadd_q; |
| 1679 | } |
| 1680 | break; |
| 1681 | case 17: |
| 1682 | switch ((inst >> 25) & 0b11) { |
| 1683 | case 0: return &op_fmsub_s; |
| 1684 | case 1: return &op_fmsub_d; |
| 1685 | case 3: return &op_fmsub_q; |
| 1686 | } |
| 1687 | break; |
| 1688 | case 18: |
| 1689 | switch ((inst >> 25) & 0b11) { |
| 1690 | case 0: return &op_fnmsub_s; |
| 1691 | case 1: return &op_fnmsub_d; |
| 1692 | case 3: return &op_fnmsub_q; |
| 1693 | } |
| 1694 | break; |
| 1695 | case 19: |
| 1696 | switch ((inst >> 25) & 0b11) { |
| 1697 | case 0: return &op_fnmadd_s; |
| 1698 | case 1: return &op_fnmadd_d; |
| 1699 | case 3: return &op_fnmadd_q; |
| 1700 | } |
| 1701 | break; |
| 1702 | case 20: |
| 1703 | switch ((inst >> 25) & 0b1111111) { |
| 1704 | case 0: return &op_fadd_s; |
| 1705 | case 1: return &op_fadd_d; |
| 1706 | case 3: return &op_fadd_q; |
| 1707 | case 4: return &op_fsub_s; |
| 1708 | case 5: return &op_fsub_d; |
| 1709 | case 7: return &op_fsub_q; |
| 1710 | case 8: return &op_fmul_s; |
| 1711 | case 9: return &op_fmul_d; |
| 1712 | case 11: return &op_fmul_q; |
| 1713 | case 12: return &op_fdiv_s; |
| 1714 | case 13: return &op_fdiv_d; |
| 1715 | case 15: return &op_fdiv_q; |
| 1716 | case 16: |
| 1717 | switch ((inst >> 12) & 0b111) { |
| 1718 | case 0: return &op_fsgnj_s; |
| 1719 | case 1: return &op_fsgnjn_s; |
| 1720 | case 2: return &op_fsgnjx_s; |
| 1721 | } |
| 1722 | break; |
| 1723 | case 17: |
| 1724 | switch ((inst >> 12) & 0b111) { |
| 1725 | case 0: return &op_fsgnj_d; |
| 1726 | case 1: return &op_fsgnjn_d; |
| 1727 | case 2: return &op_fsgnjx_d; |
| 1728 | } |
| 1729 | break; |
| 1730 | case 19: |
| 1731 | switch ((inst >> 12) & 0b111) { |
| 1732 | case 0: return &op_fsgnj_q; |
| 1733 | case 1: return &op_fsgnjn_q; |
| 1734 | case 2: return &op_fsgnjx_q; |
| 1735 | } |
| 1736 | break; |
| 1737 | case 20: |
| 1738 | switch ((inst >> 12) & 0b111) { |
| 1739 | case 0: return &op_fmin_s; |
| 1740 | case 1: return &op_fmax_s; |
| 1741 | case 2: return &op_fminm_s; |
| 1742 | case 3: return &op_fmaxm_s; |
| 1743 | } |
| 1744 | break; |
| 1745 | case 21: |
| 1746 | switch ((inst >> 12) & 0b111) { |
| 1747 | case 0: return &op_fmin_d; |
| 1748 | case 1: return &op_fmax_d; |
| 1749 | case 2: return &op_fminm_d; |
| 1750 | case 3: return &op_fmaxm_d; |
| 1751 | } |
| 1752 | break; |
| 1753 | case 22: |
| 1754 | switch (((inst >> 12) & 0b111)) { |
| 1755 | case 2: return &op_fminm_h; |
| 1756 | case 3: return &op_fmaxm_h; |
| 1757 | } |
| 1758 | break; |
| 1759 | case 23: |
| 1760 | switch ((inst >> 12) & 0b111) { |
| 1761 | case 0: return &op_fmin_q; |
| 1762 | case 1: return &op_fmax_q; |
| 1763 | case 2: return &op_fminm_q; |
| 1764 | case 3: return &op_fmaxm_q; |
| 1765 | } |
| 1766 | break; |
| 1767 | case 32: |
| 1768 | switch ((inst >> 20) & 0b11111) { |
| 1769 | case 1: return &op_fcvt_s_d; |
| 1770 | case 3: return &op_fcvt_s_q; |
| 1771 | case 4: return &op_fround_s; |
| 1772 | case 5: return &op_froundnx_s; |
| 1773 | case 6: return &op_fcvt_s_bf16; |
| 1774 | } |
| 1775 | break; |
| 1776 | case 33: |
| 1777 | switch ((inst >> 20) & 0b11111) { |
| 1778 | case 0: return &op_fcvt_d_s; |
| 1779 | case 3: return &op_fcvt_d_q; |
| 1780 | case 4: return &op_fround_d; |
| 1781 | case 5: return &op_froundnx_d; |
| 1782 | } |
| 1783 | break; |
| 1784 | case 34: |
| 1785 | switch (((inst >> 20) & 0b11111)) { |
| 1786 | case 4: return &op_fround_h; |
| 1787 | case 5: return &op_froundnx_h; |
| 1788 | case 8: return &op_fcvt_bf16_s; |
| 1789 | } |
| 1790 | break; |
| 1791 | case 35: |
| 1792 | switch ((inst >> 20) & 0b11111) { |
| 1793 | case 0: return &op_fcvt_q_s; |
| 1794 | case 1: return &op_fcvt_q_d; |
| 1795 | case 4: return &op_fround_q; |
| 1796 | case 5: return &op_froundnx_q; |
| 1797 | } |
| 1798 | break; |
| 1799 | case 44: |
| 1800 | switch ((inst >> 20) & 0b11111) { |
| 1801 | case 0: return &op_fsqrt_s; |
| 1802 | } |
| 1803 | break; |
| 1804 | case 45: |
| 1805 | switch ((inst >> 20) & 0b11111) { |
| 1806 | case 0: return &op_fsqrt_d; |
| 1807 | } |
| 1808 | break; |
| 1809 | case 47: |
| 1810 | switch ((inst >> 20) & 0b11111) { |
| 1811 | case 0: return &op_fsqrt_q; |
| 1812 | } |
| 1813 | break; |
| 1814 | case 80: |
| 1815 | switch ((inst >> 12) & 0b111) { |
| 1816 | case 0: return &op_fle_s; |
| 1817 | case 1: return &op_flt_s; |
| 1818 | case 2: return &op_feq_s; |
| 1819 | case 4: return &op_fleq_s; |
| 1820 | case 5: return &op_fltq_s; |
| 1821 | } |
| 1822 | break; |
| 1823 | case 81: |
| 1824 | switch ((inst >> 12) & 0b111) { |
| 1825 | case 0: return &op_fle_d; |
| 1826 | case 1: return &op_flt_d; |
| 1827 | case 2: return &op_feq_d; |
| 1828 | case 4: return &op_fleq_d; |
| 1829 | case 5: return &op_fltq_d; |
| 1830 | } |
| 1831 | break; |
| 1832 | case 82: |
| 1833 | switch (((inst >> 12) & 0b111)) { |
| 1834 | case 4: return &op_fleq_h; |
| 1835 | case 5: return &op_fltq_h; |
| 1836 | } |
| 1837 | break; |
| 1838 | case 83: |
| 1839 | switch ((inst >> 12) & 0b111) { |
| 1840 | case 0: return &op_fle_q; |
| 1841 | case 1: return &op_flt_q; |
| 1842 | case 2: return &op_feq_q; |
| 1843 | case 4: return &op_fleq_q; |
| 1844 | case 5: return &op_fltq_q; |
| 1845 | } |
| 1846 | break; |
| 1847 | case 89: |
| 1848 | switch (((inst >> 12) & 0b111)) { |
| 1849 | case 0: return &op_fmvp_d_x; |
| 1850 | } |
| 1851 | break; |
| 1852 | case 91: |
| 1853 | switch (((inst >> 12) & 0b111)) { |
| 1854 | case 0: return &op_fmvp_q_x; |
| 1855 | } |
| 1856 | break; |
| 1857 | case 96: |
| 1858 | switch ((inst >> 20) & 0b11111) { |
| 1859 | case 0: return &op_fcvt_w_s; |
| 1860 | case 1: return &op_fcvt_wu_s; |
| 1861 | case 2: return &op_fcvt_l_s; |
| 1862 | case 3: return &op_fcvt_lu_s; |
| 1863 | } |
| 1864 | break; |
| 1865 | case 97: |
| 1866 | switch ((inst >> 20) & 0b11111) { |
| 1867 | case 0: return &op_fcvt_w_d; |
| 1868 | case 1: return &op_fcvt_wu_d; |
| 1869 | case 2: return &op_fcvt_l_d; |
| 1870 | case 3: return &op_fcvt_lu_d; |
| 1871 | case 8: return &op_fcvtmod_w_d; |
| 1872 | } |
| 1873 | break; |
| 1874 | case 99: |
| 1875 | switch ((inst >> 20) & 0b11111) { |
| 1876 | case 0: return &op_fcvt_w_q; |
| 1877 | case 1: return &op_fcvt_wu_q; |
| 1878 | case 2: return &op_fcvt_l_q; |
| 1879 | case 3: return &op_fcvt_lu_q; |
| 1880 | } |
| 1881 | break; |
| 1882 | case 104: |
| 1883 | switch ((inst >> 20) & 0b11111) { |
| 1884 | case 0: return &op_fcvt_s_w; |
| 1885 | case 1: return &op_fcvt_s_wu; |
| 1886 | case 2: return &op_fcvt_s_l; |
| 1887 | case 3: return &op_fcvt_s_lu; |
| 1888 | } |
| 1889 | break; |
| 1890 | case 105: |
| 1891 | switch ((inst >> 20) & 0b11111) { |
| 1892 | case 0: return &op_fcvt_d_w; |
| 1893 | case 1: return &op_fcvt_d_wu; |
| 1894 | case 2: return &op_fcvt_d_l; |
| 1895 | case 3: return &op_fcvt_d_lu; |
| 1896 | } |
| 1897 | break; |
| 1898 | case 107: |
| 1899 | switch ((inst >> 20) & 0b11111) { |
| 1900 | case 0: return &op_fcvt_q_w; |
| 1901 | case 1: return &op_fcvt_q_wu; |
| 1902 | case 2: return &op_fcvt_q_l; |
| 1903 | case 3: return &op_fcvt_q_lu; |
| 1904 | } |
| 1905 | break; |
| 1906 | case 112: |
| 1907 | switch (((inst >> 17) & 0b11111000) | |
| 1908 | ((inst >> 12) & 0b00000111)) { |
| 1909 | case 0: return &op_fmv_x_s; |
| 1910 | case 1: return &op_fclass_s; |
| 1911 | } |
| 1912 | break; |
| 1913 | case 113: |
| 1914 | switch (((inst >> 17) & 0b11111000) | |
| 1915 | ((inst >> 12) & 0b00000111)) { |
| 1916 | case 0: return &op_fmv_x_d; |
| 1917 | case 1: return &op_fclass_d; |
| 1918 | case 8: return &op_fmvh_x_d; |
| 1919 | } |
| 1920 | break; |
| 1921 | case 114: |
| 1922 | switch (((inst >> 17) & 0b11111000) | |
| 1923 | ((inst >> 12) & 0b00000111)) { |
| 1924 | case 0: return &op_fmv_x_h; |
| 1925 | } |
| 1926 | break; |
| 1927 | case 115: |
| 1928 | switch (((inst >> 17) & 0b11111000) | |
| 1929 | ((inst >> 12) & 0b00000111)) { |
| 1930 | case 0: return &op_fmv_x_q; |
| 1931 | case 1: return &op_fclass_q; |
| 1932 | case 8: return &op_fmvh_x_q; |
| 1933 | } |
| 1934 | break; |
| 1935 | case 120: |
| 1936 | switch (((inst >> 17) & 0b11111000) | |
| 1937 | ((inst >> 12) & 0b00000111)) { |
| 1938 | case 0: return &op_fmv_s_x; |
| 1939 | case 8: return &op_fli_s; |
| 1940 | } |
| 1941 | break; |
| 1942 | case 121: |
| 1943 | switch (((inst >> 17) & 0b11111000) | |
| 1944 | ((inst >> 12) & 0b00000111)) { |
| 1945 | case 0: return &op_fmv_d_x; |
| 1946 | case 8: return &op_fli_d; |
| 1947 | } |
| 1948 | break; |
| 1949 | case 122: |
| 1950 | switch (((inst >> 17) & 0b11111000) | |
| 1951 | ((inst >> 12) & 0b00000111)) { |
| 1952 | case 0: return &op_fmv_h_x; |
| 1953 | case 8: return &op_fli_h; |
| 1954 | } |
| 1955 | break; |
| 1956 | case 123: |
| 1957 | switch (((inst >> 17) & 0b11111000) | |
| 1958 | ((inst >> 12) & 0b00000111)) { |
| 1959 | case 0: return &op_fmv_q_x; |
| 1960 | case 8: return &op_fli_q; |
| 1961 | } |
| 1962 | break; |
| 1963 | } |
| 1964 | break; |
| 1965 | case 21: |
| 1966 | switch ((inst >> 12) & 0b111) { |
| 1967 | case 0: |
| 1968 | switch ((inst >> 26) & 0b111111) { |
| 1969 | case 0: return &op_vadd_vv; |
| 1970 | case 1: return &op_vandn_vv; |
| 1971 | case 2: return &op_vsub_vv; |
| 1972 | case 4: return &op_vminu_vv; |
| 1973 | case 5: return &op_vmin_vv; |
| 1974 | case 6: return &op_vmaxu_vv; |
| 1975 | case 7: return &op_vmax_vv; |
| 1976 | case 9: return &op_vand_vv; |
| 1977 | case 10: return &op_vor_vv; |
| 1978 | case 11: return &op_vxor_vv; |
| 1979 | case 12: return &op_vrgather_vv; |
| 1980 | case 14: return &op_vrgatherei16_vv; |
| 1981 | case 16: |
| 1982 | if (((inst >> 25) & 1) == 0) { |
| 1983 | return &op_vadc_vvm; |
| 1984 | } |
| 1985 | break; |
| 1986 | case 17: return &op_vmadc_vvm; |
| 1987 | case 18: |
| 1988 | if (((inst >> 25) & 1) == 0) { |
| 1989 | return &op_vsbc_vvm; |
| 1990 | } |
| 1991 | break; |
| 1992 | case 19: return &op_vmsbc_vvm; |
| 1993 | case 20: return &op_vror_vv; |
| 1994 | case 21: return &op_vrol_vv; |
| 1995 | case 23: |
| 1996 | if (((inst >> 20) & 0b111111) == 32) { |
| 1997 | return &op_vmv_v_v; |
| 1998 | } else if (((inst >> 25) & 1) == 0) { |
| 1999 | return &op_vmerge_vvm; |
| 2000 | } |
| 2001 | break; |
| 2002 | case 24: return &op_vmseq_vv; |
| 2003 | case 25: return &op_vmsne_vv; |
| 2004 | case 26: return &op_vmsltu_vv; |
| 2005 | case 27: return &op_vmslt_vv; |
| 2006 | case 28: return &op_vmsleu_vv; |
| 2007 | case 29: return &op_vmsle_vv; |
| 2008 | case 32: return &op_vsaddu_vv; |
| 2009 | case 33: return &op_vsadd_vv; |
| 2010 | case 34: return &op_vssubu_vv; |
| 2011 | case 35: return &op_vssub_vv; |
| 2012 | case 37: return &op_vsll_vv; |
| 2013 | case 39: return &op_vsmul_vv; |
| 2014 | case 40: return &op_vsrl_vv; |
| 2015 | case 41: return &op_vsra_vv; |
| 2016 | case 42: return &op_vssrl_vv; |
| 2017 | case 43: return &op_vssra_vv; |
| 2018 | case 44: return &op_vnsrl_wv; |
| 2019 | case 45: return &op_vnsra_wv; |
| 2020 | case 46: return &op_vnclipu_wv; |
| 2021 | case 47: return &op_vnclip_wv; |
| 2022 | case 48: return &op_vwredsumu_vs; |
| 2023 | case 49: return &op_vwredsum_vs; |
| 2024 | case 53: return &op_vwsll_vv; |
| 2025 | } |
| 2026 | break; |
| 2027 | case 1: |
| 2028 | switch ((inst >> 26) & 0b111111) { |
| 2029 | case 0: return &op_vfadd_vv; |
| 2030 | case 1: return &op_vfredusum_vs; |
| 2031 | case 2: return &op_vfsub_vv; |
| 2032 | case 3: return &op_vfredosum_vs; |
| 2033 | case 4: return &op_vfmin_vv; |
| 2034 | case 5: return &op_vfredmin_vs; |
| 2035 | case 6: return &op_vfmax_vv; |
| 2036 | case 7: return &op_vfredmax_vs; |
| 2037 | case 8: return &op_vfsgnj_vv; |
| 2038 | case 9: return &op_vfsgnjn_vv; |
| 2039 | case 10: return &op_vfsgnjx_vv; |
| 2040 | case 16: |
| 2041 | switch ((inst >> 15) & 0b11111) { |
| 2042 | case 0: |
| 2043 | if ((inst >> 25) & 1) { |
| 2044 | return &op_vfmv_f_s; |
| 2045 | } |
| 2046 | } |
| 2047 | break; |
| 2048 | case 18: |
| 2049 | switch ((inst >> 15) & 0b11111) { |
| 2050 | case 0: return &op_vfcvt_xu_f_v; |
| 2051 | case 1: return &op_vfcvt_x_f_v; |
| 2052 | case 2: return &op_vfcvt_f_xu_v; |
| 2053 | case 3: return &op_vfcvt_f_x_v; |
| 2054 | case 6: return &op_vfcvt_rtz_xu_f_v; |
| 2055 | case 7: return &op_vfcvt_rtz_x_f_v; |
| 2056 | case 8: return &op_vfwcvt_xu_f_v; |
| 2057 | case 9: return &op_vfwcvt_x_f_v; |
| 2058 | case 10: return &op_vfwcvt_f_xu_v; |
| 2059 | case 11: return &op_vfwcvt_f_x_v; |
| 2060 | case 12: return &op_vfwcvt_f_f_v; |
| 2061 | case 13: return &op_vfwcvtbf16_f_f_v; |
| 2062 | case 14: return &op_vfwcvt_rtz_xu_f_v; |
| 2063 | case 15: return &op_vfwcvt_rtz_x_f_v; |
| 2064 | case 16: return &op_vfncvt_xu_f_w; |
| 2065 | case 17: return &op_vfncvt_x_f_w; |
| 2066 | case 18: return &op_vfncvt_f_xu_w; |
| 2067 | case 19: return &op_vfncvt_f_x_w; |
| 2068 | case 20: return &op_vfncvt_f_f_w; |
| 2069 | case 21: return &op_vfncvt_rod_f_f_w; |
| 2070 | case 22: return &op_vfncvt_rtz_xu_f_w; |
| 2071 | case 23: return &op_vfncvt_rtz_x_f_w; |
| 2072 | case 29: return &op_vfncvtbf16_f_f_w; |
| 2073 | } |
| 2074 | break; |
| 2075 | case 19: |
| 2076 | switch ((inst >> 15) & 0b11111) { |
| 2077 | case 0: return &op_vfsqrt_v; |
| 2078 | case 4: return &op_vfrsqrt7_v; |
| 2079 | case 5: return &op_vfrec7_v; |
| 2080 | case 16: return &op_vfclass_v; |
| 2081 | } |
| 2082 | break; |
| 2083 | case 24: return &op_vmfeq_vv; |
| 2084 | case 25: return &op_vmfle_vv; |
| 2085 | case 27: return &op_vmflt_vv; |
| 2086 | case 28: return &op_vmfne_vv; |
| 2087 | case 32: return &op_vfdiv_vv; |
| 2088 | case 36: return &op_vfmul_vv; |
| 2089 | case 40: return &op_vfmadd_vv; |
| 2090 | case 41: return &op_vfnmadd_vv; |
| 2091 | case 42: return &op_vfmsub_vv; |
| 2092 | case 43: return &op_vfnmsub_vv; |
| 2093 | case 44: return &op_vfmacc_vv; |
| 2094 | case 45: return &op_vfnmacc_vv; |
| 2095 | case 46: return &op_vfmsac_vv; |
| 2096 | case 47: return &op_vfnmsac_vv; |
| 2097 | case 48: return &op_vfwadd_vv; |
| 2098 | case 49: return &op_vfwredusum_vs; |
| 2099 | case 50: return &op_vfwsub_vv; |
| 2100 | case 51: return &op_vfwredosum_vs; |
| 2101 | case 52: return &op_vfwadd_wv; |
| 2102 | case 54: return &op_vfwsub_wv; |
| 2103 | case 56: return &op_vfwmul_vv; |
| 2104 | case 59: return &op_vfwmaccbf16_vv; |
| 2105 | case 60: return &op_vfwmacc_vv; |
| 2106 | case 61: return &op_vfwnmacc_vv; |
| 2107 | case 62: return &op_vfwmsac_vv; |
| 2108 | case 63: return &op_vfwnmsac_vv; |
| 2109 | } |
| 2110 | break; |
| 2111 | case 2: |
| 2112 | switch ((inst >> 26) & 0b111111) { |
| 2113 | case 0: return &op_vredsum_vs; |
| 2114 | case 1: return &op_vredand_vs; |
| 2115 | case 2: return &op_vredor_vs; |
| 2116 | case 3: return &op_vredxor_vs; |
| 2117 | case 4: return &op_vredminu_vs; |
| 2118 | case 5: return &op_vredmin_vs; |
| 2119 | case 6: return &op_vredmaxu_vs; |
| 2120 | case 7: return &op_vredmax_vs; |
| 2121 | case 8: return &op_vaaddu_vv; |
| 2122 | case 9: return &op_vaadd_vv; |
| 2123 | case 10: return &op_vasubu_vv; |
| 2124 | case 11: return &op_vasub_vv; |
| 2125 | case 12: return &op_vclmul_vv; |
| 2126 | case 13: return &op_vclmulh_vv; |
| 2127 | case 16: |
| 2128 | switch ((inst >> 15) & 0b11111) { |
| 2129 | case 0: |
| 2130 | if ((inst >> 25) & 1) { |
| 2131 | return &op_vmv_x_s; |
| 2132 | } |
| 2133 | break; |
| 2134 | case 16: return &op_vcpop_m; |
| 2135 | case 17: return &op_vfirst_m; |
| 2136 | } |
| 2137 | break; |
| 2138 | case 18: |
| 2139 | switch ((inst >> 15) & 0b11111) { |
| 2140 | case 2: return &op_vzext_vf8; |
| 2141 | case 3: return &op_vsext_vf8; |
| 2142 | case 4: return &op_vzext_vf4; |
| 2143 | case 5: return &op_vsext_vf4; |
| 2144 | case 6: return &op_vzext_vf2; |
| 2145 | case 7: return &op_vsext_vf2; |
| 2146 | case 8: return &op_vbrev8_v; |
| 2147 | case 9: return &op_vrev8_v; |
| 2148 | case 10: return &op_vbrev_v; |
| 2149 | case 12: return &op_vclz_v; |
| 2150 | case 13: return &op_vctz_v; |
| 2151 | case 14: return &op_vcpop_v; |
| 2152 | } |
| 2153 | break; |
| 2154 | case 20: |
| 2155 | switch ((inst >> 15) & 0b11111) { |
| 2156 | case 1: return &op_vmsbf_m; break; |
| 2157 | case 2: return &op_vmsof_m; |
| 2158 | case 3: return &op_vmsif_m; |
| 2159 | case 16: return &op_viota_m; |
| 2160 | case 17: |
| 2161 | if (((inst >> 20) & 0b11111) == 0) { |
| 2162 | return &op_vid_v; |
| 2163 | } |
| 2164 | break; |
| 2165 | } |
| 2166 | break; |
| 2167 | case 23: |
| 2168 | if ((inst >> 25) & 1) { |
| 2169 | return &op_vcompress_vm; |
| 2170 | } |
| 2171 | break; |
| 2172 | case 24: |
| 2173 | if ((inst >> 25) & 1) { |
| 2174 | return &op_vmandn_mm; |
| 2175 | } |
| 2176 | break; |
| 2177 | case 25: |
| 2178 | if ((inst >> 25) & 1) { |
| 2179 | return &op_vmand_mm; |
| 2180 | } |
| 2181 | break; |
| 2182 | case 26: |
| 2183 | if ((inst >> 25) & 1) { |
| 2184 | return &op_vmor_mm; |
| 2185 | } |
| 2186 | break; |
| 2187 | case 27: |
| 2188 | if ((inst >> 25) & 1) { |
| 2189 | return &op_vmxor_mm; |
| 2190 | } |
| 2191 | break; |
| 2192 | case 28: |
| 2193 | if ((inst >> 25) & 1) { |
| 2194 | return &op_vmorn_mm; |
| 2195 | } |
| 2196 | break; |
| 2197 | case 29: |
| 2198 | if ((inst >> 25) & 1) { |
| 2199 | return &op_vmnand_mm; |
| 2200 | } |
| 2201 | break; |
| 2202 | case 30: |
| 2203 | if ((inst >> 25) & 1) { |
| 2204 | return &op_vmnor_mm; |
| 2205 | } |
| 2206 | break; |
| 2207 | case 31: |
| 2208 | if ((inst >> 25) & 1) { |
| 2209 | return &op_vmxnor_mm; |
| 2210 | } |
| 2211 | break; |
| 2212 | case 32: return &op_vdivu_vv; |
| 2213 | case 33: return &op_vdiv_vv; |
| 2214 | case 34: return &op_vremu_vv; |
| 2215 | case 35: return &op_vrem_vv; |
| 2216 | case 36: return &op_vmulhu_vv; |
| 2217 | case 37: return &op_vmul_vv; |
| 2218 | case 38: return &op_vmulhsu_vv; |
| 2219 | case 39: return &op_vmulh_vv; |
| 2220 | case 41: return &op_vmadd_vv; |
| 2221 | case 43: return &op_vnmsub_vv; |
| 2222 | case 45: return &op_vmacc_vv; |
| 2223 | case 47: return &op_vnmsac_vv; |
| 2224 | case 48: return &op_vwaddu_vv; |
| 2225 | case 49: return &op_vwadd_vv; |
| 2226 | case 50: return &op_vwsubu_vv; |
| 2227 | case 51: return &op_vwsub_vv; |
| 2228 | case 52: return &op_vwaddu_wv; |
| 2229 | case 53: return &op_vwadd_wv; |
| 2230 | case 54: return &op_vwsubu_wv; |
| 2231 | case 55: return &op_vwsub_wv; |
| 2232 | case 56: return &op_vwmulu_vv; |
| 2233 | case 58: return &op_vwmulsu_vv; |
| 2234 | case 59: return &op_vwmul_vv; |
| 2235 | case 60: return &op_vwmaccu_vv; |
| 2236 | case 61: return &op_vwmacc_vv; |
| 2237 | case 63: return &op_vwmaccsu_vv; |
| 2238 | } |
| 2239 | break; |
| 2240 | case 3: |
| 2241 | switch ((inst >> 26) & 0b111111) { |
| 2242 | case 0: return &op_vadd_vi; |
| 2243 | case 3: return &op_vrsub_vi; |
| 2244 | case 9: return &op_vand_vi; |
| 2245 | case 10: return &op_vor_vi; |
| 2246 | case 11: return &op_vxor_vi; |
| 2247 | case 12: return &op_vrgather_vi; |
| 2248 | case 14: return &op_vslideup_vi; |
| 2249 | case 15: return &op_vslidedown_vi; |
| 2250 | case 16: |
| 2251 | if (((inst >> 25) & 1) == 0) { |
| 2252 | return &op_vadc_vim; |
| 2253 | } |
| 2254 | break; |
| 2255 | case 17: return &op_vmadc_vim; |
| 2256 | case 20: case 21: return &op_vror_vi; |
| 2257 | case 23: |
| 2258 | if (((inst >> 20) & 0b111111) == 32) { |
| 2259 | return &op_vmv_v_i; |
| 2260 | } else if (((inst >> 25) & 1) == 0) { |
| 2261 | return &op_vmerge_vim; |
| 2262 | } |
| 2263 | break; |
| 2264 | case 24: return &op_vmseq_vi; |
| 2265 | case 25: return &op_vmsne_vi; |
| 2266 | case 28: return &op_vmsleu_vi; |
| 2267 | case 29: return &op_vmsle_vi; |
| 2268 | case 30: return &op_vmsgtu_vi; |
| 2269 | case 31: return &op_vmsgt_vi; |
| 2270 | case 32: return &op_vsaddu_vi; |
| 2271 | case 33: return &op_vsadd_vi; |
| 2272 | case 37: return &op_vsll_vi; |
| 2273 | case 39: |
| 2274 | switch ((inst >> 15) & 0b11111) { |
| 2275 | case 0: return &op_vmv1r_v; |
| 2276 | case 1: return &op_vmv2r_v; |
| 2277 | case 3: return &op_vmv4r_v; |
| 2278 | case 7: return &op_vmv8r_v; |
| 2279 | } |
| 2280 | break; |
| 2281 | case 40: return &op_vsrl_vi; |
| 2282 | case 41: return &op_vsra_vi; |
| 2283 | case 42: return &op_vssrl_vi; |
| 2284 | case 43: return &op_vssra_vi; |
| 2285 | case 44: return &op_vnsrl_wi; |
| 2286 | case 45: return &op_vnsra_wi; |
| 2287 | case 46: return &op_vnclipu_wi; |
| 2288 | case 47: return &op_vnclip_wi; |
| 2289 | case 53: return &op_vwsll_vi; |
| 2290 | } |
| 2291 | break; |
| 2292 | case 4: |
| 2293 | switch ((inst >> 26) & 0b111111) { |
| 2294 | case 0: return &op_vadd_vx; |
| 2295 | case 1: return &op_vandn_vx; |
| 2296 | case 2: return &op_vsub_vx; |
| 2297 | case 3: return &op_vrsub_vx; |
| 2298 | case 4: return &op_vminu_vx; |
| 2299 | case 5: return &op_vmin_vx; |
| 2300 | case 6: return &op_vmaxu_vx; |
| 2301 | case 7: return &op_vmax_vx; |
| 2302 | case 9: return &op_vand_vx; |
| 2303 | case 10: return &op_vor_vx; |
| 2304 | case 11: return &op_vxor_vx; |
| 2305 | case 12: return &op_vrgather_vx; |
| 2306 | case 14: return &op_vslideup_vx; |
| 2307 | case 15: return &op_vslidedown_vx; |
| 2308 | case 16: |
| 2309 | if (((inst >> 25) & 1) == 0) { |
| 2310 | return &op_vadc_vxm; |
| 2311 | } |
| 2312 | break; |
| 2313 | case 17: return &op_vmadc_vxm; |
| 2314 | case 18: |
| 2315 | if (((inst >> 25) & 1) == 0) { |
| 2316 | return &op_vsbc_vxm; |
| 2317 | } |
| 2318 | break; |
| 2319 | case 19: return &op_vmsbc_vxm; |
| 2320 | case 20: return &op_vror_vx; |
| 2321 | case 21: return &op_vrol_vx; |
| 2322 | case 23: |
| 2323 | if (((inst >> 20) & 0b111111) == 32) { |
| 2324 | return &op_vmv_v_x; |
| 2325 | } else if (((inst >> 25) & 1) == 0) { |
| 2326 | return &op_vmerge_vxm; |
| 2327 | } |
| 2328 | break; |
| 2329 | case 24: return &op_vmseq_vx; |
| 2330 | case 25: return &op_vmsne_vx; |
| 2331 | case 26: return &op_vmsltu_vx; |
| 2332 | case 27: return &op_vmslt_vx; |
| 2333 | case 28: return &op_vmsleu_vx; |
| 2334 | case 29: return &op_vmsle_vx; |
| 2335 | case 30: return &op_vmsgtu_vx; |
| 2336 | case 31: return &op_vmsgt_vx; |
| 2337 | case 32: return &op_vsaddu_vx; |
| 2338 | case 33: return &op_vsadd_vx; |
| 2339 | case 34: return &op_vssubu_vx; |
| 2340 | case 35: return &op_vssub_vx; |
| 2341 | case 37: return &op_vsll_vx; |
| 2342 | case 39: return &op_vsmul_vx; |
| 2343 | case 40: return &op_vsrl_vx; |
| 2344 | case 41: return &op_vsra_vx; |
| 2345 | case 42: return &op_vssrl_vx; |
| 2346 | case 43: return &op_vssra_vx; |
| 2347 | case 44: return &op_vnsrl_wx; |
| 2348 | case 45: return &op_vnsra_wx; |
| 2349 | case 46: return &op_vnclipu_wx; |
| 2350 | case 47: return &op_vnclip_wx; |
| 2351 | case 53: return &op_vwsll_vx; |
| 2352 | } |
| 2353 | break; |
| 2354 | case 5: |
| 2355 | switch ((inst >> 26) & 0b111111) { |
| 2356 | case 0: return &op_vfadd_vf; |
| 2357 | case 2: return &op_vfsub_vf; |
| 2358 | case 4: return &op_vfmin_vf; |
| 2359 | case 6: return &op_vfmax_vf; |
| 2360 | case 8: return &op_vfsgnj_vf; |
| 2361 | case 9: return &op_vfsgnjn_vf; |
| 2362 | case 10: return &op_vfsgnjx_vf; |
| 2363 | case 14: return &op_vfslide1up_vf; |
| 2364 | case 15: return &op_vfslide1down_vf; |
| 2365 | case 16: |
| 2366 | switch ((inst >> 20) & 0b11111) { |
| 2367 | case 0: |
| 2368 | if ((inst >> 25) & 1) { |
| 2369 | return &op_vfmv_s_f; |
| 2370 | } |
| 2371 | } |
| 2372 | break; |
| 2373 | case 23: |
| 2374 | if (((inst >> 25) & 1) == 0) { |
| 2375 | return &op_vfmerge_vfm; |
| 2376 | } else if (((inst >> 20) & 0b111111) == 32) { |
| 2377 | return &op_vfmv_v_f; |
| 2378 | } |
| 2379 | break; |
| 2380 | case 24: return &op_vmfeq_vf; |
| 2381 | case 25: return &op_vmfle_vf; |
| 2382 | case 27: return &op_vmflt_vf; |
| 2383 | case 28: return &op_vmfne_vf; |
| 2384 | case 29: return &op_vmfgt_vf; |
| 2385 | case 31: return &op_vmfge_vf; |
| 2386 | case 32: return &op_vfdiv_vf; |
| 2387 | case 33: return &op_vfrdiv_vf; |
| 2388 | case 36: return &op_vfmul_vf; |
| 2389 | case 39: return &op_vfrsub_vf; |
| 2390 | case 40: return &op_vfmadd_vf; |
| 2391 | case 41: return &op_vfnmadd_vf; |
| 2392 | case 42: return &op_vfmsub_vf; |
| 2393 | case 43: return &op_vfnmsub_vf; |
| 2394 | case 44: return &op_vfmacc_vf; |
| 2395 | case 45: return &op_vfnmacc_vf; |
| 2396 | case 46: return &op_vfmsac_vf; |
| 2397 | case 47: return &op_vfnmsac_vf; |
| 2398 | case 48: return &op_vfwadd_vf; |
| 2399 | case 50: return &op_vfwsub_vf; |
| 2400 | case 52: return &op_vfwadd_wf; |
| 2401 | case 54: return &op_vfwsub_wf; |
| 2402 | case 56: return &op_vfwmul_vf; |
| 2403 | case 59: return &op_vfwmaccbf16_vf; |
| 2404 | case 60: return &op_vfwmacc_vf; |
| 2405 | case 61: return &op_vfwnmacc_vf; |
| 2406 | case 62: return &op_vfwmsac_vf; |
| 2407 | case 63: return &op_vfwnmsac_vf; |
| 2408 | } |
| 2409 | break; |
| 2410 | case 6: |
| 2411 | switch ((inst >> 26) & 0b111111) { |
| 2412 | case 8: return &op_vaaddu_vx; |
| 2413 | case 9: return &op_vaadd_vx; |
| 2414 | case 10: return &op_vasubu_vx; |
| 2415 | case 11: return &op_vasub_vx; |
| 2416 | case 12: return &op_vclmul_vx; |
| 2417 | case 13: return &op_vclmulh_vx; |
| 2418 | case 14: return &op_vslide1up_vx; |
| 2419 | case 15: return &op_vslide1down_vx; |
| 2420 | case 16: |
| 2421 | switch ((inst >> 20) & 0b11111) { |
| 2422 | case 0: |
| 2423 | if ((inst >> 25) & 1) { |
| 2424 | return &op_vmv_s_x; |
| 2425 | } |
| 2426 | } |
| 2427 | break; |
| 2428 | case 32: return &op_vdivu_vx; |
| 2429 | case 33: return &op_vdiv_vx; |
| 2430 | case 34: return &op_vremu_vx; |
| 2431 | case 35: return &op_vrem_vx; |
| 2432 | case 36: return &op_vmulhu_vx; |
| 2433 | case 37: return &op_vmul_vx; |
| 2434 | case 38: return &op_vmulhsu_vx; |
| 2435 | case 39: return &op_vmulh_vx; |
| 2436 | case 41: return &op_vmadd_vx; |
| 2437 | case 43: return &op_vnmsub_vx; |
| 2438 | case 45: return &op_vmacc_vx; |
| 2439 | case 47: return &op_vnmsac_vx; |
| 2440 | case 48: return &op_vwaddu_vx; |
| 2441 | case 49: return &op_vwadd_vx; |
| 2442 | case 50: return &op_vwsubu_vx; |
| 2443 | case 51: return &op_vwsub_vx; |
| 2444 | case 52: return &op_vwaddu_wx; |
| 2445 | case 53: return &op_vwadd_wx; |
| 2446 | case 54: return &op_vwsubu_wx; |
| 2447 | case 55: return &op_vwsub_wx; |
| 2448 | case 56: return &op_vwmulu_vx; |
| 2449 | case 58: return &op_vwmulsu_vx; |
| 2450 | case 59: return &op_vwmul_vx; |
| 2451 | case 60: return &op_vwmaccu_vx; |
| 2452 | case 61: return &op_vwmacc_vx; |
| 2453 | case 62: return &op_vwmaccus_vx; |
| 2454 | case 63: return &op_vwmaccsu_vx; |
| 2455 | } |
| 2456 | break; |
| 2457 | case 7: |
| 2458 | if (((inst >> 31) & 1) == 0) { |
| 2459 | return &op_vsetvli; |
| 2460 | } else if ((inst >> 30) & 1) { |
| 2461 | return &op_vsetivli; |
| 2462 | } else if (((inst >> 25) & 0b11111) == 0) { |
| 2463 | return &op_vsetvl; |
| 2464 | } |
| 2465 | break; |
| 2466 | } |
| 2467 | break; |
| 2468 | case 22: |
| 2469 | switch ((inst >> 12) & 0b111) { |
| 2470 | case 0: return &op_addid; |
| 2471 | case 1: |
| 2472 | switch ((inst >> 26) & 0b111111) { |
| 2473 | case 0: return &op_sllid; |
| 2474 | } |
| 2475 | break; |
| 2476 | case 5: |
| 2477 | switch ((inst >> 26) & 0b111111) { |
| 2478 | case 0: return &op_srlid; |
| 2479 | case 16: return &op_sraid; |
| 2480 | } |
| 2481 | break; |
| 2482 | } |
| 2483 | break; |
| 2484 | case 24: |
| 2485 | switch ((inst >> 12) & 0b111) { |
| 2486 | case 0: return &op_beq; |
| 2487 | case 1: return &op_bne; |
| 2488 | case 4: return &op_blt; |
| 2489 | case 5: return &op_bge; |
| 2490 | case 6: return &op_bltu; |
| 2491 | case 7: return &op_bgeu; |
| 2492 | } |
| 2493 | break; |
| 2494 | case 25: |
| 2495 | switch ((inst >> 12) & 0b111) { |
| 2496 | case 0: return &op_jalr; |
| 2497 | } |
| 2498 | break; |
| 2499 | case 27: return &op_jal; |
| 2500 | case 28: |
| 2501 | switch ((inst >> 12) & 0b111) { |
| 2502 | case 0: |
| 2503 | switch (((inst >> 20) & 0b111111100000) | |
| 2504 | ((inst >> 7) & 0b000000011111)) { |
| 2505 | case 0: |
| 2506 | switch ((inst >> 15) & 0b1111111111) { |
| 2507 | case 0: return &op_ecall; |
| 2508 | case 32: return &op_ebreak; |
| 2509 | case 64: return &op_uret; |
| 2510 | case 416: return &op_wrs_nto; |
| 2511 | case 928: return &op_wrs_sto; |
| 2512 | } |
| 2513 | break; |
| 2514 | case 256: |
| 2515 | switch ((inst >> 20) & 0b11111) { |
| 2516 | case 2: |
| 2517 | switch ((inst >> 15) & 0b11111) { |
| 2518 | case 0: return &op_sret; |
| 2519 | } |
| 2520 | break; |
| 2521 | case 4: return &op_sfence_vm; |
| 2522 | case 5: |
| 2523 | switch ((inst >> 15) & 0b11111) { |
| 2524 | case 0: return &op_wfi; |
| 2525 | } |
| 2526 | break; |
| 2527 | } |
| 2528 | break; |
| 2529 | case 288: return &op_sfence_vma; |
| 2530 | case 512: |
| 2531 | switch ((inst >> 15) & 0b1111111111) { |
| 2532 | case 64: return &op_hret; |
| 2533 | } |
| 2534 | break; |
| 2535 | case 768: |
| 2536 | switch ((inst >> 15) & 0b1111111111) { |
| 2537 | case 64: return &op_mret; |
| 2538 | } |
| 2539 | break; |
| 2540 | case 1792: |
| 2541 | switch ((inst >> 15) & 0b1111111111) { |
| 2542 | case 64: return &op_mnret; |
| 2543 | } |
| 2544 | break; |
| 2545 | case 1952: |
| 2546 | switch ((inst >> 15) & 0b1111111111) { |
| 2547 | case 576: return &op_dret; |
| 2548 | } |
| 2549 | break; |
| 2550 | } |
| 2551 | break; |
| 2552 | case 1: |
| 2553 | switch (operand_csr12(inst)) { |
| 2554 | case 1: return &op_fsflags; |
| 2555 | case 2: return &op_fsrm; |
| 2556 | case 3: return &op_fscsr; |
| 2557 | default: return &op_csrrw; |
| 2558 | } |
| 2559 | break; |
| 2560 | case 2: |
| 2561 | return &op_csrrs; |
| 2562 | if (operand_rs1(inst) == 0) { |
| 2563 | switch (operand_csr12(inst)) { |
| 2564 | case 0x001: return &op_frflags; |
| 2565 | case 0x002: return &op_frrm; |
| 2566 | case 0x003: return &op_frcsr; |
| 2567 | case 0xc00: return &op_rdcycle; |
| 2568 | case 0xc01: return &op_rdtime; |
| 2569 | case 0xc02: return &op_rdinstret; |
| 2570 | case 0xc80: return &op_rdcycleh; |
| 2571 | case 0xc81: return &op_rdtimeh; |
| 2572 | case 0xc82: return &op_rdinstreth; |
| 2573 | } |
| 2574 | } |
| 2575 | break; |
| 2576 | case 3: return &op_csrrc; |
| 2577 | case 4: |
| 2578 | if (dec->cfg && dec->cfg->ext_zimop) { |
| 2579 | if (((inst >> 22) & 0b1011001111) == 0b1000000111) { |
| 2580 | if (dec->cfg->ext_zicfiss |
| 2581 | && operand_mop_r_imm(inst) == 28) { |
| 2582 | switch (operand_rs1(inst)) { |
| 2583 | case 0: |
| 2584 | return &op_ssrdp; |
| 2585 | case 1: |
| 2586 | case 5: |
| 2587 | if (operand_rd(inst) == 0) { |
| 2588 | return &op_sspopchk; |
| 2589 | } |
| 2590 | } |
| 2591 | } |
| 2592 | return &op_mop_r; |
| 2593 | } |
| 2594 | if (((inst >> 25) & 0b1011001) == 0b1000001) { |
| 2595 | if (dec->cfg->ext_zicfiss |
| 2596 | && operand_mop_rr_imm(inst) == 7 |
| 2597 | && operand_rd(inst) == 0 |
| 2598 | && operand_rs1(inst) == 0) { |
| 2599 | switch (operand_rs2(inst)) { |
| 2600 | case 1: |
| 2601 | case 5: |
| 2602 | return &op_sspush; |
| 2603 | } |
| 2604 | } |
| 2605 | return &op_mop_rr; |
| 2606 | } |
| 2607 | } |
| 2608 | break; |
| 2609 | case 5: |
| 2610 | switch (operand_csr12(inst)) { |
| 2611 | case 1: return &op_fsflagsi; |
| 2612 | case 2: return &op_fsrmi; |
| 2613 | default: return &op_csrrwi; |
| 2614 | } |
| 2615 | break; |
| 2616 | case 6: return &op_csrrsi; |
| 2617 | case 7: return &op_csrrci; |
| 2618 | } |
| 2619 | break; |
| 2620 | case 29: |
| 2621 | if (((inst >> 25) & 1) == 1 && ((inst >> 12) & 0b111) == 2) { |
| 2622 | switch ((inst >> 26) & 0b111111) { |
| 2623 | case 32: return &op_vsm3me_vv; |
| 2624 | case 33: return &op_vsm4k_vi; |
| 2625 | case 34: return &op_vaeskf1_vi; |
| 2626 | case 40: |
| 2627 | switch ((inst >> 15) & 0b11111) { |
| 2628 | case 0: return &op_vaesdm_vv; |
| 2629 | case 1: return &op_vaesdf_vv; |
| 2630 | case 2: return &op_vaesem_vv; |
| 2631 | case 3: return &op_vaesef_vv; |
| 2632 | case 16: return &op_vsm4r_vv; |
| 2633 | case 17: return &op_vgmul_vv; |
| 2634 | } |
| 2635 | break; |
| 2636 | case 41: |
| 2637 | switch ((inst >> 15) & 0b11111) { |
| 2638 | case 0: return &op_vaesdm_vs; |
| 2639 | case 1: return &op_vaesdf_vs; |
| 2640 | case 2: return &op_vaesem_vs; |
| 2641 | case 3: return &op_vaesef_vs; |
| 2642 | case 7: return &op_vaesz_vs; |
| 2643 | case 16: return &op_vsm4r_vs; |
| 2644 | } |
| 2645 | break; |
| 2646 | case 42: return &op_vaeskf2_vi; |
| 2647 | case 43: return &op_vsm3c_vi; |
| 2648 | case 44: return &op_vghsh_vv; |
| 2649 | case 45: return &op_vsha2ms_vv; |
| 2650 | case 46: return &op_vsha2ch_vv; |
| 2651 | case 47: return &op_vsha2cl_vv; |
| 2652 | } |
| 2653 | } |
| 2654 | break; |
| 2655 | case 30: |
| 2656 | switch (((inst >> 22) & 0b1111111000) | |
| 2657 | ((inst >> 12) & 0b0000000111)) { |
| 2658 | case 0: return &op_addd; |
| 2659 | case 1: return &op_slld; |
| 2660 | case 5: return &op_srld; |
| 2661 | case 8: return &op_muld; |
| 2662 | case 12: return &op_divd; |
| 2663 | case 13: return &op_divud; |
| 2664 | case 14: return &op_remd; |
| 2665 | case 15: return &op_remud; |
| 2666 | case 256: return &op_subd; |
| 2667 | case 261: return &op_srad; |
| 2668 | } |
| 2669 | break; |
| 2670 | } |
| 2671 | break; |
| 2672 | } |
| 2673 | |
| 2674 | return NULL; |
| 2675 | } |
| 2676 | |
| 2677 | /* decode operands */ |
| 2678 | |
| 2679 | static void decode_inst_operands(rv_decode *dec, rv_isa isa, |
| 2680 | const rv_opcode_data *op) |
| 2681 | { |
| 2682 | rv_inst inst = dec->inst; |
| 2683 | |
| 2684 | switch (op->codec) { |
| 2685 | case rv_codec_none: |
| 2686 | dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero; |
| 2687 | dec->imm = 0; |
| 2688 | break; |
| 2689 | case rv_codec_u: |
| 2690 | dec->rd = operand_rd(inst); |
| 2691 | dec->rs1 = dec->rs2 = rv_ireg_zero; |
| 2692 | dec->imm = operand_imm20(inst); |
| 2693 | break; |
| 2694 | case rv_codec_uj: |
| 2695 | dec->rd = operand_rd(inst); |
| 2696 | dec->rs1 = dec->rs2 = rv_ireg_zero; |
| 2697 | dec->imm = operand_jimm20(inst); |
| 2698 | break; |
| 2699 | case rv_codec_i: |
| 2700 | dec->rd = operand_rd(inst); |
| 2701 | dec->rs1 = operand_rs1(inst); |
| 2702 | dec->rs2 = rv_ireg_zero; |
| 2703 | dec->imm = operand_imm12(inst); |
| 2704 | break; |
| 2705 | case rv_codec_i_sh5: |
| 2706 | dec->rd = operand_rd(inst); |
| 2707 | dec->rs1 = operand_rs1(inst); |
| 2708 | dec->rs2 = rv_ireg_zero; |
| 2709 | dec->imm = operand_shamt5(inst); |
| 2710 | break; |
| 2711 | case rv_codec_i_sh6: |
| 2712 | dec->rd = operand_rd(inst); |
| 2713 | dec->rs1 = operand_rs1(inst); |
| 2714 | dec->rs2 = rv_ireg_zero; |
| 2715 | dec->imm = operand_shamt6(inst); |
| 2716 | break; |
| 2717 | case rv_codec_i_sh7: |
| 2718 | dec->rd = operand_rd(inst); |
| 2719 | dec->rs1 = operand_rs1(inst); |
| 2720 | dec->rs2 = rv_ireg_zero; |
| 2721 | dec->imm = operand_shamt7(inst); |
| 2722 | break; |
| 2723 | case rv_codec_i_csr: |
| 2724 | dec->rd = operand_rd(inst); |
| 2725 | dec->rs1 = operand_rs1(inst); |
| 2726 | dec->rs2 = rv_ireg_zero; |
| 2727 | dec->imm = operand_csr12(inst); |
| 2728 | break; |
| 2729 | case rv_codec_s: |
| 2730 | dec->rd = rv_ireg_zero; |
| 2731 | dec->rs1 = operand_rs1(inst); |
| 2732 | dec->rs2 = operand_rs2(inst); |
| 2733 | dec->imm = operand_simm12(inst); |
| 2734 | break; |
| 2735 | case rv_codec_sb: |
| 2736 | dec->rd = rv_ireg_zero; |
| 2737 | dec->rs1 = operand_rs1(inst); |
| 2738 | dec->rs2 = operand_rs2(inst); |
| 2739 | dec->imm = operand_sbimm12(inst); |
| 2740 | break; |
| 2741 | case rv_codec_r: |
| 2742 | dec->rd = operand_rd(inst); |
| 2743 | dec->rs1 = operand_rs1(inst); |
| 2744 | dec->rs2 = operand_rs2(inst); |
| 2745 | dec->imm = 0; |
| 2746 | break; |
| 2747 | case rv_codec_r_m: |
| 2748 | dec->rd = operand_rd(inst); |
| 2749 | dec->rs1 = operand_rs1(inst); |
| 2750 | dec->rs2 = operand_rs2(inst); |
| 2751 | dec->imm = 0; |
| 2752 | dec->rm = operand_rm(inst); |
| 2753 | break; |
| 2754 | case rv_codec_r4_m: |
| 2755 | dec->rd = operand_rd(inst); |
| 2756 | dec->rs1 = operand_rs1(inst); |
| 2757 | dec->rs2 = operand_rs2(inst); |
| 2758 | dec->rs3 = operand_rs3(inst); |
| 2759 | dec->imm = 0; |
| 2760 | dec->rm = operand_rm(inst); |
| 2761 | break; |
| 2762 | case rv_codec_r_a: |
| 2763 | dec->rd = operand_rd(inst); |
| 2764 | dec->rs1 = operand_rs1(inst); |
| 2765 | dec->rs2 = operand_rs2(inst); |
| 2766 | dec->imm = 0; |
| 2767 | dec->aq = operand_aq(inst); |
| 2768 | dec->rl = operand_rl(inst); |
| 2769 | break; |
| 2770 | case rv_codec_r_l: |
| 2771 | dec->rd = operand_rd(inst); |
| 2772 | dec->rs1 = operand_rs1(inst); |
| 2773 | dec->rs2 = rv_ireg_zero; |
| 2774 | dec->imm = 0; |
| 2775 | dec->aq = operand_aq(inst); |
| 2776 | dec->rl = operand_rl(inst); |
| 2777 | break; |
| 2778 | case rv_codec_r_f: |
| 2779 | dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero; |
| 2780 | dec->pred = operand_pred(inst); |
| 2781 | dec->succ = operand_succ(inst); |
| 2782 | dec->imm = 0; |
| 2783 | break; |
| 2784 | case rv_codec_cb: |
| 2785 | dec->rd = rv_ireg_zero; |
| 2786 | dec->rs1 = operand_crs1q(inst) + 8; |
| 2787 | dec->rs2 = rv_ireg_zero; |
| 2788 | dec->imm = operand_cimmb(inst); |
| 2789 | break; |
| 2790 | case rv_codec_cb_imm: |
| 2791 | dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8; |
| 2792 | dec->rs2 = rv_ireg_zero; |
| 2793 | dec->imm = operand_cimmi(inst); |
| 2794 | break; |
| 2795 | case rv_codec_cb_sh5: |
| 2796 | dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8; |
| 2797 | dec->rs2 = rv_ireg_zero; |
| 2798 | dec->imm = operand_cimmsh5(inst); |
| 2799 | break; |
| 2800 | case rv_codec_cb_sh6: |
| 2801 | dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8; |
| 2802 | dec->rs2 = rv_ireg_zero; |
| 2803 | dec->imm = operand_cimmshr6(inst, isa); |
| 2804 | break; |
| 2805 | case rv_codec_ci: |
| 2806 | dec->rd = dec->rs1 = operand_crs1rd(inst); |
| 2807 | dec->rs2 = rv_ireg_zero; |
| 2808 | dec->imm = operand_cimmi(inst); |
| 2809 | break; |
| 2810 | case rv_codec_ci_sh5: |
| 2811 | dec->rd = dec->rs1 = operand_crs1rd(inst); |
| 2812 | dec->rs2 = rv_ireg_zero; |
| 2813 | dec->imm = operand_cimmsh5(inst); |
| 2814 | break; |
| 2815 | case rv_codec_ci_sh6: |
| 2816 | dec->rd = dec->rs1 = operand_crs1rd(inst); |
| 2817 | dec->rs2 = rv_ireg_zero; |
| 2818 | dec->imm = operand_cimmshl6(inst, isa); |
| 2819 | break; |
| 2820 | case rv_codec_ci_16sp: |
| 2821 | dec->rd = rv_ireg_sp; |
| 2822 | dec->rs1 = rv_ireg_sp; |
| 2823 | dec->rs2 = rv_ireg_zero; |
| 2824 | dec->imm = operand_cimm16sp(inst); |
| 2825 | break; |
| 2826 | case rv_codec_ci_lwsp: |
| 2827 | dec->rd = operand_crd(inst); |
| 2828 | dec->rs1 = rv_ireg_sp; |
| 2829 | dec->rs2 = rv_ireg_zero; |
| 2830 | dec->imm = operand_cimmlwsp(inst); |
| 2831 | break; |
| 2832 | case rv_codec_ci_ldsp: |
| 2833 | dec->rd = operand_crd(inst); |
| 2834 | dec->rs1 = rv_ireg_sp; |
| 2835 | dec->rs2 = rv_ireg_zero; |
| 2836 | dec->imm = operand_cimmldsp(inst); |
| 2837 | break; |
| 2838 | case rv_codec_ci_lqsp: |
| 2839 | dec->rd = operand_crd(inst); |
| 2840 | dec->rs1 = rv_ireg_sp; |
| 2841 | dec->rs2 = rv_ireg_zero; |
| 2842 | dec->imm = operand_cimmlqsp(inst); |
| 2843 | break; |
| 2844 | case rv_codec_ci_li: |
| 2845 | dec->rd = operand_crd(inst); |
| 2846 | dec->rs1 = rv_ireg_zero; |
| 2847 | dec->rs2 = rv_ireg_zero; |
| 2848 | dec->imm = operand_cimmi(inst); |
| 2849 | break; |
| 2850 | case rv_codec_ci_lui: |
| 2851 | dec->rd = operand_crd(inst); |
| 2852 | dec->rs1 = rv_ireg_zero; |
| 2853 | dec->rs2 = rv_ireg_zero; |
| 2854 | dec->imm = operand_cimmui(inst); |
| 2855 | break; |
| 2856 | case rv_codec_ci_none: |
| 2857 | dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero; |
| 2858 | dec->imm = 0; |
| 2859 | break; |
| 2860 | case rv_codec_ciw_4spn: |
| 2861 | dec->rd = operand_crdq(inst) + 8; |
| 2862 | dec->rs1 = rv_ireg_sp; |
| 2863 | dec->rs2 = rv_ireg_zero; |
| 2864 | dec->imm = operand_cimm4spn(inst); |
| 2865 | break; |
| 2866 | case rv_codec_cj: |
| 2867 | dec->rd = dec->rs1 = dec->rs2 = rv_ireg_zero; |
| 2868 | dec->imm = operand_cimmj(inst); |
| 2869 | break; |
| 2870 | case rv_codec_cj_jal: |
| 2871 | dec->rd = rv_ireg_ra; |
| 2872 | dec->rs1 = dec->rs2 = rv_ireg_zero; |
| 2873 | dec->imm = operand_cimmj(inst); |
| 2874 | break; |
| 2875 | case rv_codec_cl_lw: |
| 2876 | dec->rd = operand_crdq(inst) + 8; |
| 2877 | dec->rs1 = operand_crs1q(inst) + 8; |
| 2878 | dec->rs2 = rv_ireg_zero; |
| 2879 | dec->imm = operand_cimmw(inst); |
| 2880 | break; |
| 2881 | case rv_codec_cl_ld: |
| 2882 | dec->rd = operand_crdq(inst) + 8; |
| 2883 | dec->rs1 = operand_crs1q(inst) + 8; |
| 2884 | dec->rs2 = rv_ireg_zero; |
| 2885 | dec->imm = operand_cimmd(inst); |
| 2886 | break; |
| 2887 | case rv_codec_cl_lq: |
| 2888 | dec->rd = operand_crdq(inst) + 8; |
| 2889 | dec->rs1 = operand_crs1q(inst) + 8; |
| 2890 | dec->rs2 = rv_ireg_zero; |
| 2891 | dec->imm = operand_cimmq(inst); |
| 2892 | break; |
| 2893 | case rv_codec_cr: |
| 2894 | dec->rd = dec->rs1 = operand_crs1rd(inst); |
| 2895 | dec->rs2 = operand_crs2(inst); |
| 2896 | dec->imm = 0; |
| 2897 | break; |
| 2898 | case rv_codec_cr_mv: |
| 2899 | dec->rd = operand_crd(inst); |
| 2900 | dec->rs1 = operand_crs2(inst); |
| 2901 | dec->rs2 = rv_ireg_zero; |
| 2902 | dec->imm = 0; |
| 2903 | break; |
| 2904 | case rv_codec_cr_jalr: |
| 2905 | dec->rd = rv_ireg_ra; |
| 2906 | dec->rs1 = operand_crs1(inst); |
| 2907 | dec->rs2 = rv_ireg_zero; |
| 2908 | dec->imm = 0; |
| 2909 | break; |
| 2910 | case rv_codec_cr_jr: |
| 2911 | dec->rd = rv_ireg_zero; |
| 2912 | dec->rs1 = operand_crs1(inst); |
| 2913 | dec->rs2 = rv_ireg_zero; |
| 2914 | dec->imm = 0; |
| 2915 | break; |
| 2916 | case rv_codec_cs: |
| 2917 | dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8; |
| 2918 | dec->rs2 = operand_crs2q(inst) + 8; |
| 2919 | dec->imm = 0; |
| 2920 | break; |
| 2921 | case rv_codec_cs_sw: |
| 2922 | dec->rd = rv_ireg_zero; |
| 2923 | dec->rs1 = operand_crs1q(inst) + 8; |
| 2924 | dec->rs2 = operand_crs2q(inst) + 8; |
| 2925 | dec->imm = operand_cimmw(inst); |
| 2926 | break; |
| 2927 | case rv_codec_cs_sd: |
| 2928 | dec->rd = rv_ireg_zero; |
| 2929 | dec->rs1 = operand_crs1q(inst) + 8; |
| 2930 | dec->rs2 = operand_crs2q(inst) + 8; |
| 2931 | dec->imm = operand_cimmd(inst); |
| 2932 | break; |
| 2933 | case rv_codec_cs_sq: |
| 2934 | dec->rd = rv_ireg_zero; |
| 2935 | dec->rs1 = operand_crs1q(inst) + 8; |
| 2936 | dec->rs2 = operand_crs2q(inst) + 8; |
| 2937 | dec->imm = operand_cimmq(inst); |
| 2938 | break; |
| 2939 | case rv_codec_css_swsp: |
| 2940 | dec->rd = rv_ireg_zero; |
| 2941 | dec->rs1 = rv_ireg_sp; |
| 2942 | dec->rs2 = operand_crs2(inst); |
| 2943 | dec->imm = operand_cimmswsp(inst); |
| 2944 | break; |
| 2945 | case rv_codec_css_sdsp: |
| 2946 | dec->rd = rv_ireg_zero; |
| 2947 | dec->rs1 = rv_ireg_sp; |
| 2948 | dec->rs2 = operand_crs2(inst); |
| 2949 | dec->imm = operand_cimmsdsp(inst); |
| 2950 | break; |
| 2951 | case rv_codec_css_sqsp: |
| 2952 | dec->rd = rv_ireg_zero; |
| 2953 | dec->rs1 = rv_ireg_sp; |
| 2954 | dec->rs2 = operand_crs2(inst); |
| 2955 | dec->imm = operand_cimmsqsp(inst); |
| 2956 | break; |
| 2957 | case rv_codec_k_bs: |
| 2958 | dec->rs1 = operand_rs1(inst); |
| 2959 | dec->rs2 = operand_rs2(inst); |
| 2960 | dec->bs = operand_bs(inst); |
| 2961 | break; |
| 2962 | case rv_codec_k_rnum: |
| 2963 | dec->rd = operand_rd(inst); |
| 2964 | dec->rs1 = operand_rs1(inst); |
| 2965 | dec->rnum = operand_rnum(inst); |
| 2966 | break; |
| 2967 | case rv_codec_v_r: |
| 2968 | dec->rd = operand_rd(inst); |
| 2969 | dec->rs1 = operand_rs1(inst); |
| 2970 | dec->rs2 = operand_rs2(inst); |
| 2971 | dec->vm = operand_vm(inst); |
| 2972 | break; |
| 2973 | case rv_codec_v_ldst: |
| 2974 | dec->rd = operand_rd(inst); |
| 2975 | dec->rs1 = operand_rs1(inst); |
| 2976 | dec->vm = operand_vm(inst); |
| 2977 | break; |
| 2978 | case rv_codec_v_i: |
| 2979 | dec->rd = operand_rd(inst); |
| 2980 | dec->rs2 = operand_rs2(inst); |
| 2981 | dec->imm = operand_vimm(inst); |
| 2982 | dec->vm = operand_vm(inst); |
| 2983 | break; |
| 2984 | case rv_codec_v_i_u: |
| 2985 | dec->rd = operand_rd(inst); |
| 2986 | dec->rs2 = operand_rs2(inst); |
| 2987 | dec->imm = operand_vuimm(inst); |
| 2988 | dec->vm = operand_vm(inst); |
| 2989 | break; |
| 2990 | case rv_codec_vror_vi: |
| 2991 | dec->rd = operand_rd(inst); |
| 2992 | dec->rs2 = operand_rs2(inst); |
| 2993 | dec->imm = operand_vzimm6(inst); |
| 2994 | dec->vm = operand_vm(inst); |
| 2995 | break; |
| 2996 | case rv_codec_vsetvli: |
| 2997 | dec->rd = operand_rd(inst); |
| 2998 | dec->rs1 = operand_rs1(inst); |
| 2999 | dec->vzimm = operand_vzimm11(inst); |
| 3000 | break; |
| 3001 | case rv_codec_vsetivli: |
| 3002 | dec->rd = operand_rd(inst); |
| 3003 | dec->imm = extract32(inst, 15, 5); |
| 3004 | dec->vzimm = operand_vzimm10(inst); |
| 3005 | break; |
| 3006 | case rv_codec_zcb_lb: |
| 3007 | dec->rs1 = operand_crs1q(inst) + 8; |
| 3008 | dec->rs2 = operand_crs2q(inst) + 8; |
| 3009 | dec->imm = operand_uimm_c_lb(inst); |
| 3010 | break; |
| 3011 | case rv_codec_zcb_lh: |
| 3012 | dec->rs1 = operand_crs1q(inst) + 8; |
| 3013 | dec->rs2 = operand_crs2q(inst) + 8; |
| 3014 | dec->imm = operand_uimm_c_lh(inst); |
| 3015 | break; |
| 3016 | case rv_codec_zcb_ext: |
| 3017 | dec->rd = operand_crs1q(inst) + 8; |
| 3018 | break; |
| 3019 | case rv_codec_zcb_mul: |
| 3020 | dec->rd = operand_crs1rdq(inst) + 8; |
| 3021 | dec->rs2 = operand_crs2q(inst) + 8; |
| 3022 | break; |
| 3023 | case rv_codec_zcmp_cm_pushpop: |
| 3024 | dec->imm = operand_zcmp_stack_adj(inst, isa); |
| 3025 | dec->rlist = operand_zcmp_rlist(inst); |
| 3026 | break; |
| 3027 | case rv_codec_zcmp_cm_mv: |
| 3028 | dec->rd = operand_sreg1(inst); |
| 3029 | dec->rs2 = operand_sreg2(inst); |
| 3030 | break; |
| 3031 | case rv_codec_zcmt_jt: |
| 3032 | dec->imm = operand_tbl_index(inst); |
| 3033 | break; |
| 3034 | case rv_codec_fli: |
| 3035 | dec->rd = operand_rd(inst); |
| 3036 | dec->imm = operand_rs1(inst); |
| 3037 | break; |
| 3038 | case rv_codec_r2_imm5: |
| 3039 | dec->rd = operand_rd(inst); |
| 3040 | dec->rs1 = operand_rs1(inst); |
| 3041 | dec->imm = operand_rs2(inst); |
| 3042 | break; |
| 3043 | case rv_codec_r2: |
| 3044 | dec->rd = operand_rd(inst); |
| 3045 | dec->rs1 = operand_rs1(inst); |
| 3046 | break; |
| 3047 | case rv_codec_r2_imm6: |
| 3048 | dec->rd = operand_rd(inst); |
| 3049 | dec->rs1 = operand_rs1(inst); |
| 3050 | dec->imm = operand_imm6(inst); |
| 3051 | break; |
| 3052 | case rv_codec_r_imm2: |
| 3053 | dec->rd = operand_rd(inst); |
| 3054 | dec->rs1 = operand_rs1(inst); |
| 3055 | dec->rs2 = operand_rs2(inst); |
| 3056 | dec->imm = operand_imm2(inst); |
| 3057 | break; |
| 3058 | case rv_codec_r2_immhl: |
| 3059 | dec->rd = operand_rd(inst); |
| 3060 | dec->rs1 = operand_rs1(inst); |
| 3061 | dec->imm = operand_immh(inst); |
| 3062 | dec->imm1 = operand_imml(inst); |
| 3063 | break; |
| 3064 | case rv_codec_r2_imm2_imm5: |
| 3065 | dec->rd = operand_rd(inst); |
| 3066 | dec->rs1 = operand_rs1(inst); |
| 3067 | dec->imm = sextract32(operand_rs2(inst), 0, 5); |
| 3068 | dec->imm1 = operand_imm2(inst); |
| 3069 | break; |
| 3070 | case rv_codec_lp: |
| 3071 | dec->imm = operand_lpl(inst); |
| 3072 | break; |
| 3073 | case rv_codec_cmop: |
| 3074 | dec->imm = operand_cmop_imm(inst); |
| 3075 | break; |
| 3076 | case rv_codec_cmop_ss: |
| 3077 | dec->rd = rv_ireg_zero; |
| 3078 | dec->rs1 = dec->rs2 = operand_crs1(inst); |
| 3079 | dec->imm = 0; |
| 3080 | break; |
| 3081 | case rv_codec_mop_r: |
| 3082 | dec->rd = operand_rd(inst); |
| 3083 | dec->rs1 = operand_rs1(inst); |
| 3084 | dec->imm = operand_mop_r_imm(inst); |
| 3085 | break; |
| 3086 | case rv_codec_mop_rr: |
| 3087 | dec->rd = operand_rd(inst); |
| 3088 | dec->rs1 = operand_rs1(inst); |
| 3089 | dec->rs2 = operand_rs2(inst); |
| 3090 | dec->imm = operand_mop_rr_imm(inst); |
| 3091 | break; |
| 3092 | default: |
| 3093 | g_assert_not_reached(); |
| 3094 | } |
| 3095 | } |
| 3096 | |
| 3097 | /* check constraint */ |
| 3098 | |
| 3099 | static bool check_constraints(rv_decode *dec, const rvc_constraint *c) |
| 3100 | { |
| 3101 | int32_t imm = dec->imm; |
| 3102 | uint8_t rd = dec->rd, rs1 = dec->rs1, rs2 = dec->rs2; |
| 3103 | while (*c != rvc_end) { |
| 3104 | switch (*c) { |
| 3105 | case rvc_rd_eq_ra: |
| 3106 | if (!(rd == 1)) { |
| 3107 | return false; |
| 3108 | } |
| 3109 | break; |
| 3110 | case rvc_rd_eq_x0: |
| 3111 | if (!(rd == 0)) { |
| 3112 | return false; |
| 3113 | } |
| 3114 | break; |
| 3115 | case rvc_rs1_eq_x0: |
| 3116 | if (!(rs1 == 0)) { |
| 3117 | return false; |
| 3118 | } |
| 3119 | break; |
| 3120 | case rvc_rs2_eq_x0: |
| 3121 | if (!(rs2 == 0)) { |
| 3122 | return false; |
| 3123 | } |
| 3124 | break; |
| 3125 | case rvc_rs2_eq_rs1: |
| 3126 | if (!(rs2 == rs1)) { |
| 3127 | return false; |
| 3128 | } |
| 3129 | break; |
| 3130 | case rvc_rs1_eq_ra: |
| 3131 | if (!(rs1 == 1)) { |
| 3132 | return false; |
| 3133 | } |
| 3134 | break; |
| 3135 | case rvc_imm_eq_zero: |
| 3136 | if (!(imm == 0)) { |
| 3137 | return false; |
| 3138 | } |
| 3139 | break; |
| 3140 | case rvc_imm_eq_n1: |
| 3141 | if (!(imm == -1)) { |
| 3142 | return false; |
| 3143 | } |
| 3144 | break; |
| 3145 | case rvc_imm_eq_p1: |
| 3146 | if (!(imm == 1)) { |
| 3147 | return false; |
| 3148 | } |
| 3149 | break; |
| 3150 | default: break; |
| 3151 | } |
| 3152 | c++; |
| 3153 | } |
| 3154 | return true; |
| 3155 | } |
| 3156 | |
| 3157 | /* Same as insn_len() from target/riscv/internals.h */ |
| 3158 | static size_t inst_length(rv_inst inst) |
| 3159 | { |
| 3160 | return (inst & 3) == 3 ? 4 : 2; |
| 3161 | } |
| 3162 | |
| 3163 | /* format instruction */ |
| 3164 | |
| 3165 | static GString *format_inst(size_t tab, rv_decode *dec, |
| 3166 | const rv_opcode_data *op) |
| 3167 | { |
| 3168 | GString *buf = g_string_sized_new(64); |
| 3169 | const char *fmt = op->format; |
| 3170 | |
| 3171 | while (*fmt) { |
| 3172 | switch (*fmt) { |
| 3173 | case 'O': |
| 3174 | g_string_append(buf, op->name); |
| 3175 | break; |
| 3176 | case '(': |
| 3177 | case '.': |
| 3178 | case ',': |
| 3179 | case ')': |
| 3180 | case '-': |
| 3181 | g_string_append_c(buf, *fmt); |
| 3182 | break; |
| 3183 | case 'b': |
| 3184 | g_string_append_printf(buf, "%d", dec->bs); |
| 3185 | break; |
| 3186 | case 'n': |
| 3187 | g_string_append_printf(buf, "%d", dec->rnum); |
| 3188 | break; |
| 3189 | case '0': |
| 3190 | g_string_append(buf, rv_ireg_name_sym[dec->rd]); |
| 3191 | break; |
| 3192 | case '1': |
| 3193 | g_string_append(buf, rv_ireg_name_sym[dec->rs1]); |
| 3194 | break; |
| 3195 | case '2': |
| 3196 | g_string_append(buf, rv_ireg_name_sym[dec->rs2]); |
| 3197 | break; |
| 3198 | case '3': |
| 3199 | if (dec->cfg && dec->cfg->ext_zfinx) { |
| 3200 | g_string_append(buf, rv_ireg_name_sym[dec->rd]); |
| 3201 | } else { |
| 3202 | g_string_append(buf, rv_freg_name_sym[dec->rd]); |
| 3203 | } |
| 3204 | break; |
| 3205 | case '4': |
| 3206 | if (dec->cfg && dec->cfg->ext_zfinx) { |
| 3207 | g_string_append(buf, rv_ireg_name_sym[dec->rs1]); |
| 3208 | } else { |
| 3209 | g_string_append(buf, rv_freg_name_sym[dec->rs1]); |
| 3210 | } |
| 3211 | break; |
| 3212 | case '5': |
| 3213 | if (dec->cfg && dec->cfg->ext_zfinx) { |
| 3214 | g_string_append(buf, rv_ireg_name_sym[dec->rs2]); |
| 3215 | } else { |
| 3216 | g_string_append(buf, rv_freg_name_sym[dec->rs2]); |
| 3217 | } |
| 3218 | break; |
| 3219 | case '6': |
| 3220 | if (dec->cfg && dec->cfg->ext_zfinx) { |
| 3221 | g_string_append(buf, rv_ireg_name_sym[dec->rs3]); |
| 3222 | } else { |
| 3223 | g_string_append(buf, rv_freg_name_sym[dec->rs3]); |
| 3224 | } |
| 3225 | break; |
| 3226 | case '7': |
| 3227 | g_string_append_printf(buf, "%d", dec->rs1); |
| 3228 | break; |
| 3229 | case 'i': |
| 3230 | g_string_append_printf(buf, "%d", dec->imm); |
| 3231 | break; |
| 3232 | case 'u': |
| 3233 | g_string_append_printf(buf, "%u", ((uint32_t)dec->imm & 0b111111)); |
| 3234 | break; |
| 3235 | case 'j': |
| 3236 | g_string_append_printf(buf, "%d", dec->imm1); |
| 3237 | break; |
| 3238 | case 'o': |
| 3239 | g_string_append_printf(buf, "%d", dec->imm); |
| 3240 | while (buf->len < tab * 2) { |
| 3241 | g_string_append_c(buf, ' '); |
| 3242 | } |
| 3243 | g_string_append_printf(buf, "# 0x%" PRIx64, dec->pc + dec->imm); |
| 3244 | break; |
| 3245 | case 'U': |
| 3246 | fmt++; |
| 3247 | g_string_append_printf(buf, "%d", dec->imm >> 12); |
| 3248 | if (*fmt == 'o') { |
| 3249 | while (buf->len < tab * 2) { |
| 3250 | g_string_append_c(buf, ' '); |
| 3251 | } |
| 3252 | g_string_append_printf(buf, "# 0x%" PRIx64, dec->pc + dec->imm); |
| 3253 | } |
| 3254 | break; |
| 3255 | case 'c': { |
| 3256 | const char *name = csr_name(dec->imm & 0xfff); |
| 3257 | if (name) { |
| 3258 | g_string_append(buf, name); |
| 3259 | } else { |
| 3260 | g_string_append_printf(buf, "0x%03x", dec->imm & 0xfff); |
| 3261 | } |
| 3262 | break; |
| 3263 | } |
| 3264 | case 'r': |
| 3265 | switch (dec->rm) { |
| 3266 | case rv_rm_rne: |
| 3267 | g_string_append(buf, "rne"); |
| 3268 | break; |
| 3269 | case rv_rm_rtz: |
| 3270 | g_string_append(buf, "rtz"); |
| 3271 | break; |
| 3272 | case rv_rm_rdn: |
| 3273 | g_string_append(buf, "rdn"); |
| 3274 | break; |
| 3275 | case rv_rm_rup: |
| 3276 | g_string_append(buf, "rup"); |
| 3277 | break; |
| 3278 | case rv_rm_rmm: |
| 3279 | g_string_append(buf, "rmm"); |
| 3280 | break; |
| 3281 | case rv_rm_dyn: |
| 3282 | g_string_append(buf, "dyn"); |
| 3283 | break; |
| 3284 | default: |
| 3285 | g_string_append(buf, "inv"); |
| 3286 | break; |
| 3287 | } |
| 3288 | break; |
| 3289 | case 'p': |
| 3290 | if (dec->pred & rv_fence_i) { |
| 3291 | g_string_append_c(buf, 'i'); |
| 3292 | } |
| 3293 | if (dec->pred & rv_fence_o) { |
| 3294 | g_string_append_c(buf, 'o'); |
| 3295 | } |
| 3296 | if (dec->pred & rv_fence_r) { |
| 3297 | g_string_append_c(buf, 'r'); |
| 3298 | } |
| 3299 | if (dec->pred & rv_fence_w) { |
| 3300 | g_string_append_c(buf, 'w'); |
| 3301 | } |
| 3302 | break; |
| 3303 | case 's': |
| 3304 | if (dec->succ & rv_fence_i) { |
| 3305 | g_string_append_c(buf, 'i'); |
| 3306 | } |
| 3307 | if (dec->succ & rv_fence_o) { |
| 3308 | g_string_append_c(buf, 'o'); |
| 3309 | } |
| 3310 | if (dec->succ & rv_fence_r) { |
| 3311 | g_string_append_c(buf, 'r'); |
| 3312 | } |
| 3313 | if (dec->succ & rv_fence_w) { |
| 3314 | g_string_append_c(buf, 'w'); |
| 3315 | } |
| 3316 | break; |
| 3317 | case '\t': |
| 3318 | while (buf->len < tab) { |
| 3319 | g_string_append_c(buf, ' '); |
| 3320 | } |
| 3321 | break; |
| 3322 | case 'A': |
| 3323 | if (dec->aq) { |
| 3324 | g_string_append(buf, ".aq"); |
| 3325 | } |
| 3326 | break; |
| 3327 | case 'R': |
| 3328 | if (dec->rl) { |
| 3329 | g_string_append(buf, ".rl"); |
| 3330 | } |
| 3331 | break; |
| 3332 | case 'l': |
| 3333 | g_string_append(buf, ",v0"); |
| 3334 | break; |
| 3335 | case 'm': |
| 3336 | if (dec->vm == 0) { |
| 3337 | g_string_append(buf, ",v0.t"); |
| 3338 | } |
| 3339 | break; |
| 3340 | case 'D': |
| 3341 | g_string_append(buf, rv_vreg_name_sym[dec->rd]); |
| 3342 | break; |
| 3343 | case 'E': |
| 3344 | g_string_append(buf, rv_vreg_name_sym[dec->rs1]); |
| 3345 | break; |
| 3346 | case 'F': |
| 3347 | g_string_append(buf, rv_vreg_name_sym[dec->rs2]); |
| 3348 | break; |
| 3349 | case 'G': |
| 3350 | g_string_append(buf, rv_vreg_name_sym[dec->rs3]); |
| 3351 | break; |
| 3352 | case 'v': { |
| 3353 | const int sew = 1 << (((dec->vzimm >> 3) & 0b111) + 3); |
| 3354 | const int lmul = dec->vzimm & 0b11; |
| 3355 | const int flmul = (dec->vzimm >> 2) & 1; |
| 3356 | const char *vta = (dec->vzimm >> 6) & 1 ? "ta" : "tu"; |
| 3357 | const char *vma = (dec->vzimm >> 7) & 1 ? "ma" : "mu"; |
| 3358 | |
| 3359 | g_string_append_printf(buf, "e%d,m", sew); |
| 3360 | if (flmul) { |
| 3361 | switch (lmul) { |
| 3362 | case 3: |
| 3363 | g_string_append(buf, "f2"); |
| 3364 | break; |
| 3365 | case 2: |
| 3366 | g_string_append(buf, "f4"); |
| 3367 | break; |
| 3368 | case 1: |
| 3369 | g_string_append(buf, "f8"); |
| 3370 | break; |
| 3371 | } |
| 3372 | } else { |
| 3373 | g_string_append_printf(buf, "%d", 1 << lmul); |
| 3374 | } |
| 3375 | g_string_append_c(buf, ','); |
| 3376 | g_string_append(buf, vta); |
| 3377 | g_string_append_c(buf, ','); |
| 3378 | g_string_append(buf, vma); |
| 3379 | break; |
| 3380 | } |
| 3381 | case 'x': { |
| 3382 | switch (dec->rlist) { |
| 3383 | case 4: |
| 3384 | g_string_append(buf, "{ra}"); |
| 3385 | break; |
| 3386 | case 5: |
| 3387 | g_string_append(buf, "{ra, s0}"); |
| 3388 | break; |
| 3389 | case 15: |
| 3390 | g_string_append(buf, "{ra, s0-s11}"); |
| 3391 | break; |
| 3392 | default: |
| 3393 | g_string_append_printf(buf, "{ra, s0-s%d}", dec->rlist - 5); |
| 3394 | break; |
| 3395 | } |
| 3396 | break; |
| 3397 | } |
| 3398 | case 'h': |
| 3399 | g_string_append(buf, rv_fli_name_const[dec->imm]); |
| 3400 | break; |
| 3401 | default: |
| 3402 | break; |
| 3403 | } |
| 3404 | fmt++; |
| 3405 | } |
| 3406 | |
| 3407 | return buf; |
| 3408 | } |
| 3409 | |
| 3410 | /* lift instruction to pseudo-instruction */ |
| 3411 | |
| 3412 | static const rv_opcode_data *decode_inst_lift_pseudo(rv_decode *dec, |
| 3413 | const rv_opcode_data *op) |
| 3414 | { |
| 3415 | const rv_comp_data *comp_data = op->pseudo; |
| 3416 | if (comp_data) { |
| 3417 | while (comp_data->constraints) { |
| 3418 | if (check_constraints(dec, comp_data->constraints)) { |
| 3419 | assert(op != comp_data->op); |
| 3420 | return decode_inst_lift_pseudo(dec, comp_data->op); |
| 3421 | } |
| 3422 | comp_data++; |
| 3423 | } |
| 3424 | } |
| 3425 | return op; |
| 3426 | } |
| 3427 | |
| 3428 | /* disassemble instruction */ |
| 3429 | |
| 3430 | static GString *disasm_inst(rv_isa isa, uint64_t pc, rv_inst inst, |
| 3431 | const RISCVCPUConfig *cfg) |
| 3432 | { |
| 3433 | rv_decode dec = { |
| 3434 | .pc = pc, |
| 3435 | .inst = inst, |
| 3436 | .cfg = cfg, |
| 3437 | }; |
| 3438 | const rv_opcode_data *op = decode_inst_opcode(&dec, isa); |
| 3439 | |
| 3440 | if (!op && cfg) { |
| 3441 | static const struct { |
| 3442 | bool (*guard_func)(const RISCVCPUConfig *); |
| 3443 | const rv_opcode_data *(*decode_func)(rv_decode *, rv_isa); |
| 3444 | } decoders[] = { |
| 3445 | { has_xtheadba_p, decode_xtheadba }, |
| 3446 | { has_xtheadbb_p, decode_xtheadbb }, |
| 3447 | { has_xtheadbs_p, decode_xtheadbs }, |
| 3448 | { has_xtheadcmo_p, decode_xtheadcmo }, |
| 3449 | { has_xtheadcondmov_p, decode_xtheadcondmov }, |
| 3450 | { has_xtheadfmemidx_p, decode_xtheadfmemidx }, |
| 3451 | { has_xtheadfmv_p, decode_xtheadfmv }, |
| 3452 | { has_xtheadmac_p, decode_xtheadmac }, |
| 3453 | { has_xtheadmemidx_p, decode_xtheadmemidx }, |
| 3454 | { has_xtheadmempair_p, decode_xtheadmempair }, |
| 3455 | { has_xtheadsync_p, decode_xtheadsync }, |
| 3456 | { has_XVentanaCondOps_p, decode_xventanacondops }, |
| 3457 | { has_xlrbr_p, decode_xlrbr }, |
| 3458 | }; |
| 3459 | |
| 3460 | for (size_t i = 0; i < ARRAY_SIZE(decoders); i++) { |
| 3461 | if (decoders[i].guard_func(cfg)) { |
| 3462 | op = decoders[i].decode_func(&dec, isa); |
| 3463 | if (op) { |
| 3464 | break; |
| 3465 | } |
| 3466 | } |
| 3467 | } |
| 3468 | } |
| 3469 | |
| 3470 | if (op) { |
| 3471 | decode_inst_operands(&dec, isa, op); |
| 3472 | op = decode_inst_lift_pseudo(&dec, op); |
| 3473 | } else { |
| 3474 | op = &op_illegal; |
| 3475 | } |
| 3476 | |
| 3477 | return format_inst(24, &dec, op); |
| 3478 | } |
| 3479 | |
| 3480 | #define INST_FMT_2 "%04x " |
| 3481 | #define INST_FMT_4 "%08x " |
| 3482 | |
| 3483 | static int |
| 3484 | print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa) |
| 3485 | { |
| 3486 | bfd_byte packet[2]; |
| 3487 | rv_inst inst = 0; |
| 3488 | size_t len = 2; |
| 3489 | bfd_vma n; |
| 3490 | int status; |
| 3491 | |
| 3492 | /* Instructions are made of 2-byte packets in little-endian order */ |
| 3493 | for (n = 0; n < len; n += 2) { |
| 3494 | status = (*info->read_memory_func)(memaddr + n, packet, 2, info); |
| 3495 | if (status != 0) { |
| 3496 | /* Don't fail just because we fell off the end. */ |
| 3497 | if (n > 0) { |
| 3498 | break; |
| 3499 | } |
| 3500 | (*info->memory_error_func)(status, memaddr, info); |
| 3501 | return status; |
| 3502 | } |
| 3503 | inst |= ((rv_inst) bfd_getl16(packet)) << (8 * n); |
| 3504 | if (n == 0) { |
| 3505 | len = inst_length(inst); |
| 3506 | } |
| 3507 | } |
| 3508 | |
| 3509 | if (info->show_opcodes) { |
| 3510 | switch (len) { |
| 3511 | case 2: |
| 3512 | (*info->fprintf_func)(info->stream, INST_FMT_2, inst); |
| 3513 | break; |
| 3514 | case 4: |
| 3515 | (*info->fprintf_func)(info->stream, INST_FMT_4, inst); |
| 3516 | break; |
| 3517 | default: |
| 3518 | g_assert_not_reached(); |
| 3519 | } |
| 3520 | } |
| 3521 | |
| 3522 | g_autoptr(GString) str = |
| 3523 | disasm_inst(isa, memaddr, inst, |
| 3524 | (const RISCVCPUConfig *)info->target_info); |
| 3525 | (*info->fprintf_func)(info->stream, "%s", str->str); |
| 3526 | |
| 3527 | return len; |
| 3528 | } |
| 3529 | |
| 3530 | int print_insn_riscv32(bfd_vma memaddr, struct disassemble_info *info) |
| 3531 | { |
| 3532 | return print_insn_riscv(memaddr, info, rv32); |
| 3533 | } |
| 3534 | |
| 3535 | int print_insn_riscv64(bfd_vma memaddr, struct disassemble_info *info) |
| 3536 | { |
| 3537 | return print_insn_riscv(memaddr, info, rv64); |
| 3538 | } |
| 3539 | |
| 3540 | int print_insn_riscv128(bfd_vma memaddr, struct disassemble_info *info) |
| 3541 | { |
| 3542 | return print_insn_riscv(memaddr, info, rv128); |
| 3543 | } |