diff --git a/librz/arch/isa_gnu/riscv/riscv-opc.c b/librz/arch/isa_gnu/riscv/riscv-opc.c
deleted file mode 100644
index 707028d6cbd..00000000000
--- a/librz/arch/isa_gnu/riscv/riscv-opc.c
+++ /dev/null
@@ -1,688 +0,0 @@
-// SPDX-FileCopyrightText: 2011-2015 Free Software Foundation, Inc.
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-/* RISC-V opcode list
- Copyright 2011-2015 Free Software Foundation, Inc.
-
- Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
- Based on MIPS target.
-
- This file is part of the GNU opcodes library.
-
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- It is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING3. If not,
- see . */
-
-#include "riscv.h"
-#include
-
-/* Register names used by gas and objdump. */
-
-static const char * const riscv_gpr_names_numeric[NGPR] =
-{
- "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
- "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
- "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
- "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31"
-};
-
-static const char * const riscv_gpr_names_abi[NGPR] = {
- "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
- "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
- "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
- "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
-};
-
-static const char * const riscv_fpr_names_numeric[NFPR] =
-{
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
-};
-
-static const char * const riscv_fpr_names_abi[NFPR] = {
- "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
- "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
- "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
- "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"
-};
-
-/* The order of overloaded instructions matters. Label arguments and
- register arguments look the same. Instructions that can have either
- for arguments must apear in the correct order in this table for the
- assembler to pick the right one. In other words, entries with
- immediate operands must apear after the same instruction with
- registers.
-
- Because of the lookup algorithm used, entries with the same opcode
- name must be contiguous. */
-
-#define MASK_RS1 (OP_MASK_RS1 << OP_SH_RS1)
-#define MASK_RS2 (OP_MASK_RS2 << OP_SH_RS2)
-#define MASK_RD (OP_MASK_RD << OP_SH_RD)
-#define MASK_CRS2 (OP_MASK_CRS2 << OP_SH_CRS2)
-#define MASK_IMM ENCODE_ITYPE_IMM (-1U)
-#define MASK_RVC_IMM ENCODE_RVC_IMM (-1U)
-#define MASK_UIMM ENCODE_UTYPE_IMM (-1U)
-#define MASK_RM (OP_MASK_RM << OP_SH_RM)
-#define MASK_PRED (OP_MASK_PRED << OP_SH_PRED)
-#define MASK_SUCC (OP_MASK_SUCC << OP_SH_SUCC)
-#define MASK_AQ (OP_MASK_AQ << OP_SH_AQ)
-#define MASK_RL (OP_MASK_RL << OP_SH_RL)
-#define MASK_AQRL (MASK_AQ | MASK_RL)
-
-static int match_opcode(const struct riscv_opcode *op, insn_t insn)
-{
- return ((insn ^ op->match) & op->mask) == 0;
-}
-
-static int match_never(const struct riscv_opcode *op, insn_t insn)
-{
- return 0;
-}
-
-static int match_rs1_eq_rs2(const struct riscv_opcode *op, insn_t insn)
-{
- int rs1 = (insn & MASK_RS1) >> OP_SH_RS1;
- int rs2 = (insn & MASK_RS2) >> OP_SH_RS2;
- return match_opcode (op, insn) && rs1 == rs2;
-}
-
-static int match_rd_nonzero(const struct riscv_opcode *op, insn_t insn)
-{
- return match_opcode (op, insn) && ((insn & MASK_RD) != 0);
-}
-
-static int match_c_add(const struct riscv_opcode *op, insn_t insn)
-{
- return match_rd_nonzero (op, insn) && ((insn & MASK_CRS2) != 0);
-}
-
-static int match_c_lui(const struct riscv_opcode *op, insn_t insn)
-{
- return match_rd_nonzero (op, insn) && (((insn & MASK_RD) >> OP_SH_RD) != 2);
-}
-
-static const struct riscv_opcode riscv_builtin_opcodes[] =
-{
-/* name, isa, operands, match, mask, match_func, pinfo. */
-{"illegal", "C", "", 0, 0xffffU, match_opcode, 0 },
-{"unimp", "I", "", MATCH_CSRRW | (CSR_CYCLE << OP_SH_CSR), 0xffffffffU, match_opcode, 0 }, /* csrw cycle, x0 */
-{"ebreak", "C", "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS },
-{"ebreak", "I", "", MATCH_EBREAK, MASK_EBREAK, match_opcode, 0 },
-{"sbreak", "C", "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, INSN_ALIAS },
-{"sbreak", "I", "", MATCH_EBREAK, MASK_EBREAK, match_opcode, INSN_ALIAS },
-{"ret", "C", "", MATCH_C_JR | (X_RA << OP_SH_RD), MASK_C_JR | MASK_RD, match_opcode, INSN_ALIAS },
-{"ret", "I", "", MATCH_JALR | (X_RA << OP_SH_RS1), MASK_JALR | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, INSN_ALIAS },
-{"jr", "C", "d", MATCH_C_JR, MASK_C_JR, match_rd_nonzero, INSN_ALIAS },
-{"jr", "I", "s", MATCH_JALR, MASK_JALR | MASK_RD | MASK_IMM, match_opcode, INSN_ALIAS },
-{"jr", "I", "o(s)", MATCH_JALR, MASK_JALR | MASK_RD, match_opcode, INSN_ALIAS },
-{"jr", "I", "s,j", MATCH_JALR, MASK_JALR | MASK_RD, match_opcode, INSN_ALIAS },
-{"jalr", "C", "d", MATCH_C_JALR, MASK_C_JALR, match_rd_nonzero, INSN_ALIAS },
-{"jalr", "I", "s", MATCH_JALR | (X_RA << OP_SH_RD), MASK_JALR | MASK_RD | MASK_IMM, match_opcode, INSN_ALIAS },
-{"jalr", "I", "o(s)", MATCH_JALR | (X_RA << OP_SH_RD), MASK_JALR | MASK_RD, match_opcode, INSN_ALIAS },
-{"jalr", "I", "s,j", MATCH_JALR | (X_RA << OP_SH_RD), MASK_JALR | MASK_RD, match_opcode, INSN_ALIAS },
-{"jalr", "I", "d,s", MATCH_JALR, MASK_JALR | MASK_IMM, match_opcode, INSN_ALIAS },
-{"jalr", "I", "d,o(s)", MATCH_JALR, MASK_JALR, match_opcode, 0 },
-{"jalr", "I", "d,s,j", MATCH_JALR, MASK_JALR, match_opcode, 0 },
-{"j", "C", "Ca", MATCH_C_J, MASK_C_J, match_opcode, INSN_ALIAS },
-{"j", "I", "a", MATCH_JAL, MASK_JAL | MASK_RD, match_opcode, INSN_ALIAS },
-{"jal", "I", "d,a", MATCH_JAL, MASK_JAL, match_opcode, 0 },
-{"jal", "32C", "Ca", MATCH_C_JAL, MASK_C_JAL, match_opcode, INSN_ALIAS },
-{"jal", "I", "a", MATCH_JAL | (X_RA << OP_SH_RD), MASK_JAL | MASK_RD, match_opcode, INSN_ALIAS },
-{"call", "I", "d,c", (X_T1 << OP_SH_RS1), (int) M_CALL, match_never, INSN_MACRO },
-{"call", "I", "c", (X_T1 << OP_SH_RS1) | (X_RA << OP_SH_RD), (int) M_CALL, match_never, INSN_MACRO },
-{"tail", "I", "c", (X_T1 << OP_SH_RS1), (int) M_CALL, match_never, INSN_MACRO },
-{"jump", "I", "c,s", 0, (int) M_CALL, match_never, INSN_MACRO },
-{"nop", "C", "", MATCH_C_ADDI, 0xffff, match_opcode, INSN_ALIAS },
-{"nop", "I", "", MATCH_ADDI, MASK_ADDI | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, INSN_ALIAS },
-{"lui", "C", "d,Cu", MATCH_C_LUI, MASK_C_LUI, match_c_lui, INSN_ALIAS },
-{"lui", "I", "d,u", MATCH_LUI, MASK_LUI, match_opcode, 0 },
-{"li", "C", "d,Cv", MATCH_C_LUI, MASK_C_LUI, match_c_lui, INSN_ALIAS },
-{"li", "C", "d,Cj", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, INSN_ALIAS },
-{"li", "C", "d,0", MATCH_C_LI, MASK_C_LI | MASK_RVC_IMM, match_rd_nonzero, INSN_ALIAS },
-{"li", "I", "d,j", MATCH_ADDI, MASK_ADDI | MASK_RS1, match_opcode, INSN_ALIAS }, /* addi */
-{"li", "I", "d,I", 0, (int) M_LI, match_never, INSN_MACRO },
-{"mv", "C", "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS },
-{"mv", "I", "d,s", MATCH_ADDI, MASK_ADDI | MASK_IMM, match_opcode, INSN_ALIAS },
-{"move", "C", "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, INSN_ALIAS },
-{"move", "I", "d,s", MATCH_ADDI, MASK_ADDI | MASK_IMM, match_opcode, INSN_ALIAS },
-{"andi", "C", "Cs,Cw,Cj", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS },
-{"andi", "I", "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, 0 },
-{"and", "C", "Cs,Cw,Ct", MATCH_C_AND, MASK_C_AND, match_opcode, INSN_ALIAS },
-{"and", "C", "Cs,Ct,Cw", MATCH_C_AND, MASK_C_AND, match_opcode, INSN_ALIAS },
-{"and", "C", "Cs,Cw,Cj", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, INSN_ALIAS },
-{"and", "I", "d,s,t", MATCH_AND, MASK_AND, match_opcode, 0 },
-{"and", "I", "d,s,j", MATCH_ANDI, MASK_ANDI, match_opcode, INSN_ALIAS },
-{"beqz", "C", "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, INSN_ALIAS },
-{"beqz", "I", "s,p", MATCH_BEQ, MASK_BEQ | MASK_RS2, match_opcode, INSN_ALIAS },
-{"beq", "I", "s,t,p", MATCH_BEQ, MASK_BEQ, match_opcode, 0 },
-{"blez", "I", "t,p", MATCH_BGE, MASK_BGE | MASK_RS1, match_opcode, INSN_ALIAS },
-{"bgez", "I", "s,p", MATCH_BGE, MASK_BGE | MASK_RS2, match_opcode, INSN_ALIAS },
-{"ble", "I", "t,s,p", MATCH_BGE, MASK_BGE, match_opcode, INSN_ALIAS },
-{"bleu", "I", "t,s,p", MATCH_BGEU, MASK_BGEU, match_opcode, INSN_ALIAS },
-{"bge", "I", "s,t,p", MATCH_BGE, MASK_BGE, match_opcode, 0 },
-{"bgeu", "I", "s,t,p", MATCH_BGEU, MASK_BGEU, match_opcode, 0 },
-{"bltz", "I", "s,p", MATCH_BLT, MASK_BLT | MASK_RS2, match_opcode, INSN_ALIAS },
-{"bgtz", "I", "t,p", MATCH_BLT, MASK_BLT | MASK_RS1, match_opcode, INSN_ALIAS },
-{"blt", "I", "s,t,p", MATCH_BLT, MASK_BLT, match_opcode, 0 },
-{"bltu", "I", "s,t,p", MATCH_BLTU, MASK_BLTU, match_opcode, 0 },
-{"bgt", "I", "t,s,p", MATCH_BLT, MASK_BLT, match_opcode, INSN_ALIAS },
-{"bgtu", "I", "t,s,p", MATCH_BLTU, MASK_BLTU, match_opcode, INSN_ALIAS },
-{"bnez", "C", "Cs,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, INSN_ALIAS },
-{"bnez", "I", "s,p", MATCH_BNE, MASK_BNE | MASK_RS2, match_opcode, INSN_ALIAS },
-{"bne", "I", "s,t,p", MATCH_BNE, MASK_BNE, match_opcode, 0 },
-{"addi", "C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_opcode, INSN_ALIAS },
-{"addi", "C", "d,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
-{"addi", "C", "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_opcode, INSN_ALIAS },
-{"addi", "I", "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, 0 },
-{"add", "C", "d,CU,CV", MATCH_C_ADD, MASK_C_ADD, match_c_add, INSN_ALIAS },
-{"add", "C", "d,CV,CU", MATCH_C_ADD, MASK_C_ADD, match_c_add, INSN_ALIAS },
-{"add", "C", "d,CU,Cj", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, INSN_ALIAS },
-{"add", "C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_opcode, INSN_ALIAS },
-{"add", "C", "Cc,Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_opcode, INSN_ALIAS },
-{"add", "I", "d,s,t", MATCH_ADD, MASK_ADD, match_opcode, 0 },
-{"add", "I", "d,s,t,0",MATCH_ADD, MASK_ADD, match_opcode, 0 },
-{"add", "I", "d,s,j", MATCH_ADDI, MASK_ADDI, match_opcode, INSN_ALIAS },
-{"la", "I", "d,A", 0, (int) M_LA, match_never, INSN_MACRO },
-{"lla", "I", "d,A", 0, (int) M_LLA, match_never, INSN_MACRO },
-{"la.tls.gd", "I", "d,A", 0, (int) M_LA_TLS_GD, match_never, INSN_MACRO },
-{"la.tls.ie", "I", "d,A", 0, (int) M_LA_TLS_IE, match_never, INSN_MACRO },
-{"neg", "I", "d,t", MATCH_SUB, MASK_SUB | MASK_RS1, match_opcode, INSN_ALIAS }, /* sub 0 */
-{"slli", "C", "d,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_rd_nonzero, INSN_ALIAS },
-{"slli", "I", "d,s,>", MATCH_SLLI, MASK_SLLI, match_opcode, 0 },
-{"sll", "C", "d,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_rd_nonzero, INSN_ALIAS },
-{"sll", "I", "d,s,t", MATCH_SLL, MASK_SLL, match_opcode, 0 },
-{"sll", "I", "d,s,>", MATCH_SLLI, MASK_SLLI, match_opcode, INSN_ALIAS },
-{"srli", "C", "Cs,Cw,C>", MATCH_C_SRLI, MASK_C_SRLI, match_rd_nonzero, INSN_ALIAS },
-{"srli", "I", "d,s,>", MATCH_SRLI, MASK_SRLI, match_opcode, 0 },
-{"srl", "C", "Cs,Cw,C>", MATCH_C_SRLI, MASK_C_SRLI, match_rd_nonzero, INSN_ALIAS },
-{"srl", "I", "d,s,t", MATCH_SRL, MASK_SRL, match_opcode, 0 },
-{"srl", "I", "d,s,>", MATCH_SRLI, MASK_SRLI, match_opcode, INSN_ALIAS },
-{"srai", "C", "Cs,Cw,C>", MATCH_C_SRAI, MASK_C_SRAI, match_rd_nonzero, INSN_ALIAS },
-{"srai", "I", "d,s,>", MATCH_SRAI, MASK_SRAI, match_opcode, 0 },
-{"sra", "C", "Cs,Cw,C>", MATCH_C_SRAI, MASK_C_SRAI, match_rd_nonzero, INSN_ALIAS },
-{"sra", "I", "d,s,t", MATCH_SRA, MASK_SRA, match_opcode, 0 },
-{"sra", "I", "d,s,>", MATCH_SRAI, MASK_SRAI, match_opcode, INSN_ALIAS },
-{"sub", "C", "Cs,Cw,Ct", MATCH_C_SUB, MASK_C_SUB, match_opcode, INSN_ALIAS },
-{"sub", "I", "d,s,t", MATCH_SUB, MASK_SUB, match_opcode, 0 },
-{"lb", "I", "d,o(s)", MATCH_LB, MASK_LB, match_opcode, 0 },
-{"lb", "I", "d,A", 0, (int) M_LB, match_never, INSN_MACRO },
-{"lbu", "I", "d,o(s)", MATCH_LBU, MASK_LBU, match_opcode, 0 },
-{"lbu", "I", "d,A", 0, (int) M_LBU, match_never, INSN_MACRO },
-{"lh", "I", "d,o(s)", MATCH_LH, MASK_LH, match_opcode, 0 },
-{"lh", "I", "d,A", 0, (int) M_LH, match_never, INSN_MACRO },
-{"lhu", "I", "d,o(s)", MATCH_LHU, MASK_LHU, match_opcode, 0 },
-{"lhu", "I", "d,A", 0, (int) M_LHU, match_never, INSN_MACRO },
-{"lw", "C", "d,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_rd_nonzero, INSN_ALIAS },
-{"lw", "C", "Ct,Ck(Cs)", MATCH_C_LW, MASK_C_LW, match_opcode, INSN_ALIAS },
-{"lw", "I", "d,o(s)", MATCH_LW, MASK_LW, match_opcode, 0 },
-{"lw", "I", "d,A", 0, (int) M_LW, match_never, INSN_MACRO },
-{"not", "I", "d,s", MATCH_XORI | MASK_IMM, MASK_XORI | MASK_IMM, match_opcode, INSN_ALIAS },
-{"ori", "I", "d,s,j", MATCH_ORI, MASK_ORI, match_opcode, 0 },
-{"or", "C", "Cs,Cw,Ct", MATCH_C_OR, MASK_C_OR, match_opcode, INSN_ALIAS },
-{"or", "C", "Cs,Ct,Cw", MATCH_C_OR, MASK_C_OR, match_opcode, INSN_ALIAS },
-{"or", "I", "d,s,t", MATCH_OR, MASK_OR, match_opcode, 0 },
-{"or", "I", "d,s,j", MATCH_ORI, MASK_ORI, match_opcode, INSN_ALIAS },
-{"auipc", "I", "d,u", MATCH_AUIPC, MASK_AUIPC, match_opcode, 0 },
-{"seqz", "I", "d,s", MATCH_SLTIU | ENCODE_ITYPE_IMM (1), MASK_SLTIU | MASK_IMM, match_opcode, INSN_ALIAS },
-{"snez", "I", "d,t", MATCH_SLTU, MASK_SLTU | MASK_RS1, match_opcode, INSN_ALIAS },
-{"sltz", "I", "d,s", MATCH_SLT, MASK_SLT | MASK_RS2, match_opcode, INSN_ALIAS },
-{"sgtz", "I", "d,t", MATCH_SLT, MASK_SLT | MASK_RS1, match_opcode, INSN_ALIAS },
-{"slti", "I", "d,s,j", MATCH_SLTI, MASK_SLTI, match_opcode, INSN_ALIAS },
-{"slt", "I", "d,s,t", MATCH_SLT, MASK_SLT, match_opcode, 0 },
-{"slt", "I", "d,s,j", MATCH_SLTI, MASK_SLTI, match_opcode, 0 },
-{"sltiu", "I", "d,s,j", MATCH_SLTIU, MASK_SLTIU, match_opcode, 0 },
-{"sltu", "I", "d,s,t", MATCH_SLTU, MASK_SLTU, match_opcode, 0 },
-{"sltu", "I", "d,s,j", MATCH_SLTIU, MASK_SLTIU, match_opcode, INSN_ALIAS },
-{"sgt", "I", "d,t,s", MATCH_SLT, MASK_SLT, match_opcode, INSN_ALIAS },
-{"sgtu", "I", "d,t,s", MATCH_SLTU, MASK_SLTU, match_opcode, INSN_ALIAS },
-{"sb", "I", "t,q(s)", MATCH_SB, MASK_SB, match_opcode, 0 },
-{"sb", "I", "t,A,s", 0, (int) M_SB, match_never, INSN_MACRO },
-{"sh", "I", "t,q(s)", MATCH_SH, MASK_SH, match_opcode, 0 },
-{"sh", "I", "t,A,s", 0, (int) M_SH, match_never, INSN_MACRO },
-{"sw", "C", "CV,CM(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, INSN_ALIAS },
-{"sw", "C", "Ct,Ck(Cs)", MATCH_C_SW, MASK_C_SW, match_opcode, INSN_ALIAS },
-{"sw", "I", "t,q(s)", MATCH_SW, MASK_SW, match_opcode, 0 },
-{"sw", "I", "t,A,s", 0, (int) M_SW, match_never, INSN_MACRO },
-{"fence", "I", "", MATCH_FENCE | MASK_PRED | MASK_SUCC, MASK_FENCE | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, INSN_ALIAS },
-{"fence", "I", "P,Q", MATCH_FENCE, MASK_FENCE | MASK_RD | MASK_RS1 | (MASK_IMM & ~MASK_PRED & ~MASK_SUCC), match_opcode, 0 },
-{"fence.i", "I", "", MATCH_FENCE_I, MASK_FENCE | MASK_RD | MASK_RS1 | MASK_IMM, match_opcode, 0 },
-{"rdcycle", "I", "d", MATCH_RDCYCLE, MASK_RDCYCLE, match_opcode, INSN_ALIAS },
-{"rdinstret", "I", "d", MATCH_RDINSTRET, MASK_RDINSTRET, match_opcode, INSN_ALIAS },
-{"rdtime", "I", "d", MATCH_RDTIME, MASK_RDTIME, match_opcode, INSN_ALIAS },
-{"rdcycleh", "32I", "d", MATCH_RDCYCLEH, MASK_RDCYCLEH, match_opcode, INSN_ALIAS },
-{"rdinstreth","32I", "d", MATCH_RDINSTRETH, MASK_RDINSTRETH, match_opcode, INSN_ALIAS },
-{"rdtimeh", "32I", "d", MATCH_RDTIMEH, MASK_RDTIMEH, match_opcode, INSN_ALIAS },
-{"ecall", "I", "", MATCH_SCALL, MASK_SCALL, match_opcode, 0 },
-{"scall", "I", "", MATCH_SCALL, MASK_SCALL, match_opcode, 0 },
-{"xori", "I", "d,s,j", MATCH_XORI, MASK_XORI, match_opcode, 0 },
-{"xor", "C", "Cs,Cw,Ct", MATCH_C_XOR, MASK_C_XOR, match_opcode, INSN_ALIAS },
-{"xor", "C", "Cs,Ct,Cw", MATCH_C_XOR, MASK_C_XOR, match_opcode, INSN_ALIAS },
-{"xor", "I", "d,s,t", MATCH_XOR, MASK_XOR, match_opcode, 0 },
-{"xor", "I", "d,s,j", MATCH_XORI, MASK_XORI, match_opcode, INSN_ALIAS },
-{"lwu", "64I", "d,o(s)", MATCH_LWU, MASK_LWU, match_opcode, 0 },
-{"lwu", "64I", "d,A", 0, (int) M_LWU, match_never, INSN_MACRO },
-{"ld", "64C", "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, INSN_ALIAS },
-{"ld", "64C", "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, INSN_ALIAS },
-{"ld", "64I", "d,o(s)", MATCH_LD, MASK_LD, match_opcode, 0 },
-{"ld", "64I", "d,A", 0, (int) M_LD, match_never, INSN_MACRO },
-{"sd", "64C", "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, INSN_ALIAS },
-{"sd", "64C", "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, INSN_ALIAS },
-{"sd", "64I", "t,q(s)", MATCH_SD, MASK_SD, match_opcode, 0 },
-{"sd", "64I", "t,A,s", 0, (int) M_SD, match_never, INSN_MACRO },
-{"sext.w", "64C", "d,CU", MATCH_C_ADDIW, MASK_C_ADDIW | MASK_RVC_IMM, match_rd_nonzero, INSN_ALIAS },
-{"sext.w", "64I", "d,s", MATCH_ADDIW, MASK_ADDIW | MASK_IMM, match_opcode, INSN_ALIAS },
-{"addiw", "64C", "d,CU,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
-{"addiw", "64I", "d,s,j", MATCH_ADDIW, MASK_ADDIW, match_opcode, 0 },
-{"addw", "64C", "Cs,Cw,Ct", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, INSN_ALIAS },
-{"addw", "64C", "Cs,Ct,Cw", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, INSN_ALIAS },
-{"addw", "64C", "d,CU,Cj", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, INSN_ALIAS },
-{"addw", "64I", "d,s,t", MATCH_ADDW, MASK_ADDW, match_opcode, 0 },
-{"addw", "64I", "d,s,j", MATCH_ADDIW, MASK_ADDIW, match_opcode, INSN_ALIAS },
-{"negw", "64I", "d,t", MATCH_SUBW, MASK_SUBW | MASK_RS1, match_opcode, INSN_ALIAS }, /* sub 0 */
-{"slliw", "64I", "d,s,<", MATCH_SLLIW, MASK_SLLIW, match_opcode, 0 },
-{"sllw", "64I", "d,s,t", MATCH_SLLW, MASK_SLLW, match_opcode, 0 },
-{"sllw", "64I", "d,s,<", MATCH_SLLIW, MASK_SLLIW, match_opcode, INSN_ALIAS },
-{"srliw", "64I", "d,s,<", MATCH_SRLIW, MASK_SRLIW, match_opcode, 0 },
-{"srlw", "64I", "d,s,t", MATCH_SRLW, MASK_SRLW, match_opcode, 0 },
-{"srlw", "64I", "d,s,<", MATCH_SRLIW, MASK_SRLIW, match_opcode, INSN_ALIAS },
-{"sraiw", "64I", "d,s,<", MATCH_SRAIW, MASK_SRAIW, match_opcode, 0 },
-{"sraw", "64I", "d,s,t", MATCH_SRAW, MASK_SRAW, match_opcode, 0 },
-{"sraw", "64I", "d,s,<", MATCH_SRAIW, MASK_SRAIW, match_opcode, INSN_ALIAS },
-{"subw", "64C", "Cs,Cw,Ct", MATCH_C_SUBW, MASK_C_SUBW, match_opcode, INSN_ALIAS },
-{"subw", "64I", "d,s,t", MATCH_SUBW, MASK_SUBW, match_opcode, 0 },
-
-/* Atomic memory operation instruction subset */
-{"lr.w", "A", "d,0(s)", MATCH_LR_W, MASK_LR_W | MASK_AQRL, match_opcode, 0 },
-{"sc.w", "A", "d,t,0(s)", MATCH_SC_W, MASK_SC_W | MASK_AQRL, match_opcode, 0 },
-{"amoadd.w", "A", "d,t,0(s)", MATCH_AMOADD_W, MASK_AMOADD_W | MASK_AQRL, match_opcode, 0 },
-{"amoswap.w", "A", "d,t,0(s)", MATCH_AMOSWAP_W, MASK_AMOSWAP_W | MASK_AQRL, match_opcode, 0 },
-{"amoand.w", "A", "d,t,0(s)", MATCH_AMOAND_W, MASK_AMOAND_W | MASK_AQRL, match_opcode, 0 },
-{"amoor.w", "A", "d,t,0(s)", MATCH_AMOOR_W, MASK_AMOOR_W | MASK_AQRL, match_opcode, 0 },
-{"amoxor.w", "A", "d,t,0(s)", MATCH_AMOXOR_W, MASK_AMOXOR_W | MASK_AQRL, match_opcode, 0 },
-{"amomax.w", "A", "d,t,0(s)", MATCH_AMOMAX_W, MASK_AMOMAX_W | MASK_AQRL, match_opcode, 0 },
-{"amomaxu.w", "A", "d,t,0(s)", MATCH_AMOMAXU_W, MASK_AMOMAXU_W | MASK_AQRL, match_opcode, 0 },
-{"amomin.w", "A", "d,t,0(s)", MATCH_AMOMIN_W, MASK_AMOMIN_W | MASK_AQRL, match_opcode, 0 },
-{"amominu.w", "A", "d,t,0(s)", MATCH_AMOMINU_W, MASK_AMOMINU_W | MASK_AQRL, match_opcode, 0 },
-{"lr.w.aq", "A", "d,0(s)", MATCH_LR_W | MASK_AQ, MASK_LR_W | MASK_AQRL, match_opcode, 0 },
-{"sc.w.aq", "A", "d,t,0(s)", MATCH_SC_W | MASK_AQ, MASK_SC_W | MASK_AQRL, match_opcode, 0 },
-{"amoadd.w.aq", "A", "d,t,0(s)", MATCH_AMOADD_W | MASK_AQ, MASK_AMOADD_W | MASK_AQRL, match_opcode, 0 },
-{"amoswap.w.aq", "A", "d,t,0(s)", MATCH_AMOSWAP_W | MASK_AQ, MASK_AMOSWAP_W | MASK_AQRL, match_opcode, 0 },
-{"amoand.w.aq", "A", "d,t,0(s)", MATCH_AMOAND_W | MASK_AQ, MASK_AMOAND_W | MASK_AQRL, match_opcode, 0 },
-{"amoor.w.aq", "A", "d,t,0(s)", MATCH_AMOOR_W | MASK_AQ, MASK_AMOOR_W | MASK_AQRL, match_opcode, 0 },
-{"amoxor.w.aq", "A", "d,t,0(s)", MATCH_AMOXOR_W | MASK_AQ, MASK_AMOXOR_W | MASK_AQRL, match_opcode, 0 },
-{"amomax.w.aq", "A", "d,t,0(s)", MATCH_AMOMAX_W | MASK_AQ, MASK_AMOMAX_W | MASK_AQRL, match_opcode, 0 },
-{"amomaxu.w.aq", "A", "d,t,0(s)", MATCH_AMOMAXU_W | MASK_AQ, MASK_AMOMAXU_W | MASK_AQRL, match_opcode, 0 },
-{"amomin.w.aq", "A", "d,t,0(s)", MATCH_AMOMIN_W | MASK_AQ, MASK_AMOMIN_W | MASK_AQRL, match_opcode, 0 },
-{"amominu.w.aq", "A", "d,t,0(s)", MATCH_AMOMINU_W | MASK_AQ, MASK_AMOMINU_W | MASK_AQRL, match_opcode, 0 },
-{"lr.w.rl", "A", "d,0(s)", MATCH_LR_W | MASK_RL, MASK_LR_W | MASK_AQRL, match_opcode, 0 },
-{"sc.w.rl", "A", "d,t,0(s)", MATCH_SC_W | MASK_RL, MASK_SC_W | MASK_AQRL, match_opcode, 0 },
-{"amoadd.w.rl", "A", "d,t,0(s)", MATCH_AMOADD_W | MASK_RL, MASK_AMOADD_W | MASK_AQRL, match_opcode, 0 },
-{"amoswap.w.rl", "A", "d,t,0(s)", MATCH_AMOSWAP_W | MASK_RL, MASK_AMOSWAP_W | MASK_AQRL, match_opcode, 0 },
-{"amoand.w.rl", "A", "d,t,0(s)", MATCH_AMOAND_W | MASK_RL, MASK_AMOAND_W | MASK_AQRL, match_opcode, 0 },
-{"amoor.w.rl", "A", "d,t,0(s)", MATCH_AMOOR_W | MASK_RL, MASK_AMOOR_W | MASK_AQRL, match_opcode, 0 },
-{"amoxor.w.rl", "A", "d,t,0(s)", MATCH_AMOXOR_W | MASK_RL, MASK_AMOXOR_W | MASK_AQRL, match_opcode, 0 },
-{"amomax.w.rl", "A", "d,t,0(s)", MATCH_AMOMAX_W | MASK_RL, MASK_AMOMAX_W | MASK_AQRL, match_opcode, 0 },
-{"amomaxu.w.rl", "A", "d,t,0(s)", MATCH_AMOMAXU_W | MASK_RL, MASK_AMOMAXU_W | MASK_AQRL, match_opcode, 0 },
-{"amomin.w.rl", "A", "d,t,0(s)", MATCH_AMOMIN_W | MASK_RL, MASK_AMOMIN_W | MASK_AQRL, match_opcode, 0 },
-{"amominu.w.rl", "A", "d,t,0(s)", MATCH_AMOMINU_W | MASK_RL, MASK_AMOMINU_W | MASK_AQRL, match_opcode, 0 },
-{"lr.w.aqrl", "A", "d,0(s)", MATCH_LR_W | MASK_AQRL, MASK_LR_W | MASK_AQRL, match_opcode, 0 },
-{"sc.w.aqrl", "A", "d,t,0(s)", MATCH_SC_W | MASK_AQRL, MASK_SC_W | MASK_AQRL, match_opcode, 0 },
-{"amoadd.w.aqrl", "A", "d,t,0(s)", MATCH_AMOADD_W | MASK_AQRL, MASK_AMOADD_W | MASK_AQRL, match_opcode, 0 },
-{"amoswap.w.aqrl", "A", "d,t,0(s)", MATCH_AMOSWAP_W | MASK_AQRL, MASK_AMOSWAP_W | MASK_AQRL, match_opcode, 0 },
-{"amoand.w.aqrl", "A", "d,t,0(s)", MATCH_AMOAND_W | MASK_AQRL, MASK_AMOAND_W | MASK_AQRL, match_opcode, 0 },
-{"amoor.w.aqrl", "A", "d,t,0(s)", MATCH_AMOOR_W | MASK_AQRL, MASK_AMOOR_W | MASK_AQRL, match_opcode, 0 },
-{"amoxor.w.aqrl", "A", "d,t,0(s)", MATCH_AMOXOR_W | MASK_AQRL, MASK_AMOXOR_W | MASK_AQRL, match_opcode, 0 },
-{"amomax.w.aqrl", "A", "d,t,0(s)", MATCH_AMOMAX_W | MASK_AQRL, MASK_AMOMAX_W | MASK_AQRL, match_opcode, 0 },
-{"amomaxu.w.aqrl", "A", "d,t,0(s)", MATCH_AMOMAXU_W | MASK_AQRL, MASK_AMOMAXU_W | MASK_AQRL, match_opcode, 0 },
-{"amomin.w.aqrl", "A", "d,t,0(s)", MATCH_AMOMIN_W | MASK_AQRL, MASK_AMOMIN_W | MASK_AQRL, match_opcode, 0 },
-{"amominu.w.aqrl", "A", "d,t,0(s)", MATCH_AMOMINU_W | MASK_AQRL, MASK_AMOMINU_W | MASK_AQRL, match_opcode, 0 },
-{"lr.d", "64A", "d,0(s)", MATCH_LR_D, MASK_LR_D | MASK_AQRL, match_opcode, 0 },
-{"sc.d", "64A", "d,t,0(s)", MATCH_SC_D, MASK_SC_D | MASK_AQRL, match_opcode, 0 },
-{"amoadd.d", "64A", "d,t,0(s)", MATCH_AMOADD_D, MASK_AMOADD_D | MASK_AQRL, match_opcode, 0 },
-{"amoswap.d", "64A", "d,t,0(s)", MATCH_AMOSWAP_D, MASK_AMOSWAP_D | MASK_AQRL, match_opcode, 0 },
-{"amoand.d", "64A", "d,t,0(s)", MATCH_AMOAND_D, MASK_AMOAND_D | MASK_AQRL, match_opcode, 0 },
-{"amoor.d", "64A", "d,t,0(s)", MATCH_AMOOR_D, MASK_AMOOR_D | MASK_AQRL, match_opcode, 0 },
-{"amoxor.d", "64A", "d,t,0(s)", MATCH_AMOXOR_D, MASK_AMOXOR_D | MASK_AQRL, match_opcode, 0 },
-{"amomax.d", "64A", "d,t,0(s)", MATCH_AMOMAX_D, MASK_AMOMAX_D | MASK_AQRL, match_opcode, 0 },
-{"amomaxu.d", "64A", "d,t,0(s)", MATCH_AMOMAXU_D, MASK_AMOMAXU_D | MASK_AQRL, match_opcode, 0 },
-{"amomin.d", "64A", "d,t,0(s)", MATCH_AMOMIN_D, MASK_AMOMIN_D | MASK_AQRL, match_opcode, 0 },
-{"amominu.d", "64A", "d,t,0(s)", MATCH_AMOMINU_D, MASK_AMOMINU_D | MASK_AQRL, match_opcode, 0 },
-{"lr.d.aq", "64A", "d,0(s)", MATCH_LR_D | MASK_AQ, MASK_LR_D | MASK_AQRL, match_opcode, 0 },
-{"sc.d.aq", "64A", "d,t,0(s)", MATCH_SC_D | MASK_AQ, MASK_SC_D | MASK_AQRL, match_opcode, 0 },
-{"amoadd.d.aq", "64A", "d,t,0(s)", MATCH_AMOADD_D | MASK_AQ, MASK_AMOADD_D | MASK_AQRL, match_opcode, 0 },
-{"amoswap.d.aq", "64A", "d,t,0(s)", MATCH_AMOSWAP_D | MASK_AQ, MASK_AMOSWAP_D | MASK_AQRL, match_opcode, 0 },
-{"amoand.d.aq", "64A", "d,t,0(s)", MATCH_AMOAND_D | MASK_AQ, MASK_AMOAND_D | MASK_AQRL, match_opcode, 0 },
-{"amoor.d.aq", "64A", "d,t,0(s)", MATCH_AMOOR_D | MASK_AQ, MASK_AMOOR_D | MASK_AQRL, match_opcode, 0 },
-{"amoxor.d.aq", "64A", "d,t,0(s)", MATCH_AMOXOR_D | MASK_AQ, MASK_AMOXOR_D | MASK_AQRL, match_opcode, 0 },
-{"amomax.d.aq", "64A", "d,t,0(s)", MATCH_AMOMAX_D | MASK_AQ, MASK_AMOMAX_D | MASK_AQRL, match_opcode, 0 },
-{"amomaxu.d.aq", "64A", "d,t,0(s)", MATCH_AMOMAXU_D | MASK_AQ, MASK_AMOMAXU_D | MASK_AQRL, match_opcode, 0 },
-{"amomin.d.aq", "64A", "d,t,0(s)", MATCH_AMOMIN_D | MASK_AQ, MASK_AMOMIN_D | MASK_AQRL, match_opcode, 0 },
-{"amominu.d.aq", "64A", "d,t,0(s)", MATCH_AMOMINU_D | MASK_AQ, MASK_AMOMINU_D | MASK_AQRL, match_opcode, 0 },
-{"lr.d.rl", "64A", "d,0(s)", MATCH_LR_D | MASK_RL, MASK_LR_D | MASK_AQRL, match_opcode, 0 },
-{"sc.d.rl", "64A", "d,t,0(s)", MATCH_SC_D | MASK_RL, MASK_SC_D | MASK_AQRL, match_opcode, 0 },
-{"amoadd.d.rl", "64A", "d,t,0(s)", MATCH_AMOADD_D | MASK_RL, MASK_AMOADD_D | MASK_AQRL, match_opcode, 0 },
-{"amoswap.d.rl", "64A", "d,t,0(s)", MATCH_AMOSWAP_D | MASK_RL, MASK_AMOSWAP_D | MASK_AQRL, match_opcode, 0 },
-{"amoand.d.rl", "64A", "d,t,0(s)", MATCH_AMOAND_D | MASK_RL, MASK_AMOAND_D | MASK_AQRL, match_opcode, 0 },
-{"amoor.d.rl", "64A", "d,t,0(s)", MATCH_AMOOR_D | MASK_RL, MASK_AMOOR_D | MASK_AQRL, match_opcode, 0 },
-{"amoxor.d.rl", "64A", "d,t,0(s)", MATCH_AMOXOR_D | MASK_RL, MASK_AMOXOR_D | MASK_AQRL, match_opcode, 0 },
-{"amomax.d.rl", "64A", "d,t,0(s)", MATCH_AMOMAX_D | MASK_RL, MASK_AMOMAX_D | MASK_AQRL, match_opcode, 0 },
-{"amomaxu.d.rl", "64A", "d,t,0(s)", MATCH_AMOMAXU_D | MASK_RL, MASK_AMOMAXU_D | MASK_AQRL, match_opcode, 0 },
-{"amomin.d.rl", "64A", "d,t,0(s)", MATCH_AMOMIN_D | MASK_RL, MASK_AMOMIN_D | MASK_AQRL, match_opcode, 0 },
-{"amominu.d.rl", "64A", "d,t,0(s)", MATCH_AMOMINU_D | MASK_RL, MASK_AMOMINU_D | MASK_AQRL, match_opcode, 0 },
-{"lr.d.aqrl", "64A", "d,0(s)", MATCH_LR_D | MASK_AQRL, MASK_LR_D | MASK_AQRL, match_opcode, 0 },
-{"sc.d.aqrl", "64A", "d,t,0(s)", MATCH_SC_D | MASK_AQRL, MASK_SC_D | MASK_AQRL, match_opcode, 0 },
-{"amoadd.d.aqrl", "64A", "d,t,0(s)", MATCH_AMOADD_D | MASK_AQRL, MASK_AMOADD_D | MASK_AQRL, match_opcode, 0 },
-{"amoswap.d.aqrl", "64A", "d,t,0(s)", MATCH_AMOSWAP_D | MASK_AQRL, MASK_AMOSWAP_D | MASK_AQRL, match_opcode, 0 },
-{"amoand.d.aqrl", "64A", "d,t,0(s)", MATCH_AMOAND_D | MASK_AQRL, MASK_AMOAND_D | MASK_AQRL, match_opcode, 0 },
-{"amoor.d.aqrl", "64A", "d,t,0(s)", MATCH_AMOOR_D | MASK_AQRL, MASK_AMOOR_D | MASK_AQRL, match_opcode, 0 },
-{"amoxor.d.aqrl", "64A", "d,t,0(s)", MATCH_AMOXOR_D | MASK_AQRL, MASK_AMOXOR_D | MASK_AQRL, match_opcode, 0 },
-{"amomax.d.aqrl", "64A", "d,t,0(s)", MATCH_AMOMAX_D | MASK_AQRL, MASK_AMOMAX_D | MASK_AQRL, match_opcode, 0 },
-{"amomaxu.d.aqrl", "64A", "d,t,0(s)", MATCH_AMOMAXU_D | MASK_AQRL, MASK_AMOMAXU_D | MASK_AQRL, match_opcode, 0 },
-{"amomin.d.aqrl", "64A", "d,t,0(s)", MATCH_AMOMIN_D | MASK_AQRL, MASK_AMOMIN_D | MASK_AQRL, match_opcode, 0 },
-{"amominu.d.aqrl", "64A", "d,t,0(s)", MATCH_AMOMINU_D | MASK_AQRL, MASK_AMOMINU_D | MASK_AQRL, match_opcode, 0 },
-
-/* Multiply/Divide instruction subset */
-{"mul", "M", "d,s,t", MATCH_MUL, MASK_MUL, match_opcode, 0 },
-{"mulh", "M", "d,s,t", MATCH_MULH, MASK_MULH, match_opcode, 0 },
-{"mulhu", "M", "d,s,t", MATCH_MULHU, MASK_MULHU, match_opcode, 0 },
-{"mulhsu", "M", "d,s,t", MATCH_MULHSU, MASK_MULHSU, match_opcode, 0 },
-{"div", "M", "d,s,t", MATCH_DIV, MASK_DIV, match_opcode, 0 },
-{"divu", "M", "d,s,t", MATCH_DIVU, MASK_DIVU, match_opcode, 0 },
-{"rem", "M", "d,s,t", MATCH_REM, MASK_REM, match_opcode, 0 },
-{"remu", "M", "d,s,t", MATCH_REMU, MASK_REMU, match_opcode, 0 },
-{"mulw", "64M", "d,s,t", MATCH_MULW, MASK_MULW, match_opcode, 0 },
-{"divw", "64M", "d,s,t", MATCH_DIVW, MASK_DIVW, match_opcode, 0 },
-{"divuw", "64M", "d,s,t", MATCH_DIVUW, MASK_DIVUW, match_opcode, 0 },
-{"remw", "64M", "d,s,t", MATCH_REMW, MASK_REMW, match_opcode, 0 },
-{"remuw", "64M", "d,s,t", MATCH_REMUW, MASK_REMUW, match_opcode, 0 },
-
-/* Single-precision floating-point instruction subset */
-{"frsr", "F", "d", MATCH_FRCSR, MASK_FRCSR, match_opcode, 0 },
-{"fssr", "F", "s", MATCH_FSCSR, MASK_FSCSR | MASK_RD, match_opcode, 0 },
-{"fssr", "F", "d,s", MATCH_FSCSR, MASK_FSCSR, match_opcode, 0 },
-{"frcsr", "F", "d", MATCH_FRCSR, MASK_FRCSR, match_opcode, 0 },
-{"fscsr", "F", "s", MATCH_FSCSR, MASK_FSCSR | MASK_RD, match_opcode, 0 },
-{"fscsr", "F", "d,s", MATCH_FSCSR, MASK_FSCSR, match_opcode, 0 },
-{"frrm", "F", "d", MATCH_FRRM, MASK_FRRM, match_opcode, 0 },
-{"fsrm", "F", "s", MATCH_FSRM, MASK_FSRM | MASK_RD, match_opcode, 0 },
-{"fsrm", "F", "d,s", MATCH_FSRM, MASK_FSRM, match_opcode, 0 },
-{"frflags", "F", "d", MATCH_FRFLAGS, MASK_FRFLAGS, match_opcode, 0 },
-{"fsflags", "F", "s", MATCH_FSFLAGS, MASK_FSFLAGS | MASK_RD, match_opcode, 0 },
-{"fsflags", "F", "d,s", MATCH_FSFLAGS, MASK_FSFLAGS, match_opcode, 0 },
-{"flw", "32C", "D,Cm(Cc)", MATCH_C_FLWSP, MASK_C_FLWSP, match_opcode, INSN_ALIAS },
-{"flw", "32C", "CD,Ck(Cs)", MATCH_C_FLW, MASK_C_FLW, match_opcode, INSN_ALIAS },
-{"flw", "F", "D,o(s)", MATCH_FLW, MASK_FLW, match_opcode, 0 },
-{"flw", "F", "D,A,s", 0, (int) M_FLW, match_never, INSN_MACRO },
-{"fsw", "32C", "CT,CM(Cc)", MATCH_C_FSWSP, MASK_C_FSWSP, match_opcode, INSN_ALIAS },
-{"fsw", "32C", "CD,Ck(Cs)", MATCH_C_FSW, MASK_C_FSW, match_opcode, INSN_ALIAS },
-{"fsw", "F", "T,q(s)", MATCH_FSW, MASK_FSW, match_opcode, 0 },
-{"fsw", "F", "T,A,s", 0, (int) M_FSW, match_never, INSN_MACRO },
-{"fmv.x.s", "F", "d,S", MATCH_FMV_X_S, MASK_FMV_X_S, match_opcode, 0 },
-{"fmv.s.x", "F", "D,s", MATCH_FMV_S_X, MASK_FMV_S_X, match_opcode, 0 },
-{"fmv.s", "F", "D,U", MATCH_FSGNJ_S, MASK_FSGNJ_S, match_rs1_eq_rs2, INSN_ALIAS },
-{"fneg.s", "F", "D,U", MATCH_FSGNJN_S, MASK_FSGNJN_S, match_rs1_eq_rs2, INSN_ALIAS },
-{"fabs.s", "F", "D,U", MATCH_FSGNJX_S, MASK_FSGNJX_S, match_rs1_eq_rs2, INSN_ALIAS },
-{"fsgnj.s", "F", "D,S,T", MATCH_FSGNJ_S, MASK_FSGNJ_S, match_opcode, 0 },
-{"fsgnjn.s", "F", "D,S,T", MATCH_FSGNJN_S, MASK_FSGNJN_S, match_opcode, 0 },
-{"fsgnjx.s", "F", "D,S,T", MATCH_FSGNJX_S, MASK_FSGNJX_S, match_opcode, 0 },
-{"fadd.s", "F", "D,S,T", MATCH_FADD_S | MASK_RM, MASK_FADD_S | MASK_RM, match_opcode, 0 },
-{"fadd.s", "F", "D,S,T,m", MATCH_FADD_S, MASK_FADD_S, match_opcode, 0 },
-{"fsub.s", "F", "D,S,T", MATCH_FSUB_S | MASK_RM, MASK_FSUB_S | MASK_RM, match_opcode, 0 },
-{"fsub.s", "F", "D,S,T,m", MATCH_FSUB_S, MASK_FSUB_S, match_opcode, 0 },
-{"fmul.s", "F", "D,S,T", MATCH_FMUL_S | MASK_RM, MASK_FMUL_S | MASK_RM, match_opcode, 0 },
-{"fmul.s", "F", "D,S,T,m", MATCH_FMUL_S, MASK_FMUL_S, match_opcode, 0 },
-{"fdiv.s", "F", "D,S,T", MATCH_FDIV_S | MASK_RM, MASK_FDIV_S | MASK_RM, match_opcode, 0 },
-{"fdiv.s", "F", "D,S,T,m", MATCH_FDIV_S, MASK_FDIV_S, match_opcode, 0 },
-{"fsqrt.s", "F", "D,S", MATCH_FSQRT_S | MASK_RM, MASK_FSQRT_S | MASK_RM, match_opcode, 0 },
-{"fsqrt.s", "F", "D,S,m", MATCH_FSQRT_S, MASK_FSQRT_S, match_opcode, 0 },
-{"fmin.s", "F", "D,S,T", MATCH_FMIN_S, MASK_FMIN_S, match_opcode, 0 },
-{"fmax.s", "F", "D,S,T", MATCH_FMAX_S, MASK_FMAX_S, match_opcode, 0 },
-{"fmadd.s", "F", "D,S,T,R", MATCH_FMADD_S | MASK_RM, MASK_FMADD_S | MASK_RM, match_opcode, 0 },
-{"fmadd.s", "F", "D,S,T,R,m", MATCH_FMADD_S, MASK_FMADD_S, match_opcode, 0 },
-{"fnmadd.s", "F", "D,S,T,R", MATCH_FNMADD_S | MASK_RM, MASK_FNMADD_S | MASK_RM, match_opcode, 0 },
-{"fnmadd.s", "F", "D,S,T,R,m", MATCH_FNMADD_S, MASK_FNMADD_S, match_opcode, 0 },
-{"fmsub.s", "F", "D,S,T,R", MATCH_FMSUB_S | MASK_RM, MASK_FMSUB_S | MASK_RM, match_opcode, 0 },
-{"fmsub.s", "F", "D,S,T,R,m", MATCH_FMSUB_S, MASK_FMSUB_S, match_opcode, 0 },
-{"fnmsub.s", "F", "D,S,T,R", MATCH_FNMSUB_S | MASK_RM, MASK_FNMSUB_S | MASK_RM, match_opcode, 0 },
-{"fnmsub.s", "F", "D,S,T,R,m", MATCH_FNMSUB_S, MASK_FNMSUB_S, match_opcode, 0 },
-{"fcvt.w.s", "F", "d,S", MATCH_FCVT_W_S | MASK_RM, MASK_FCVT_W_S | MASK_RM, match_opcode, 0 },
-{"fcvt.w.s", "F", "d,S,m", MATCH_FCVT_W_S, MASK_FCVT_W_S, match_opcode, 0 },
-{"fcvt.wu.s", "F", "d,S", MATCH_FCVT_WU_S | MASK_RM, MASK_FCVT_WU_S | MASK_RM, match_opcode, 0 },
-{"fcvt.wu.s", "F", "d,S,m", MATCH_FCVT_WU_S, MASK_FCVT_WU_S, match_opcode, 0 },
-{"fcvt.s.w", "F", "D,s", MATCH_FCVT_S_W | MASK_RM, MASK_FCVT_S_W | MASK_RM, match_opcode, 0 },
-{"fcvt.s.w", "F", "D,s,m", MATCH_FCVT_S_W, MASK_FCVT_S_W, match_opcode, 0 },
-{"fcvt.s.wu", "F", "D,s", MATCH_FCVT_S_WU | MASK_RM, MASK_FCVT_S_W | MASK_RM, match_opcode, 0 },
-{"fcvt.s.wu", "F", "D,s,m", MATCH_FCVT_S_WU, MASK_FCVT_S_WU, match_opcode, 0 },
-{"fclass.s", "F", "d,S", MATCH_FCLASS_S, MASK_FCLASS_S, match_opcode, 0 },
-{"feq.s", "F", "d,S,T", MATCH_FEQ_S, MASK_FEQ_S, match_opcode, 0 },
-{"flt.s", "F", "d,S,T", MATCH_FLT_S, MASK_FLT_S, match_opcode, 0 },
-{"fle.s", "F", "d,S,T", MATCH_FLE_S, MASK_FLE_S, match_opcode, 0 },
-{"fgt.s", "F", "d,T,S", MATCH_FLT_S, MASK_FLT_S, match_opcode, 0 },
-{"fge.s", "F", "d,T,S", MATCH_FLE_S, MASK_FLE_S, match_opcode, 0 },
-{"fcvt.l.s", "64F", "d,S", MATCH_FCVT_L_S | MASK_RM, MASK_FCVT_L_S | MASK_RM, match_opcode, 0 },
-{"fcvt.l.s", "64F", "d,S,m", MATCH_FCVT_L_S, MASK_FCVT_L_S, match_opcode, 0 },
-{"fcvt.lu.s", "64F", "d,S", MATCH_FCVT_LU_S | MASK_RM, MASK_FCVT_LU_S | MASK_RM, match_opcode, 0 },
-{"fcvt.lu.s", "64F", "d,S,m", MATCH_FCVT_LU_S, MASK_FCVT_LU_S, match_opcode, 0 },
-{"fcvt.s.l", "64F", "D,s", MATCH_FCVT_S_L | MASK_RM, MASK_FCVT_S_L | MASK_RM, match_opcode, 0 },
-{"fcvt.s.l", "64F", "D,s,m", MATCH_FCVT_S_L, MASK_FCVT_S_L, match_opcode, 0 },
-{"fcvt.s.lu", "64F", "D,s", MATCH_FCVT_S_LU | MASK_RM, MASK_FCVT_S_L | MASK_RM, match_opcode, 0 },
-{"fcvt.s.lu", "64F", "D,s,m", MATCH_FCVT_S_LU, MASK_FCVT_S_LU, match_opcode, 0 },
-
-/* Double-precision floating-point instruction subset */
-{"fld", "C", "D,Cn(Cc)", MATCH_C_FLDSP, MASK_C_FLDSP, match_opcode, INSN_ALIAS },
-{"fld", "C", "CD,Cl(Cs)", MATCH_C_FLD, MASK_C_FLD, match_opcode, INSN_ALIAS },
-{"fld", "D", "D,o(s)", MATCH_FLD, MASK_FLD, match_opcode, 0 },
-{"fld", "D", "D,A,s", 0, (int) M_FLD, match_never, INSN_MACRO },
-{"fsd", "C", "CT,CN(Cc)", MATCH_C_FSDSP, MASK_C_FSDSP, match_opcode, INSN_ALIAS },
-{"fsd", "C", "CD,Cl(Cs)", MATCH_C_FSD, MASK_C_FSD, match_opcode, INSN_ALIAS },
-{"fsd", "D", "T,q(s)", MATCH_FSD, MASK_FSD, match_opcode, 0 },
-{"fsd", "D", "T,A,s", 0, (int) M_FSD, match_never, INSN_MACRO },
-{"fmv.d", "D", "D,U", MATCH_FSGNJ_D, MASK_FSGNJ_D, match_rs1_eq_rs2, INSN_ALIAS },
-{"fneg.d", "D", "D,U", MATCH_FSGNJN_D, MASK_FSGNJN_D, match_rs1_eq_rs2, INSN_ALIAS },
-{"fabs.d", "D", "D,U", MATCH_FSGNJX_D, MASK_FSGNJX_D, match_rs1_eq_rs2, INSN_ALIAS },
-{"fsgnj.d", "D", "D,S,T", MATCH_FSGNJ_D, MASK_FSGNJ_D, match_opcode, 0 },
-{"fsgnjn.d", "D", "D,S,T", MATCH_FSGNJN_D, MASK_FSGNJN_D, match_opcode, 0 },
-{"fsgnjx.d", "D", "D,S,T", MATCH_FSGNJX_D, MASK_FSGNJX_D, match_opcode, 0 },
-{"fadd.d", "D", "D,S,T", MATCH_FADD_D | MASK_RM, MASK_FADD_D | MASK_RM, match_opcode, 0 },
-{"fadd.d", "D", "D,S,T,m", MATCH_FADD_D, MASK_FADD_D, match_opcode, 0 },
-{"fsub.d", "D", "D,S,T", MATCH_FSUB_D | MASK_RM, MASK_FSUB_D | MASK_RM, match_opcode, 0 },
-{"fsub.d", "D", "D,S,T,m", MATCH_FSUB_D, MASK_FSUB_D, match_opcode, 0 },
-{"fmul.d", "D", "D,S,T", MATCH_FMUL_D | MASK_RM, MASK_FMUL_D | MASK_RM, match_opcode, 0 },
-{"fmul.d", "D", "D,S,T,m", MATCH_FMUL_D, MASK_FMUL_D, match_opcode, 0 },
-{"fdiv.d", "D", "D,S,T", MATCH_FDIV_D | MASK_RM, MASK_FDIV_D | MASK_RM, match_opcode, 0 },
-{"fdiv.d", "D", "D,S,T,m", MATCH_FDIV_D, MASK_FDIV_D, match_opcode, 0 },
-{"fsqrt.d", "D", "D,S", MATCH_FSQRT_D | MASK_RM, MASK_FSQRT_D | MASK_RM, match_opcode, 0 },
-{"fsqrt.d", "D", "D,S,m", MATCH_FSQRT_D, MASK_FSQRT_D, match_opcode, 0 },
-{"fmin.d", "D", "D,S,T", MATCH_FMIN_D, MASK_FMIN_D, match_opcode, 0 },
-{"fmax.d", "D", "D,S,T", MATCH_FMAX_D, MASK_FMAX_D, match_opcode, 0 },
-{"fmadd.d", "D", "D,S,T,R", MATCH_FMADD_D | MASK_RM, MASK_FMADD_D | MASK_RM, match_opcode, 0 },
-{"fmadd.d", "D", "D,S,T,R,m", MATCH_FMADD_D, MASK_FMADD_D, match_opcode, 0 },
-{"fnmadd.d", "D", "D,S,T,R", MATCH_FNMADD_D | MASK_RM, MASK_FNMADD_D | MASK_RM, match_opcode, 0 },
-{"fnmadd.d", "D", "D,S,T,R,m", MATCH_FNMADD_D, MASK_FNMADD_D, match_opcode, 0 },
-{"fmsub.d", "D", "D,S,T,R", MATCH_FMSUB_D | MASK_RM, MASK_FMSUB_D | MASK_RM, match_opcode, 0 },
-{"fmsub.d", "D", "D,S,T,R,m", MATCH_FMSUB_D, MASK_FMSUB_D, match_opcode, 0 },
-{"fnmsub.d", "D", "D,S,T,R", MATCH_FNMSUB_D | MASK_RM, MASK_FNMSUB_D | MASK_RM, match_opcode, 0 },
-{"fnmsub.d", "D", "D,S,T,R,m", MATCH_FNMSUB_D, MASK_FNMSUB_D, match_opcode, 0 },
-{"fcvt.w.d", "D", "d,S", MATCH_FCVT_W_D | MASK_RM, MASK_FCVT_W_D | MASK_RM, match_opcode, 0 },
-{"fcvt.w.d", "D", "d,S,m", MATCH_FCVT_W_D, MASK_FCVT_W_D, match_opcode, 0 },
-{"fcvt.wu.d", "D", "d,S", MATCH_FCVT_WU_D | MASK_RM, MASK_FCVT_WU_D | MASK_RM, match_opcode, 0 },
-{"fcvt.wu.d", "D", "d,S,m", MATCH_FCVT_WU_D, MASK_FCVT_WU_D, match_opcode, 0 },
-{"fcvt.d.w", "D", "D,s", MATCH_FCVT_D_W, MASK_FCVT_D_W | MASK_RM, match_opcode, 0 },
-{"fcvt.d.wu", "D", "D,s", MATCH_FCVT_D_WU, MASK_FCVT_D_WU | MASK_RM, match_opcode, 0 },
-{"fcvt.d.s", "D", "D,S", MATCH_FCVT_D_S, MASK_FCVT_D_S | MASK_RM, match_opcode, 0 },
-{"fcvt.s.d", "D", "D,S", MATCH_FCVT_S_D | MASK_RM, MASK_FCVT_S_D | MASK_RM, match_opcode, 0 },
-{"fcvt.s.d", "D", "D,S,m", MATCH_FCVT_S_D, MASK_FCVT_S_D, match_opcode, 0 },
-{"fclass.d", "D", "d,S", MATCH_FCLASS_D, MASK_FCLASS_D, match_opcode, 0 },
-{"feq.d", "D", "d,S,T", MATCH_FEQ_D, MASK_FEQ_D, match_opcode, 0 },
-{"flt.d", "D", "d,S,T", MATCH_FLT_D, MASK_FLT_D, match_opcode, 0 },
-{"fle.d", "D", "d,S,T", MATCH_FLE_D, MASK_FLE_D, match_opcode, 0 },
-{"fgt.d", "D", "d,T,S", MATCH_FLT_D, MASK_FLT_D, match_opcode, 0 },
-{"fge.d", "D", "d,T,S", MATCH_FLE_D, MASK_FLE_D, match_opcode, 0 },
-{"fmv.x.d", "64D", "d,S", MATCH_FMV_X_D, MASK_FMV_X_D, match_opcode, 0 },
-{"fmv.d.x", "64D", "D,s", MATCH_FMV_D_X, MASK_FMV_D_X, match_opcode, 0 },
-{"fcvt.l.d", "64D", "d,S", MATCH_FCVT_L_D | MASK_RM, MASK_FCVT_L_D | MASK_RM, match_opcode, 0 },
-{"fcvt.l.d", "64D", "d,S,m", MATCH_FCVT_L_D, MASK_FCVT_L_D, match_opcode, 0 },
-{"fcvt.lu.d", "64D", "d,S", MATCH_FCVT_LU_D | MASK_RM, MASK_FCVT_LU_D | MASK_RM, match_opcode, 0 },
-{"fcvt.lu.d", "64D", "d,S,m", MATCH_FCVT_LU_D, MASK_FCVT_LU_D, match_opcode, 0 },
-{"fcvt.d.l", "64D", "D,s", MATCH_FCVT_D_L | MASK_RM, MASK_FCVT_D_L | MASK_RM, match_opcode, 0 },
-{"fcvt.d.l", "64D", "D,s,m", MATCH_FCVT_D_L, MASK_FCVT_D_L, match_opcode, 0 },
-{"fcvt.d.lu", "64D", "D,s", MATCH_FCVT_D_LU | MASK_RM, MASK_FCVT_D_L | MASK_RM, match_opcode, 0 },
-{"fcvt.d.lu", "64D", "D,s,m", MATCH_FCVT_D_LU, MASK_FCVT_D_LU, match_opcode, 0 },
-
-/* Quad-precision floating-point instruction subset */
-{"flq", "Q", "D,o(s)", MATCH_FLQ, MASK_FLQ, match_opcode, 0 },
-{"flq", "Q", "D,A,s", 0, (int) M_FLQ, match_never, INSN_MACRO },
-{"fsq", "Q", "T,q(s)", MATCH_FSQ, MASK_FSQ, match_opcode, 0 },
-{"fsq", "Q", "T,A,s", 0, (int) M_FSQ, match_never, INSN_MACRO },
-{"fmv.q", "Q", "D,U", MATCH_FSGNJ_Q, MASK_FSGNJ_Q, match_rs1_eq_rs2, INSN_ALIAS },
-{"fneg.q", "Q", "D,U", MATCH_FSGNJN_Q, MASK_FSGNJN_Q, match_rs1_eq_rs2, INSN_ALIAS },
-{"fabs.q", "Q", "D,U", MATCH_FSGNJX_Q, MASK_FSGNJX_Q, match_rs1_eq_rs2, INSN_ALIAS },
-{"fsgnj.q", "Q", "D,S,T", MATCH_FSGNJ_Q, MASK_FSGNJ_Q, match_opcode, 0 },
-{"fsgnjn.q", "Q", "D,S,T", MATCH_FSGNJN_Q, MASK_FSGNJN_Q, match_opcode, 0 },
-{"fsgnjx.q", "Q", "D,S,T", MATCH_FSGNJX_Q, MASK_FSGNJX_Q, match_opcode, 0 },
-{"fadd.q", "Q", "D,S,T", MATCH_FADD_Q | MASK_RM, MASK_FADD_Q | MASK_RM, match_opcode, 0 },
-{"fadd.q", "Q", "D,S,T,m", MATCH_FADD_Q, MASK_FADD_Q, match_opcode, 0 },
-{"fsub.q", "Q", "D,S,T", MATCH_FSUB_Q | MASK_RM, MASK_FSUB_Q | MASK_RM, match_opcode, 0 },
-{"fsub.q", "Q", "D,S,T,m", MATCH_FSUB_Q, MASK_FSUB_Q, match_opcode, 0 },
-{"fmul.q", "Q", "D,S,T", MATCH_FMUL_Q | MASK_RM, MASK_FMUL_Q | MASK_RM, match_opcode, 0 },
-{"fmul.q", "Q", "D,S,T,m", MATCH_FMUL_Q, MASK_FMUL_Q, match_opcode, 0 },
-{"fdiv.q", "Q", "D,S,T", MATCH_FDIV_Q | MASK_RM, MASK_FDIV_Q | MASK_RM, match_opcode, 0 },
-{"fdiv.q", "Q", "D,S,T,m", MATCH_FDIV_Q, MASK_FDIV_Q, match_opcode, 0 },
-{"fsqrt.q", "Q", "D,S", MATCH_FSQRT_Q | MASK_RM, MASK_FSQRT_Q | MASK_RM, match_opcode, 0 },
-{"fsqrt.q", "Q", "D,S,m", MATCH_FSQRT_Q, MASK_FSQRT_Q, match_opcode, 0 },
-{"fmin.q", "Q", "D,S,T", MATCH_FMIN_Q, MASK_FMIN_Q, match_opcode, 0 },
-{"fmax.q", "Q", "D,S,T", MATCH_FMAX_Q, MASK_FMAX_Q, match_opcode, 0 },
-{"fmadd.q", "Q", "D,S,T,R", MATCH_FMADD_Q | MASK_RM, MASK_FMADD_Q | MASK_RM, match_opcode, 0 },
-{"fmadd.q", "Q", "D,S,T,R,m", MATCH_FMADD_Q, MASK_FMADD_Q, match_opcode, 0 },
-{"fnmadd.q", "Q", "D,S,T,R", MATCH_FNMADD_Q | MASK_RM, MASK_FNMADD_Q | MASK_RM, match_opcode, 0 },
-{"fnmadd.q", "Q", "D,S,T,R,m", MATCH_FNMADD_Q, MASK_FNMADD_Q, match_opcode, 0 },
-{"fmsub.q", "Q", "D,S,T,R", MATCH_FMSUB_Q | MASK_RM, MASK_FMSUB_Q | MASK_RM, match_opcode, 0 },
-{"fmsub.q", "Q", "D,S,T,R,m", MATCH_FMSUB_Q, MASK_FMSUB_Q, match_opcode, 0 },
-{"fnmsub.q", "Q", "D,S,T,R", MATCH_FNMSUB_Q | MASK_RM, MASK_FNMSUB_Q | MASK_RM, match_opcode, 0 },
-{"fnmsub.q", "Q", "D,S,T,R,m", MATCH_FNMSUB_Q, MASK_FNMSUB_Q, match_opcode, 0 },
-{"fcvt.w.q", "Q", "d,S", MATCH_FCVT_W_Q | MASK_RM, MASK_FCVT_W_Q | MASK_RM, match_opcode, 0 },
-{"fcvt.w.q", "Q", "d,S,m", MATCH_FCVT_W_Q, MASK_FCVT_W_Q, match_opcode, 0 },
-{"fcvt.wu.q", "Q", "d,S", MATCH_FCVT_WU_Q | MASK_RM, MASK_FCVT_WU_Q | MASK_RM, match_opcode, 0 },
-{"fcvt.wu.q", "Q", "d,S,m", MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q, match_opcode, 0 },
-{"fcvt.q.w", "Q", "D,s", MATCH_FCVT_Q_W, MASK_FCVT_Q_W | MASK_RM, match_opcode, 0 },
-{"fcvt.q.wu", "Q", "D,s", MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU | MASK_RM, match_opcode, 0 },
-{"fcvt.q.s", "Q", "D,S", MATCH_FCVT_Q_S, MASK_FCVT_Q_S | MASK_RM, match_opcode, 0 },
-{"fcvt.q.d", "Q", "D,S", MATCH_FCVT_Q_D, MASK_FCVT_Q_D | MASK_RM, match_opcode, 0 },
-{"fcvt.s.q", "Q", "D,S", MATCH_FCVT_S_Q | MASK_RM, MASK_FCVT_S_Q | MASK_RM, match_opcode, 0 },
-{"fcvt.s.q", "Q", "D,S,m", MATCH_FCVT_S_Q, MASK_FCVT_S_Q, match_opcode, 0 },
-{"fcvt.d.q", "Q", "D,S", MATCH_FCVT_D_Q | MASK_RM, MASK_FCVT_D_Q | MASK_RM, match_opcode, 0 },
-{"fcvt.d.q", "Q", "D,S,m", MATCH_FCVT_D_Q, MASK_FCVT_D_Q, match_opcode, 0 },
-{"fclass.q", "Q", "d,S", MATCH_FCLASS_Q, MASK_FCLASS_Q, match_opcode, 0 },
-{"feq.q", "Q", "d,S,T", MATCH_FEQ_Q, MASK_FEQ_Q, match_opcode, 0 },
-{"flt.q", "Q", "d,S,T", MATCH_FLT_Q, MASK_FLT_Q, match_opcode, 0 },
-{"fle.q", "Q", "d,S,T", MATCH_FLE_Q, MASK_FLE_Q, match_opcode, 0 },
-{"fgt.q", "Q", "d,T,S", MATCH_FLT_Q, MASK_FLT_Q, match_opcode, 0 },
-{"fge.q", "Q", "d,T,S", MATCH_FLE_Q, MASK_FLE_Q, match_opcode, 0 },
-{"fmv.x.q", "64Q", "d,S", MATCH_FMV_X_Q, MASK_FMV_X_Q, match_opcode, 0 },
-{"fmv.q.x", "64Q", "D,s", MATCH_FMV_Q_X, MASK_FMV_Q_X, match_opcode, 0 },
-{"fcvt.l.q", "64Q", "d,S", MATCH_FCVT_L_Q | MASK_RM, MASK_FCVT_L_Q | MASK_RM, match_opcode, 0 },
-{"fcvt.l.q", "64Q", "d,S,m", MATCH_FCVT_L_Q, MASK_FCVT_L_Q, match_opcode, 0 },
-{"fcvt.lu.q", "64Q", "d,S", MATCH_FCVT_LU_Q | MASK_RM, MASK_FCVT_LU_Q | MASK_RM, match_opcode, 0 },
-{"fcvt.lu.q", "64Q", "d,S,m", MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q, match_opcode, 0 },
-{"fcvt.q.l", "64Q", "D,s", MATCH_FCVT_Q_L | MASK_RM, MASK_FCVT_Q_L | MASK_RM, match_opcode, 0 },
-{"fcvt.q.l", "64Q", "D,s,m", MATCH_FCVT_Q_L, MASK_FCVT_Q_L, match_opcode, 0 },
-{"fcvt.q.lu", "64Q", "D,s", MATCH_FCVT_Q_LU | MASK_RM, MASK_FCVT_Q_L | MASK_RM, match_opcode, 0 },
-{"fcvt.q.lu", "64Q", "D,s,m", MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU, match_opcode, 0 },
-
-/* Compressed instructions. */
-{"c.ebreak", "C", "", MATCH_C_EBREAK, MASK_C_EBREAK, match_opcode, 0 },
-{"c.jr", "C", "d", MATCH_C_JR, MASK_C_JR, match_rd_nonzero, 0 },
-{"c.jalr", "C", "d", MATCH_C_JALR, MASK_C_JALR, match_rd_nonzero, 0 },
-{"c.j", "C", "Ca", MATCH_C_J, MASK_C_J, match_opcode, 0 },
-{"c.jal", "32C", "Ca", MATCH_C_JAL, MASK_C_JAL, match_opcode, 0 },
-{"c.beqz", "C", "Cs,Cp", MATCH_C_BEQZ, MASK_C_BEQZ, match_opcode, 0 },
-{"c.bnez", "C", "Cs,Cp", MATCH_C_BNEZ, MASK_C_BNEZ, match_opcode, 0 },
-{"c.lwsp", "C", "d,Cm(Cc)", MATCH_C_LWSP, MASK_C_LWSP, match_rd_nonzero, 0 },
-{"c.lw", "C", "Ct,Ck(Cs)", MATCH_C_LW, MASK_C_LW, match_opcode, 0 },
-{"c.swsp", "C", "CV,CM(Cc)", MATCH_C_SWSP, MASK_C_SWSP, match_opcode, 0 },
-{"c.sw", "C", "Ct,Ck(Cs)", MATCH_C_SW, MASK_C_SW, match_opcode, 0 },
-{"c.nop", "C", "", MATCH_C_ADDI, 0xffff, match_opcode, 0 },
-{"c.mv", "C", "d,CV", MATCH_C_MV, MASK_C_MV, match_c_add, 0 },
-{"c.lui", "C", "d,Cu", MATCH_C_LUI, MASK_C_LUI, match_c_lui, 0 },
-{"c.li", "C", "d,Cj", MATCH_C_LI, MASK_C_LI, match_rd_nonzero, 0 },
-{"c.addi4spn","C", "Ct,Cc,CK", MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN, match_opcode, 0 },
-{"c.addi16sp","C", "Cc,CL", MATCH_C_ADDI16SP, MASK_C_ADDI16SP, match_opcode, 0 },
-{"c.addi", "C", "d,Cj,CU", MATCH_C_ADDI, MASK_C_ADDI, match_rd_nonzero, 0 },
-{"c.add", "C", "d,CV,CU", MATCH_C_ADD, MASK_C_ADD, match_c_add, 0 },
-{"c.sub", "C", "Cs,Cs,Ct", MATCH_C_SUB, MASK_C_SUB, match_opcode, 0 },
-{"c.and", "C", "Cs,Cs,Ct", MATCH_C_AND, MASK_C_AND, match_opcode, 0 },
-{"c.or", "C", "Cs,Cs,Ct", MATCH_C_OR, MASK_C_OR, match_opcode, 0 },
-{"c.xor", "C", "Cs,Cs,Ct", MATCH_C_XOR, MASK_C_XOR, match_opcode, 0 },
-{"c.slli", "C", "d,CU,C>", MATCH_C_SLLI, MASK_C_SLLI, match_rd_nonzero, 0 },
-{"c.srli", "C", "Cs,Cs,C>", MATCH_C_SRLI, MASK_C_SRLI, match_opcode, 0 },
-{"c.srai", "C", "Cs,Cs,C>", MATCH_C_SRAI, MASK_C_SRAI, match_opcode, 0 },
-{"c.andi", "C", "Cs,Cj,Cs", MATCH_C_ANDI, MASK_C_ANDI, match_opcode, 0 },
-{"c.addiw", "64C", "d,Cj,CU", MATCH_C_ADDIW, MASK_C_ADDIW, match_rd_nonzero, 0 },
-{"c.addw", "64C", "Cs,Ct,Cs", MATCH_C_ADDW, MASK_C_ADDW, match_opcode, 0 },
-{"c.subw", "64C", "Cs,Cs,Ct", MATCH_C_SUBW, MASK_C_SUBW, match_opcode, 0 },
-{"c.ldsp", "64C", "d,Cn(Cc)", MATCH_C_LDSP, MASK_C_LDSP, match_rd_nonzero, 0 },
-{"c.ld", "64C", "Ct,Cl(Cs)", MATCH_C_LD, MASK_C_LD, match_opcode, 0 },
-{"c.sdsp", "64C", "CV,CN(Cc)", MATCH_C_SDSP, MASK_C_SDSP, match_opcode, 0 },
-{"c.sd", "64C", "Ct,Cl(Cs)", MATCH_C_SD, MASK_C_SD, match_opcode, 0 },
-{"c.fldsp", "C", "D,Cn(Cc)", MATCH_C_FLDSP, MASK_C_FLDSP, match_opcode, 0 },
-{"c.fld", "C", "CD,Cl(Cs)", MATCH_C_FLD, MASK_C_FLD, match_opcode, 0 },
-{"c.fsdsp", "C", "CT,CN(Cc)", MATCH_C_FSDSP, MASK_C_FSDSP, match_opcode, 0 },
-{"c.fsd", "C", "CD,Cl(Cs)", MATCH_C_FSD, MASK_C_FSD, match_opcode, 0 },
-{"c.flwsp", "32C", "D,Cm(Cc)", MATCH_C_FLWSP, MASK_C_FLWSP, match_opcode, 0 },
-{"c.flw", "32C", "CD,Ck(Cs)", MATCH_C_FLW, MASK_C_FLW, match_opcode, 0 },
-{"c.fswsp", "32C", "CT,CM(Cc)", MATCH_C_FSWSP, MASK_C_FSWSP, match_opcode, 0 },
-{"c.fsw", "32C", "CD,Ck(Cs)", MATCH_C_FSW, MASK_C_FSW, match_opcode, 0 },
-
-/* Supervisor instructions */
-{"csrr", "I", "d,E", MATCH_CSRRS, MASK_CSRRS | MASK_RS1, match_opcode, INSN_ALIAS },
-{"csrwi", "I", "E,Z", MATCH_CSRRWI, MASK_CSRRWI | MASK_RD, match_opcode, INSN_ALIAS },
-{"csrsi", "I", "E,Z", MATCH_CSRRSI, MASK_CSRRSI | MASK_RD, match_opcode, INSN_ALIAS },
-{"csrci", "I", "E,Z", MATCH_CSRRCI, MASK_CSRRCI | MASK_RD, match_opcode, INSN_ALIAS },
-{"csrw", "I", "E,s", MATCH_CSRRW, MASK_CSRRW | MASK_RD, match_opcode, INSN_ALIAS },
-{"csrw", "I", "E,Z", MATCH_CSRRWI, MASK_CSRRWI | MASK_RD, match_opcode, INSN_ALIAS },
-{"csrs", "I", "E,s", MATCH_CSRRS, MASK_CSRRS | MASK_RD, match_opcode, INSN_ALIAS },
-{"csrs", "I", "E,Z", MATCH_CSRRSI, MASK_CSRRSI | MASK_RD, match_opcode, INSN_ALIAS },
-{"csrc", "I", "E,s", MATCH_CSRRC, MASK_CSRRC | MASK_RD, match_opcode, INSN_ALIAS },
-{"csrc", "I", "E,Z", MATCH_CSRRCI, MASK_CSRRCI | MASK_RD, match_opcode, INSN_ALIAS },
-{"csrrwi", "I", "d,E,Z", MATCH_CSRRWI, MASK_CSRRWI, match_opcode, 0 },
-{"csrrsi", "I", "d,E,Z", MATCH_CSRRSI, MASK_CSRRSI, match_opcode, 0 },
-{"csrrci", "I", "d,E,Z", MATCH_CSRRCI, MASK_CSRRCI, match_opcode, 0 },
-{"csrrw", "I", "d,E,s", MATCH_CSRRW, MASK_CSRRW, match_opcode, 0 },
-{"csrrw", "I", "d,E,Z", MATCH_CSRRWI, MASK_CSRRWI, match_opcode, INSN_ALIAS },
-{"csrrs", "I", "d,E,s", MATCH_CSRRS, MASK_CSRRS, match_opcode, 0 },
-{"csrrs", "I", "d,E,Z", MATCH_CSRRSI, MASK_CSRRSI, match_opcode, INSN_ALIAS },
-{"csrrc", "I", "d,E,s", MATCH_CSRRC, MASK_CSRRC, match_opcode, 0 },
-{"csrrc", "I", "d,E,Z", MATCH_CSRRCI, MASK_CSRRCI, match_opcode, INSN_ALIAS },
-{"uret", "I", "", MATCH_URET, MASK_URET, match_opcode, 0 },
-{"sret", "I", "", MATCH_SRET, MASK_SRET, match_opcode, 0 },
-{"hret", "I", "", MATCH_HRET, MASK_HRET, match_opcode, 0 },
-{"mret", "I", "", MATCH_MRET, MASK_MRET, match_opcode, 0 },
-{"dret", "I", "", MATCH_DRET, MASK_DRET, match_opcode, 0 },
-{"sfence.vm", "I", "", MATCH_SFENCE_VM, MASK_SFENCE_VM | MASK_RS1, match_opcode, 0 },
-{"sfence.vm", "I", "s", MATCH_SFENCE_VM, MASK_SFENCE_VM, match_opcode, 0 },
-{"wfi", "I", "", MATCH_WFI, MASK_WFI, match_opcode, 0 },
-};
-
-#define RISCV_NUM_OPCODES \
- ((sizeof riscv_builtin_opcodes) / (sizeof (riscv_builtin_opcodes[0])))
-//const int bfd_riscv_num_builtin_opcodes = RISCV_NUM_OPCODES;
-
-/* Removed const from the following to allow for dynamic extensions to the
- built-in instruction set. */
-static struct riscv_opcode *riscv_opcodes =
- (struct riscv_opcode *) riscv_builtin_opcodes;
-static int bfd_riscv_num_opcodes = RISCV_NUM_OPCODES;
-#undef RISCV_NUM_OPCODES
diff --git a/librz/arch/isa_gnu/riscv/riscv-opc.h b/librz/arch/isa_gnu/riscv/riscv-opc.h
deleted file mode 100644
index af333e46980..00000000000
--- a/librz/arch/isa_gnu/riscv/riscv-opc.h
+++ /dev/null
@@ -1,1266 +0,0 @@
-// SPDX-FileCopyrightText: 2011-2015 Free Software Foundation, Inc.
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-/* Automatically generated by parse-opcodes. */
-#ifndef RISCV_ENCODING_H
-#define RISCV_ENCODING_H
-#define MATCH_SLLI_RV32 0x1013
-#define MASK_SLLI_RV32 0xfe00707f
-#define MATCH_SRLI_RV32 0x5013
-#define MASK_SRLI_RV32 0xfe00707f
-#define MATCH_SRAI_RV32 0x40005013
-#define MASK_SRAI_RV32 0xfe00707f
-#define MATCH_FRFLAGS 0x102073
-#define MASK_FRFLAGS 0xfffff07f
-#define MATCH_FSFLAGS 0x101073
-#define MASK_FSFLAGS 0xfff0707f
-#define MATCH_FSFLAGSI 0x105073
-#define MASK_FSFLAGSI 0xfff0707f
-#define MATCH_FRRM 0x202073
-#define MASK_FRRM 0xfffff07f
-#define MATCH_FSRM 0x201073
-#define MASK_FSRM 0xfff0707f
-#define MATCH_FSRMI 0x205073
-#define MASK_FSRMI 0xfff0707f
-#define MATCH_FSCSR 0x301073
-#define MASK_FSCSR 0xfff0707f
-#define MATCH_FRCSR 0x302073
-#define MASK_FRCSR 0xfffff07f
-#define MATCH_RDCYCLE 0xc0002073
-#define MASK_RDCYCLE 0xfffff07f
-#define MATCH_RDTIME 0xc0102073
-#define MASK_RDTIME 0xfffff07f
-#define MATCH_RDINSTRET 0xc0202073
-#define MASK_RDINSTRET 0xfffff07f
-#define MATCH_RDCYCLEH 0xc8002073
-#define MASK_RDCYCLEH 0xfffff07f
-#define MATCH_RDTIMEH 0xc8102073
-#define MASK_RDTIMEH 0xfffff07f
-#define MATCH_RDINSTRETH 0xc8202073
-#define MASK_RDINSTRETH 0xfffff07f
-#define MATCH_SCALL 0x73
-#define MASK_SCALL 0xffffffff
-#define MATCH_SBREAK 0x100073
-#define MASK_SBREAK 0xffffffff
-#define MATCH_BEQ 0x63
-#define MASK_BEQ 0x707f
-#define MATCH_BNE 0x1063
-#define MASK_BNE 0x707f
-#define MATCH_BLT 0x4063
-#define MASK_BLT 0x707f
-#define MATCH_BGE 0x5063
-#define MASK_BGE 0x707f
-#define MATCH_BLTU 0x6063
-#define MASK_BLTU 0x707f
-#define MATCH_BGEU 0x7063
-#define MASK_BGEU 0x707f
-#define MATCH_JALR 0x67
-#define MASK_JALR 0x707f
-#define MATCH_JAL 0x6f
-#define MASK_JAL 0x7f
-#define MATCH_LUI 0x37
-#define MASK_LUI 0x7f
-#define MATCH_AUIPC 0x17
-#define MASK_AUIPC 0x7f
-#define MATCH_ADDI 0x13
-#define MASK_ADDI 0x707f
-#define MATCH_SLLI 0x1013
-#define MASK_SLLI 0xfc00707f
-#define MATCH_SLTI 0x2013
-#define MASK_SLTI 0x707f
-#define MATCH_SLTIU 0x3013
-#define MASK_SLTIU 0x707f
-#define MATCH_XORI 0x4013
-#define MASK_XORI 0x707f
-#define MATCH_SRLI 0x5013
-#define MASK_SRLI 0xfc00707f
-#define MATCH_SRAI 0x40005013
-#define MASK_SRAI 0xfc00707f
-#define MATCH_ORI 0x6013
-#define MASK_ORI 0x707f
-#define MATCH_ANDI 0x7013
-#define MASK_ANDI 0x707f
-#define MATCH_ADD 0x33
-#define MASK_ADD 0xfe00707f
-#define MATCH_SUB 0x40000033
-#define MASK_SUB 0xfe00707f
-#define MATCH_SLL 0x1033
-#define MASK_SLL 0xfe00707f
-#define MATCH_SLT 0x2033
-#define MASK_SLT 0xfe00707f
-#define MATCH_SLTU 0x3033
-#define MASK_SLTU 0xfe00707f
-#define MATCH_XOR 0x4033
-#define MASK_XOR 0xfe00707f
-#define MATCH_SRL 0x5033
-#define MASK_SRL 0xfe00707f
-#define MATCH_SRA 0x40005033
-#define MASK_SRA 0xfe00707f
-#define MATCH_OR 0x6033
-#define MASK_OR 0xfe00707f
-#define MATCH_AND 0x7033
-#define MASK_AND 0xfe00707f
-#define MATCH_ADDIW 0x1b
-#define MASK_ADDIW 0x707f
-#define MATCH_SLLIW 0x101b
-#define MASK_SLLIW 0xfe00707f
-#define MATCH_SRLIW 0x501b
-#define MASK_SRLIW 0xfe00707f
-#define MATCH_SRAIW 0x4000501b
-#define MASK_SRAIW 0xfe00707f
-#define MATCH_ADDW 0x3b
-#define MASK_ADDW 0xfe00707f
-#define MATCH_SUBW 0x4000003b
-#define MASK_SUBW 0xfe00707f
-#define MATCH_SLLW 0x103b
-#define MASK_SLLW 0xfe00707f
-#define MATCH_SRLW 0x503b
-#define MASK_SRLW 0xfe00707f
-#define MATCH_SRAW 0x4000503b
-#define MASK_SRAW 0xfe00707f
-#define MATCH_LB 0x3
-#define MASK_LB 0x707f
-#define MATCH_LH 0x1003
-#define MASK_LH 0x707f
-#define MATCH_LW 0x2003
-#define MASK_LW 0x707f
-#define MATCH_LD 0x3003
-#define MASK_LD 0x707f
-#define MATCH_LBU 0x4003
-#define MASK_LBU 0x707f
-#define MATCH_LHU 0x5003
-#define MASK_LHU 0x707f
-#define MATCH_LWU 0x6003
-#define MASK_LWU 0x707f
-#define MATCH_SB 0x23
-#define MASK_SB 0x707f
-#define MATCH_SH 0x1023
-#define MASK_SH 0x707f
-#define MATCH_SW 0x2023
-#define MASK_SW 0x707f
-#define MATCH_SD 0x3023
-#define MASK_SD 0x707f
-#define MATCH_FENCE 0xf
-#define MASK_FENCE 0x707f
-#define MATCH_FENCE_I 0x100f
-#define MASK_FENCE_I 0x707f
-#define MATCH_MUL 0x2000033
-#define MASK_MUL 0xfe00707f
-#define MATCH_MULH 0x2001033
-#define MASK_MULH 0xfe00707f
-#define MATCH_MULHSU 0x2002033
-#define MASK_MULHSU 0xfe00707f
-#define MATCH_MULHU 0x2003033
-#define MASK_MULHU 0xfe00707f
-#define MATCH_DIV 0x2004033
-#define MASK_DIV 0xfe00707f
-#define MATCH_DIVU 0x2005033
-#define MASK_DIVU 0xfe00707f
-#define MATCH_REM 0x2006033
-#define MASK_REM 0xfe00707f
-#define MATCH_REMU 0x2007033
-#define MASK_REMU 0xfe00707f
-#define MATCH_MULW 0x200003b
-#define MASK_MULW 0xfe00707f
-#define MATCH_DIVW 0x200403b
-#define MASK_DIVW 0xfe00707f
-#define MATCH_DIVUW 0x200503b
-#define MASK_DIVUW 0xfe00707f
-#define MATCH_REMW 0x200603b
-#define MASK_REMW 0xfe00707f
-#define MATCH_REMUW 0x200703b
-#define MASK_REMUW 0xfe00707f
-#define MATCH_AMOADD_W 0x202f
-#define MASK_AMOADD_W 0xf800707f
-#define MATCH_AMOXOR_W 0x2000202f
-#define MASK_AMOXOR_W 0xf800707f
-#define MATCH_AMOOR_W 0x4000202f
-#define MASK_AMOOR_W 0xf800707f
-#define MATCH_AMOAND_W 0x6000202f
-#define MASK_AMOAND_W 0xf800707f
-#define MATCH_AMOMIN_W 0x8000202f
-#define MASK_AMOMIN_W 0xf800707f
-#define MATCH_AMOMAX_W 0xa000202f
-#define MASK_AMOMAX_W 0xf800707f
-#define MATCH_AMOMINU_W 0xc000202f
-#define MASK_AMOMINU_W 0xf800707f
-#define MATCH_AMOMAXU_W 0xe000202f
-#define MASK_AMOMAXU_W 0xf800707f
-#define MATCH_AMOSWAP_W 0x800202f
-#define MASK_AMOSWAP_W 0xf800707f
-#define MATCH_LR_W 0x1000202f
-#define MASK_LR_W 0xf9f0707f
-#define MATCH_SC_W 0x1800202f
-#define MASK_SC_W 0xf800707f
-#define MATCH_AMOADD_D 0x302f
-#define MASK_AMOADD_D 0xf800707f
-#define MATCH_AMOXOR_D 0x2000302f
-#define MASK_AMOXOR_D 0xf800707f
-#define MATCH_AMOOR_D 0x4000302f
-#define MASK_AMOOR_D 0xf800707f
-#define MATCH_AMOAND_D 0x6000302f
-#define MASK_AMOAND_D 0xf800707f
-#define MATCH_AMOMIN_D 0x8000302f
-#define MASK_AMOMIN_D 0xf800707f
-#define MATCH_AMOMAX_D 0xa000302f
-#define MASK_AMOMAX_D 0xf800707f
-#define MATCH_AMOMINU_D 0xc000302f
-#define MASK_AMOMINU_D 0xf800707f
-#define MATCH_AMOMAXU_D 0xe000302f
-#define MASK_AMOMAXU_D 0xf800707f
-#define MATCH_AMOSWAP_D 0x800302f
-#define MASK_AMOSWAP_D 0xf800707f
-#define MATCH_LR_D 0x1000302f
-#define MASK_LR_D 0xf9f0707f
-#define MATCH_SC_D 0x1800302f
-#define MASK_SC_D 0xf800707f
-#define MATCH_ECALL 0x73
-#define MASK_ECALL 0xffffffff
-#define MATCH_EBREAK 0x100073
-#define MASK_EBREAK 0xffffffff
-#define MATCH_URET 0x200073
-#define MASK_URET 0xffffffff
-#define MATCH_SRET 0x10200073
-#define MASK_SRET 0xffffffff
-#define MATCH_HRET 0x20200073
-#define MASK_HRET 0xffffffff
-#define MATCH_MRET 0x30200073
-#define MASK_MRET 0xffffffff
-#define MATCH_DRET 0x7b200073
-#define MASK_DRET 0xffffffff
-#define MATCH_SFENCE_VM 0x10400073
-#define MASK_SFENCE_VM 0xfff07fff
-#define MATCH_WFI 0x10500073
-#define MASK_WFI 0xffffffff
-#define MATCH_CSRRW 0x1073
-#define MASK_CSRRW 0x707f
-#define MATCH_CSRRS 0x2073
-#define MASK_CSRRS 0x707f
-#define MATCH_CSRRC 0x3073
-#define MASK_CSRRC 0x707f
-#define MATCH_CSRRWI 0x5073
-#define MASK_CSRRWI 0x707f
-#define MATCH_CSRRSI 0x6073
-#define MASK_CSRRSI 0x707f
-#define MATCH_CSRRCI 0x7073
-#define MASK_CSRRCI 0x707f
-#define MATCH_FADD_S 0x53
-#define MASK_FADD_S 0xfe00007f
-#define MATCH_FSUB_S 0x8000053
-#define MASK_FSUB_S 0xfe00007f
-#define MATCH_FMUL_S 0x10000053
-#define MASK_FMUL_S 0xfe00007f
-#define MATCH_FDIV_S 0x18000053
-#define MASK_FDIV_S 0xfe00007f
-#define MATCH_FSGNJ_S 0x20000053
-#define MASK_FSGNJ_S 0xfe00707f
-#define MATCH_FSGNJN_S 0x20001053
-#define MASK_FSGNJN_S 0xfe00707f
-#define MATCH_FSGNJX_S 0x20002053
-#define MASK_FSGNJX_S 0xfe00707f
-#define MATCH_FMIN_S 0x28000053
-#define MASK_FMIN_S 0xfe00707f
-#define MATCH_FMAX_S 0x28001053
-#define MASK_FMAX_S 0xfe00707f
-#define MATCH_FSQRT_S 0x58000053
-#define MASK_FSQRT_S 0xfff0007f
-#define MATCH_FADD_D 0x2000053
-#define MASK_FADD_D 0xfe00007f
-#define MATCH_FSUB_D 0xa000053
-#define MASK_FSUB_D 0xfe00007f
-#define MATCH_FMUL_D 0x12000053
-#define MASK_FMUL_D 0xfe00007f
-#define MATCH_FDIV_D 0x1a000053
-#define MASK_FDIV_D 0xfe00007f
-#define MATCH_FSGNJ_D 0x22000053
-#define MASK_FSGNJ_D 0xfe00707f
-#define MATCH_FSGNJN_D 0x22001053
-#define MASK_FSGNJN_D 0xfe00707f
-#define MATCH_FSGNJX_D 0x22002053
-#define MASK_FSGNJX_D 0xfe00707f
-#define MATCH_FMIN_D 0x2a000053
-#define MASK_FMIN_D 0xfe00707f
-#define MATCH_FMAX_D 0x2a001053
-#define MASK_FMAX_D 0xfe00707f
-#define MATCH_FCVT_S_D 0x40100053
-#define MASK_FCVT_S_D 0xfff0007f
-#define MATCH_FCVT_D_S 0x42000053
-#define MASK_FCVT_D_S 0xfff0007f
-#define MATCH_FSQRT_D 0x5a000053
-#define MASK_FSQRT_D 0xfff0007f
-#define MATCH_FADD_Q 0x6000053
-#define MASK_FADD_Q 0xfe00007f
-#define MATCH_FSUB_Q 0xe000053
-#define MASK_FSUB_Q 0xfe00007f
-#define MATCH_FMUL_Q 0x16000053
-#define MASK_FMUL_Q 0xfe00007f
-#define MATCH_FDIV_Q 0x1e000053
-#define MASK_FDIV_Q 0xfe00007f
-#define MATCH_FSGNJ_Q 0x26000053
-#define MASK_FSGNJ_Q 0xfe00707f
-#define MATCH_FSGNJN_Q 0x26001053
-#define MASK_FSGNJN_Q 0xfe00707f
-#define MATCH_FSGNJX_Q 0x26002053
-#define MASK_FSGNJX_Q 0xfe00707f
-#define MATCH_FMIN_Q 0x2e000053
-#define MASK_FMIN_Q 0xfe00707f
-#define MATCH_FMAX_Q 0x2e001053
-#define MASK_FMAX_Q 0xfe00707f
-#define MATCH_FCVT_S_Q 0x40300053
-#define MASK_FCVT_S_Q 0xfff0007f
-#define MATCH_FCVT_Q_S 0x46000053
-#define MASK_FCVT_Q_S 0xfff0007f
-#define MATCH_FCVT_D_Q 0x42300053
-#define MASK_FCVT_D_Q 0xfff0007f
-#define MATCH_FCVT_Q_D 0x46100053
-#define MASK_FCVT_Q_D 0xfff0007f
-#define MATCH_FSQRT_Q 0x5e000053
-#define MASK_FSQRT_Q 0xfff0007f
-#define MATCH_FLE_S 0xa0000053
-#define MASK_FLE_S 0xfe00707f
-#define MATCH_FLT_S 0xa0001053
-#define MASK_FLT_S 0xfe00707f
-#define MATCH_FEQ_S 0xa0002053
-#define MASK_FEQ_S 0xfe00707f
-#define MATCH_FLE_D 0xa2000053
-#define MASK_FLE_D 0xfe00707f
-#define MATCH_FLT_D 0xa2001053
-#define MASK_FLT_D 0xfe00707f
-#define MATCH_FEQ_D 0xa2002053
-#define MASK_FEQ_D 0xfe00707f
-#define MATCH_FLE_Q 0xa6000053
-#define MASK_FLE_Q 0xfe00707f
-#define MATCH_FLT_Q 0xa6001053
-#define MASK_FLT_Q 0xfe00707f
-#define MATCH_FEQ_Q 0xa6002053
-#define MASK_FEQ_Q 0xfe00707f
-#define MATCH_FCVT_W_S 0xc0000053
-#define MASK_FCVT_W_S 0xfff0007f
-#define MATCH_FCVT_WU_S 0xc0100053
-#define MASK_FCVT_WU_S 0xfff0007f
-#define MATCH_FCVT_L_S 0xc0200053
-#define MASK_FCVT_L_S 0xfff0007f
-#define MATCH_FCVT_LU_S 0xc0300053
-#define MASK_FCVT_LU_S 0xfff0007f
-#define MATCH_FMV_X_S 0xe0000053
-#define MASK_FMV_X_S 0xfff0707f
-#define MATCH_FCLASS_S 0xe0001053
-#define MASK_FCLASS_S 0xfff0707f
-#define MATCH_FCVT_W_D 0xc2000053
-#define MASK_FCVT_W_D 0xfff0007f
-#define MATCH_FCVT_WU_D 0xc2100053
-#define MASK_FCVT_WU_D 0xfff0007f
-#define MATCH_FCVT_L_D 0xc2200053
-#define MASK_FCVT_L_D 0xfff0007f
-#define MATCH_FCVT_LU_D 0xc2300053
-#define MASK_FCVT_LU_D 0xfff0007f
-#define MATCH_FMV_X_D 0xe2000053
-#define MASK_FMV_X_D 0xfff0707f
-#define MATCH_FCLASS_D 0xe2001053
-#define MASK_FCLASS_D 0xfff0707f
-#define MATCH_FCVT_W_Q 0xc6000053
-#define MASK_FCVT_W_Q 0xfff0007f
-#define MATCH_FCVT_WU_Q 0xc6100053
-#define MASK_FCVT_WU_Q 0xfff0007f
-#define MATCH_FCVT_L_Q 0xc6200053
-#define MASK_FCVT_L_Q 0xfff0007f
-#define MATCH_FCVT_LU_Q 0xc6300053
-#define MASK_FCVT_LU_Q 0xfff0007f
-#define MATCH_FMV_X_Q 0xe6000053
-#define MASK_FMV_X_Q 0xfff0707f
-#define MATCH_FCLASS_Q 0xe6001053
-#define MASK_FCLASS_Q 0xfff0707f
-#define MATCH_FCVT_S_W 0xd0000053
-#define MASK_FCVT_S_W 0xfff0007f
-#define MATCH_FCVT_S_WU 0xd0100053
-#define MASK_FCVT_S_WU 0xfff0007f
-#define MATCH_FCVT_S_L 0xd0200053
-#define MASK_FCVT_S_L 0xfff0007f
-#define MATCH_FCVT_S_LU 0xd0300053
-#define MASK_FCVT_S_LU 0xfff0007f
-#define MATCH_FMV_S_X 0xf0000053
-#define MASK_FMV_S_X 0xfff0707f
-#define MATCH_FCVT_D_W 0xd2000053
-#define MASK_FCVT_D_W 0xfff0007f
-#define MATCH_FCVT_D_WU 0xd2100053
-#define MASK_FCVT_D_WU 0xfff0007f
-#define MATCH_FCVT_D_L 0xd2200053
-#define MASK_FCVT_D_L 0xfff0007f
-#define MATCH_FCVT_D_LU 0xd2300053
-#define MASK_FCVT_D_LU 0xfff0007f
-#define MATCH_FMV_D_X 0xf2000053
-#define MASK_FMV_D_X 0xfff0707f
-#define MATCH_FCVT_Q_W 0xd6000053
-#define MASK_FCVT_Q_W 0xfff0007f
-#define MATCH_FCVT_Q_WU 0xd6100053
-#define MASK_FCVT_Q_WU 0xfff0007f
-#define MATCH_FCVT_Q_L 0xd6200053
-#define MASK_FCVT_Q_L 0xfff0007f
-#define MATCH_FCVT_Q_LU 0xd6300053
-#define MASK_FCVT_Q_LU 0xfff0007f
-#define MATCH_FMV_Q_X 0xf6000053
-#define MASK_FMV_Q_X 0xfff0707f
-#define MATCH_FLW 0x2007
-#define MASK_FLW 0x707f
-#define MATCH_FLD 0x3007
-#define MASK_FLD 0x707f
-#define MATCH_FLQ 0x4007
-#define MASK_FLQ 0x707f
-#define MATCH_FSW 0x2027
-#define MASK_FSW 0x707f
-#define MATCH_FSD 0x3027
-#define MASK_FSD 0x707f
-#define MATCH_FSQ 0x4027
-#define MASK_FSQ 0x707f
-#define MATCH_FMADD_S 0x43
-#define MASK_FMADD_S 0x600007f
-#define MATCH_FMSUB_S 0x47
-#define MASK_FMSUB_S 0x600007f
-#define MATCH_FNMSUB_S 0x4b
-#define MASK_FNMSUB_S 0x600007f
-#define MATCH_FNMADD_S 0x4f
-#define MASK_FNMADD_S 0x600007f
-#define MATCH_FMADD_D 0x2000043
-#define MASK_FMADD_D 0x600007f
-#define MATCH_FMSUB_D 0x2000047
-#define MASK_FMSUB_D 0x600007f
-#define MATCH_FNMSUB_D 0x200004b
-#define MASK_FNMSUB_D 0x600007f
-#define MATCH_FNMADD_D 0x200004f
-#define MASK_FNMADD_D 0x600007f
-#define MATCH_FMADD_Q 0x6000043
-#define MASK_FMADD_Q 0x600007f
-#define MATCH_FMSUB_Q 0x6000047
-#define MASK_FMSUB_Q 0x600007f
-#define MATCH_FNMSUB_Q 0x600004b
-#define MASK_FNMSUB_Q 0x600007f
-#define MATCH_FNMADD_Q 0x600004f
-#define MASK_FNMADD_Q 0x600007f
-#define MATCH_C_ADDI4SPN 0x0
-#define MASK_C_ADDI4SPN 0xe003
-#define MATCH_C_FLD 0x2000
-#define MASK_C_FLD 0xe003
-#define MATCH_C_LW 0x4000
-#define MASK_C_LW 0xe003
-#define MATCH_C_FLW 0x6000
-#define MASK_C_FLW 0xe003
-#define MATCH_C_FSD 0xa000
-#define MASK_C_FSD 0xe003
-#define MATCH_C_SW 0xc000
-#define MASK_C_SW 0xe003
-#define MATCH_C_FSW 0xe000
-#define MASK_C_FSW 0xe003
-#define MATCH_C_ADDI 0x1
-#define MASK_C_ADDI 0xe003
-#define MATCH_C_JAL 0x2001
-#define MASK_C_JAL 0xe003
-#define MATCH_C_LI 0x4001
-#define MASK_C_LI 0xe003
-#define MATCH_C_LUI 0x6001
-#define MASK_C_LUI 0xe003
-#define MATCH_C_SRLI 0x8001
-#define MASK_C_SRLI 0xec03
-#define MATCH_C_SRAI 0x8401
-#define MASK_C_SRAI 0xec03
-#define MATCH_C_ANDI 0x8801
-#define MASK_C_ANDI 0xec03
-#define MATCH_C_SUB 0x8c01
-#define MASK_C_SUB 0xfc63
-#define MATCH_C_XOR 0x8c21
-#define MASK_C_XOR 0xfc63
-#define MATCH_C_OR 0x8c41
-#define MASK_C_OR 0xfc63
-#define MATCH_C_AND 0x8c61
-#define MASK_C_AND 0xfc63
-#define MATCH_C_SUBW 0x9c01
-#define MASK_C_SUBW 0xfc63
-#define MATCH_C_ADDW 0x9c21
-#define MASK_C_ADDW 0xfc63
-#define MATCH_C_J 0xa001
-#define MASK_C_J 0xe003
-#define MATCH_C_BEQZ 0xc001
-#define MASK_C_BEQZ 0xe003
-#define MATCH_C_BNEZ 0xe001
-#define MASK_C_BNEZ 0xe003
-#define MATCH_C_SLLI 0x2
-#define MASK_C_SLLI 0xe003
-#define MATCH_C_FLDSP 0x2002
-#define MASK_C_FLDSP 0xe003
-#define MATCH_C_LWSP 0x4002
-#define MASK_C_LWSP 0xe003
-#define MATCH_C_FLWSP 0x6002
-#define MASK_C_FLWSP 0xe003
-#define MATCH_C_MV 0x8002
-#define MASK_C_MV 0xf003
-#define MATCH_C_ADD 0x9002
-#define MASK_C_ADD 0xf003
-#define MATCH_C_FSDSP 0xa002
-#define MASK_C_FSDSP 0xe003
-#define MATCH_C_SWSP 0xc002
-#define MASK_C_SWSP 0xe003
-#define MATCH_C_FSWSP 0xe002
-#define MASK_C_FSWSP 0xe003
-#define MATCH_C_NOP 0x1
-#define MASK_C_NOP 0xffff
-#define MATCH_C_ADDI16SP 0x6101
-#define MASK_C_ADDI16SP 0xef83
-#define MATCH_C_JR 0x8002
-#define MASK_C_JR 0xf07f
-#define MATCH_C_JALR 0x9002
-#define MASK_C_JALR 0xf07f
-#define MATCH_C_EBREAK 0x9002
-#define MASK_C_EBREAK 0xffff
-#define MATCH_C_LD 0x6000
-#define MASK_C_LD 0xe003
-#define MATCH_C_SD 0xe000
-#define MASK_C_SD 0xe003
-#define MATCH_C_ADDIW 0x2001
-#define MASK_C_ADDIW 0xe003
-#define MATCH_C_LDSP 0x6002
-#define MASK_C_LDSP 0xe003
-#define MATCH_C_SDSP 0xe002
-#define MASK_C_SDSP 0xe003
-#define MATCH_CUSTOM0 0xb
-#define MASK_CUSTOM0 0x707f
-#define MATCH_CUSTOM0_RS1 0x200b
-#define MASK_CUSTOM0_RS1 0x707f
-#define MATCH_CUSTOM0_RS1_RS2 0x300b
-#define MASK_CUSTOM0_RS1_RS2 0x707f
-#define MATCH_CUSTOM0_RD 0x400b
-#define MASK_CUSTOM0_RD 0x707f
-#define MATCH_CUSTOM0_RD_RS1 0x600b
-#define MASK_CUSTOM0_RD_RS1 0x707f
-#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b
-#define MASK_CUSTOM0_RD_RS1_RS2 0x707f
-#define MATCH_CUSTOM1 0x2b
-#define MASK_CUSTOM1 0x707f
-#define MATCH_CUSTOM1_RS1 0x202b
-#define MASK_CUSTOM1_RS1 0x707f
-#define MATCH_CUSTOM1_RS1_RS2 0x302b
-#define MASK_CUSTOM1_RS1_RS2 0x707f
-#define MATCH_CUSTOM1_RD 0x402b
-#define MASK_CUSTOM1_RD 0x707f
-#define MATCH_CUSTOM1_RD_RS1 0x602b
-#define MASK_CUSTOM1_RD_RS1 0x707f
-#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b
-#define MASK_CUSTOM1_RD_RS1_RS2 0x707f
-#define MATCH_CUSTOM2 0x5b
-#define MASK_CUSTOM2 0x707f
-#define MATCH_CUSTOM2_RS1 0x205b
-#define MASK_CUSTOM2_RS1 0x707f
-#define MATCH_CUSTOM2_RS1_RS2 0x305b
-#define MASK_CUSTOM2_RS1_RS2 0x707f
-#define MATCH_CUSTOM2_RD 0x405b
-#define MASK_CUSTOM2_RD 0x707f
-#define MATCH_CUSTOM2_RD_RS1 0x605b
-#define MASK_CUSTOM2_RD_RS1 0x707f
-#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b
-#define MASK_CUSTOM2_RD_RS1_RS2 0x707f
-#define MATCH_CUSTOM3 0x7b
-#define MASK_CUSTOM3 0x707f
-#define MATCH_CUSTOM3_RS1 0x207b
-#define MASK_CUSTOM3_RS1 0x707f
-#define MATCH_CUSTOM3_RS1_RS2 0x307b
-#define MASK_CUSTOM3_RS1_RS2 0x707f
-#define MATCH_CUSTOM3_RD 0x407b
-#define MASK_CUSTOM3_RD 0x707f
-#define MATCH_CUSTOM3_RD_RS1 0x607b
-#define MASK_CUSTOM3_RD_RS1 0x707f
-#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b
-#define MASK_CUSTOM3_RD_RS1_RS2 0x707f
-#define CSR_FFLAGS 0x1
-#define CSR_FRM 0x2
-#define CSR_FCSR 0x3
-#define CSR_CYCLE 0xc00
-#define CSR_TIME 0xc01
-#define CSR_INSTRET 0xc02
-#define CSR_HPMCOUNTER3 0xc03
-#define CSR_HPMCOUNTER4 0xc04
-#define CSR_HPMCOUNTER5 0xc05
-#define CSR_HPMCOUNTER6 0xc06
-#define CSR_HPMCOUNTER7 0xc07
-#define CSR_HPMCOUNTER8 0xc08
-#define CSR_HPMCOUNTER9 0xc09
-#define CSR_HPMCOUNTER10 0xc0a
-#define CSR_HPMCOUNTER11 0xc0b
-#define CSR_HPMCOUNTER12 0xc0c
-#define CSR_HPMCOUNTER13 0xc0d
-#define CSR_HPMCOUNTER14 0xc0e
-#define CSR_HPMCOUNTER15 0xc0f
-#define CSR_HPMCOUNTER16 0xc10
-#define CSR_HPMCOUNTER17 0xc11
-#define CSR_HPMCOUNTER18 0xc12
-#define CSR_HPMCOUNTER19 0xc13
-#define CSR_HPMCOUNTER20 0xc14
-#define CSR_HPMCOUNTER21 0xc15
-#define CSR_HPMCOUNTER22 0xc16
-#define CSR_HPMCOUNTER23 0xc17
-#define CSR_HPMCOUNTER24 0xc18
-#define CSR_HPMCOUNTER25 0xc19
-#define CSR_HPMCOUNTER26 0xc1a
-#define CSR_HPMCOUNTER27 0xc1b
-#define CSR_HPMCOUNTER28 0xc1c
-#define CSR_HPMCOUNTER29 0xc1d
-#define CSR_HPMCOUNTER30 0xc1e
-#define CSR_HPMCOUNTER31 0xc1f
-#define CSR_SSTATUS 0x100
-#define CSR_SIE 0x104
-#define CSR_STVEC 0x105
-#define CSR_SSCRATCH 0x140
-#define CSR_SEPC 0x141
-#define CSR_SCAUSE 0x142
-#define CSR_SBADADDR 0x143
-#define CSR_SIP 0x144
-#define CSR_SPTBR 0x180
-#define CSR_MSTATUS 0x300
-#define CSR_MISA 0x301
-#define CSR_MEDELEG 0x302
-#define CSR_MIDELEG 0x303
-#define CSR_MIE 0x304
-#define CSR_MTVEC 0x305
-#define CSR_MSCRATCH 0x340
-#define CSR_MEPC 0x341
-#define CSR_MCAUSE 0x342
-#define CSR_MBADADDR 0x343
-#define CSR_MIP 0x344
-#define CSR_TSELECT 0x7a0
-#define CSR_TDATA1 0x7a1
-#define CSR_TDATA2 0x7a2
-#define CSR_TDATA3 0x7a3
-#define CSR_DCSR 0x7b0
-#define CSR_DPC 0x7b1
-#define CSR_DSCRATCH 0x7b2
-#define CSR_MCYCLE 0xb00
-#define CSR_MINSTRET 0xb02
-#define CSR_MHPMCOUNTER3 0xb03
-#define CSR_MHPMCOUNTER4 0xb04
-#define CSR_MHPMCOUNTER5 0xb05
-#define CSR_MHPMCOUNTER6 0xb06
-#define CSR_MHPMCOUNTER7 0xb07
-#define CSR_MHPMCOUNTER8 0xb08
-#define CSR_MHPMCOUNTER9 0xb09
-#define CSR_MHPMCOUNTER10 0xb0a
-#define CSR_MHPMCOUNTER11 0xb0b
-#define CSR_MHPMCOUNTER12 0xb0c
-#define CSR_MHPMCOUNTER13 0xb0d
-#define CSR_MHPMCOUNTER14 0xb0e
-#define CSR_MHPMCOUNTER15 0xb0f
-#define CSR_MHPMCOUNTER16 0xb10
-#define CSR_MHPMCOUNTER17 0xb11
-#define CSR_MHPMCOUNTER18 0xb12
-#define CSR_MHPMCOUNTER19 0xb13
-#define CSR_MHPMCOUNTER20 0xb14
-#define CSR_MHPMCOUNTER21 0xb15
-#define CSR_MHPMCOUNTER22 0xb16
-#define CSR_MHPMCOUNTER23 0xb17
-#define CSR_MHPMCOUNTER24 0xb18
-#define CSR_MHPMCOUNTER25 0xb19
-#define CSR_MHPMCOUNTER26 0xb1a
-#define CSR_MHPMCOUNTER27 0xb1b
-#define CSR_MHPMCOUNTER28 0xb1c
-#define CSR_MHPMCOUNTER29 0xb1d
-#define CSR_MHPMCOUNTER30 0xb1e
-#define CSR_MHPMCOUNTER31 0xb1f
-#define CSR_MUCOUNTEREN 0x320
-#define CSR_MSCOUNTEREN 0x321
-#define CSR_MHPMEVENT3 0x323
-#define CSR_MHPMEVENT4 0x324
-#define CSR_MHPMEVENT5 0x325
-#define CSR_MHPMEVENT6 0x326
-#define CSR_MHPMEVENT7 0x327
-#define CSR_MHPMEVENT8 0x328
-#define CSR_MHPMEVENT9 0x329
-#define CSR_MHPMEVENT10 0x32a
-#define CSR_MHPMEVENT11 0x32b
-#define CSR_MHPMEVENT12 0x32c
-#define CSR_MHPMEVENT13 0x32d
-#define CSR_MHPMEVENT14 0x32e
-#define CSR_MHPMEVENT15 0x32f
-#define CSR_MHPMEVENT16 0x330
-#define CSR_MHPMEVENT17 0x331
-#define CSR_MHPMEVENT18 0x332
-#define CSR_MHPMEVENT19 0x333
-#define CSR_MHPMEVENT20 0x334
-#define CSR_MHPMEVENT21 0x335
-#define CSR_MHPMEVENT22 0x336
-#define CSR_MHPMEVENT23 0x337
-#define CSR_MHPMEVENT24 0x338
-#define CSR_MHPMEVENT25 0x339
-#define CSR_MHPMEVENT26 0x33a
-#define CSR_MHPMEVENT27 0x33b
-#define CSR_MHPMEVENT28 0x33c
-#define CSR_MHPMEVENT29 0x33d
-#define CSR_MHPMEVENT30 0x33e
-#define CSR_MHPMEVENT31 0x33f
-#define CSR_MVENDORID 0xf11
-#define CSR_MARCHID 0xf12
-#define CSR_MIMPID 0xf13
-#define CSR_MHARTID 0xf14
-#define CSR_CYCLEH 0xc80
-#define CSR_TIMEH 0xc81
-#define CSR_INSTRETH 0xc82
-#define CSR_HPMCOUNTER3H 0xc83
-#define CSR_HPMCOUNTER4H 0xc84
-#define CSR_HPMCOUNTER5H 0xc85
-#define CSR_HPMCOUNTER6H 0xc86
-#define CSR_HPMCOUNTER7H 0xc87
-#define CSR_HPMCOUNTER8H 0xc88
-#define CSR_HPMCOUNTER9H 0xc89
-#define CSR_HPMCOUNTER10H 0xc8a
-#define CSR_HPMCOUNTER11H 0xc8b
-#define CSR_HPMCOUNTER12H 0xc8c
-#define CSR_HPMCOUNTER13H 0xc8d
-#define CSR_HPMCOUNTER14H 0xc8e
-#define CSR_HPMCOUNTER15H 0xc8f
-#define CSR_HPMCOUNTER16H 0xc90
-#define CSR_HPMCOUNTER17H 0xc91
-#define CSR_HPMCOUNTER18H 0xc92
-#define CSR_HPMCOUNTER19H 0xc93
-#define CSR_HPMCOUNTER20H 0xc94
-#define CSR_HPMCOUNTER21H 0xc95
-#define CSR_HPMCOUNTER22H 0xc96
-#define CSR_HPMCOUNTER23H 0xc97
-#define CSR_HPMCOUNTER24H 0xc98
-#define CSR_HPMCOUNTER25H 0xc99
-#define CSR_HPMCOUNTER26H 0xc9a
-#define CSR_HPMCOUNTER27H 0xc9b
-#define CSR_HPMCOUNTER28H 0xc9c
-#define CSR_HPMCOUNTER29H 0xc9d
-#define CSR_HPMCOUNTER30H 0xc9e
-#define CSR_HPMCOUNTER31H 0xc9f
-#define CSR_MCYCLEH 0xb80
-#define CSR_MINSTRETH 0xb82
-#define CSR_MHPMCOUNTER3H 0xb83
-#define CSR_MHPMCOUNTER4H 0xb84
-#define CSR_MHPMCOUNTER5H 0xb85
-#define CSR_MHPMCOUNTER6H 0xb86
-#define CSR_MHPMCOUNTER7H 0xb87
-#define CSR_MHPMCOUNTER8H 0xb88
-#define CSR_MHPMCOUNTER9H 0xb89
-#define CSR_MHPMCOUNTER10H 0xb8a
-#define CSR_MHPMCOUNTER11H 0xb8b
-#define CSR_MHPMCOUNTER12H 0xb8c
-#define CSR_MHPMCOUNTER13H 0xb8d
-#define CSR_MHPMCOUNTER14H 0xb8e
-#define CSR_MHPMCOUNTER15H 0xb8f
-#define CSR_MHPMCOUNTER16H 0xb90
-#define CSR_MHPMCOUNTER17H 0xb91
-#define CSR_MHPMCOUNTER18H 0xb92
-#define CSR_MHPMCOUNTER19H 0xb93
-#define CSR_MHPMCOUNTER20H 0xb94
-#define CSR_MHPMCOUNTER21H 0xb95
-#define CSR_MHPMCOUNTER22H 0xb96
-#define CSR_MHPMCOUNTER23H 0xb97
-#define CSR_MHPMCOUNTER24H 0xb98
-#define CSR_MHPMCOUNTER25H 0xb99
-#define CSR_MHPMCOUNTER26H 0xb9a
-#define CSR_MHPMCOUNTER27H 0xb9b
-#define CSR_MHPMCOUNTER28H 0xb9c
-#define CSR_MHPMCOUNTER29H 0xb9d
-#define CSR_MHPMCOUNTER30H 0xb9e
-#define CSR_MHPMCOUNTER31H 0xb9f
-#define CAUSE_MISALIGNED_FETCH 0x0
-#define CAUSE_FAULT_FETCH 0x1
-#define CAUSE_ILLEGAL_INSTRUCTION 0x2
-#define CAUSE_BREAKPOINT 0x3
-#define CAUSE_MISALIGNED_LOAD 0x4
-#define CAUSE_FAULT_LOAD 0x5
-#define CAUSE_MISALIGNED_STORE 0x6
-#define CAUSE_FAULT_STORE 0x7
-#define CAUSE_USER_ECALL 0x8
-#define CAUSE_SUPERVISOR_ECALL 0x9
-#define CAUSE_HYPERVISOR_ECALL 0xa
-#define CAUSE_MACHINE_ECALL 0xb
-#endif
-#ifdef DECLARE_INSN
-DECLARE_INSN(slli_rv32, MATCH_SLLI_RV32, MASK_SLLI_RV32)
-DECLARE_INSN(srli_rv32, MATCH_SRLI_RV32, MASK_SRLI_RV32)
-DECLARE_INSN(srai_rv32, MATCH_SRAI_RV32, MASK_SRAI_RV32)
-DECLARE_INSN(frflags, MATCH_FRFLAGS, MASK_FRFLAGS)
-DECLARE_INSN(fsflags, MATCH_FSFLAGS, MASK_FSFLAGS)
-DECLARE_INSN(fsflagsi, MATCH_FSFLAGSI, MASK_FSFLAGSI)
-DECLARE_INSN(frrm, MATCH_FRRM, MASK_FRRM)
-DECLARE_INSN(fsrm, MATCH_FSRM, MASK_FSRM)
-DECLARE_INSN(fsrmi, MATCH_FSRMI, MASK_FSRMI)
-DECLARE_INSN(fscsr, MATCH_FSCSR, MASK_FSCSR)
-DECLARE_INSN(frcsr, MATCH_FRCSR, MASK_FRCSR)
-DECLARE_INSN(rdcycle, MATCH_RDCYCLE, MASK_RDCYCLE)
-DECLARE_INSN(rdtime, MATCH_RDTIME, MASK_RDTIME)
-DECLARE_INSN(rdinstret, MATCH_RDINSTRET, MASK_RDINSTRET)
-DECLARE_INSN(rdcycleh, MATCH_RDCYCLEH, MASK_RDCYCLEH)
-DECLARE_INSN(rdtimeh, MATCH_RDTIMEH, MASK_RDTIMEH)
-DECLARE_INSN(rdinstreth, MATCH_RDINSTRETH, MASK_RDINSTRETH)
-DECLARE_INSN(scall, MATCH_SCALL, MASK_SCALL)
-DECLARE_INSN(sbreak, MATCH_SBREAK, MASK_SBREAK)
-DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ)
-DECLARE_INSN(bne, MATCH_BNE, MASK_BNE)
-DECLARE_INSN(blt, MATCH_BLT, MASK_BLT)
-DECLARE_INSN(bge, MATCH_BGE, MASK_BGE)
-DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU)
-DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU)
-DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR)
-DECLARE_INSN(jal, MATCH_JAL, MASK_JAL)
-DECLARE_INSN(lui, MATCH_LUI, MASK_LUI)
-DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC)
-DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI)
-DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI)
-DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI)
-DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU)
-DECLARE_INSN(xori, MATCH_XORI, MASK_XORI)
-DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI)
-DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI)
-DECLARE_INSN(ori, MATCH_ORI, MASK_ORI)
-DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI)
-DECLARE_INSN(add, MATCH_ADD, MASK_ADD)
-DECLARE_INSN(sub, MATCH_SUB, MASK_SUB)
-DECLARE_INSN(sll, MATCH_SLL, MASK_SLL)
-DECLARE_INSN(slt, MATCH_SLT, MASK_SLT)
-DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU)
-DECLARE_INSN(xor, MATCH_XOR, MASK_XOR)
-DECLARE_INSN(srl, MATCH_SRL, MASK_SRL)
-DECLARE_INSN(sra, MATCH_SRA, MASK_SRA)
-DECLARE_INSN(or, MATCH_OR, MASK_OR)
-DECLARE_INSN(and, MATCH_AND, MASK_AND)
-DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW)
-DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW)
-DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW)
-DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW)
-DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW)
-DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW)
-DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW)
-DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW)
-DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW)
-DECLARE_INSN(lb, MATCH_LB, MASK_LB)
-DECLARE_INSN(lh, MATCH_LH, MASK_LH)
-DECLARE_INSN(lw, MATCH_LW, MASK_LW)
-DECLARE_INSN(ld, MATCH_LD, MASK_LD)
-DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU)
-DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU)
-DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU)
-DECLARE_INSN(sb, MATCH_SB, MASK_SB)
-DECLARE_INSN(sh, MATCH_SH, MASK_SH)
-DECLARE_INSN(sw, MATCH_SW, MASK_SW)
-DECLARE_INSN(sd, MATCH_SD, MASK_SD)
-DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE)
-DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I)
-DECLARE_INSN(mul, MATCH_MUL, MASK_MUL)
-DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH)
-DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU)
-DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU)
-DECLARE_INSN(div, MATCH_DIV, MASK_DIV)
-DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU)
-DECLARE_INSN(rem, MATCH_REM, MASK_REM)
-DECLARE_INSN(remu, MATCH_REMU, MASK_REMU)
-DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW)
-DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW)
-DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW)
-DECLARE_INSN(remw, MATCH_REMW, MASK_REMW)
-DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW)
-DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W)
-DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W)
-DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W)
-DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W)
-DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W)
-DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W)
-DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W)
-DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W)
-DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W)
-DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W)
-DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W)
-DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D)
-DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D)
-DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D)
-DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D)
-DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D)
-DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D)
-DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D)
-DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D)
-DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D)
-DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D)
-DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D)
-DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL)
-DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK)
-DECLARE_INSN(uret, MATCH_URET, MASK_URET)
-DECLARE_INSN(sret, MATCH_SRET, MASK_SRET)
-DECLARE_INSN(hret, MATCH_HRET, MASK_HRET)
-DECLARE_INSN(mret, MATCH_MRET, MASK_MRET)
-DECLARE_INSN(dret, MATCH_DRET, MASK_DRET)
-DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM)
-DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI)
-DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW)
-DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS)
-DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC)
-DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI)
-DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI)
-DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI)
-DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S)
-DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S)
-DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S)
-DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S)
-DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S)
-DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S)
-DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S)
-DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S)
-DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S)
-DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S)
-DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D)
-DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D)
-DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D)
-DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D)
-DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D)
-DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D)
-DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D)
-DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D)
-DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D)
-DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D)
-DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S)
-DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D)
-DECLARE_INSN(fadd_q, MATCH_FADD_Q, MASK_FADD_Q)
-DECLARE_INSN(fsub_q, MATCH_FSUB_Q, MASK_FSUB_Q)
-DECLARE_INSN(fmul_q, MATCH_FMUL_Q, MASK_FMUL_Q)
-DECLARE_INSN(fdiv_q, MATCH_FDIV_Q, MASK_FDIV_Q)
-DECLARE_INSN(fsgnj_q, MATCH_FSGNJ_Q, MASK_FSGNJ_Q)
-DECLARE_INSN(fsgnjn_q, MATCH_FSGNJN_Q, MASK_FSGNJN_Q)
-DECLARE_INSN(fsgnjx_q, MATCH_FSGNJX_Q, MASK_FSGNJX_Q)
-DECLARE_INSN(fmin_q, MATCH_FMIN_Q, MASK_FMIN_Q)
-DECLARE_INSN(fmax_q, MATCH_FMAX_Q, MASK_FMAX_Q)
-DECLARE_INSN(fcvt_s_q, MATCH_FCVT_S_Q, MASK_FCVT_S_Q)
-DECLARE_INSN(fcvt_q_s, MATCH_FCVT_Q_S, MASK_FCVT_Q_S)
-DECLARE_INSN(fcvt_d_q, MATCH_FCVT_D_Q, MASK_FCVT_D_Q)
-DECLARE_INSN(fcvt_q_d, MATCH_FCVT_Q_D, MASK_FCVT_Q_D)
-DECLARE_INSN(fsqrt_q, MATCH_FSQRT_Q, MASK_FSQRT_Q)
-DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S)
-DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S)
-DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S)
-DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D)
-DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D)
-DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D)
-DECLARE_INSN(fle_q, MATCH_FLE_Q, MASK_FLE_Q)
-DECLARE_INSN(flt_q, MATCH_FLT_Q, MASK_FLT_Q)
-DECLARE_INSN(feq_q, MATCH_FEQ_Q, MASK_FEQ_Q)
-DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S)
-DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S)
-DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S)
-DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S)
-DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S)
-DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S)
-DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D)
-DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D)
-DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D)
-DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D)
-DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D)
-DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D)
-DECLARE_INSN(fcvt_w_q, MATCH_FCVT_W_Q, MASK_FCVT_W_Q)
-DECLARE_INSN(fcvt_wu_q, MATCH_FCVT_WU_Q, MASK_FCVT_WU_Q)
-DECLARE_INSN(fcvt_l_q, MATCH_FCVT_L_Q, MASK_FCVT_L_Q)
-DECLARE_INSN(fcvt_lu_q, MATCH_FCVT_LU_Q, MASK_FCVT_LU_Q)
-DECLARE_INSN(fmv_x_q, MATCH_FMV_X_Q, MASK_FMV_X_Q)
-DECLARE_INSN(fclass_q, MATCH_FCLASS_Q, MASK_FCLASS_Q)
-DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W)
-DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU)
-DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L)
-DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU)
-DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X)
-DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W)
-DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU)
-DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L)
-DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU)
-DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X)
-DECLARE_INSN(fcvt_q_w, MATCH_FCVT_Q_W, MASK_FCVT_Q_W)
-DECLARE_INSN(fcvt_q_wu, MATCH_FCVT_Q_WU, MASK_FCVT_Q_WU)
-DECLARE_INSN(fcvt_q_l, MATCH_FCVT_Q_L, MASK_FCVT_Q_L)
-DECLARE_INSN(fcvt_q_lu, MATCH_FCVT_Q_LU, MASK_FCVT_Q_LU)
-DECLARE_INSN(fmv_q_x, MATCH_FMV_Q_X, MASK_FMV_Q_X)
-DECLARE_INSN(flw, MATCH_FLW, MASK_FLW)
-DECLARE_INSN(fld, MATCH_FLD, MASK_FLD)
-DECLARE_INSN(flq, MATCH_FLQ, MASK_FLQ)
-DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW)
-DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD)
-DECLARE_INSN(fsq, MATCH_FSQ, MASK_FSQ)
-DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S)
-DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S)
-DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S)
-DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S)
-DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D)
-DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D)
-DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D)
-DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D)
-DECLARE_INSN(fmadd_q, MATCH_FMADD_Q, MASK_FMADD_Q)
-DECLARE_INSN(fmsub_q, MATCH_FMSUB_Q, MASK_FMSUB_Q)
-DECLARE_INSN(fnmsub_q, MATCH_FNMSUB_Q, MASK_FNMSUB_Q)
-DECLARE_INSN(fnmadd_q, MATCH_FNMADD_Q, MASK_FNMADD_Q)
-DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN)
-DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD)
-DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW)
-DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW)
-DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD)
-DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW)
-DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW)
-DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI)
-DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL)
-DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI)
-DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI)
-DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI)
-DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI)
-DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI)
-DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB)
-DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR)
-DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR)
-DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND)
-DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW)
-DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW)
-DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J)
-DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ)
-DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ)
-DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI)
-DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP)
-DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP)
-DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP)
-DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV)
-DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD)
-DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP)
-DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP)
-DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP)
-DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP)
-DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP)
-DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR)
-DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR)
-DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK)
-DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD)
-DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD)
-DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW)
-DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP)
-DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP)
-DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0)
-DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1)
-DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2)
-DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD)
-DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1)
-DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2)
-DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1)
-DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1)
-DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2)
-DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD)
-DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1)
-DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2)
-DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2)
-DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1)
-DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2)
-DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD)
-DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1)
-DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2)
-DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3)
-DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1)
-DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2)
-DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD)
-DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1)
-DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2)
-#endif
-#ifdef DECLARE_CSR
-DECLARE_CSR(fflags, CSR_FFLAGS)
-DECLARE_CSR(frm, CSR_FRM)
-DECLARE_CSR(fcsr, CSR_FCSR)
-DECLARE_CSR(cycle, CSR_CYCLE)
-DECLARE_CSR(time, CSR_TIME)
-DECLARE_CSR(instret, CSR_INSTRET)
-DECLARE_CSR(hpmcounter3, CSR_HPMCOUNTER3)
-DECLARE_CSR(hpmcounter4, CSR_HPMCOUNTER4)
-DECLARE_CSR(hpmcounter5, CSR_HPMCOUNTER5)
-DECLARE_CSR(hpmcounter6, CSR_HPMCOUNTER6)
-DECLARE_CSR(hpmcounter7, CSR_HPMCOUNTER7)
-DECLARE_CSR(hpmcounter8, CSR_HPMCOUNTER8)
-DECLARE_CSR(hpmcounter9, CSR_HPMCOUNTER9)
-DECLARE_CSR(hpmcounter10, CSR_HPMCOUNTER10)
-DECLARE_CSR(hpmcounter11, CSR_HPMCOUNTER11)
-DECLARE_CSR(hpmcounter12, CSR_HPMCOUNTER12)
-DECLARE_CSR(hpmcounter13, CSR_HPMCOUNTER13)
-DECLARE_CSR(hpmcounter14, CSR_HPMCOUNTER14)
-DECLARE_CSR(hpmcounter15, CSR_HPMCOUNTER15)
-DECLARE_CSR(hpmcounter16, CSR_HPMCOUNTER16)
-DECLARE_CSR(hpmcounter17, CSR_HPMCOUNTER17)
-DECLARE_CSR(hpmcounter18, CSR_HPMCOUNTER18)
-DECLARE_CSR(hpmcounter19, CSR_HPMCOUNTER19)
-DECLARE_CSR(hpmcounter20, CSR_HPMCOUNTER20)
-DECLARE_CSR(hpmcounter21, CSR_HPMCOUNTER21)
-DECLARE_CSR(hpmcounter22, CSR_HPMCOUNTER22)
-DECLARE_CSR(hpmcounter23, CSR_HPMCOUNTER23)
-DECLARE_CSR(hpmcounter24, CSR_HPMCOUNTER24)
-DECLARE_CSR(hpmcounter25, CSR_HPMCOUNTER25)
-DECLARE_CSR(hpmcounter26, CSR_HPMCOUNTER26)
-DECLARE_CSR(hpmcounter27, CSR_HPMCOUNTER27)
-DECLARE_CSR(hpmcounter28, CSR_HPMCOUNTER28)
-DECLARE_CSR(hpmcounter29, CSR_HPMCOUNTER29)
-DECLARE_CSR(hpmcounter30, CSR_HPMCOUNTER30)
-DECLARE_CSR(hpmcounter31, CSR_HPMCOUNTER31)
-DECLARE_CSR(sstatus, CSR_SSTATUS)
-DECLARE_CSR(sie, CSR_SIE)
-DECLARE_CSR(stvec, CSR_STVEC)
-DECLARE_CSR(sscratch, CSR_SSCRATCH)
-DECLARE_CSR(sepc, CSR_SEPC)
-DECLARE_CSR(scause, CSR_SCAUSE)
-DECLARE_CSR(sbadaddr, CSR_SBADADDR)
-DECLARE_CSR(sip, CSR_SIP)
-DECLARE_CSR(sptbr, CSR_SPTBR)
-DECLARE_CSR(mstatus, CSR_MSTATUS)
-DECLARE_CSR(misa, CSR_MISA)
-DECLARE_CSR(medeleg, CSR_MEDELEG)
-DECLARE_CSR(mideleg, CSR_MIDELEG)
-DECLARE_CSR(mie, CSR_MIE)
-DECLARE_CSR(mtvec, CSR_MTVEC)
-DECLARE_CSR(mscratch, CSR_MSCRATCH)
-DECLARE_CSR(mepc, CSR_MEPC)
-DECLARE_CSR(mcause, CSR_MCAUSE)
-DECLARE_CSR(mbadaddr, CSR_MBADADDR)
-DECLARE_CSR(mip, CSR_MIP)
-DECLARE_CSR(tselect, CSR_TSELECT)
-DECLARE_CSR(tdata1, CSR_TDATA1)
-DECLARE_CSR(tdata2, CSR_TDATA2)
-DECLARE_CSR(tdata3, CSR_TDATA3)
-DECLARE_CSR(dcsr, CSR_DCSR)
-DECLARE_CSR(dpc, CSR_DPC)
-DECLARE_CSR(dscratch, CSR_DSCRATCH)
-DECLARE_CSR(mcycle, CSR_MCYCLE)
-DECLARE_CSR(minstret, CSR_MINSTRET)
-DECLARE_CSR(mhpmcounter3, CSR_MHPMCOUNTER3)
-DECLARE_CSR(mhpmcounter4, CSR_MHPMCOUNTER4)
-DECLARE_CSR(mhpmcounter5, CSR_MHPMCOUNTER5)
-DECLARE_CSR(mhpmcounter6, CSR_MHPMCOUNTER6)
-DECLARE_CSR(mhpmcounter7, CSR_MHPMCOUNTER7)
-DECLARE_CSR(mhpmcounter8, CSR_MHPMCOUNTER8)
-DECLARE_CSR(mhpmcounter9, CSR_MHPMCOUNTER9)
-DECLARE_CSR(mhpmcounter10, CSR_MHPMCOUNTER10)
-DECLARE_CSR(mhpmcounter11, CSR_MHPMCOUNTER11)
-DECLARE_CSR(mhpmcounter12, CSR_MHPMCOUNTER12)
-DECLARE_CSR(mhpmcounter13, CSR_MHPMCOUNTER13)
-DECLARE_CSR(mhpmcounter14, CSR_MHPMCOUNTER14)
-DECLARE_CSR(mhpmcounter15, CSR_MHPMCOUNTER15)
-DECLARE_CSR(mhpmcounter16, CSR_MHPMCOUNTER16)
-DECLARE_CSR(mhpmcounter17, CSR_MHPMCOUNTER17)
-DECLARE_CSR(mhpmcounter18, CSR_MHPMCOUNTER18)
-DECLARE_CSR(mhpmcounter19, CSR_MHPMCOUNTER19)
-DECLARE_CSR(mhpmcounter20, CSR_MHPMCOUNTER20)
-DECLARE_CSR(mhpmcounter21, CSR_MHPMCOUNTER21)
-DECLARE_CSR(mhpmcounter22, CSR_MHPMCOUNTER22)
-DECLARE_CSR(mhpmcounter23, CSR_MHPMCOUNTER23)
-DECLARE_CSR(mhpmcounter24, CSR_MHPMCOUNTER24)
-DECLARE_CSR(mhpmcounter25, CSR_MHPMCOUNTER25)
-DECLARE_CSR(mhpmcounter26, CSR_MHPMCOUNTER26)
-DECLARE_CSR(mhpmcounter27, CSR_MHPMCOUNTER27)
-DECLARE_CSR(mhpmcounter28, CSR_MHPMCOUNTER28)
-DECLARE_CSR(mhpmcounter29, CSR_MHPMCOUNTER29)
-DECLARE_CSR(mhpmcounter30, CSR_MHPMCOUNTER30)
-DECLARE_CSR(mhpmcounter31, CSR_MHPMCOUNTER31)
-DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN)
-DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN)
-DECLARE_CSR(mhpmevent3, CSR_MHPMEVENT3)
-DECLARE_CSR(mhpmevent4, CSR_MHPMEVENT4)
-DECLARE_CSR(mhpmevent5, CSR_MHPMEVENT5)
-DECLARE_CSR(mhpmevent6, CSR_MHPMEVENT6)
-DECLARE_CSR(mhpmevent7, CSR_MHPMEVENT7)
-DECLARE_CSR(mhpmevent8, CSR_MHPMEVENT8)
-DECLARE_CSR(mhpmevent9, CSR_MHPMEVENT9)
-DECLARE_CSR(mhpmevent10, CSR_MHPMEVENT10)
-DECLARE_CSR(mhpmevent11, CSR_MHPMEVENT11)
-DECLARE_CSR(mhpmevent12, CSR_MHPMEVENT12)
-DECLARE_CSR(mhpmevent13, CSR_MHPMEVENT13)
-DECLARE_CSR(mhpmevent14, CSR_MHPMEVENT14)
-DECLARE_CSR(mhpmevent15, CSR_MHPMEVENT15)
-DECLARE_CSR(mhpmevent16, CSR_MHPMEVENT16)
-DECLARE_CSR(mhpmevent17, CSR_MHPMEVENT17)
-DECLARE_CSR(mhpmevent18, CSR_MHPMEVENT18)
-DECLARE_CSR(mhpmevent19, CSR_MHPMEVENT19)
-DECLARE_CSR(mhpmevent20, CSR_MHPMEVENT20)
-DECLARE_CSR(mhpmevent21, CSR_MHPMEVENT21)
-DECLARE_CSR(mhpmevent22, CSR_MHPMEVENT22)
-DECLARE_CSR(mhpmevent23, CSR_MHPMEVENT23)
-DECLARE_CSR(mhpmevent24, CSR_MHPMEVENT24)
-DECLARE_CSR(mhpmevent25, CSR_MHPMEVENT25)
-DECLARE_CSR(mhpmevent26, CSR_MHPMEVENT26)
-DECLARE_CSR(mhpmevent27, CSR_MHPMEVENT27)
-DECLARE_CSR(mhpmevent28, CSR_MHPMEVENT28)
-DECLARE_CSR(mhpmevent29, CSR_MHPMEVENT29)
-DECLARE_CSR(mhpmevent30, CSR_MHPMEVENT30)
-DECLARE_CSR(mhpmevent31, CSR_MHPMEVENT31)
-DECLARE_CSR(mvendorid, CSR_MVENDORID)
-DECLARE_CSR(marchid, CSR_MARCHID)
-DECLARE_CSR(mimpid, CSR_MIMPID)
-DECLARE_CSR(mhartid, CSR_MHARTID)
-DECLARE_CSR(cycleh, CSR_CYCLEH)
-DECLARE_CSR(timeh, CSR_TIMEH)
-DECLARE_CSR(instreth, CSR_INSTRETH)
-DECLARE_CSR(hpmcounter3h, CSR_HPMCOUNTER3H)
-DECLARE_CSR(hpmcounter4h, CSR_HPMCOUNTER4H)
-DECLARE_CSR(hpmcounter5h, CSR_HPMCOUNTER5H)
-DECLARE_CSR(hpmcounter6h, CSR_HPMCOUNTER6H)
-DECLARE_CSR(hpmcounter7h, CSR_HPMCOUNTER7H)
-DECLARE_CSR(hpmcounter8h, CSR_HPMCOUNTER8H)
-DECLARE_CSR(hpmcounter9h, CSR_HPMCOUNTER9H)
-DECLARE_CSR(hpmcounter10h, CSR_HPMCOUNTER10H)
-DECLARE_CSR(hpmcounter11h, CSR_HPMCOUNTER11H)
-DECLARE_CSR(hpmcounter12h, CSR_HPMCOUNTER12H)
-DECLARE_CSR(hpmcounter13h, CSR_HPMCOUNTER13H)
-DECLARE_CSR(hpmcounter14h, CSR_HPMCOUNTER14H)
-DECLARE_CSR(hpmcounter15h, CSR_HPMCOUNTER15H)
-DECLARE_CSR(hpmcounter16h, CSR_HPMCOUNTER16H)
-DECLARE_CSR(hpmcounter17h, CSR_HPMCOUNTER17H)
-DECLARE_CSR(hpmcounter18h, CSR_HPMCOUNTER18H)
-DECLARE_CSR(hpmcounter19h, CSR_HPMCOUNTER19H)
-DECLARE_CSR(hpmcounter20h, CSR_HPMCOUNTER20H)
-DECLARE_CSR(hpmcounter21h, CSR_HPMCOUNTER21H)
-DECLARE_CSR(hpmcounter22h, CSR_HPMCOUNTER22H)
-DECLARE_CSR(hpmcounter23h, CSR_HPMCOUNTER23H)
-DECLARE_CSR(hpmcounter24h, CSR_HPMCOUNTER24H)
-DECLARE_CSR(hpmcounter25h, CSR_HPMCOUNTER25H)
-DECLARE_CSR(hpmcounter26h, CSR_HPMCOUNTER26H)
-DECLARE_CSR(hpmcounter27h, CSR_HPMCOUNTER27H)
-DECLARE_CSR(hpmcounter28h, CSR_HPMCOUNTER28H)
-DECLARE_CSR(hpmcounter29h, CSR_HPMCOUNTER29H)
-DECLARE_CSR(hpmcounter30h, CSR_HPMCOUNTER30H)
-DECLARE_CSR(hpmcounter31h, CSR_HPMCOUNTER31H)
-DECLARE_CSR(mcycleh, CSR_MCYCLEH)
-DECLARE_CSR(minstreth, CSR_MINSTRETH)
-DECLARE_CSR(mhpmcounter3h, CSR_MHPMCOUNTER3H)
-DECLARE_CSR(mhpmcounter4h, CSR_MHPMCOUNTER4H)
-DECLARE_CSR(mhpmcounter5h, CSR_MHPMCOUNTER5H)
-DECLARE_CSR(mhpmcounter6h, CSR_MHPMCOUNTER6H)
-DECLARE_CSR(mhpmcounter7h, CSR_MHPMCOUNTER7H)
-DECLARE_CSR(mhpmcounter8h, CSR_MHPMCOUNTER8H)
-DECLARE_CSR(mhpmcounter9h, CSR_MHPMCOUNTER9H)
-DECLARE_CSR(mhpmcounter10h, CSR_MHPMCOUNTER10H)
-DECLARE_CSR(mhpmcounter11h, CSR_MHPMCOUNTER11H)
-DECLARE_CSR(mhpmcounter12h, CSR_MHPMCOUNTER12H)
-DECLARE_CSR(mhpmcounter13h, CSR_MHPMCOUNTER13H)
-DECLARE_CSR(mhpmcounter14h, CSR_MHPMCOUNTER14H)
-DECLARE_CSR(mhpmcounter15h, CSR_MHPMCOUNTER15H)
-DECLARE_CSR(mhpmcounter16h, CSR_MHPMCOUNTER16H)
-DECLARE_CSR(mhpmcounter17h, CSR_MHPMCOUNTER17H)
-DECLARE_CSR(mhpmcounter18h, CSR_MHPMCOUNTER18H)
-DECLARE_CSR(mhpmcounter19h, CSR_MHPMCOUNTER19H)
-DECLARE_CSR(mhpmcounter20h, CSR_MHPMCOUNTER20H)
-DECLARE_CSR(mhpmcounter21h, CSR_MHPMCOUNTER21H)
-DECLARE_CSR(mhpmcounter22h, CSR_MHPMCOUNTER22H)
-DECLARE_CSR(mhpmcounter23h, CSR_MHPMCOUNTER23H)
-DECLARE_CSR(mhpmcounter24h, CSR_MHPMCOUNTER24H)
-DECLARE_CSR(mhpmcounter25h, CSR_MHPMCOUNTER25H)
-DECLARE_CSR(mhpmcounter26h, CSR_MHPMCOUNTER26H)
-DECLARE_CSR(mhpmcounter27h, CSR_MHPMCOUNTER27H)
-DECLARE_CSR(mhpmcounter28h, CSR_MHPMCOUNTER28H)
-DECLARE_CSR(mhpmcounter29h, CSR_MHPMCOUNTER29H)
-DECLARE_CSR(mhpmcounter30h, CSR_MHPMCOUNTER30H)
-DECLARE_CSR(mhpmcounter31h, CSR_MHPMCOUNTER31H)
-#endif
-#ifdef DECLARE_CAUSE
-DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH)
-DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH)
-DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION)
-DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT)
-DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD)
-DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD)
-DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE)
-DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE)
-DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL)
-DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL)
-DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL)
-DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL)
-#endif
-
diff --git a/librz/arch/isa_gnu/riscv/riscv.c b/librz/arch/isa_gnu/riscv/riscv.c
deleted file mode 100644
index 9af87e2bf49..00000000000
--- a/librz/arch/isa_gnu/riscv/riscv.c
+++ /dev/null
@@ -1,333 +0,0 @@
-// SPDX-FileCopyrightText: 2011-2015 Free Software Foundation, Inc.
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-/* RISC-V disassembler
- Copyright 2011-2015 Free Software Foundation, Inc.
- Contributed by Andrew Waterman (waterman@cs.berkeley.edu) at UC Berkeley.
- Based on MIPS target.
- This file is part of the GNU opcodes library.
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- It is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING3. If not,
- see .
-
- - Code changes to make r2 friendly (qnix@0x80.org)
-*/
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "riscv-opc.h"
-#include "riscv.h"
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
-
-// TODO : an conf to chose between abi or numeric
-static const char *const *riscv_gpr_names = riscv_gpr_names_abi;
-static const char *const *riscv_fpr_names = riscv_fpr_names_abi;
-static bool init_asm = 0;
-
-static void arg_p(char *buf, unsigned long val, const char *const *array, size_t size) {
- const char *s = val >= size || array[val] ? array[val] : "unknown";
- sprintf(buf + strlen(buf), "%s", s);
-}
-
-/* Print insn arguments for 32/64-bit code. */
-static void get_insn_args(char *buf, const char *d, insn_t l, uint64_t pc) {
- int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
- int rd = (l >> OP_SH_RD) & OP_MASK_RD;
- uint64_t target;
-
- if (*d != '\0') {
- sprintf(buf + strlen(buf), " ");
- }
-
- for (; *d != '\0'; d++) {
- switch (*d) {
- /* Xcustom */
- case '^':
- switch (*++d) {
- case 'd':
- sprintf(buf + strlen(buf), "%d", rd);
- break;
- case 's':
- sprintf(buf + strlen(buf), "%d", rs1);
- break;
- case 't':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_OPERAND(RS2, l));
- break;
- case 'j':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_OPERAND(CUSTOM_IMM, l));
- break;
- }
- break;
-
- case 'C': /* RVC */
- switch (*++d) {
- case 's': /* RS1 x8-x15 */
- case 'w': /* RS1 x8-x15 */
- sprintf(buf + strlen(buf), "%s",
- riscv_gpr_names[EXTRACT_OPERAND(CRS1S, l) + 8]);
- break;
- case 't': /* RS2 x8-x15 */
- case 'x': /* RS2 x8-x15 */
- sprintf(buf + strlen(buf), "%s",
- riscv_gpr_names[EXTRACT_OPERAND(CRS2S, l) + 8]);
- break;
- case 'U': /* RS1, constrained to equal RD */
- sprintf(buf + strlen(buf), "%s", riscv_gpr_names[rd]);
- break;
- case 'c': /* RS1, constrained to equal sp */
- sprintf(buf + strlen(buf), "%s", riscv_gpr_names[X_SP]);
- break;
- case 'V': /* RS2 */
- sprintf(buf + strlen(buf), "%s",
- riscv_gpr_names[EXTRACT_OPERAND(CRS2, l)]);
- break;
- case 'i':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_RVC_SIMM3(l));
- break;
- case 'j':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_RVC_IMM(l));
- break;
- case 'k':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_RVC_LW_IMM(l));
- break;
- case 'l':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_RVC_LD_IMM(l));
- break;
- case 'm':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_RVC_LWSP_IMM(l));
- break;
- case 'n':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_RVC_LDSP_IMM(l));
- break;
- case 'K':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_RVC_ADDI4SPN_IMM(l));
- break;
- case 'L':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_RVC_ADDI16SP_IMM(l));
- break;
- case 'M':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_RVC_SWSP_IMM(l));
- break;
- case 'N':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_RVC_SDSP_IMM(l));
- break;
- case 'p':
- target = EXTRACT_RVC_B_IMM(l) + pc;
- sprintf(buf + strlen(buf), "0x%" PFMT64x, (ut64)target);
- break;
- case 'a':
- target = EXTRACT_RVC_J_IMM(l) + pc;
- sprintf(buf + strlen(buf), "0x%" PFMT64x, (ut64)target);
- break;
- case 'u':
- sprintf(buf + strlen(buf), "0x%x",
- (int)(EXTRACT_RVC_IMM(l) & (RISCV_BIGIMM_REACH - 1)));
- break;
- case '>':
- sprintf(buf + strlen(buf), "0x%x", (int)EXTRACT_RVC_IMM(l) & 0x3f);
- break;
- case '<':
- sprintf(buf + strlen(buf), "0x%x", (int)EXTRACT_RVC_IMM(l) & 0x1f);
- break;
- case 'T': /* floating-point RS2 */
- sprintf(buf + strlen(buf), "%s",
- riscv_fpr_names[EXTRACT_OPERAND(CRS2, l)]);
- break;
- case 'D': /* floating-point RS2 x8-x15 */
- sprintf(buf + strlen(buf), "%s",
- riscv_fpr_names[EXTRACT_OPERAND(CRS2S, l) + 8]);
- break;
- }
- break;
-
- case ',':
- sprintf(buf + strlen(buf), "%c ", *d);
- break;
- case '(':
- case ')':
- case '[':
- case ']':
- sprintf(buf + strlen(buf), "%c", *d);
- break;
- case '0':
- /* Only print constant 0 if it is the last argument */
- if (!d[1]) {
- sprintf(buf + strlen(buf), "0");
- }
- break;
-
- case 'b':
- case 's':
- sprintf(buf + strlen(buf), "%s", riscv_gpr_names[rs1]);
- break;
-
- case 't':
- sprintf(buf + strlen(buf), "%s",
- riscv_gpr_names[EXTRACT_OPERAND(RS2, l)]);
- break;
-
- case 'u':
- sprintf(buf + strlen(buf), "0x%x",
- (unsigned)EXTRACT_UTYPE_IMM(l) >> RISCV_IMM_BITS);
- break;
-
- case 'm':
- arg_p(buf, EXTRACT_OPERAND(RM, l),
- riscv_rm, ARRAY_SIZE(riscv_rm));
- break;
-
- case 'P':
- arg_p(buf, EXTRACT_OPERAND(PRED, l),
- riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
- break;
-
- case 'Q':
- arg_p(buf, EXTRACT_OPERAND(SUCC, l),
- riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
- break;
- case 'o':
- case 'j':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_ITYPE_IMM(l));
- break;
- case 'q':
- sprintf(buf + strlen(buf), "%d", (int)EXTRACT_STYPE_IMM(l));
- break;
- case 'a':
- target = EXTRACT_UJTYPE_IMM(l) + pc;
- sprintf(buf + strlen(buf), "0x%" PFMT64x, (ut64)target);
- break;
- case 'p':
- target = EXTRACT_SBTYPE_IMM(l) + pc;
- sprintf(buf + strlen(buf), "0x%" PFMT64x, (ut64)target);
- break;
- case 'd':
- sprintf(buf + strlen(buf), "%s", riscv_gpr_names[rd]);
- break;
- case 'z':
- sprintf(buf + strlen(buf), "%s", riscv_gpr_names[0]);
- break;
- case '>':
- sprintf(buf + strlen(buf), "0x%x", (int)EXTRACT_OPERAND(SHAMT, l));
- break;
- case '<':
- sprintf(buf + strlen(buf), "0x%x", (int)EXTRACT_OPERAND(SHAMTW, l));
- break;
- case 'S':
- case 'U':
- sprintf(buf + strlen(buf), "%s", riscv_fpr_names[rs1]);
- break;
- case 'T':
- sprintf(buf + strlen(buf), "%s", riscv_fpr_names[EXTRACT_OPERAND(RS2, l)]);
- break;
- case 'D':
- sprintf(buf + strlen(buf), "%s", riscv_fpr_names[rd]);
- break;
- case 'R':
- sprintf(buf + strlen(buf), "%s", riscv_fpr_names[EXTRACT_OPERAND(RS3, l)]);
- break;
- case 'E': {
- const char *csr_name = NULL;
- unsigned int csr = EXTRACT_OPERAND(CSR, l);
- switch (csr) {
-#define DECLARE_CSR(name, num) \
- case num: csr_name = #name; break;
-#include "riscv-opc.h"
-#undef DECLARE_CSR
- }
- if (csr_name) {
- sprintf(buf + strlen(buf), "%s", csr_name);
- } else {
- sprintf(buf + strlen(buf), "0x%x", csr);
- }
- break;
- }
- case 'Z':
- sprintf(buf + strlen(buf), "%d", rs1);
- break;
- default:
- /* xgettext:c-format */
- sprintf(buf + strlen(buf), "# internal error, undefined modifier (%c)",
- *d);
- return;
- }
- }
-}
-
-static struct riscv_opcode *get_opcode(insn_t word) {
- struct riscv_opcode *op;
- static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1] = { 0 };
-
-#define OP_HASH_IDX(i) ((i) & (riscv_insn_length(i) == 2 ? 3 : OP_MASK_OP))
-
- if (!init_asm) {
- for (op = riscv_opcodes; op < &riscv_opcodes[NUMOPCODES]; op++) {
- if (!riscv_hash[OP_HASH_IDX(op->match)]) {
- riscv_hash[OP_HASH_IDX(op->match)] = op;
- }
- }
- init_asm = 1;
- }
-
- return (struct riscv_opcode *)riscv_hash[OP_HASH_IDX(word)];
-}
-
-static int riscv_disassemble(RzAsm *a, RzAsmOp *rop, insn_t word, int xlen, int len) {
- const bool no_alias = false;
- const struct riscv_opcode *op = get_opcode(word);
- if (!op) {
- return -1;
- }
- for (; op < &riscv_opcodes[NUMOPCODES]; op++) {
- if (!(op->match_func)(op, word)) {
- continue;
- }
- if (no_alias && (op->pinfo & INSN_ALIAS)) {
- continue;
- }
- if (isdigit((ut8)op->subset[0]) && atoi(op->subset) != xlen) {
- continue;
- }
- if (op->name && op->args) {
- rz_asm_op_set_asm(rop, op->name);
- get_insn_args(rz_asm_op_get_asm(rop), op->args, word, a->pc);
- return 0;
- }
- return -1;
- }
- return 0;
-}
-
-static int riscv_dis(RzAsm *a, RzAsmOp *rop, const ut8 *buf, ut64 len) {
- insn_t insn = { 0 };
- rz_asm_op_set_asm(rop, "invalid");
- if (len < 2) {
- return -1;
- }
- // Read <= 8 bytes into 8-byte buffer in little endian fashion
- RZ_STATIC_ASSERT(sizeof(insn) == 8);
- ut8 tmp[8] = { 0 };
- memcpy(&tmp, buf, RZ_MIN(sizeof(insn), len));
- insn = rz_read_le64(tmp);
- int insn_len = riscv_insn_length(insn);
- if (len < insn_len) {
- return -1;
- }
- riscv_disassemble(a, rop, insn, a->bits, len);
- return insn_len;
-}
diff --git a/librz/arch/isa_gnu/riscv/riscv.h b/librz/arch/isa_gnu/riscv/riscv.h
deleted file mode 100644
index dcf70306981..00000000000
--- a/librz/arch/isa_gnu/riscv/riscv.h
+++ /dev/null
@@ -1,353 +0,0 @@
-// SPDX-FileCopyrightText: 2011-2017 Free Software Foundation, Inc.
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-/* riscv.h. RISC-V opcode list for GDB, the GNU debugger.
- Copyright (C) 2011-2017 Free Software Foundation, Inc.
- Contributed by Andrew Waterman
-
- This file is part of GDB, GAS, and the GNU binutils.
-
- GDB, GAS, and the GNU binutils are free software; you can redistribute
- them and/or modify them under the terms of the GNU General Public
- License as published by the Free Software Foundation; either version
- 3, or (at your option) any later version.
-
- GDB, GAS, and the GNU binutils are distributed in the hope that they
- will be useful, but WITHOUT ANY WARRANTY; without even the implied
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; see the file COPYING3. If not,
- see . */
-
-#ifndef _RISCV_H_
-#define _RISCV_H_
-
-#include "riscv-opc.h"
-#include
-#include
-
-typedef uint64_t insn_t;
-
-static inline unsigned int riscv_insn_length (insn_t insn)
-{
- if ((insn & 0x3) != 0x3) /* RVC. */
- return 2;
- if ((insn & 0x1f) != 0x1f) /* Base ISA and extensions in 32-bit space. */
- return 4;
- if ((insn & 0x3f) == 0x1f) /* 48-bit extensions. */
- return 6;
- if ((insn & 0x7f) == 0x3f) /* 64-bit extensions. */
- return 8;
- /* Longer instructions not supported at the moment. */
- return 2;
-}
-
-static const char * const riscv_rm[8] =
-{
- "rne", "rtz", "rdn", "rup", "rmm", 0, 0, "dyn"
-};
-
-static const char * const riscv_pred_succ[16] =
-{
- 0, "w", "r", "rw", "o", "ow", "or", "orw",
- "i", "iw", "ir", "irw", "io", "iow", "ior", "iorw"
-};
-
-#define RVC_JUMP_BITS 11
-#define RVC_JUMP_REACH ((1ULL << RVC_JUMP_BITS) * RISCV_JUMP_ALIGN)
-
-#define RVC_BRANCH_BITS 8
-#define RVC_BRANCH_REACH ((1ULL << RVC_BRANCH_BITS) * RISCV_BRANCH_ALIGN)
-
-#define RV_X(x, s, n) (((x) >> (s)) & ((1 << (n)) - 1))
-#define RV_IMM_SIGN(x) (-(((x) >> 31) & 1))
-
-#define EXTRACT_ITYPE_IMM(x) \
- (RV_X(x, 20, 12) | (RV_IMM_SIGN(x) << 12))
-#define EXTRACT_STYPE_IMM(x) \
- (RV_X(x, 7, 5) | (RV_X(x, 25, 7) << 5) | (RV_IMM_SIGN(x) << 12))
-#define EXTRACT_SBTYPE_IMM(x) \
- ((RV_X(x, 8, 4) << 1) | (RV_X(x, 25, 6) << 5) | (RV_X(x, 7, 1) << 11) | (RV_IMM_SIGN(x) << 12))
-#define EXTRACT_UTYPE_IMM(x) \
- ((RV_X(x, 12, 20) << 12) | (RV_IMM_SIGN(x) << 32))
-#define EXTRACT_UJTYPE_IMM(x) \
- ((RV_X(x, 21, 10) << 1) | (RV_X(x, 20, 1) << 11) | (RV_X(x, 12, 8) << 12) | (RV_IMM_SIGN(x) << 20))
-#define EXTRACT_RVC_IMM(x) \
- (RV_X(x, 2, 5) | (-RV_X(x, 12, 1) << 5))
-#define EXTRACT_RVC_LUI_IMM(x) \
- (EXTRACT_RVC_IMM (x) << RISCV_IMM_BITS)
-#define EXTRACT_RVC_SIMM3(x) \
- (RV_X(x, 10, 2) | (-RV_X(x, 12, 1) << 2))
-#define EXTRACT_RVC_ADDI4SPN_IMM(x) \
- ((RV_X(x, 6, 1) << 2) | (RV_X(x, 5, 1) << 3) | (RV_X(x, 11, 2) << 4) | (RV_X(x, 7, 4) << 6))
-#define EXTRACT_RVC_ADDI16SP_IMM(x) \
- ((RV_X(x, 6, 1) << 4) | (RV_X(x, 2, 1) << 5) | (RV_X(x, 5, 1) << 6) | (RV_X(x, 3, 2) << 7) | (-RV_X(x, 12, 1) << 9))
-#define EXTRACT_RVC_LW_IMM(x) \
- ((RV_X(x, 6, 1) << 2) | (RV_X(x, 10, 3) << 3) | (RV_X(x, 5, 1) << 6))
-#define EXTRACT_RVC_LD_IMM(x) \
- ((RV_X(x, 10, 3) << 3) | (RV_X(x, 5, 2) << 6))
-#define EXTRACT_RVC_LWSP_IMM(x) \
- ((RV_X(x, 4, 3) << 2) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 2, 2) << 6))
-#define EXTRACT_RVC_LDSP_IMM(x) \
- ((RV_X(x, 5, 2) << 3) | (RV_X(x, 12, 1) << 5) | (RV_X(x, 2, 3) << 6))
-#define EXTRACT_RVC_SWSP_IMM(x) \
- ((RV_X(x, 9, 4) << 2) | (RV_X(x, 7, 2) << 6))
-#define EXTRACT_RVC_SDSP_IMM(x) \
- ((RV_X(x, 10, 3) << 3) | (RV_X(x, 7, 3) << 6))
-#define EXTRACT_RVC_B_IMM(x) \
- ((RV_X(x, 3, 2) << 1) | (RV_X(x, 10, 2) << 3) | (RV_X(x, 2, 1) << 5) | (RV_X(x, 5, 2) << 6) | (-RV_X(x, 12, 1) << 8))
-#define EXTRACT_RVC_J_IMM(x) \
- ((RV_X(x, 3, 3) << 1) | (RV_X(x, 11, 1) << 4) | (RV_X(x, 2, 1) << 5) | (RV_X(x, 7, 1) << 6) | (RV_X(x, 6, 1) << 7) | (RV_X(x, 9, 2) << 8) | (RV_X(x, 8, 1) << 10) | (-RV_X(x, 12, 1) << 11))
-
-#define ENCODE_ITYPE_IMM(x) \
- (RV_X(x, 0, 12) << 20)
-#define ENCODE_STYPE_IMM(x) \
- ((RV_X(x, 0, 5) << 7) | (RV_X(x, 5, 7) << 25))
-#define ENCODE_SBTYPE_IMM(x) \
- ((RV_X(x, 1, 4) << 8) | (RV_X(x, 5, 6) << 25) | (RV_X(x, 11, 1) << 7) | (RV_X(x, 12, 1) << 31))
-#define ENCODE_UTYPE_IMM(x) \
- (RV_X(x, 12, 20) << 12)
-#define ENCODE_UJTYPE_IMM(x) \
- ((RV_X(x, 1, 10) << 21) | (RV_X(x, 11, 1) << 20) | (RV_X(x, 12, 8) << 12) | (RV_X(x, 20, 1) << 31))
-#define ENCODE_RVC_IMM(x) \
- ((RV_X(x, 0, 5) << 2) | (RV_X(x, 5, 1) << 12))
-#define ENCODE_RVC_LUI_IMM(x) \
- ENCODE_RVC_IMM ((x) >> RISCV_IMM_BITS)
-#define ENCODE_RVC_SIMM3(x) \
- (RV_X(x, 0, 3) << 10)
-#define ENCODE_RVC_ADDI4SPN_IMM(x) \
- ((RV_X(x, 2, 1) << 6) | (RV_X(x, 3, 1) << 5) | (RV_X(x, 4, 2) << 11) | (RV_X(x, 6, 4) << 7))
-#define ENCODE_RVC_ADDI16SP_IMM(x) \
- ((RV_X(x, 4, 1) << 6) | (RV_X(x, 5, 1) << 2) | (RV_X(x, 6, 1) << 5) | (RV_X(x, 7, 2) << 3) | (RV_X(x, 9, 1) << 12))
-#define ENCODE_RVC_LW_IMM(x) \
- ((RV_X(x, 2, 1) << 6) | (RV_X(x, 3, 3) << 10) | (RV_X(x, 6, 1) << 5))
-#define ENCODE_RVC_LD_IMM(x) \
- ((RV_X(x, 3, 3) << 10) | (RV_X(x, 6, 2) << 5))
-#define ENCODE_RVC_LWSP_IMM(x) \
- ((RV_X(x, 2, 3) << 4) | (RV_X(x, 5, 1) << 12) | (RV_X(x, 6, 2) << 2))
-#define ENCODE_RVC_LDSP_IMM(x) \
- ((RV_X(x, 3, 2) << 5) | (RV_X(x, 5, 1) << 12) | (RV_X(x, 6, 3) << 2))
-#define ENCODE_RVC_SWSP_IMM(x) \
- ((RV_X(x, 2, 4) << 9) | (RV_X(x, 6, 2) << 7))
-#define ENCODE_RVC_SDSP_IMM(x) \
- ((RV_X(x, 3, 3) << 10) | (RV_X(x, 6, 3) << 7))
-#define ENCODE_RVC_B_IMM(x) \
- ((RV_X(x, 1, 2) << 3) | (RV_X(x, 3, 2) << 10) | (RV_X(x, 5, 1) << 2) | (RV_X(x, 6, 2) << 5) | (RV_X(x, 8, 1) << 12))
-#define ENCODE_RVC_J_IMM(x) \
- ((RV_X(x, 1, 3) << 3) | (RV_X(x, 4, 1) << 11) | (RV_X(x, 5, 1) << 2) | (RV_X(x, 6, 1) << 7) | (RV_X(x, 7, 1) << 6) | (RV_X(x, 8, 2) << 9) | (RV_X(x, 10, 1) << 8) | (RV_X(x, 11, 1) << 12))
-
-#define VALID_ITYPE_IMM(x) (EXTRACT_ITYPE_IMM(ENCODE_ITYPE_IMM(x)) == (x))
-#define VALID_STYPE_IMM(x) (EXTRACT_STYPE_IMM(ENCODE_STYPE_IMM(x)) == (x))
-#define VALID_SBTYPE_IMM(x) (EXTRACT_SBTYPE_IMM(ENCODE_SBTYPE_IMM(x)) == (x))
-#define VALID_UTYPE_IMM(x) (EXTRACT_UTYPE_IMM(ENCODE_UTYPE_IMM(x)) == (x))
-#define VALID_UJTYPE_IMM(x) (EXTRACT_UJTYPE_IMM(ENCODE_UJTYPE_IMM(x)) == (x))
-#define VALID_RVC_IMM(x) (EXTRACT_RVC_IMM(ENCODE_RVC_IMM(x)) == (x))
-#define VALID_RVC_LUI_IMM(x) (EXTRACT_RVC_LUI_IMM(ENCODE_RVC_LUI_IMM(x)) == (x))
-#define VALID_RVC_SIMM3(x) (EXTRACT_RVC_SIMM3(ENCODE_RVC_SIMM3(x)) == (x))
-#define VALID_RVC_ADDI4SPN_IMM(x) (EXTRACT_RVC_ADDI4SPN_IMM(ENCODE_RVC_ADDI4SPN_IMM(x)) == (x))
-#define VALID_RVC_ADDI16SP_IMM(x) (EXTRACT_RVC_ADDI16SP_IMM(ENCODE_RVC_ADDI16SP_IMM(x)) == (x))
-#define VALID_RVC_LW_IMM(x) (EXTRACT_RVC_LW_IMM(ENCODE_RVC_LW_IMM(x)) == (x))
-#define VALID_RVC_LD_IMM(x) (EXTRACT_RVC_LD_IMM(ENCODE_RVC_LD_IMM(x)) == (x))
-#define VALID_RVC_LWSP_IMM(x) (EXTRACT_RVC_LWSP_IMM(ENCODE_RVC_LWSP_IMM(x)) == (x))
-#define VALID_RVC_LDSP_IMM(x) (EXTRACT_RVC_LDSP_IMM(ENCODE_RVC_LDSP_IMM(x)) == (x))
-#define VALID_RVC_SWSP_IMM(x) (EXTRACT_RVC_SWSP_IMM(ENCODE_RVC_SWSP_IMM(x)) == (x))
-#define VALID_RVC_SDSP_IMM(x) (EXTRACT_RVC_SDSP_IMM(ENCODE_RVC_SDSP_IMM(x)) == (x))
-#define VALID_RVC_B_IMM(x) (EXTRACT_RVC_B_IMM(ENCODE_RVC_B_IMM(x)) == (x))
-#define VALID_RVC_J_IMM(x) (EXTRACT_RVC_J_IMM(ENCODE_RVC_J_IMM(x)) == (x))
-
-#define RISCV_RTYPE(insn, rd, rs1, rs2) \
- ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2))
-#define RISCV_ITYPE(insn, rd, rs1, imm) \
- ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ((rs1) << OP_SH_RS1) | ENCODE_ITYPE_IMM(imm))
-#define RISCV_STYPE(insn, rs1, rs2, imm) \
- ((MATCH_ ## insn) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2) | ENCODE_STYPE_IMM(imm))
-#define RISCV_SBTYPE(insn, rs1, rs2, target) \
- ((MATCH_ ## insn) | ((rs1) << OP_SH_RS1) | ((rs2) << OP_SH_RS2) | ENCODE_SBTYPE_IMM(target))
-#define RISCV_UTYPE(insn, rd, bigimm) \
- ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ENCODE_UTYPE_IMM(bigimm))
-#define RISCV_UJTYPE(insn, rd, target) \
- ((MATCH_ ## insn) | ((rd) << OP_SH_RD) | ENCODE_UJTYPE_IMM(target))
-
-#define RISCV_NOP RISCV_ITYPE(ADDI, 0, 0, 0)
-#define RVC_NOP MATCH_C_ADDI
-
-#define RISCV_CONST_HIGH_PART(VALUE) \
- (((VALUE) + (RISCV_IMM_REACH/2)) & ~(RISCV_IMM_REACH-1))
-#define RISCV_CONST_LOW_PART(VALUE) ((VALUE) - RISCV_CONST_HIGH_PART (VALUE))
-#define RISCV_PCREL_HIGH_PART(VALUE, PC) RISCV_CONST_HIGH_PART((VALUE) - (PC))
-#define RISCV_PCREL_LOW_PART(VALUE, PC) RISCV_CONST_LOW_PART((VALUE) - (PC))
-
-#define RISCV_JUMP_BITS RISCV_BIGIMM_BITS
-#define RISCV_JUMP_ALIGN_BITS 1
-#define RISCV_JUMP_ALIGN (1 << RISCV_JUMP_ALIGN_BITS)
-#define RISCV_JUMP_REACH ((1ULL << RISCV_JUMP_BITS) * RISCV_JUMP_ALIGN)
-
-#define RISCV_IMM_BITS 12
-#define RISCV_BIGIMM_BITS (32 - RISCV_IMM_BITS)
-#define RISCV_IMM_REACH (1LL << RISCV_IMM_BITS)
-#define RISCV_BIGIMM_REACH (1LL << RISCV_BIGIMM_BITS)
-#define RISCV_RVC_IMM_REACH (1LL << 6)
-#define RISCV_BRANCH_BITS RISCV_IMM_BITS
-#define RISCV_BRANCH_ALIGN_BITS RISCV_JUMP_ALIGN_BITS
-#define RISCV_BRANCH_ALIGN (1 << RISCV_BRANCH_ALIGN_BITS)
-#define RISCV_BRANCH_REACH (RISCV_IMM_REACH * RISCV_BRANCH_ALIGN)
-
-/* RV fields. */
-
-#define OP_MASK_OP 0x7f
-#define OP_SH_OP 0
-#define OP_MASK_RS2 0x1f
-#define OP_SH_RS2 20
-#define OP_MASK_RS1 0x1f
-#define OP_SH_RS1 15
-#define OP_MASK_RS3 0x1f
-#define OP_SH_RS3 27
-#define OP_MASK_RD 0x1f
-#define OP_SH_RD 7
-#define OP_MASK_SHAMT 0x3f
-#define OP_SH_SHAMT 20
-#define OP_MASK_SHAMTW 0x1f
-#define OP_SH_SHAMTW 20
-#define OP_MASK_RM 0x7
-#define OP_SH_RM 12
-#define OP_MASK_PRED 0xf
-#define OP_SH_PRED 24
-#define OP_MASK_SUCC 0xf
-#define OP_SH_SUCC 20
-#define OP_MASK_AQ 0x1
-#define OP_SH_AQ 26
-#define OP_MASK_RL 0x1
-#define OP_SH_RL 25
-
-#define OP_MASK_CUSTOM_IMM 0x7f
-#define OP_SH_CUSTOM_IMM 25
-#define OP_MASK_CSR 0xfff
-#define OP_SH_CSR 20
-
-/* RVC fields. */
-
-#define OP_MASK_CRS2 0x1f
-#define OP_SH_CRS2 2
-#define OP_MASK_CRS1S 0x7
-#define OP_SH_CRS1S 7
-#define OP_MASK_CRS2S 0x7
-#define OP_SH_CRS2S 2
-
-/* ABI names for selected x-registers. */
-
-#define X_RA 1
-#define X_SP 2
-#define X_GP 3
-#define X_TP 4
-#define X_T0 5
-#define X_T1 6
-#define X_T2 7
-#define X_T3 28
-
-#define NGPR 32
-#define NFPR 32
-
-/* Replace bits MASK << SHIFT of STRUCT with the equivalent bits in
- VALUE << SHIFT. VALUE is evaluated exactly once. */
-#define INSERT_BITS(STRUCT, VALUE, MASK, SHIFT) \
- (STRUCT) = (((STRUCT) & ~((insn_t)(MASK) << (SHIFT))) \
- | ((insn_t)((VALUE) & (MASK)) << (SHIFT)))
-
-/* Extract bits MASK << SHIFT from STRUCT and shift them right
- SHIFT places. */
-#define EXTRACT_BITS(STRUCT, MASK, SHIFT) \
- (((STRUCT) >> (SHIFT)) & (MASK))
-
-/* Extract the operand given by FIELD from integer INSN. */
-#define EXTRACT_OPERAND(FIELD, INSN) \
- EXTRACT_BITS ((INSN), OP_MASK_##FIELD, OP_SH_##FIELD)
-
-/* This structure holds information for a particular instruction. */
-
-struct riscv_opcode
-{
- /* The name of the instruction. */
- const char *name;
- /* The ISA subset name (I, M, A, F, D, Xextension). */
- const char *subset;
- /* A string describing the arguments for this instruction. */
- const char *args;
- /* The basic opcode for the instruction. When assembling, this
- opcode is modified by the arguments to produce the actual opcode
- that is used. If pinfo is INSN_MACRO, then this is 0. */
- insn_t match;
- /* If pinfo is not INSN_MACRO, then this is a bit mask for the
- relevant portions of the opcode when disassembling. If the
- actual opcode anded with the match field equals the opcode field,
- then we have found the correct instruction. If pinfo is
- INSN_MACRO, then this field is the macro identifier. */
- insn_t mask;
- /* A function to determine if a word corresponds to this instruction.
- Usually, this computes ((word & mask) == match). */
- int (*match_func) (const struct riscv_opcode *op, insn_t word);
- /* For a macro, this is INSN_MACRO. Otherwise, it is a collection
- of bits describing the instruction, notably any relevant hazard
- information. */
- unsigned long pinfo;
-};
-
-/* Instruction is a simple alias (e.g. "mv" for "addi"). */
-#define INSN_ALIAS 0x00000001
-/* Instruction is actually a macro. It should be ignored by the
- disassembler, and requires special treatment by the assembler. */
-#define INSN_MACRO 0xffffffff
-
-/* This is a list of macro expanded instructions.
-
- _I appended means immediate
- _A appended means address
- _AB appended means address with base register
- _D appended means 64 bit floating point constant
- _S appended means 32 bit floating point constant. */
-
-enum
-{
- M_LA,
- M_LLA,
- M_LA_TLS_GD,
- M_LA_TLS_IE,
- M_LB,
- M_LBU,
- M_LH,
- M_LHU,
- M_LW,
- M_LWU,
- M_LD,
- M_SB,
- M_SH,
- M_SW,
- M_SD,
- M_FLW,
- M_FLD,
- M_FLQ,
- M_FSW,
- M_FSD,
- M_FSQ,
- M_CALL,
- M_J,
- M_LI,
- M_NUM_MACROS
-};
-
-
-#if 0 || _MSC_VER
-extern const char * const riscv_gpr_names_numeric[NGPR];
-extern const char * const riscv_gpr_names_abi[NGPR];
-extern const char * const riscv_fpr_names_numeric[NFPR];
-extern const char * const riscv_fpr_names_abi[NFPR];
-extern struct riscv_opcode *riscv_opcodes;
-//extern const struct riscv_opcode riscv_opcodes[];
-#ifdef _MSC_VER
-extern int bfd_riscv_num_opcodes;
-#endif
-#endif
-#define NUMOPCODES bfd_riscv_num_opcodes
-
-#endif /* _RISCV_H_ */
diff --git a/librz/arch/isa_gnu/riscv/riscv_inc.h b/librz/arch/isa_gnu/riscv/riscv_inc.h
deleted file mode 100644
index 21c6fec9eea..00000000000
--- a/librz/arch/isa_gnu/riscv/riscv_inc.h
+++ /dev/null
@@ -1,11 +0,0 @@
-// SPDX-FileCopyrightText: 2024 deroad
-// SPDX-License-Identifier: LGPL-3.0-only
-
-#ifndef RISCV_INC_H
-#define RISCV_INC_H
-
-#include
-
-int riscv_dis(RzAsm *a, RzAsmOp *rop, const ut8 *buf, ut64 len);
-
-#endif /* RISCV_INC_H */
\ No newline at end of file
diff --git a/librz/arch/meson.build b/librz/arch/meson.build
index df6c5b98cbe..702a36ffc54 100644
--- a/librz/arch/meson.build
+++ b/librz/arch/meson.build
@@ -315,7 +315,7 @@ arch_isa_includes = [
'isa',
]
-if capstone_dep.version() == 'next' or capstone_dep.version().split('.')[0].to_int() > 4
+if capstone_dep.version() == 'next' or capstone_dep.version().split('.')[0].to_int() > 6
# plugins
arch_plugins_list += [
'riscv_cs',
@@ -365,7 +365,6 @@ if get_option('use_gpl')
'arc_gnu',
'cris_gnu',
'lanai_gnu',
- 'riscv_gnu',
'vax_gnu',
'z80_gnu',
]
@@ -375,7 +374,6 @@ if get_option('use_gpl')
'p_gnu/arch_arc.c',
'p_gnu/arch_cris.c',
'p_gnu/arch_lanai.c',
- 'p_gnu/arch_riscv.c',
'p_gnu/arch_vax.c',
'p_gnu/arch_z80.c',
]
@@ -390,8 +388,6 @@ if get_option('use_gpl')
'isa_gnu/cris/cris-opc.c',
'isa_gnu/lanai/lanai-dis.c',
'isa_gnu/lanai/lanai-opc.c',
- # 'isa_gnu/riscv/riscv-opc.c',
- # 'isa_gnu/riscv/riscv.c',
'isa_gnu/vax/vax-dis.c',
# 'isa_gnu/z80/expressions.c',
# 'isa_gnu/z80/z80.c',
diff --git a/librz/arch/p/analysis/analysis_riscv_cs.c b/librz/arch/p/analysis/analysis_riscv_cs.c
index cd07add92ac..1c7cb74435d 100644
--- a/librz/arch/p/analysis/analysis_riscv_cs.c
+++ b/librz/arch/p/analysis/analysis_riscv_cs.c
@@ -1,13 +1,18 @@
+// SPDX-FileCopyrightText: 2024-2026 moste00
// SPDX-FileCopyrightText: 2013-2020 pancake
-// SPDX-License-Identifier: LGPL-3.0-only
+// SPDX-License-Identifier: BSD-3-Clause
+#include
+#include "rz_reg.h"
+#include "rz_util/rz_log.h"
#include
#include
#include
#include
-// http://www.mrc.uidaho.edu/mrc/people/jff/digital/RISCVir.html
+#include "analysis_riscv_utils.h"
+#include
#define OPERAND(x) insn->detail->riscv.operands[x]
#define REGID(x) insn->detail->riscv.operands[x].reg
@@ -19,10 +24,7 @@
#define OPCOUNT() insn->detail->riscv.op_count
// TODO scale and disp
-#define SET_VAL(op, i) \
- if ((i) < OPCOUNT() && OPERAND(i).type == RISCV_OP_IMM) { \
- (op)->val = OPERAND(i).imm; \
- }
+#define NEXT_ADDRESS(op) (op->addr + op->size)
#define CREATE_SRC_DST_3(op) \
(op)->src[0] = rz_analysis_value_new(); \
@@ -57,6 +59,8 @@
SET_SRC_DST_3_REGS(op); \
}
+static void set_stack_effect(RzAnalysisOp *op, cs_insn *insn);
+
static RzStructuredData *riscv_opex(csh handle, cs_insn *insn) {
if (!insn->detail) {
return NULL;
@@ -144,19 +148,29 @@ static void op_fillval(RzAnalysis *analysis, RzAnalysisOp *op, csh *handle, cs_i
case RZ_ANALYSIS_OP_TYPE_LOAD:
if (OPERAND(1).type == RISCV_OP_MEM) {
ZERO_FILL(ctx->reg);
+ op->dst = rz_analysis_value_new();
+ op->dst->type = RZ_ANALYSIS_VAL_REG;
+ op->dst->reg = rz_reg_get(analysis->reg, cs_reg_name(*handle, FIRST_WRITTEN_REGID(insn)), RZ_REG_TYPE_GPR);
op->src[0] = rz_analysis_value_new();
+ op->src[0]->type = RZ_ANALYSIS_VAL_MEM;
op->src[0]->reg = &ctx->reg;
parse_reg_name(op->src[0]->reg, *handle, insn, 1);
op->src[0]->delta = OPERAND(1).mem.disp;
+ op->src[0]->memref = op->refptr;
}
break;
case RZ_ANALYSIS_OP_TYPE_STORE:
if (OPERAND(1).type == RISCV_OP_MEM) {
ZERO_FILL(ctx->reg);
op->dst = rz_analysis_value_new();
+ op->dst->type = RZ_ANALYSIS_VAL_MEM;
op->dst->reg = &ctx->reg;
parse_reg_name(op->dst->reg, *handle, insn, 1);
op->dst->delta = OPERAND(1).mem.disp;
+ op->dst->memref = op->refptr;
+ op->src[0] = rz_analysis_value_new();
+ op->src[0]->type = RZ_ANALYSIS_VAL_REG;
+ op->src[0]->reg = rz_reg_get(analysis->reg, cs_reg_name(*handle, FIRST_READ_REGID(insn)), RZ_REG_TYPE_GPR);
}
break;
case RZ_ANALYSIS_OP_TYPE_SHL:
@@ -209,20 +223,559 @@ static void set_opdir(RzAnalysisOp *op) {
}
}
-static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) {
+static inline bool group_exists_in(uint8_t *groups, uint8_t groups_count, uint8_t group) {
+ for (int i = 0; i < groups_count; i++) {
+ if (groups[i] == group) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void set_op_sign(RzAnalysisOp *op, cs_insn *insn) {
+ switch (insn->id) {
+ // Signed loads
+ case RISCV_INS_LB:
+ case RISCV_INS_LH:
+ case RISCV_INS_LW:
+ case RISCV_INS_LD:
+ case RISCV_INS_TH_LRB:
+ case RISCV_INS_TH_LRH:
+ case RISCV_INS_TH_LRW:
+ case RISCV_INS_TH_LRD:
+ // Core-V loads
+ case RISCV_INS_CV_LB:
+ case RISCV_INS_CV_LBU:
+ case RISCV_INS_CV_LH:
+ case RISCV_INS_CV_LHU:
+ case RISCV_INS_CV_LW:
+ op->sign = true;
+ break;
+ // Signed Arithmetic & Comparison
+ case RISCV_INS_DIV:
+ case RISCV_INS_DIVW:
+ case RISCV_INS_REM:
+ case RISCV_INS_REMW:
+ case RISCV_INS_MULH:
+ case RISCV_INS_MULHSU:
+ case RISCV_INS_SLT:
+ case RISCV_INS_SLTI:
+ case RISCV_INS_SRA:
+ case RISCV_INS_SRAI:
+ case RISCV_INS_SRAW:
+ case RISCV_INS_SRAIW:
+ case RISCV_INS_C_SRAI64:
+ case RISCV_INS_BLT:
+ case RISCV_INS_BGE:
+ // Atomic signed (AMOMIN/MAX)
+ case RISCV_INS_AMOMAX_W:
+ case RISCV_INS_AMOMAX_D:
+ case RISCV_INS_AMOMIN_W:
+ case RISCV_INS_AMOMIN_D:
+ // Bitmanip signed
+ case RISCV_INS_MIN:
+ case RISCV_INS_MAX:
+ // Core-V signs
+ case RISCV_INS_CV_ABS:
+ case RISCV_INS_CV_ABS_B:
+ case RISCV_INS_CV_ABS_H:
+ case RISCV_INS_CV_ADD_B:
+ case RISCV_INS_CV_ADD_H:
+ case RISCV_INS_CV_AVG_B:
+ case RISCV_INS_CV_AVG_H:
+ case RISCV_INS_CV_MAX_B:
+ case RISCV_INS_CV_MAX_H:
+ case RISCV_INS_CV_MIN_B:
+ case RISCV_INS_CV_MIN_H:
+ case RISCV_INS_CV_SUB_B:
+ case RISCV_INS_CV_SUB_H:
+ op->sign = true;
+ break;
+ // RV64 "W" instructions (result is sign-extended to 64 bits)
+ case RISCV_INS_ADDW:
+ case RISCV_INS_ADDIW:
+ case RISCV_INS_SUBW:
+ case RISCV_INS_MULW:
+ case RISCV_INS_C_ADDW:
+ case RISCV_INS_C_ADDIW:
+ case RISCV_INS_C_SUBW:
+ op->sign = true;
+ break;
+ // FP Comparison & Sign-Aware Ops
+ case RISCV_INS_FEQ_S:
+ case RISCV_INS_FLT_S:
+ case RISCV_INS_FLE_S:
+ case RISCV_INS_FEQ_D:
+ case RISCV_INS_FLT_D:
+ case RISCV_INS_FLE_D:
+ case RISCV_INS_FEQ_H:
+ case RISCV_INS_FLT_H:
+ case RISCV_INS_FLE_H:
+ case RISCV_INS_FMIN_S:
+ case RISCV_INS_FMAX_S:
+ case RISCV_INS_FMIN_D:
+ case RISCV_INS_FMAX_D:
+ case RISCV_INS_FMIN_H:
+ case RISCV_INS_FMAX_H:
+ op->sign = true;
+ break;
+ // Explicit sign extensions
+ case RISCV_INS_SEXT_B:
+ case RISCV_INS_SEXT_H:
+ case RISCV_INS_C_SEXT_B:
+ case RISCV_INS_C_SEXT_H:
+ op->sign = true;
+ break;
+ default:
+ break;
+ }
+}
+
+static void set_op_data_size(RzAnalysisOp *op, cs_insn *insn) {
+ switch (insn->id) {
+ // 1 byte
+ case RISCV_INS_LB:
+ case RISCV_INS_LBU:
+ case RISCV_INS_SB:
+ case RISCV_INS_C_LBU:
+ case RISCV_INS_C_SB:
+ case RISCV_INS_TH_LRB:
+ case RISCV_INS_TH_LRBU:
+ op->refptr = 1;
+ break;
+ // 2 bytes
+ case RISCV_INS_LH:
+ case RISCV_INS_LHU:
+ case RISCV_INS_SH:
+ case RISCV_INS_FLH:
+ case RISCV_INS_FSH:
+ case RISCV_INS_C_LH:
+ case RISCV_INS_C_LHU:
+ case RISCV_INS_C_SH:
+ case RISCV_INS_TH_LRH:
+ case RISCV_INS_TH_LRHU:
+ op->refptr = 2;
+ break;
+ // 4 bytes
+ case RISCV_INS_LW:
+ case RISCV_INS_LWU:
+ case RISCV_INS_SW:
+ case RISCV_INS_FLW:
+ case RISCV_INS_FSW:
+ case RISCV_INS_C_LW:
+ case RISCV_INS_C_LWSP:
+ case RISCV_INS_C_SW:
+ case RISCV_INS_C_SWSP:
+ case RISCV_INS_C_FLW:
+ case RISCV_INS_C_FLWSP:
+ case RISCV_INS_C_FSW:
+ case RISCV_INS_C_FSWSP:
+ case RISCV_INS_TH_LRW:
+ case RISCV_INS_TH_LRWU:
+ case RISCV_INS_LR_W:
+ case RISCV_INS_LR_W_AQ:
+ case RISCV_INS_LR_W_AQRL:
+ case RISCV_INS_LR_W_RL:
+ case RISCV_INS_SC_W:
+ case RISCV_INS_SC_W_AQ:
+ case RISCV_INS_SC_W_AQRL:
+ case RISCV_INS_SC_W_RL:
+ // Atomic 4-byte
+ case RISCV_INS_AMOSWAP_W:
+ case RISCV_INS_AMOADD_W:
+ case RISCV_INS_AMOAND_W:
+ case RISCV_INS_AMOOR_W:
+ case RISCV_INS_AMOXOR_W:
+ case RISCV_INS_AMOMAX_W:
+ case RISCV_INS_AMOMIN_W:
+ case RISCV_INS_AMOMAXU_W:
+ case RISCV_INS_AMOMINU_W:
+ case RISCV_INS_AMOCAS_W:
+ op->refptr = 4;
+ break;
+ // 8 bytes
+ case RISCV_INS_LD:
+ case RISCV_INS_SD:
+ case RISCV_INS_FLD:
+ case RISCV_INS_FSD:
+ case RISCV_INS_C_LD:
+ case RISCV_INS_C_LDSP:
+ case RISCV_INS_C_SD:
+ case RISCV_INS_C_SDSP:
+ case RISCV_INS_C_FLD:
+ case RISCV_INS_C_FLDSP:
+ case RISCV_INS_C_FSD:
+ case RISCV_INS_C_FSDSP:
+ case RISCV_INS_TH_LRD:
+ case RISCV_INS_LR_D:
+ case RISCV_INS_LR_D_AQ:
+ case RISCV_INS_LR_D_AQRL:
+ case RISCV_INS_LR_D_RL:
+ case RISCV_INS_SC_D:
+ case RISCV_INS_SC_D_AQ:
+ case RISCV_INS_SC_D_AQRL:
+ case RISCV_INS_SC_D_RL:
+ // Atomic 8-byte
+ case RISCV_INS_AMOSWAP_D:
+ case RISCV_INS_AMOADD_D:
+ case RISCV_INS_AMOAND_D:
+ case RISCV_INS_AMOOR_D:
+ case RISCV_INS_AMOXOR_D:
+ case RISCV_INS_AMOMAX_D:
+ case RISCV_INS_AMOMIN_D:
+ case RISCV_INS_AMOMAXU_D:
+ case RISCV_INS_AMOMINU_D:
+ case RISCV_INS_AMOCAS_D:
+ op->refptr = 8;
+ break;
+ // 16 bytes
+ case RISCV_INS_AMOCAS_Q:
+ op->refptr = 16;
+ break;
+ default:
+ break;
+ }
+}
+
+static void set_op_val(RzAnalysisOp *op, cs_insn *insn) {
+ if (!insn->detail) {
+ return;
+ }
+
+ uint8_t *groups = insn->detail->groups;
+ uint8_t groups_count = insn->detail->groups_count;
+ if (group_exists_in(groups, groups_count, RISCV_GRP_JUMP) ||
+ group_exists_in(groups, groups_count, RISCV_GRP_CALL) ||
+ group_exists_in(groups, groups_count, RISCV_GRP_BRANCH_RELATIVE)) {
+ return;
+ }
+
+ // Exclude instructions where the immediate is a configuration bitfield
+ // to prevent misleading ASCII hints
+ switch (insn->id) {
+ case RISCV_INS_VSETVLI:
+ case RISCV_INS_VSETIVLI:
+ return;
+ }
+
+ st64 imm = FIRST_IMM(insn);
+ if (imm != INT64_MAX) {
+ switch (insn->id) {
+ case RISCV_INS_LUI:
+ case RISCV_INS_C_LUI:
+ case RISCV_INS_AUIPC:
+ op->val = imm << 12;
+ break;
+ default:
+ op->val = imm;
+ break;
+ }
+ }
+}
+
+static void set_op_eob(RzAnalysisOp *op, cs_insn *insn) {
+ switch (insn->id) {
+ case RISCV_INS_JAL:
+ case RISCV_INS_JALR:
+ case RISCV_INS_TAIL:
+ case RISCV_INS_JUMP:
+ case RISCV_INS_BEQ:
+ case RISCV_INS_BNE:
+ case RISCV_INS_BLT:
+ case RISCV_INS_BGE:
+ case RISCV_INS_BLTU:
+ case RISCV_INS_BGEU:
+ case RISCV_INS_ECALL:
+ case RISCV_INS_EBREAK:
+ case RISCV_INS_MRET:
+ case RISCV_INS_SRET:
+ case RISCV_INS_DRET:
+ case RISCV_INS_WFI:
+ case RISCV_INS_CM_POPRET:
+ case RISCV_INS_CM_POPRETZ:
+ case RISCV_INS_CM_JT:
+ case RISCV_INS_CM_JALT:
+ case RISCV_INS_C_J:
+ case RISCV_INS_C_JR:
+ case RISCV_INS_C_JAL:
+ case RISCV_INS_C_JALR:
+ case RISCV_INS_C_BEQZ:
+ case RISCV_INS_C_BNEZ:
+ case RISCV_INS_C_EBREAK:
+ // Core-V branches
+ case RISCV_INS_CV_BEQIMM:
+ case RISCV_INS_CV_BNEIMM:
+ op->eob = true;
+ break;
+ default:
+ break;
+ }
+}
+
+static void set_op_cond(RzAnalysisOp *op, cs_insn *insn) {
+ switch (insn->id) {
+ case RISCV_INS_BEQ:
+ case RISCV_INS_C_BEQZ:
+ case RISCV_INS_CV_BEQIMM:
+ op->cond = RZ_TYPE_COND_EQ;
+ break;
+ case RISCV_INS_BNE:
+ case RISCV_INS_C_BNEZ:
+ case RISCV_INS_CV_BNEIMM:
+ op->cond = RZ_TYPE_COND_NE;
+ break;
+ case RISCV_INS_BLT:
+ op->cond = RZ_TYPE_COND_LT;
+ break;
+ case RISCV_INS_BGE:
+ op->cond = RZ_TYPE_COND_GE;
+ break;
+ case RISCV_INS_BLTU:
+ op->cond = RZ_TYPE_COND_LO;
+ break;
+ case RISCV_INS_BGEU:
+ op->cond = RZ_TYPE_COND_HS;
+ break;
+ default:
+ op->cond = RZ_TYPE_COND_AL;
+ break;
+ }
+}
+
+static void set_op_family(RzAnalysisOp *op, cs_insn *insn) {
+ if (op->type & RZ_ANALYSIS_OP_TYPE_SIMD) {
+ op->family = RZ_ANALYSIS_OP_FAMILY_MMX;
+ return;
+ }
+ if (op->type & RZ_ANALYSIS_OP_TYPE_CRYPTO) {
+ op->family = RZ_ANALYSIS_OP_FAMILY_CRYPTO;
+ return;
+ }
+
+ if (op->type & RZ_ANALYSIS_OP_TYPE_SYNC) {
+ op->family = RZ_ANALYSIS_OP_FAMILY_THREAD;
+ return;
+ }
+
+ switch (insn->id) {
+ // Virtualization
+ case RISCV_INS_HFENCE_GVMA:
+ case RISCV_INS_HFENCE_VVMA:
+ case RISCV_INS_HLV_B:
+ case RISCV_INS_HLV_BU:
+ case RISCV_INS_HLV_D:
+ case RISCV_INS_HLV_H:
+ case RISCV_INS_HLV_HU:
+ case RISCV_INS_HLV_W:
+ case RISCV_INS_HLV_WU:
+ case RISCV_INS_HLVX_HU:
+ case RISCV_INS_HLVX_WU:
+ case RISCV_INS_HSV_B:
+ case RISCV_INS_HSV_D:
+ case RISCV_INS_HSV_H:
+ case RISCV_INS_HSV_W:
+ op->family = RZ_ANALYSIS_OP_FAMILY_VIRT;
+ break;
+ // Crypto (if not already handled by type check)
+ case RISCV_INS_AES32DSI:
+ case RISCV_INS_AES32DSMI:
+ case RISCV_INS_AES32ESI:
+ case RISCV_INS_AES32ESMI:
+ case RISCV_INS_AES64DS:
+ case RISCV_INS_AES64DSM:
+ case RISCV_INS_AES64ES:
+ case RISCV_INS_AES64ESM:
+ case RISCV_INS_AES64IM:
+ case RISCV_INS_AES64KS1I:
+ case RISCV_INS_AES64KS2:
+ case RISCV_INS_SHA256SIG0:
+ case RISCV_INS_SHA256SIG1:
+ case RISCV_INS_SHA256SUM0:
+ case RISCV_INS_SHA256SUM1:
+ case RISCV_INS_SHA512SIG0:
+ case RISCV_INS_SHA512SIG0H:
+ case RISCV_INS_SHA512SIG0L:
+ case RISCV_INS_SHA512SIG1:
+ case RISCV_INS_SHA512SIG1H:
+ case RISCV_INS_SHA512SIG1L:
+ case RISCV_INS_SHA512SUM0:
+ case RISCV_INS_SHA512SUM0R:
+ case RISCV_INS_SHA512SUM1:
+ case RISCV_INS_SHA512SUM1R:
+ case RISCV_INS_SM3P0:
+ case RISCV_INS_SM3P1:
+ case RISCV_INS_SM4ED:
+ case RISCV_INS_SM4KS:
+ op->family = RZ_ANALYSIS_OP_FAMILY_CRYPTO;
+ break;
+ // Floating Point
+ case RISCV_INS_FADD_S:
+ case RISCV_INS_FADD_D:
+ case RISCV_INS_FADD_H:
+ case RISCV_INS_FSUB_S:
+ case RISCV_INS_FSUB_D:
+ case RISCV_INS_FSUB_H:
+ case RISCV_INS_FMUL_S:
+ case RISCV_INS_FMUL_D:
+ case RISCV_INS_FMUL_H:
+ case RISCV_INS_FDIV_S:
+ case RISCV_INS_FDIV_D:
+ case RISCV_INS_FDIV_H:
+ case RISCV_INS_FSQRT_S:
+ case RISCV_INS_FSQRT_D:
+ case RISCV_INS_FSQRT_H:
+ case RISCV_INS_FMIN_S:
+ case RISCV_INS_FMIN_D:
+ case RISCV_INS_FMIN_H:
+ case RISCV_INS_FMAX_S:
+ case RISCV_INS_FMAX_D:
+ case RISCV_INS_FMAX_H:
+ case RISCV_INS_FEQ_S:
+ case RISCV_INS_FEQ_D:
+ case RISCV_INS_FEQ_H:
+ case RISCV_INS_FLT_S:
+ case RISCV_INS_FLT_D:
+ case RISCV_INS_FLT_H:
+ case RISCV_INS_FLE_S:
+ case RISCV_INS_FLE_D:
+ case RISCV_INS_FLE_H:
+ case RISCV_INS_FMADD_S:
+ case RISCV_INS_FMADD_D:
+ case RISCV_INS_FMADD_H:
+ case RISCV_INS_FMSUB_S:
+ case RISCV_INS_FMSUB_D:
+ case RISCV_INS_FMSUB_H:
+ case RISCV_INS_FNMADD_S:
+ case RISCV_INS_FNMADD_D:
+ case RISCV_INS_FNMADD_H:
+ case RISCV_INS_FNMSUB_S:
+ case RISCV_INS_FNMSUB_D:
+ case RISCV_INS_FNMSUB_H:
+ case RISCV_INS_FCVT_S_D:
+ case RISCV_INS_FCVT_D_S:
+ case RISCV_INS_FCVT_W_S:
+ case RISCV_INS_FCVT_WU_S:
+ case RISCV_INS_FCVT_S_W:
+ case RISCV_INS_FCVT_S_WU:
+ case RISCV_INS_FLW:
+ case RISCV_INS_FSW:
+ case RISCV_INS_FLD:
+ case RISCV_INS_FSD:
+ case RISCV_INS_FLH:
+ case RISCV_INS_FSH:
+ case RISCV_INS_C_FLW:
+ case RISCV_INS_C_FLWSP:
+ case RISCV_INS_C_FSW:
+ case RISCV_INS_C_FSWSP:
+ case RISCV_INS_C_FLD:
+ case RISCV_INS_C_FLDSP:
+ case RISCV_INS_C_FSD:
+ case RISCV_INS_C_FSDSP:
+ op->family = RZ_ANALYSIS_OP_FAMILY_FPU;
+ break;
+ // Privileged / System
+ case RISCV_INS_ECALL:
+ case RISCV_INS_EBREAK:
+ case RISCV_INS_MRET:
+ case RISCV_INS_SRET:
+ case RISCV_INS_DRET:
+ case RISCV_INS_WFI:
+ case RISCV_INS_CSRRW:
+ case RISCV_INS_CSRRS:
+ case RISCV_INS_CSRRC:
+ case RISCV_INS_CSRRWI:
+ case RISCV_INS_CSRRSI:
+ case RISCV_INS_CSRRCI:
+ case RISCV_INS_SFENCE_VMA:
+ case RISCV_INS_SINVAL_VMA:
+ case RISCV_INS_SFENCE_W_INVAL:
+ op->family = RZ_ANALYSIS_OP_FAMILY_PRIV;
+ break;
+ // Atomic (Thread/Sync)
+ case RISCV_INS_FENCE:
+ case RISCV_INS_FENCE_I:
+ case RISCV_INS_FENCE_TSO:
+ case RISCV_INS_ALIAS_PAUSE:
+ case RISCV_INS_LR_W:
+ case RISCV_INS_LR_D:
+ case RISCV_INS_SC_W:
+ case RISCV_INS_SC_D:
+ case RISCV_INS_AMOSWAP_W:
+ case RISCV_INS_AMOSWAP_D:
+ case RISCV_INS_AMOADD_W:
+ case RISCV_INS_AMOADD_D:
+ case RISCV_INS_AMOAND_W:
+ case RISCV_INS_AMOAND_D:
+ case RISCV_INS_AMOOR_W:
+ case RISCV_INS_AMOOR_D:
+ case RISCV_INS_AMOXOR_W:
+ case RISCV_INS_AMOXOR_D:
+ case RISCV_INS_AMOMAX_W:
+ case RISCV_INS_AMOMAX_D:
+ case RISCV_INS_AMOMIN_W:
+ case RISCV_INS_AMOMIN_D:
+ case RISCV_INS_AMOMAXU_W:
+ case RISCV_INS_AMOMAXU_D:
+ case RISCV_INS_AMOMINU_W:
+ case RISCV_INS_AMOMINU_D:
+ case RISCV_INS_AMOCAS_W:
+ case RISCV_INS_AMOCAS_D:
+ case RISCV_INS_AMOCAS_Q:
+ op->family = RZ_ANALYSIS_OP_FAMILY_THREAD;
+ break;
+ default:
+ op->family = RZ_ANALYSIS_OP_FAMILY_CPU;
+ break;
+ }
+}
+
+static void set_op_extra_metadata(RzAnalysis *analysis, RzAnalysisOp *op, csh handle, cs_insn *insn) {
+ if (!insn->detail) {
+ return;
+ }
+ // Set destination register name
+ if (insn->detail->riscv.op_count > 0 && insn->detail->riscv.operands[0].type == RISCV_OP_REG && (insn->detail->riscv.operands[0].access & CS_AC_WRITE)) {
+ op->reg = cs_reg_name(handle, insn->detail->riscv.operands[0].reg);
+ }
+
+ // Set indirect register name (base for loads/stores)
+ for (int i = 0; i < insn->detail->riscv.op_count; i++) {
+ if (insn->detail->riscv.operands[i].type == RISCV_OP_MEM) {
+ op->ireg = cs_reg_name(handle, insn->detail->riscv.operands[i].mem.base);
+ op->disp = insn->detail->riscv.operands[i].mem.disp;
+ break;
+ }
+ }
+
+ // Set datatype
+ if (op->family == RZ_ANALYSIS_OP_FAMILY_FPU) {
+ op->datatype = RZ_ANALYSIS_DATATYPE_FLOAT;
+ } else if (op->type & RZ_ANALYSIS_OP_TYPE_LOAD || op->type & RZ_ANALYSIS_OP_TYPE_STORE) {
+ switch (op->refptr) {
+ case 2: op->datatype = RZ_ANALYSIS_DATATYPE_INT16; break;
+ case 4: op->datatype = RZ_ANALYSIS_DATATYPE_INT32; break;
+ case 8: op->datatype = RZ_ANALYSIS_DATATYPE_INT64; break;
+ default: break;
+ }
+ }
+}
+
+int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) {
RiscvContext *ctx = (RiscvContext *)analysis->plugin_data;
int n, ret, opsize = -1;
cs_insn *insn;
- int mode = (analysis->bits == 64) ? CS_MODE_RISCV64 : CS_MODE_RISCV32;
- if (mode != ctx->omode || analysis->bits != ctx->obits) {
+ cs_mode mode = (analysis->bits == 64) ? CS_MODE_RISCV64 : CS_MODE_RISCV32;
+ mode |= mode_from_arch_string(analysis->cpu);
+
+ if (mode != ctx->omode || analysis->bits != ctx->obits || cs_option(ctx->hndl, CS_OPT_DETAIL, CS_OPT_ON | CS_OPT_DETAIL_REAL) != CS_ERR_OK) {
cs_close(&ctx->hndl);
ctx->hndl = 0;
ctx->omode = mode;
ctx->obits = analysis->bits;
}
- // XXX no arch->cpu ?!?! CS_MODE_MICRO, N64
+
op->addr = addr;
- if (len < 4) {
+ if (len < 2) {
return -1;
}
op->size = 4;
@@ -234,39 +787,1131 @@ static int analyze_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const u
cs_option(ctx->hndl, CS_OPT_DETAIL, CS_OPT_ON);
}
n = cs_disasm(ctx->hndl, (ut8 *)buf, len, addr, 1, &insn);
+
if (n < 1 || insn->size < 1) {
goto beach;
}
op->id = insn->id;
opsize = op->size = insn->size;
+
switch (insn->id) {
case RISCV_INS_C_NOP:
+ case RISCV_INS_CMOP_1:
+ case RISCV_INS_CMOP_3:
+ case RISCV_INS_CMOP_5:
+ case RISCV_INS_CMOP_7:
+ case RISCV_INS_CMOP_9:
+ case RISCV_INS_CMOP_11:
+ case RISCV_INS_CMOP_13:
+ case RISCV_INS_CMOP_15:
op->type = RZ_ANALYSIS_OP_TYPE_NOP;
break;
+
case RISCV_INS_INVALID:
+ case RISCV_INS_UNIMP:
+ case RISCV_INS_C_UNIMP:
op->type = RZ_ANALYSIS_OP_TYPE_ILL;
break;
+
case RISCV_INS_C_JALR:
- op->type = RZ_ANALYSIS_OP_TYPE_UCALL;
+ op->type = RZ_ANALYSIS_OP_TYPE_RCALL;
+ op->fail = UINT64_MAX;
break;
+
case RISCV_INS_C_JR:
- op->type = RZ_ANALYSIS_OP_TYPE_UJMP;
+ if (group_exists_in(insn->detail->groups, insn->detail->groups_count, RISCV_GRP_RET)) {
+ op->type = RZ_ANALYSIS_OP_TYPE_RET;
+ } else {
+ op->type = RZ_ANALYSIS_OP_TYPE_RJMP;
+ }
+ op->fail = UINT64_MAX;
+ break;
+
+ case RISCV_INS_JUMP:
+ op->type = RZ_ANALYSIS_OP_TYPE_JMP;
+ break;
+
+ case RISCV_INS_C_J:
+ case RISCV_INS_C_JAL: {
+ bool is_call = insn->id == RISCV_INS_C_JAL;
+ op->type = is_call ? RZ_ANALYSIS_OP_TYPE_CALL : RZ_ANALYSIS_OP_TYPE_JMP;
+ op->jump = SINGLE_IMM(insn);
+ op->fail = UINT64_MAX;
+ break;
+ }
+
+ case RISCV_INS_JALR:
+ if (group_exists_in(insn->detail->groups, insn->detail->groups_count, RISCV_GRP_RET)) {
+ op->type = RZ_ANALYSIS_OP_TYPE_RET;
+ break;
+ }
+ // no fallthrough
+ op->fail = UINT64_MAX;
+ // special case: known base register, namely the always-0 register
+ bool is_known_base = FIRST_READ_REGID(insn) == RISCV_REG_X0;
+
+ if (group_exists_in(insn->detail->groups, insn->detail->groups_count, RISCV_GRP_CALL)) {
+ op->type = is_known_base ? RZ_ANALYSIS_OP_TYPE_CALL : RZ_ANALYSIS_OP_TYPE_RCALL;
+ } else {
+ op->type = is_known_base ? RZ_ANALYSIS_OP_TYPE_JMP : RZ_ANALYSIS_OP_TYPE_RJMP;
+ }
+ if (is_known_base) {
+ op->jump = SINGLE_IMM(insn);
+ }
break;
+
+ case RISCV_INS_JAL: {
+ bool is_call = group_exists_in(insn->detail->groups, insn->detail->groups_count, RISCV_GRP_CALL);
+ op->type = is_call ? RZ_ANALYSIS_OP_TYPE_CALL : RZ_ANALYSIS_OP_TYPE_JMP;
+
+ op->jump = SINGLE_IMM(insn);
+ op->fail = UINT64_MAX;
+ break;
+ }
+
+ case RISCV_INS_CM_JALT:
+ op->type = RZ_ANALYSIS_OP_TYPE_ICALL;
+ break;
+
+ case RISCV_INS_CM_JT:
+ op->type = RZ_ANALYSIS_OP_TYPE_IJMP;
+ break;
+
+ case RISCV_INS_AUIPC:
+ case RISCV_INS_ADD:
+ case RISCV_INS_ADDW:
+ case RISCV_INS_ADDI:
+ case RISCV_INS_ADDIW:
+ case RISCV_INS_C_ADD:
+ case RISCV_INS_C_ADDI:
+ case RISCV_INS_C_ADDW:
+ case RISCV_INS_C_ADDIW:
+ case RISCV_INS_C_ADDI16SP:
+ case RISCV_INS_C_ADDI4SPN:
+ case RISCV_INS_FADD_H:
+ case RISCV_INS_FADD_S:
+ case RISCV_INS_FADD_D:
+ case RISCV_INS_TH_ADDSL:
+ op->type = RZ_ANALYSIS_OP_TYPE_ADD;
+ break;
+ case RISCV_INS_SUB:
+ case RISCV_INS_SUBW:
+ case RISCV_INS_C_SUB:
+ case RISCV_INS_C_SUBW:
+ case RISCV_INS_FSUB_H:
+ case RISCV_INS_FSUB_S:
+ case RISCV_INS_FSUB_D:
+ op->type = RZ_ANALYSIS_OP_TYPE_SUB;
+ break;
+ case RISCV_INS_MUL:
+ case RISCV_INS_MULW:
+ case RISCV_INS_MULH:
+ case RISCV_INS_MULHU:
+ case RISCV_INS_MULHSU:
+ case RISCV_INS_C_MUL:
+ case RISCV_INS_FMUL_H:
+ case RISCV_INS_FMUL_S:
+ case RISCV_INS_FMUL_D:
+ case RISCV_INS_CLMUL:
+ case RISCV_INS_CLMULH:
+ case RISCV_INS_CLMULR:
+ op->type = RZ_ANALYSIS_OP_TYPE_MUL;
+ break;
+
+ case RISCV_INS_DIV:
+ case RISCV_INS_DIVU:
+ case RISCV_INS_DIVW:
+ case RISCV_INS_DIVUW:
+ case RISCV_INS_FDIV_H:
+ case RISCV_INS_FDIV_S:
+ case RISCV_INS_FDIV_D:
+ op->type = RZ_ANALYSIS_OP_TYPE_DIV;
+ break;
+ case RISCV_INS_REM:
+ case RISCV_INS_REMU:
+ case RISCV_INS_REMW:
+ case RISCV_INS_REMUW:
+ op->type = RZ_ANALYSIS_OP_TYPE_MOD;
+ break;
+
case RISCV_INS_C_MV:
+ case RISCV_INS_LUI:
+ case RISCV_INS_LI:
+ case RISCV_INS_LA:
op->type = RZ_ANALYSIS_OP_TYPE_MOV;
break;
- case RISCV_INS_JAL:
- op->type = RZ_ANALYSIS_OP_TYPE_CALL;
- op->jump = IMM(0);
- op->fail = op->addr + op->size;
+
+ // normal loads of various sizes
+ case RISCV_INS_LB:
+ case RISCV_INS_LBU:
+ case RISCV_INS_LH:
+ case RISCV_INS_LHU:
+ case RISCV_INS_LW:
+ case RISCV_INS_LWU:
+ case RISCV_INS_LD:
+ case RISCV_INS_C_LBU:
+ case RISCV_INS_C_LH:
+ case RISCV_INS_C_LHU:
+ case RISCV_INS_C_LW:
+ case RISCV_INS_C_LWSP:
+ case RISCV_INS_C_LD:
+ case RISCV_INS_C_LDSP:
+ // FP loads
+ case RISCV_INS_FLH:
+ case RISCV_INS_FLW:
+ case RISCV_INS_FLD:
+ case RISCV_INS_C_FLD:
+ case RISCV_INS_C_FLDSP:
+ case RISCV_INS_C_FLW:
+ case RISCV_INS_C_FLWSP:
+ // atomic loads
+ case RISCV_INS_LR_D:
+ case RISCV_INS_LR_D_AQ:
+ case RISCV_INS_LR_D_AQRL:
+ case RISCV_INS_LR_D_RL:
+ case RISCV_INS_LR_W:
+ case RISCV_INS_LR_W_AQ:
+ case RISCV_INS_LR_W_AQRL:
+ case RISCV_INS_LR_W_RL:
+ // T-Head loads
+ case RISCV_INS_TH_LRB:
+ case RISCV_INS_TH_LRBU:
+ case RISCV_INS_TH_LRD:
+ case RISCV_INS_TH_LRH:
+ case RISCV_INS_TH_LRHU:
+ case RISCV_INS_TH_LRW:
+ case RISCV_INS_TH_LRWU:
+ op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
+ break;
+
+ case RISCV_INS_SB:
+ case RISCV_INS_SH:
+ case RISCV_INS_SW:
+ case RISCV_INS_SD:
+ case RISCV_INS_FSH:
+ case RISCV_INS_FSW:
+ case RISCV_INS_FSD:
+ case RISCV_INS_C_FSD:
+ case RISCV_INS_C_FSDSP:
+ case RISCV_INS_C_FSW:
+ case RISCV_INS_C_FSWSP:
+ case RISCV_INS_C_SB:
+ case RISCV_INS_C_SH:
+ case RISCV_INS_C_SW:
+ case RISCV_INS_C_SD:
+ case RISCV_INS_C_SWSP:
+ case RISCV_INS_C_SDSP:
+ case RISCV_INS_SC_D:
+ case RISCV_INS_SC_D_AQ:
+ case RISCV_INS_SC_D_AQRL:
+ case RISCV_INS_SC_D_RL:
+ case RISCV_INS_SC_W:
+ case RISCV_INS_SC_W_AQ:
+ case RISCV_INS_SC_W_AQRL:
+ case RISCV_INS_SC_W_RL:
+
+ case RISCV_INS_WRS_NTO:
+ case RISCV_INS_WRS_STO:
+ op->type = RZ_ANALYSIS_OP_TYPE_STORE;
+ break;
+ case RISCV_INS_AND:
+ case RISCV_INS_ANDI:
+ op->type = RZ_ANALYSIS_OP_TYPE_AND;
+ break;
+ case RISCV_INS_OR:
+ case RISCV_INS_ORI:
+ op->type = RZ_ANALYSIS_OP_TYPE_OR;
+ break;
+
+ case RISCV_INS_XOR:
+ case RISCV_INS_XORI:
+ case RISCV_INS_C_NOT:
+ case RISCV_INS_XNOR:
+ case RISCV_INS_C_XOR:
+ op->type = RZ_ANALYSIS_OP_TYPE_XOR;
+ break;
+
+ case RISCV_INS_SLL:
+ case RISCV_INS_SLLI:
+ case RISCV_INS_SLLW:
+ case RISCV_INS_SLLIW:
+ case RISCV_INS_C_SLLI64:
+ op->type = RZ_ANALYSIS_OP_TYPE_SHL;
+ break;
+ case RISCV_INS_SRL:
+ case RISCV_INS_SRLI:
+ case RISCV_INS_SRLW:
+ case RISCV_INS_SRLIW:
+ case RISCV_INS_C_SRLI64:
+ op->type = RZ_ANALYSIS_OP_TYPE_SHR;
+ break;
+ case RISCV_INS_SRA:
+ case RISCV_INS_SRAI:
+ case RISCV_INS_SRAW:
+ case RISCV_INS_SRAIW:
+ case RISCV_INS_C_SRAI64:
+ op->type = RZ_ANALYSIS_OP_TYPE_SAR;
+ break;
+
+ case RISCV_INS_ROL:
+ case RISCV_INS_ROLW:
+ op->type = RZ_ANALYSIS_OP_TYPE_ROL;
+ break;
+
+ case RISCV_INS_ROR:
+ case RISCV_INS_RORI:
+ case RISCV_INS_RORIW:
+ case RISCV_INS_RORW:
+ op->type = RZ_ANALYSIS_OP_TYPE_ROR;
+ break;
+ case RISCV_INS_BCLR:
+ case RISCV_INS_BCLRI:
+ case RISCV_INS_CV_BCLR:
+ case RISCV_INS_CV_BCLRR:
+ op->type = RZ_ANALYSIS_OP_TYPE_AND; // Clear bit is like AND with mask
+ break;
+
+ case RISCV_INS_BSET:
+ case RISCV_INS_BSETI:
+ case RISCV_INS_CV_BSET:
+ case RISCV_INS_CV_BSETR:
+ op->type = RZ_ANALYSIS_OP_TYPE_OR; // Set bit is like OR with mask
+ break;
+
+ case RISCV_INS_BINV:
+ case RISCV_INS_BINVI:
+ op->type = RZ_ANALYSIS_OP_TYPE_XOR; // Invert bit is like XOR with mask
+ break;
+
+ case RISCV_INS_BEXT:
+ case RISCV_INS_BEXTI:
+ case RISCV_INS_CV_EXTRACT:
+ case RISCV_INS_CV_EXTRACTR:
+ case RISCV_INS_CV_EXTRACTU:
+ case RISCV_INS_CV_EXTRACTUR:
+ case RISCV_INS_CV_EXTRACT_B:
+ case RISCV_INS_CV_EXTRACT_H:
+ case RISCV_INS_CV_EXTRACTU_B:
+ case RISCV_INS_CV_EXTRACTU_H:
+ case RISCV_INS_TH_EXT:
+ case RISCV_INS_TH_EXTU:
+ op->type = RZ_ANALYSIS_OP_TYPE_AND; // Extract is masking operation
+ break;
+
+ case RISCV_INS_CV_INSERT:
+ case RISCV_INS_CV_INSERTR:
+ case RISCV_INS_CV_INSERT_B:
+ case RISCV_INS_CV_INSERT_H:
+
+ case RISCV_INS_ORC_B:
+
+ case RISCV_INS_TH_TSTNBZ:
+ case RISCV_INS_TH_TST:
+ op->type = RZ_ANALYSIS_OP_TYPE_OR; // Insert is OR-ing bits
+ break;
+
+ case RISCV_INS_CLZ:
+ case RISCV_INS_CLZW:
+ case RISCV_INS_CTZ:
+ case RISCV_INS_CTZW:
+ case RISCV_INS_CPOP:
+ case RISCV_INS_CPOPW:
+ case RISCV_INS_CV_CNT:
+ case RISCV_INS_CV_CLB:
+ case RISCV_INS_CV_FF1:
+ case RISCV_INS_CV_FL1:
+ case RISCV_INS_TH_FF0:
+ case RISCV_INS_TH_FF1:
+ op->type = RZ_ANALYSIS_OP_TYPE_BCNT;
+ break;
+
+ case RISCV_INS_VCLZ_V:
+ case RISCV_INS_VCPOP_V:
+ case RISCV_INS_VCTZ_V:
+ op->type = RZ_ANALYSIS_OP_TYPE_BCNT;
+ break;
+
+ case RISCV_INS_REV8:
+ case RISCV_INS_BREV8:
+ case RISCV_INS_CV_BITREV:
+ case RISCV_INS_TH_REV:
+ case RISCV_INS_TH_REVW:
+ op->type = RZ_ANALYSIS_OP_TYPE_REV;
+ break;
+
+ case RISCV_INS_PACK:
+ case RISCV_INS_PACKH:
+ case RISCV_INS_PACKW:
+ case RISCV_INS_CV_PACK:
+ case RISCV_INS_CV_PACK_H:
+ case RISCV_INS_CV_PACKHI_B:
+ case RISCV_INS_CV_PACKLO_B:
+ case RISCV_INS_UNZIP:
+ case RISCV_INS_ZIP:
+ op->type = RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_MIN:
+ case RISCV_INS_MINU:
+ case RISCV_INS_MAX:
+ case RISCV_INS_MAXU:
+ case RISCV_INS_CV_MIN:
+ case RISCV_INS_CV_MINU:
+ case RISCV_INS_CV_MAX:
+ case RISCV_INS_CV_MAXU:
+ op->type = RZ_ANALYSIS_OP_TYPE_CMP;
+ break;
+ case RISCV_INS_FMIN_S:
+ case RISCV_INS_FMIN_D:
+ case RISCV_INS_FMIN_H:
+ case RISCV_INS_FMAX_S:
+ case RISCV_INS_FMAX_D:
+ case RISCV_INS_FMAX_H:
+ case RISCV_INS_FMINM_S:
+ case RISCV_INS_FMINM_D:
+ case RISCV_INS_FMINM_H:
+ case RISCV_INS_FMAXM_S:
+ case RISCV_INS_FMAXM_D:
+ case RISCV_INS_FMAXM_H:
+ op->type = RZ_ANALYSIS_OP_TYPE_CMP;
+ break;
+
+ case RISCV_INS_FLEQ_D:
+ case RISCV_INS_FLEQ_H:
+ case RISCV_INS_FLEQ_S:
+ case RISCV_INS_FLTQ_D:
+ case RISCV_INS_FLTQ_H:
+ case RISCV_INS_FLTQ_S:
+ case RISCV_INS_FEQ_D:
+ case RISCV_INS_FEQ_H:
+ case RISCV_INS_FEQ_S:
+ case RISCV_INS_FLE_H:
+ case RISCV_INS_FLT_H:
+ case RISCV_INS_VMFLE_VF:
+ case RISCV_INS_VMFLT_VF:
+ case RISCV_INS_VMFNE_VF:
+ case RISCV_INS_VMFGE_VF:
+ case RISCV_INS_VMFGT_VF:
+ case RISCV_INS_VMFEQ_VF:
+ case RISCV_INS_VMFLE_VV:
+ case RISCV_INS_VMFLT_VV:
+ case RISCV_INS_VMFNE_VV:
+ case RISCV_INS_VMFEQ_VV:
+ op->type = RZ_ANALYSIS_OP_TYPE_CMP;
+ break;
+
+ case RISCV_INS_FSGNJ_S:
+ case RISCV_INS_FSGNJ_D:
+ case RISCV_INS_FSGNJ_H:
+ case RISCV_INS_FSGNJN_S:
+ case RISCV_INS_FSGNJN_D:
+ case RISCV_INS_FSGNJN_H:
+ case RISCV_INS_FSGNJX_S:
+ case RISCV_INS_FSGNJX_D:
+ case RISCV_INS_FSGNJX_H:
+ op->type = RZ_ANALYSIS_OP_TYPE_MOV;
+ break;
+
+ case RISCV_INS_FCVT_W_S:
+ case RISCV_INS_FCVT_WU_S:
+ case RISCV_INS_FCVT_L_S:
+ case RISCV_INS_FCVT_LU_S:
+ case RISCV_INS_FCVT_W_D:
+ case RISCV_INS_FCVT_WU_D:
+ case RISCV_INS_FCVT_L_D:
+ case RISCV_INS_FCVT_LU_D:
+ case RISCV_INS_FCVT_W_H:
+ case RISCV_INS_FCVT_WU_H:
+ case RISCV_INS_FCVT_L_H:
+ case RISCV_INS_FCVT_LU_H:
+ case RISCV_INS_FCVT_S_W:
+ case RISCV_INS_FCVT_S_WU:
+ case RISCV_INS_FCVT_S_L:
+ case RISCV_INS_FCVT_S_LU:
+ case RISCV_INS_FCVT_D_W:
+ case RISCV_INS_FCVT_D_WU:
+ case RISCV_INS_FCVT_D_L:
+ case RISCV_INS_FCVT_D_LU:
+ case RISCV_INS_FCVT_H_W:
+ case RISCV_INS_FCVT_H_WU:
+ case RISCV_INS_FCVT_H_L:
+ case RISCV_INS_FCVT_H_LU:
+ case RISCV_INS_FCVT_S_D:
+ case RISCV_INS_FCVT_D_S:
+ case RISCV_INS_FCVT_S_H:
+ case RISCV_INS_FCVT_H_S:
+ case RISCV_INS_FCVT_D_H:
+ case RISCV_INS_FCVT_H_D:
+ case RISCV_INS_FCVT_S_BF16:
+ case RISCV_INS_FCVT_BF16_S:
+ case RISCV_INS_FCVTMOD_W_D:
+ op->type = RZ_ANALYSIS_OP_TYPE_CAST;
+ break;
+
+ case RISCV_INS_FCLASS_S:
+ case RISCV_INS_FCLASS_D:
+ case RISCV_INS_FCLASS_H:
+ op->type = RZ_ANALYSIS_OP_TYPE_CMP;
+ break;
+
+ case RISCV_INS_FROUND_S:
+ case RISCV_INS_FROUND_D:
+ case RISCV_INS_FROUND_H:
+ case RISCV_INS_FROUNDNX_S:
+ case RISCV_INS_FROUNDNX_D:
+ case RISCV_INS_FROUNDNX_H:
+ op->type = RZ_ANALYSIS_OP_TYPE_CAST;
+ break;
+
+ case RISCV_INS_SLT:
+ case RISCV_INS_SLTI:
+ case RISCV_INS_SLTU:
+ case RISCV_INS_SLTIU:
+ op->type = RZ_ANALYSIS_OP_TYPE_CMP;
+ break;
+
+ case RISCV_INS_BEQ:
+ case RISCV_INS_BNE:
+ case RISCV_INS_BLT:
+ case RISCV_INS_BGE:
+ case RISCV_INS_BLTU:
+ case RISCV_INS_BGEU:
+ case RISCV_INS_C_BEQZ:
+ case RISCV_INS_C_BNEZ:
+ op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
+ if (insn->id == RISCV_INS_C_BEQZ || insn->id == RISCV_INS_C_BNEZ) {
+ op->jump = IMM(1);
+ } else {
+ op->jump = IMM(2);
+ }
+ op->fail = NEXT_ADDRESS(op);
+ break;
+
+ case RISCV_INS_ECALL:
+ case RISCV_INS_C_EBREAK:
+ case RISCV_INS_EBREAK:
+ op->type = RZ_ANALYSIS_OP_TYPE_SWI;
+ break;
+
+ case RISCV_INS_FENCE:
+ case RISCV_INS_FENCE_I:
+ case RISCV_INS_FENCE_TSO:
+ case RISCV_INS_HFENCE_GVMA:
+ case RISCV_INS_HFENCE_VVMA:
+ case RISCV_INS_SFENCE_INVAL_IR:
+ case RISCV_INS_SFENCE_VMA:
+ case RISCV_INS_SFENCE_W_INVAL:
+ case RISCV_INS_TH_SFENCE_VMAS:
+ case RISCV_INS_HINVAL_GVMA:
+ case RISCV_INS_HINVAL_VVMA:
+ case RISCV_INS_SINVAL_VMA:
+ case RISCV_INS_WFI:
+ case RISCV_INS_CBO_CLEAN:
+ case RISCV_INS_CBO_FLUSH:
+ case RISCV_INS_CBO_INVAL:
+ case RISCV_INS_CBO_ZERO:
+ case RISCV_INS_TH_DCACHE_CALL:
+ case RISCV_INS_TH_DCACHE_CIALL:
+ case RISCV_INS_TH_DCACHE_CIPA:
+ case RISCV_INS_TH_DCACHE_CISW:
+ case RISCV_INS_TH_DCACHE_CIVA:
+ case RISCV_INS_TH_DCACHE_CPA:
+ case RISCV_INS_TH_DCACHE_CPAL1:
+ case RISCV_INS_TH_DCACHE_CSW:
+ case RISCV_INS_TH_DCACHE_CVA:
+ case RISCV_INS_TH_DCACHE_CVAL1:
+ case RISCV_INS_TH_DCACHE_IALL:
+ case RISCV_INS_TH_DCACHE_IPA:
+ case RISCV_INS_TH_DCACHE_ISW:
+ case RISCV_INS_TH_DCACHE_IVA:
+ case RISCV_INS_TH_ICACHE_IALL:
+ case RISCV_INS_TH_ICACHE_IALLS:
+ case RISCV_INS_TH_ICACHE_IPA:
+ case RISCV_INS_TH_ICACHE_IVA:
+ case RISCV_INS_TH_L2CACHE_CALL:
+ case RISCV_INS_TH_L2CACHE_CIALL:
+ case RISCV_INS_TH_L2CACHE_IALL:
+ op->type = RZ_ANALYSIS_OP_TYPE_SYNC;
+ break;
+
+ case RISCV_INS_AES32DSI:
+ case RISCV_INS_AES32DSMI:
+ case RISCV_INS_AES32ESI:
+ case RISCV_INS_AES32ESMI:
+ case RISCV_INS_AES64DS:
+ case RISCV_INS_AES64DSM:
+ case RISCV_INS_AES64ES:
+ case RISCV_INS_AES64ESM:
+ case RISCV_INS_AES64IM:
+ case RISCV_INS_AES64KS1I:
+ case RISCV_INS_AES64KS2:
+ case RISCV_INS_SHA256SIG0:
+ case RISCV_INS_SHA256SIG1:
+ case RISCV_INS_SHA256SUM0:
+ case RISCV_INS_SHA256SUM1:
+ case RISCV_INS_SHA512SIG0:
+ case RISCV_INS_SHA512SIG0H:
+ case RISCV_INS_SHA512SIG0L:
+ case RISCV_INS_SHA512SIG1:
+ case RISCV_INS_SHA512SIG1H:
+ case RISCV_INS_SHA512SIG1L:
+ case RISCV_INS_SHA512SUM0:
+ case RISCV_INS_SHA512SUM0R:
+ case RISCV_INS_SHA512SUM1:
+ case RISCV_INS_SHA512SUM1R:
+ op->type = RZ_ANALYSIS_OP_TYPE_CRYPTO;
+ break;
+
+ case RISCV_INS_SEXT_B:
+ case RISCV_INS_SEXT_H:
+ case RISCV_INS_C_SEXT_B:
+ case RISCV_INS_C_SEXT_H:
+ case RISCV_INS_CV_EXTHS:
+ case RISCV_INS_CV_EXTBS:
+ op->type = RZ_ANALYSIS_OP_TYPE_CAST;
+ break;
+
+ case RISCV_INS_ZEXT_H:
+ case RISCV_INS_ZEXT_W:
+ case RISCV_INS_C_ZEXT_B:
+ case RISCV_INS_C_ZEXT_H:
+ case RISCV_INS_C_ZEXT_W:
+ case RISCV_INS_CV_EXTHZ:
+ case RISCV_INS_CV_EXTBZ:
+ op->type = RZ_ANALYSIS_OP_TYPE_CAST;
+ break;
+
+ case RISCV_INS_CM_PUSH:
+ case RISCV_INS_C_SSPUSH:
+ case RISCV_INS_SSPUSH:
+ op->type = RZ_ANALYSIS_OP_TYPE_PUSH;
+ break;
+
+ case RISCV_INS_CM_POP:
+ case RISCV_INS_C_SSPOPCHK:
+ case RISCV_INS_SSPOPCHK:
+ op->type = RZ_ANALYSIS_OP_TYPE_POP;
+ break;
+
+ case RISCV_INS_VSETVL:
+ case RISCV_INS_VSETVLI:
+ case RISCV_INS_VSETIVLI:
+ op->type = RZ_ANALYSIS_OP_TYPE_MOV | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+ // ============================================================
+ // VECTOR LOADS
+ // ============================================================
+ case RISCV_INS_VLE8_V:
+ case RISCV_INS_VLE16_V:
+ case RISCV_INS_VLE32_V:
+ case RISCV_INS_VLE64_V:
+ case RISCV_INS_VLE8FF_V:
+ case RISCV_INS_VLE16FF_V:
+ case RISCV_INS_VLE32FF_V:
+ case RISCV_INS_VLE64FF_V:
+ case RISCV_INS_VLSE8_V:
+ case RISCV_INS_VLSE16_V:
+ case RISCV_INS_VLSE32_V:
+ case RISCV_INS_VLSE64_V:
+ case RISCV_INS_VLOXEI8_V:
+ case RISCV_INS_VLOXEI16_V:
+ case RISCV_INS_VLOXEI32_V:
+ case RISCV_INS_VLOXEI64_V:
+ case RISCV_INS_VLUXEI8_V:
+ case RISCV_INS_VLUXEI16_V:
+ case RISCV_INS_VLUXEI32_V:
+ case RISCV_INS_VLUXEI64_V:
+ case RISCV_INS_VLM_V:
+ case RISCV_INS_VL1RE8_V:
+ case RISCV_INS_VL1RE16_V:
+ case RISCV_INS_VL1RE32_V:
+ case RISCV_INS_VL1RE64_V:
+ case RISCV_INS_VL2RE8_V:
+ case RISCV_INS_VL2RE16_V:
+ case RISCV_INS_VL2RE32_V:
+ case RISCV_INS_VL2RE64_V:
+ case RISCV_INS_VL4RE8_V:
+ case RISCV_INS_VL4RE16_V:
+ case RISCV_INS_VL4RE32_V:
+ case RISCV_INS_VL4RE64_V:
+ case RISCV_INS_VL8RE8_V:
+ case RISCV_INS_VL8RE16_V:
+ case RISCV_INS_VL8RE32_V:
+ case RISCV_INS_VL8RE64_V:
+ // vector segment loads
+ case RISCV_INS_VLSEG2E8_V:
+ case RISCV_INS_VLSEG2E16_V:
+ case RISCV_INS_VLSEG2E32_V:
+ case RISCV_INS_VLSEG2E64_V:
+ case RISCV_INS_VLSEG3E8_V:
+ case RISCV_INS_VLSEG3E16_V:
+ case RISCV_INS_VLSEG3E32_V:
+ case RISCV_INS_VLSEG3E64_V:
+ case RISCV_INS_VLSEG4E8_V:
+ case RISCV_INS_VLSEG4E16_V:
+ case RISCV_INS_VLSEG4E32_V:
+ case RISCV_INS_VLSEG4E64_V:
+ case RISCV_INS_VLSEG5E8_V:
+ case RISCV_INS_VLSEG5E16_V:
+ case RISCV_INS_VLSEG5E32_V:
+ case RISCV_INS_VLSEG5E64_V:
+ case RISCV_INS_VLSEG6E8_V:
+ case RISCV_INS_VLSEG6E16_V:
+ case RISCV_INS_VLSEG6E32_V:
+ case RISCV_INS_VLSEG6E64_V:
+ case RISCV_INS_VLSEG7E8_V:
+ case RISCV_INS_VLSEG7E16_V:
+ case RISCV_INS_VLSEG7E32_V:
+ case RISCV_INS_VLSEG7E64_V:
+ case RISCV_INS_VLSEG8E8_V:
+ case RISCV_INS_VLSEG8E16_V:
+ case RISCV_INS_VLSEG8E32_V:
+ case RISCV_INS_VLSEG8E64_V:
+
+ case RISCV_INS_HLVX_HU:
+ case RISCV_INS_HLVX_WU:
+ case RISCV_INS_HLV_B:
+ case RISCV_INS_HLV_BU:
+ case RISCV_INS_HLV_D:
+ case RISCV_INS_HLV_H:
+ case RISCV_INS_HLV_HU:
+ case RISCV_INS_HLV_W:
+ case RISCV_INS_HLV_WU:
+ op->type = RZ_ANALYSIS_OP_TYPE_LOAD | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ // ============================================================
+ // VECTOR STORES
+ // ============================================================
+ case RISCV_INS_VSE8_V:
+ case RISCV_INS_VSE16_V:
+ case RISCV_INS_VSE32_V:
+ case RISCV_INS_VSE64_V:
+ case RISCV_INS_VSSE8_V:
+ case RISCV_INS_VSSE16_V:
+ case RISCV_INS_VSSE32_V:
+ case RISCV_INS_VSSE64_V:
+ case RISCV_INS_VSOXEI8_V:
+ case RISCV_INS_VSOXEI16_V:
+ case RISCV_INS_VSOXEI32_V:
+ case RISCV_INS_VSOXEI64_V:
+ case RISCV_INS_VSUXEI8_V:
+ case RISCV_INS_VSUXEI16_V:
+ case RISCV_INS_VSUXEI32_V:
+ case RISCV_INS_VSUXEI64_V:
+ case RISCV_INS_VSM_V:
+ case RISCV_INS_VS1R_V:
+ case RISCV_INS_VS2R_V:
+ case RISCV_INS_VS4R_V:
+ case RISCV_INS_VS8R_V:
+ case RISCV_INS_VSSEG2E8_V:
+ case RISCV_INS_VSSEG2E16_V:
+ case RISCV_INS_VSSEG2E32_V:
+ case RISCV_INS_VSSEG2E64_V:
+ case RISCV_INS_VSSEG3E8_V:
+ case RISCV_INS_VSSEG3E16_V:
+ case RISCV_INS_VSSEG3E32_V:
+ case RISCV_INS_VSSEG3E64_V:
+ case RISCV_INS_VSSEG4E8_V:
+ case RISCV_INS_VSSEG4E16_V:
+ case RISCV_INS_VSSEG4E32_V:
+ case RISCV_INS_VSSEG4E64_V:
+ case RISCV_INS_VSSEG5E8_V:
+ case RISCV_INS_VSSEG5E16_V:
+ case RISCV_INS_VSSEG5E32_V:
+ case RISCV_INS_VSSEG5E64_V:
+ case RISCV_INS_VSSEG6E8_V:
+ case RISCV_INS_VSSEG6E16_V:
+ case RISCV_INS_VSSEG6E32_V:
+ case RISCV_INS_VSSEG6E64_V:
+ case RISCV_INS_VSSEG7E8_V:
+ case RISCV_INS_VSSEG7E16_V:
+ case RISCV_INS_VSSEG7E32_V:
+ case RISCV_INS_VSSEG7E64_V:
+ case RISCV_INS_VSSEG8E8_V:
+ case RISCV_INS_VSSEG8E16_V:
+ case RISCV_INS_VSSEG8E32_V:
+ case RISCV_INS_VSSEG8E64_V:
+ case RISCV_INS_HSV_B:
+ case RISCV_INS_HSV_D:
+ case RISCV_INS_HSV_H:
+ case RISCV_INS_HSV_W:
+ op->type = RZ_ANALYSIS_OP_TYPE_STORE | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ // ============================================================
+ // VECTOR ARITHMETIC - ADD/SUB
+ // ============================================================
+ case RISCV_INS_VADD_VV:
+ case RISCV_INS_VADD_VX:
+ case RISCV_INS_VADD_VI:
+ case RISCV_INS_VWADDU_VV:
+ case RISCV_INS_VWADDU_VX:
+ case RISCV_INS_VWADDU_WV:
+ case RISCV_INS_VWADDU_WX:
+ case RISCV_INS_VWADD_VV:
+ case RISCV_INS_VWADD_VX:
+ case RISCV_INS_VWADD_WV:
+ case RISCV_INS_VWADD_WX:
+ case RISCV_INS_VSADDU_VV:
+ case RISCV_INS_VSADDU_VX:
+ case RISCV_INS_VSADDU_VI:
+ case RISCV_INS_VSADD_VV:
+ case RISCV_INS_VSADD_VX:
+ case RISCV_INS_VSADD_VI:
+ case RISCV_INS_VAADD_VV:
+ case RISCV_INS_VAADD_VX:
+ case RISCV_INS_VAADDU_VV:
+ case RISCV_INS_VAADDU_VX:
+
+ case RISCV_INS_VADC_VIM:
+ case RISCV_INS_VADC_VVM:
+ case RISCV_INS_VADC_VXM:
+ case RISCV_INS_VMADC_VI:
+ case RISCV_INS_VMADC_VIM:
+ case RISCV_INS_VMADC_VV:
+ case RISCV_INS_VMADC_VVM:
+ case RISCV_INS_VMADC_VX:
+ case RISCV_INS_VMADC_VXM:
+ op->type = RZ_ANALYSIS_OP_TYPE_ADD | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_VSUB_VV:
+ case RISCV_INS_VSUB_VX:
+ case RISCV_INS_VWSUBU_VV:
+ case RISCV_INS_VWSUBU_VX:
+ case RISCV_INS_VWSUBU_WV:
+ case RISCV_INS_VWSUBU_WX:
+ case RISCV_INS_VWSUB_VV:
+ case RISCV_INS_VWSUB_VX:
+ case RISCV_INS_VWSUB_WV:
+ case RISCV_INS_VWSUB_WX:
+ case RISCV_INS_VSSUBU_VV:
+ case RISCV_INS_VSSUBU_VX:
+ case RISCV_INS_VSSUB_VV:
+ case RISCV_INS_VSSUB_VX:
+ case RISCV_INS_VASUB_VV:
+ case RISCV_INS_VASUB_VX:
+ case RISCV_INS_VASUBU_VV:
+ case RISCV_INS_VASUBU_VX:
+ case RISCV_INS_VRSUB_VX:
+ case RISCV_INS_VRSUB_VI:
+
+ case RISCV_INS_VMSBC_VV:
+ case RISCV_INS_VMSBC_VVM:
+ case RISCV_INS_VMSBC_VX:
+ case RISCV_INS_VMSBC_VXM:
+ case RISCV_INS_VSBC_VVM:
+ case RISCV_INS_VSBC_VXM:
+ op->type = RZ_ANALYSIS_OP_TYPE_SUB | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ // ============================================================
+ // VECTOR ARITHMETIC - MULTIPLY
+ // ============================================================
+ case RISCV_INS_VMUL_VV:
+ case RISCV_INS_VMUL_VX:
+ case RISCV_INS_VMULH_VV:
+ case RISCV_INS_VMULH_VX:
+ case RISCV_INS_VMULHU_VV:
+ case RISCV_INS_VMULHU_VX:
+ case RISCV_INS_VMULHSU_VV:
+ case RISCV_INS_VMULHSU_VX:
+ case RISCV_INS_VWMUL_VV:
+ case RISCV_INS_VWMUL_VX:
+ case RISCV_INS_VWMULU_VV:
+ case RISCV_INS_VWMULU_VX:
+ case RISCV_INS_VWMULSU_VV:
+ case RISCV_INS_VWMULSU_VX:
+ case RISCV_INS_VSMUL_VV:
+ case RISCV_INS_VSMUL_VX:
+ case RISCV_INS_VMACC_VV:
+ case RISCV_INS_VMACC_VX:
+ case RISCV_INS_VMADD_VV:
+ case RISCV_INS_VMADD_VX:
+ case RISCV_INS_VNMSAC_VV:
+ case RISCV_INS_VNMSAC_VX:
+ case RISCV_INS_VNMSUB_VV:
+ case RISCV_INS_VNMSUB_VX:
+ case RISCV_INS_VWMACC_VV:
+ case RISCV_INS_VWMACC_VX:
+ case RISCV_INS_VWMACCU_VV:
+ case RISCV_INS_VWMACCU_VX:
+ case RISCV_INS_VWMACCSU_VV:
+ case RISCV_INS_VWMACCSU_VX:
+ case RISCV_INS_VWMACCUS_VX:
+ op->type = RZ_ANALYSIS_OP_TYPE_MUL | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ // ============================================================
+ // VECTOR ARITHMETIC - DIVIDE
+ // ============================================================
+ case RISCV_INS_VDIVU_VV:
+ case RISCV_INS_VDIVU_VX:
+ case RISCV_INS_VDIV_VV:
+ case RISCV_INS_VDIV_VX:
+ case RISCV_INS_VFREC7_V:
+ op->type = RZ_ANALYSIS_OP_TYPE_DIV | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_VREMU_VV:
+ case RISCV_INS_VREMU_VX:
+ case RISCV_INS_VREM_VV:
+ case RISCV_INS_VREM_VX:
+ op->type = RZ_ANALYSIS_OP_TYPE_MOD | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+ // ============================================================
+ // VECTOR LOGICAL
+ // ============================================================
+ case RISCV_INS_VAND_VV:
+ case RISCV_INS_VAND_VX:
+ case RISCV_INS_VAND_VI:
+ case RISCV_INS_VANDN_VV:
+ case RISCV_INS_VANDN_VX:
+ op->type = RZ_ANALYSIS_OP_TYPE_AND | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_VOR_VV:
+ case RISCV_INS_VOR_VX:
+ case RISCV_INS_VOR_VI:
+ op->type = RZ_ANALYSIS_OP_TYPE_OR | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_VXOR_VV:
+ case RISCV_INS_VXOR_VX:
+ case RISCV_INS_VXOR_VI:
+ op->type = RZ_ANALYSIS_OP_TYPE_XOR | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ // ============================================================
+ // VECTOR SHIFT
+ // ============================================================
+ case RISCV_INS_VSLL_VV:
+ case RISCV_INS_VSLL_VX:
+ case RISCV_INS_VSLL_VI:
+ case RISCV_INS_VWSLL_VV:
+ case RISCV_INS_VWSLL_VX:
+ case RISCV_INS_VWSLL_VI:
+ op->type = RZ_ANALYSIS_OP_TYPE_SHL | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_VSRL_VV:
+ case RISCV_INS_VSRL_VX:
+ case RISCV_INS_VSRL_VI:
+ case RISCV_INS_VNSRL_WV:
+ case RISCV_INS_VNSRL_WX:
+ case RISCV_INS_VNSRL_WI:
+ case RISCV_INS_VSSRL_VV:
+ case RISCV_INS_VSSRL_VX:
+ case RISCV_INS_VSSRL_VI:
+ op->type = RZ_ANALYSIS_OP_TYPE_SHR | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_VSRA_VV:
+ case RISCV_INS_VSRA_VX:
+ case RISCV_INS_VSRA_VI:
+ case RISCV_INS_VNSRA_WV:
+ case RISCV_INS_VNSRA_WX:
+ case RISCV_INS_VNSRA_WI:
+ case RISCV_INS_VSSRA_VV:
+ case RISCV_INS_VSSRA_VX:
+ case RISCV_INS_VSSRA_VI:
+ op->type = RZ_ANALYSIS_OP_TYPE_SAR | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ // ============================================================
+ // VECTOR ROTATE
+ // ============================================================
+ case RISCV_INS_VROR_VV:
+ case RISCV_INS_VROR_VX:
+ case RISCV_INS_VROR_VI:
+ op->type = RZ_ANALYSIS_OP_TYPE_ROR | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_VROL_VV:
+ case RISCV_INS_VROL_VX:
+ op->type = RZ_ANALYSIS_OP_TYPE_ROL | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ // ============================================================
+ // VECTOR COMPARE
+ // ============================================================
+ case RISCV_INS_VMSEQ_VV:
+ case RISCV_INS_VMSEQ_VX:
+ case RISCV_INS_VMSEQ_VI:
+ case RISCV_INS_VMSNE_VV:
+ case RISCV_INS_VMSNE_VX:
+ case RISCV_INS_VMSNE_VI:
+ case RISCV_INS_VMSLTU_VV:
+ case RISCV_INS_VMSLTU_VX:
+ case RISCV_INS_VMSLT_VV:
+ case RISCV_INS_VMSLT_VX:
+ case RISCV_INS_VMSLEU_VV:
+ case RISCV_INS_VMSLEU_VX:
+ case RISCV_INS_VMSLEU_VI:
+ case RISCV_INS_VMSLE_VV:
+ case RISCV_INS_VMSLE_VX:
+ case RISCV_INS_VMSLE_VI:
+ case RISCV_INS_VMSGTU_VX:
+ case RISCV_INS_VMSGTU_VI:
+ case RISCV_INS_VMSGT_VX:
+ case RISCV_INS_VMSGT_VI:
+ case RISCV_INS_VMSGEU_VX:
+ case RISCV_INS_VMSGEU_VI:
+ case RISCV_INS_VMSGE_VX:
+ case RISCV_INS_VMSGE_VI:
+ op->type = RZ_ANALYSIS_OP_TYPE_CMP | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ // ============================================================
+ // VECTOR MIN/MAX
+ // ============================================================
+ case RISCV_INS_VMIN_VV:
+ case RISCV_INS_VMIN_VX:
+ case RISCV_INS_VMINU_VV:
+ case RISCV_INS_VMINU_VX:
+ case RISCV_INS_VMAX_VV:
+ case RISCV_INS_VMAX_VX:
+ case RISCV_INS_VMAXU_VV:
+ case RISCV_INS_VMAXU_VX:
+ op->type = RZ_ANALYSIS_OP_TYPE_CMP | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ // ============================================================
+ // VECTOR MOVE/MERGE
+ // ============================================================
+ case RISCV_INS_VMV_V_V:
+ case RISCV_INS_VMV_V_X:
+ case RISCV_INS_VMV_V_I:
+ case RISCV_INS_VMV_X_S:
+ case RISCV_INS_VMV_S_X:
+ case RISCV_INS_VMV1R_V:
+ case RISCV_INS_VMV2R_V:
+ case RISCV_INS_VMV4R_V:
+ case RISCV_INS_VMV8R_V:
+ case RISCV_INS_VMERGE_VVM:
+ case RISCV_INS_VMERGE_VXM:
+ case RISCV_INS_VMERGE_VIM:
+ case RISCV_INS_VFMV_F_S:
+ case RISCV_INS_VFMV_S_F:
+ case RISCV_INS_VFMV_V_F:
+ op->type = RZ_ANALYSIS_OP_TYPE_MOV | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+ // ============================================================
+ // VECTOR MASK OPERATIONS
+ // ============================================================
+ case RISCV_INS_VMAND_MM:
+ case RISCV_INS_VMANDN_MM:
+ op->type = RZ_ANALYSIS_OP_TYPE_AND | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_VMOR_MM:
+ case RISCV_INS_VMORN_MM:
+ case RISCV_INS_VMNOR_MM:
+ op->type = RZ_ANALYSIS_OP_TYPE_OR | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_VMXOR_MM:
+ case RISCV_INS_VMXNOR_MM:
+ case RISCV_INS_VMNAND_MM:
+ op->type = RZ_ANALYSIS_OP_TYPE_XOR | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ // ============================================================
+ // VECTOR REDUCTIONS
+ // ============================================================
+ case RISCV_INS_VREDSUM_VS:
+ case RISCV_INS_VREDMAXU_VS:
+ case RISCV_INS_VREDMAX_VS:
+ case RISCV_INS_VREDMINU_VS:
+ case RISCV_INS_VREDMIN_VS:
+ case RISCV_INS_VREDAND_VS:
+ case RISCV_INS_VREDOR_VS:
+ case RISCV_INS_VREDXOR_VS:
+ case RISCV_INS_VWREDSUM_VS:
+ op->type = RZ_ANALYSIS_OP_TYPE_REDUCE | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+ // ============================================================
+ // VECTOR CRYPTO
+ // ============================================================
+ case RISCV_INS_VCLMUL_VV:
+ case RISCV_INS_VCLMUL_VX:
+ case RISCV_INS_VCLMULH_VV:
+ case RISCV_INS_VCLMULH_VX:
+ case RISCV_INS_VAESDF_VS:
+ case RISCV_INS_VAESDF_VV:
+ case RISCV_INS_VAESDM_VS:
+ case RISCV_INS_VAESDM_VV:
+ case RISCV_INS_VAESEF_VS:
+ case RISCV_INS_VAESEF_VV:
+ case RISCV_INS_VAESEM_VS:
+ case RISCV_INS_VAESEM_VV:
+ case RISCV_INS_VAESKF1_VI:
+ case RISCV_INS_VAESKF2_VI:
+ case RISCV_INS_VAESZ_VS:
+ case RISCV_INS_VSHA2CH_VV:
+ case RISCV_INS_VSHA2CL_VV:
+ case RISCV_INS_VSHA2MS_VV:
+ case RISCV_INS_VSM3C_VI:
+ case RISCV_INS_VSM3ME_VV:
+ case RISCV_INS_VSM4K_VI:
+ case RISCV_INS_VSM4R_VS:
+ case RISCV_INS_VSM4R_VV:
+ case RISCV_INS_VGHSH_VV:
+ case RISCV_INS_VGMUL_VV:
+ op->type = RZ_ANALYSIS_OP_TYPE_CRYPTO | RZ_ANALYSIS_OP_TYPE_SIMD;
break;
+
+ case RISCV_INS_VFCVT_F_XU_V:
+ case RISCV_INS_VFCVT_F_X_V:
+ case RISCV_INS_VFCVT_RTZ_XU_F_V:
+ case RISCV_INS_VFCVT_RTZ_X_F_V:
+ case RISCV_INS_VFCVT_XU_F_V:
+ case RISCV_INS_VFCVT_X_F_V:
+ case RISCV_INS_VFWCVT_F_F_V:
+ case RISCV_INS_VFWCVT_F_XU_V:
+ case RISCV_INS_VFWCVT_F_X_V:
+ case RISCV_INS_VFWCVT_RTZ_XU_F_V:
+ case RISCV_INS_VFWCVT_RTZ_X_F_V:
+ case RISCV_INS_VFWCVT_XU_F_V:
+ case RISCV_INS_VFWCVT_X_F_V:
+ case RISCV_INS_VFNCVT_F_F_W:
+ case RISCV_INS_VFNCVT_F_XU_W:
+ case RISCV_INS_VFNCVT_F_X_W:
+ case RISCV_INS_VFNCVT_ROD_F_F_W:
+ case RISCV_INS_VFNCVT_RTZ_XU_F_W:
+ case RISCV_INS_VFNCVT_RTZ_X_F_W:
+ case RISCV_INS_VFNCVT_XU_F_W:
+ case RISCV_INS_VFNCVT_X_F_W:
+ case RISCV_INS_VFNCVTBF16_F_F_W:
+ case RISCV_INS_VFWCVTBF16_F_F_V:
+ op->type = RZ_ANALYSIS_OP_TYPE_CAST | RZ_ANALYSIS_OP_TYPE_SIMD;
+ break;
+
+ case RISCV_INS_CZERO_EQZ:
+ case RISCV_INS_CZERO_NEZ:
+ op->type = RZ_ANALYSIS_OP_TYPE_CMOV;
+ break;
+
+ case RISCV_INS_CM_POPRET:
+ case RISCV_INS_CM_POPRETZ:
case RISCV_INS_MRET:
case RISCV_INS_SRET:
- case RISCV_INS_URET:
+ case RISCV_INS_DRET:
op->type = RZ_ANALYSIS_OP_TYPE_RET;
break;
}
beach:
+ if (insn) {
+ set_op_sign(op, insn);
+ set_op_data_size(op, insn);
+ set_op_val(op, insn);
+ set_op_eob(op, insn);
+ set_op_cond(op, insn);
+ set_op_family(op, insn);
+ set_op_extra_metadata(analysis, op, ctx->hndl, insn);
+ set_stack_effect(op, insn);
+ }
set_opdir(op);
if (insn && mask & RZ_ANALYSIS_OP_MASK_OPEX) {
op->opex = riscv_opex(ctx->hndl, insn);
@@ -291,6 +1936,12 @@ static char *get_reg_profile(RzAnalysis *analysis) {
"=BP s0\n" // ABI: frame pointer
"=A0 a0\n"
"=A1 a1\n"
+ "=A2 a2\n"
+ "=A3 a3\n"
+ "=A4 a4\n"
+ "=A5 a5\n"
+ "=A6 a6\n"
+ "=A7 a7\n"
"gpr pc .32 0 0\n"
// RV32I regs (ABI names)
@@ -367,8 +2018,42 @@ static char *get_reg_profile(RzAnalysis *analysis) {
"flg of .1 3074 0\n"
"flg dz .1 3075 0\n"
"flg nv .1 3076 0\n"
- "flg frm .3 3077 0\n";
-
+ "flg frm .3 3077 0\n"
+ // vector registers
+ // assume each register is 512 bits (64 bytes) for maximum compatibility
+ // TODO: make the width accurately reflect the exact width defined in the binary
+ "gpr v0 .512 4096 0\n"
+ "gpr v1 .512 4160 0\n"
+ "gpr v2 .512 4224 0\n"
+ "gpr v3 .512 4288 0\n"
+ "gpr v4 .512 4352 0\n"
+ "gpr v5 .512 4416 0\n"
+ "gpr v6 .512 4480 0\n"
+ "gpr v7 .512 4544 0\n"
+ "gpr v8 .512 4608 0\n"
+ "gpr v9 .512 4672 0\n"
+ "gpr v10 .512 4736 0\n"
+ "gpr v11 .512 4800 0\n"
+ "gpr v12 .512 4864 0\n"
+ "gpr v13 .512 4928 0\n"
+ "gpr v14 .512 4992 0\n"
+ "gpr v15 .512 5056 0\n"
+ "gpr v16 .512 5120 0\n"
+ "gpr v17 .512 5184 0\n"
+ "gpr v18 .512 5248 0\n"
+ "gpr v19 .512 5312 0\n"
+ "gpr v20 .512 5376 0\n"
+ "gpr v21 .512 5440 0\n"
+ "gpr v22 .512 5504 0\n"
+ "gpr v23 .512 5568 0\n"
+ "gpr v24 .512 5632 0\n"
+ "gpr v25 .512 5696 0\n"
+ "gpr v26 .512 5760 0\n"
+ "gpr v27 .512 5824 0\n"
+ "gpr v28 .512 5888 0\n"
+ "gpr v29 .512 5952 0\n"
+ "gpr v30 .512 6016 0\n"
+ "gpr v31 .512 6080 0\n";
break;
case 64:
p =
@@ -378,6 +2063,12 @@ static char *get_reg_profile(RzAnalysis *analysis) {
"=BP s0\n" // ABI: frame pointer
"=A0 a0\n"
"=A1 a1\n"
+ "=A2 a2\n"
+ "=A3 a3\n"
+ "=A4 a4\n"
+ "=A5 a5\n"
+ "=A6 a6\n"
+ "=A7 a7\n"
"gpr pc .64 0 0\n"
// RV64I regs (ABI names)
@@ -448,6 +2139,41 @@ static char *get_reg_profile(RzAnalysis *analysis) {
"gpr ft10 .64 496 0\n" // =f30
"gpr ft11 .64 504 0\n" // =f31
"gpr fcsr .32 512 0\n"
+ // vector registers
+ // assume each register is 512 bits (64 bytes) for maximum compatibility
+ // TODO: make the width accurately reflect the exact width defined in the binary
+ "gpr v0 .512 1024 0\n"
+ "gpr v1 .512 1088 0\n"
+ "gpr v2 .512 1152 0\n"
+ "gpr v3 .512 1216 0\n"
+ "gpr v4 .512 1280 0\n"
+ "gpr v5 .512 1344 0\n"
+ "gpr v6 .512 1408 0\n"
+ "gpr v7 .512 1472 0\n"
+ "gpr v8 .512 1536 0\n"
+ "gpr v9 .512 1600 0\n"
+ "gpr v10 .512 1664 0\n"
+ "gpr v11 .512 1728 0\n"
+ "gpr v12 .512 1792 0\n"
+ "gpr v13 .512 1856 0\n"
+ "gpr v14 .512 1920 0\n"
+ "gpr v15 .512 1984 0\n"
+ "gpr v16 .512 2048 0\n"
+ "gpr v17 .512 2112 0\n"
+ "gpr v18 .512 2176 0\n"
+ "gpr v19 .512 2240 0\n"
+ "gpr v20 .512 2304 0\n"
+ "gpr v21 .512 2368 0\n"
+ "gpr v22 .512 2432 0\n"
+ "gpr v23 .512 2496 0\n"
+ "gpr v24 .512 2560 0\n"
+ "gpr v25 .512 2624 0\n"
+ "gpr v26 .512 2688 0\n"
+ "gpr v27 .512 2752 0\n"
+ "gpr v28 .512 2816 0\n"
+ "gpr v29 .512 2880 0\n"
+ "gpr v30 .512 2944 0\n"
+ "gpr v31 .512 3008 0\n"
"flg nx .1 4096 0\n"
"flg uf .1 4097 0\n"
"flg of .1 4098 0\n"
@@ -469,7 +2195,7 @@ static int archinfo(RzAnalysis *a, RzAnalysisInfoType query) {
case RZ_ANALYSIS_ARCHINFO_MAX_OP_SIZE:
return 6;
case RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN:
- /* fall-thru */
+ return 2;
case RZ_ANALYSIS_ARCHINFO_DATA_ALIGN:
return 4;
case RZ_ANALYSIS_ARCHINFO_CAN_USE_POINTERS:
@@ -479,6 +2205,48 @@ static int archinfo(RzAnalysis *a, RzAnalysisInfoType query) {
}
}
+static void set_stack_effect(RzAnalysisOp *op, cs_insn *insn) {
+ op->stackop = RZ_ANALYSIS_STACK_NOP;
+ if (!IS_REG_WRITTEN(insn, RISCV_REG_X2)) {
+ return;
+ }
+
+ // x2 i.e. SP is written, but how ?
+
+ // incremented or decremented ?
+ switch (op->type) {
+ case RZ_ANALYSIS_OP_TYPE_ADD:
+ op->stackop = RZ_ANALYSIS_STACK_INC;
+ op->stackptr = -MAYBE_IMM(insn);
+ return;
+
+ case RZ_ANALYSIS_OP_TYPE_SUB:
+ op->stackop = RZ_ANALYSIS_STACK_DEC;
+ op->stackptr = MAYBE_IMM(insn);
+ return;
+
+ case RZ_ANALYSIS_OP_TYPE_LOAD:
+ if (MEM_BASE(insn, RISCV_REG_X2)) {
+ op->stackop = RZ_ANALYSIS_STACK_GET;
+ op->stackptr = op->refptr;
+ }
+ return;
+
+ case RZ_ANALYSIS_OP_TYPE_STORE:
+ if (MEM_BASE(insn, RISCV_REG_X2)) {
+ op->stackop = RZ_ANALYSIS_STACK_SET;
+ op->stackptr = op->refptr;
+ }
+ return;
+
+ // TODO: Add RESET and ALIGN
+
+ default:
+ break;
+ }
+ return;
+}
+
static bool riscv_fini(void *user) {
RiscvContext *ctx = (RiscvContext *)user;
if (ctx) {
@@ -488,7 +2256,7 @@ static bool riscv_fini(void *user) {
}
RzAnalysisPlugin rz_analysis_plugin_riscv_cs = {
- .name = "riscv.cs",
+ .name = "riscv",
.desc = "Capstone RISCV analyzer",
.license = "BSD",
.esil = false,
diff --git a/librz/arch/p/analysis/analysis_riscv_utils.h b/librz/arch/p/analysis/analysis_riscv_utils.h
new file mode 100644
index 00000000000..6687ad774dc
--- /dev/null
+++ b/librz/arch/p/analysis/analysis_riscv_utils.h
@@ -0,0 +1,139 @@
+// SPDX-FileCopyrightText: 2024-2026 moste00
+// SPDX-License-Identifier: BSD-3-Clause
+
+#include
+
+#include "cs_operand.h"
+#include "rz_util/rz_log.h"
+
+#include
+#include
+#include
+
+// A more high-level alternative to direct indexing that can get immediates and operands without exact
+// indices
+// While also enforcing high-level constraints such as "exactly one immediate operand is present"
+// or "at most one operand is present" or "get the single register that is read/written"
+
+static inline int find_at_most_one_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type, const char *type_str) {
+ int first = -1;
+ for (int i = 0; i < op_count; i++) {
+ if (operands[i].type == type) {
+ if (first == -1) {
+ first = i;
+ } else {
+ RZ_LOG_FATAL("Expected exactly one %s operand, two elements matched (the %ith and %ith elements)", type_str, first, i);
+ exit(-1);
+ }
+ }
+ }
+ return first;
+}
+
+static inline int find_at_most_one_imm(cs_riscv_op *operands, uint8_t op_count) {
+ return find_at_most_one_op(operands, op_count, RISCV_OP_IMM, "immediate");
+}
+
+static inline int find_exactly_one_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type, const char *type_str) {
+ int first = find_at_most_one_op(operands, op_count, type, type_str);
+ if (first == -1) {
+ RZ_LOG_FATAL("Expected exactly one %s operand, found none", type_str);
+ exit(-1);
+ }
+ return first;
+}
+
+static inline int find_exactly_one_imm(cs_riscv_op *operands, uint8_t op_count) {
+ return find_exactly_one_op(operands, op_count, RISCV_OP_IMM, "immediate");
+}
+
+static inline int64_t get_exactly_one_immediate(cs_riscv_op *operands, uint8_t op_count) {
+ return operands[find_exactly_one_imm(operands, op_count)].imm;
+}
+
+static inline int64_t get_at_most_one_immediate(cs_riscv_op *operands, uint8_t op_count) {
+ int64_t idx = find_at_most_one_imm(operands, op_count);
+ if (idx == -1) {
+ return INT64_MAX;
+ }
+ return operands[idx].imm;
+}
+
+#define SINGLE_IMM(insn) get_exactly_one_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count);
+#define MAYBE_IMM(insn) get_at_most_one_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count);
+
+static inline int find_first_op(cs_riscv_op *operands, uint8_t op_count, riscv_op_type type) {
+ for (int i = 0; i < op_count; i++) {
+ if (operands[i].type == type) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static inline int find_first_imm(cs_riscv_op *operands, uint8_t op_count) {
+ return find_first_op(operands, op_count, RISCV_OP_IMM);
+}
+
+static inline int64_t get_first_immediate(cs_riscv_op *operands, uint8_t op_count) {
+ int idx = find_first_imm(operands, op_count);
+ if (idx == -1) {
+ return INT64_MAX;
+ }
+ return operands[idx].imm;
+}
+
+#define FIRST_IMM(insn) get_first_immediate(insn->detail->riscv.operands, insn->detail->riscv.op_count);
+
+static inline unsigned int get_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_count, cs_ac_type access) {
+ for (int i = 0; i < op_count; i++) {
+ if (operands[i].type == RISCV_OP_REG && (operands[i].access & access)) {
+ return operands[i].reg;
+ }
+ }
+ RZ_LOG_FATAL("Expected at least one register with %s access, found none", access == CS_AC_READ ? "read" : "write");
+ exit(-1);
+ return 0; // dummy for type checking, never reached
+}
+
+static inline unsigned int first_read_register(cs_riscv_op *operands, uint8_t op_count) {
+ return get_any_reg_accessed_as(operands, op_count, CS_AC_READ);
+}
+
+static inline unsigned int first_written_register(cs_riscv_op *operands, uint8_t op_count) {
+ return get_any_reg_accessed_as(operands, op_count, CS_AC_WRITE);
+}
+
+#define FIRST_READ_REGID(insn) first_read_register(insn->detail->riscv.operands, insn->detail->riscv.op_count)
+#define FIRST_WRITTEN_REGID(insn) first_written_register(insn->detail->riscv.operands, insn->detail->riscv.op_count)
+
+// check if a certain reg is ever accessed as read/write register
+static inline bool is_any_reg_accessed_as(cs_riscv_op *operands, uint8_t op_count, unsigned int reg, cs_ac_type access) {
+ for (int i = 0; i < op_count; i++) {
+ if (operands[i].type == RISCV_OP_REG && operands[i].reg == reg && (operands[i].access & access)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static inline bool is_reg_written(cs_riscv_op *operands, uint8_t op_count, unsigned int reg) {
+ return is_any_reg_accessed_as(operands, op_count, reg, CS_AC_WRITE);
+}
+static inline bool is_reg_read(cs_riscv_op *operands, uint8_t op_count, unsigned int reg) {
+ return is_any_reg_accessed_as(operands, op_count, reg, CS_AC_READ);
+}
+
+#define IS_REG_WRITTEN(insn, reg) is_reg_written(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
+#define IS_REG_READ(insn, reg) is_reg_read(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
+
+static inline bool is_any_reg_memory_base(cs_riscv_op *operands, uint8_t op_count, unsigned int reg) {
+ for (int i = 0; i < op_count; i++) {
+ if (operands[i].type == RISCV_OP_MEM && operands[i].mem.base == reg) {
+ return true;
+ }
+ }
+ return false;
+}
+
+#define MEM_BASE(insn, reg) is_any_reg_memory_base(insn->detail->riscv.operands, insn->detail->riscv.op_count, reg)
\ No newline at end of file
diff --git a/librz/arch/p/arch_riscv_cs.c b/librz/arch/p/arch_riscv_cs.c
index d58b5ddcca8..b73fb9311ca 100644
--- a/librz/arch/p/arch_riscv_cs.c
+++ b/librz/arch/p/arch_riscv_cs.c
@@ -1,8 +1,246 @@
-// SPDX-FileCopyrightText: 2024 RizinOrg
+// SPDX-FileCopyrightText: 2024-2026 moste00
// SPDX-FileCopyrightText: 2024 deroad
-// SPDX-License-Identifier: LGPL-3.0-only
+// SPDX-License-Identifier: BSD-3-Clause
#include
+#include
+#include
+#include
+#include "capstone.h"
+#include "rz_util/rz_log.h"
+#include "arch_riscv_extension_parser.inc"
+
+cs_mode cs_mode_from_feature_flag(ut64 feature_flag) {
+ switch (feature_flag) {
+ case RISCV_FeatureStdExtF:
+ case RISCV_FeatureStdExtD:
+ return CS_MODE_RISCV_FD;
+ case RISCV_FeatureStdExtV:
+ return CS_MODE_RISCV_V;
+ case RISCV_FeatureStdExtZfinx:
+ case RISCV_FeatureStdExtZdinx:
+ case RISCV_FeatureStdExtZhinx:
+ case RISCV_FeatureStdExtZhinxmin:
+ return CS_MODE_RISCV_ZFINX;
+ case RISCV_FeatureStdExtC:
+ return CS_MODE_RISCV_C;
+ case RISCV_FeatureStdExtZcmp:
+ case RISCV_FeatureStdExtZcmt:
+ case RISCV_FeatureStdExtZce:
+ return CS_MODE_RISCV_ZCMP_ZCMT_ZCE;
+ case RISCV_FeatureStdExtZicfiss:
+ return CS_MODE_RISCV_ZICFISS;
+ case RISCV_FeatureStdExtA:
+ return CS_MODE_RISCV_A;
+ case RISCV_FeatureStdExtZba:
+ return CS_MODE_RISCV_ZBA;
+ case RISCV_FeatureStdExtZbb:
+ return CS_MODE_RISCV_ZBB;
+ case RISCV_FeatureStdExtZbc:
+ return CS_MODE_RISCV_ZBC;
+ case RISCV_FeatureStdExtZbkb:
+ return CS_MODE_RISCV_ZBKB;
+ case RISCV_FeatureStdExtZbkc:
+ return CS_MODE_RISCV_ZBKC;
+ case RISCV_FeatureStdExtZbkx:
+ return CS_MODE_RISCV_ZBKX;
+ case RISCV_FeatureStdExtZbs:
+ return CS_MODE_RISCV_ZBS;
+ }
+
+ return 0;
+}
+
+size_t expect_str(const char *arch_str, const char *expected, size_t curr) {
+ size_t l = strlen(expected);
+ if (strncmp(&arch_str[curr], expected, l) != 0) {
+ RZ_LOG_ERROR("Invalid architecture string: expected %s to equal %s",
+ arch_str, expected);
+ return curr;
+ }
+
+ return curr + l;
+}
+
+size_t expect_char(const char *arch_str, char c, size_t curr) {
+ if (arch_str[curr] == '\0') {
+ RZ_LOG_ERROR("Invalid architecture string: expected %c, found end of string\n",
+ c);
+ return curr;
+ }
+
+ if (arch_str[curr] != c) {
+ RZ_LOG_ERROR("Invalid architecture string: expected %c to equal %c\n",
+ arch_str[curr], c);
+ return curr;
+ }
+
+ return curr + 1;
+}
+
+size_t expect_any_str_of(const char *arch_str, const char **expected, size_t curr) {
+ size_t i = 0;
+ while (expected[i] != NULL) {
+ if (strncmp(&arch_str[curr], expected[i], strlen(expected[i])) == 0) {
+ return curr + strlen(expected[i]);
+ }
+ i++;
+ }
+
+ i = 0;
+ RZ_LOG_ERROR("Invalid architecture string: expected %s to equal any string from [",
+ arch_str);
+ while (expected[i] != NULL) {
+ RZ_LOG_ERROR("%s,", expected[i]);
+ i++;
+ }
+ RZ_LOG_ERROR("]\n");
+
+ return curr;
+}
+
+size_t skip_digit_sequence(const char *arch_str, size_t curr) {
+ while (arch_str[curr] != '\0') {
+ if (!isdigit(arch_str[curr])) {
+ break;
+ }
+ curr++;
+ }
+
+ return curr;
+}
+
+size_t skip_extension_version(const char *arch_str, size_t curr) {
+ curr = skip_digit_sequence(arch_str, curr);
+ // now reached the 'p' in the middle of the 2 version numbers
+ size_t curr1 = expect_char(arch_str, 'p', curr);
+ if (curr1 == curr) {
+ // error, expected p
+ RZ_LOG_ERROR("Invalid architecture string: expected the version separator 'p' at index %zu"
+ "in archiecture string %s, found %c instead\n",
+ curr, arch_str, arch_str[curr]);
+ return curr;
+ }
+
+ return skip_digit_sequence(arch_str, curr1);
+}
+
+size_t skip_till_char(const char *arch_str, char c, size_t curr) {
+ while (arch_str[curr] != '\0') {
+ if (arch_str[curr] == c) {
+ return curr;
+ }
+ curr++;
+ }
+
+ return curr;
+}
+
+#define CHECK_BAD_HEADER(before, after) \
+ if (before == after) { \
+ RZ_LOG_ERROR("Bad architecture string header at index %zu in archiecture string %s" \
+ "\n Will continue parsing the rest of the string from the next '_'\n", \
+ before, arch_str); \
+ return skip_till_char(arch_str, '_', before); \
+ }
+
+size_t expect_architecture_string_header(const char *arch_str) {
+ size_t curr = 0;
+ size_t curr1 = expect_str(arch_str, "rv", curr);
+ CHECK_BAD_HEADER(curr, curr1);
+ size_t curr2 = expect_any_str_of(arch_str, (const char *[]){ "32", "64", NULL }, curr1);
+ CHECK_BAD_HEADER(curr1, curr2);
+ size_t curr3 = expect_char(arch_str, 'i', curr2);
+ CHECK_BAD_HEADER(curr2, curr3);
+ size_t curr4 = skip_extension_version(arch_str, curr3);
+ CHECK_BAD_HEADER(curr3, curr4)
+ size_t curr5 = expect_char(arch_str, '_', curr4);
+ CHECK_BAD_HEADER(curr4, curr5)
+
+ return curr5;
+}
+
+bool expect_extension(const char *arch_str, size_t *curr, cs_mode *cs_mode) {
+ ut64 flag = ~0;
+
+ switch (try_consume_riscv_ext_from(arch_str, curr, &flag)) {
+ case RISCV_EXT_PARSE_END_OF_STRING:
+ *cs_mode |= cs_mode_from_feature_flag(flag);
+ return true;
+
+ case RISCV_EXT_PARSE_STOPPED_AT_NUMBER:
+ *cs_mode |= cs_mode_from_feature_flag(flag);
+ *curr = skip_extension_version(arch_str, *curr);
+ return false;
+
+ // weird, this means the extension is malformed as it has no version
+ // but we can still continue with the next underscore
+ case RISCV_EXT_PARSE_STOPPED_AT_UNDERSCORE:
+ *curr = expect_char(arch_str, '_', *curr);
+ *cs_mode |= cs_mode_from_feature_flag(flag);
+ *curr = skip_extension_version(arch_str, *curr);
+ return false;
+
+ // bad mode, don't accumulate into result
+ // but keep ignoring chars till the underscore or end of string
+ case RISCV_EXT_PARSE_STOPPED_AT_UNEXPECTED:
+ *curr = skip_till_char(arch_str, '_', *curr);
+ return false;
+
+ case RISCV_EXT_PARSE_NO_MATCH_END_OF_STRING:
+ return true;
+
+ case RISCV_EXT_PARSE_NO_MATCH_NUMBER:
+ *curr = skip_extension_version(arch_str, *curr);
+ return false;
+
+ case RISCV_EXT_PARSE_NO_MATCH_UNDERSCORE:
+ *curr = expect_char(arch_str, '_', *curr);
+ *curr = skip_extension_version(arch_str, *curr);
+ return false;
+
+ case RISCV_EXT_PARSE_NO_MATCH_UNEXPECTED:
+ *curr = skip_till_char(arch_str, '_', *curr);
+ return false;
+ }
+
+ // unreachable
+ RZ_LOG_ERROR("UNREACHABLE STATE WHEN PARSING RISCV ARCH STRING");
+ return true; // done, this is a bad state and we should terminate parsing immediately
+}
+
+cs_mode expect_extensions(const char *arch_str, size_t curr) {
+ cs_mode cs_mode = 0;
+ bool done = false;
+ while (arch_str[curr] != '\0' && !done) {
+ done = expect_extension(arch_str, &curr, &cs_mode);
+ if (arch_str[curr] != '\0') {
+ curr = expect_char(arch_str, '_', curr);
+ }
+ }
+
+ return cs_mode;
+}
+
+bool check_all_whitespace(const char *str) {
+ while (*str) {
+ if (!isspace(*str)) {
+ return false;
+ }
+ str++;
+ }
+
+ return true;
+}
+size_t mode_from_arch_string(const char *arch_str) {
+ if (!arch_str || check_all_whitespace(arch_str)) {
+ RZ_LOG_WARN("RISCV: empty architecture string, no non-default extensions enabled\n");
+ return 0;
+ }
+ size_t curr = expect_architecture_string_header(arch_str);
+
+ return expect_extensions(arch_str, curr);
+}
#include "analysis/analysis_riscv_cs.c"
#include "asm/asm_riscv_cs.c"
diff --git a/librz/arch/p/arch_riscv_extension_parser.inc b/librz/arch/p/arch_riscv_extension_parser.inc
new file mode 100644
index 00000000000..867d408bef0
--- /dev/null
+++ b/librz/arch/p/arch_riscv_extension_parser.inc
@@ -0,0 +1,2149 @@
+// SPDX-FileCopyrightText: 2024-2026 moste00
+// SPDX-License-Identifier: BSD-3-Clause
+
+/*
+ *
+
+ *********************************************** AUTO-GENERATED CODE, DO NOT EDIT BY HAND! * ***********************************************
+
+ * RISC-V Extension Parser Using a Trie trick
+ * Generated from arch/RISCV/RISCVGenSubtargetInfo.inc in Capstone sources
+ *
+ * This function parses a single RISC-V extension name and ORs the corresponding
+ * feature flags with an accumulator 'mode'.
+ *
+ * Trie Diagram:
+ * ROOT
+ * ├── a [RISCV_FeatureStdExtA]
+ * ├── c [RISCV_FeatureStdExtC]
+ * ├── d [RISCV_FeatureStdExtD]
+ * ├── f [RISCV_FeatureStdExtF]
+ * ├── h [RISCV_FeatureStdExtH]
+ * ├── i [RISCV_FeatureStdExtI]
+ * ├── m [RISCV_FeatureStdExtM]
+ * ├── s
+ * │ ├── m
+ * │ │ ├── a
+ * │ │ │ └── i
+ * │ │ │ └── a [RISCV_FeatureStdExtSmaia]
+ * │ │ └── e
+ * │ │ └── p
+ * │ │ └── m
+ * │ │ └── p [RISCV_FeatureStdExtSmepmp]
+ * │ ├── s
+ * │ │ └── a
+ * │ │ └── i
+ * │ │ └── a [RISCV_FeatureStdExtSsaia]
+ * │ └── v
+ * │ ├── i
+ * │ │ └── n
+ * │ │ └── v
+ * │ │ └── a
+ * │ │ └── l [RISCV_FeatureStdExtSvinval]
+ * │ ├── n
+ * │ │ └── a
+ * │ │ └── p
+ * │ │ └── o
+ * │ │ └── t [RISCV_FeatureStdExtSvnapot]
+ * │ └── p
+ * │ └── b
+ * │ └── m
+ * │ └── t [RISCV_FeatureStdExtSvpbmt]
+ * ├── v [RISCV_FeatureStdExtV]
+ * └── z
+ * ├── a
+ * │ ├── 1
+ * │ │ └── 2
+ * │ │ └── 8
+ * │ │ └── r
+ * │ │ └── s [RISCV_FeatureStdExtZa128rs]
+ * │ ├── 6
+ * │ │ └── 4
+ * │ │ └── r
+ * │ │ └── s [RISCV_FeatureStdExtZa64rs]
+ * │ ├── c
+ * │ │ └── a
+ * │ │ └── s [RISCV_FeatureStdExtZacas]
+ * │ └── w
+ * │ └── r
+ * │ └── s [RISCV_FeatureStdExtZawrs]
+ * ├── b
+ * │ ├── a [RISCV_FeatureStdExtZba]
+ * │ ├── b [RISCV_FeatureStdExtZbb]
+ * │ ├── c [RISCV_FeatureStdExtZbc]
+ * │ ├── k
+ * │ │ ├── b [RISCV_FeatureStdExtZbkb]
+ * │ │ ├── c [RISCV_FeatureStdExtZbkc]
+ * │ │ └── x [RISCV_FeatureStdExtZbkx]
+ * │ └── s [RISCV_FeatureStdExtZbs]
+ * ├── c
+ * │ ├── a [RISCV_FeatureStdExtZca]
+ * │ ├── b [RISCV_FeatureStdExtZcb]
+ * │ ├── d [RISCV_FeatureStdExtZcd]
+ * │ ├── e [RISCV_FeatureStdExtZce]
+ * │ ├── f [RISCV_FeatureStdExtZcf]
+ * │ └── m
+ * │ ├── o
+ * │ │ └── p [RISCV_FeatureStdExtZcmop]
+ * │ ├── p [RISCV_FeatureStdExtZcmp]
+ * │ └── t [RISCV_FeatureStdExtZcmt]
+ * ├── d
+ * │ └── i
+ * │ └── n
+ * │ └── x [RISCV_FeatureStdExtZdinx]
+ * ├── f
+ * │ ├── a [RISCV_FeatureStdExtZfa]
+ * │ ├── b
+ * │ │ └── f
+ * │ │ └── m
+ * │ │ └── i
+ * │ │ └── n [RISCV_FeatureStdExtZfbfmin]
+ * │ ├── h [RISCV_FeatureStdExtZfh]
+ * │ │ └── m
+ * │ │ └── i
+ * │ │ └── n [RISCV_FeatureStdExtZfhmin]
+ * │ └── i
+ * │ └── n
+ * │ └── x [RISCV_FeatureStdExtZfinx]
+ * ├── h
+ * │ └── i
+ * │ └── n
+ * │ └── x [RISCV_FeatureStdExtZhinx]
+ * │ └── m
+ * │ └── i
+ * │ └── n [RISCV_FeatureStdExtZhinxmin]
+ * ├── i
+ * │ ├── c
+ * │ │ ├── 6
+ * │ │ │ └── 4
+ * │ │ │ └── b [RISCV_FeatureStdExtZic64b]
+ * │ │ ├── b
+ * │ │ │ └── o
+ * │ │ │ ├── m [RISCV_FeatureStdExtZicbom]
+ * │ │ │ ├── p [RISCV_FeatureStdExtZicbop]
+ * │ │ │ └── z [RISCV_FeatureStdExtZicboz]
+ * │ │ ├── c
+ * │ │ │ ├── a
+ * │ │ │ │ └── m
+ * │ │ │ │ └── o
+ * │ │ │ │ └── a [RISCV_FeatureStdExtZiccamoa]
+ * │ │ │ ├── i
+ * │ │ │ │ └── f [RISCV_FeatureStdExtZiccif]
+ * │ │ │ ├── l
+ * │ │ │ │ └── s
+ * │ │ │ │ └── m [RISCV_FeatureStdExtZicclsm]
+ * │ │ │ └── r
+ * │ │ │ └── s
+ * │ │ │ └── e [RISCV_FeatureStdExtZiccrse]
+ * │ │ ├── f
+ * │ │ │ └── i
+ * │ │ │ ├── l
+ * │ │ │ │ └── p [RISCV_FeatureStdExtZicfilp]
+ * │ │ │ └── s
+ * │ │ │ └── s [RISCV_FeatureStdExtZicfiss]
+ * │ │ ├── n
+ * │ │ │ └── t
+ * │ │ │ └── r [RISCV_FeatureStdExtZicntr]
+ * │ │ ├── o
+ * │ │ │ └── n
+ * │ │ │ └── d [RISCV_FeatureStdExtZicond]
+ * │ │ └── s
+ * │ │ └── r [RISCV_FeatureStdExtZicsr]
+ * │ ├── f
+ * │ │ └── e
+ * │ │ └── n
+ * │ │ └── c
+ * │ │ └── e
+ * │ │ └── i [RISCV_FeatureStdExtZifencei]
+ * │ ├── h
+ * │ │ ├── i
+ * │ │ │ └── n
+ * │ │ │ └── t
+ * │ │ │ ├── n
+ * │ │ │ │ └── t
+ * │ │ │ │ └── l [RISCV_FeatureStdExtZihintntl]
+ * │ │ │ └── p
+ * │ │ │ └── a
+ * │ │ │ └── u
+ * │ │ │ └── s
+ * │ │ │ └── e [RISCV_FeatureStdExtZihintpause]
+ * │ │ └── p
+ * │ │ └── m [RISCV_FeatureStdExtZihpm]
+ * │ └── m
+ * │ └── o
+ * │ └── p [RISCV_FeatureStdExtZimop]
+ * ├── k [RISCV_FeatureStdExtZk]
+ * │ ├── n [RISCV_FeatureStdExtZkn]
+ * │ │ ├── d [RISCV_FeatureStdExtZknd]
+ * │ │ ├── e [RISCV_FeatureStdExtZkne]
+ * │ │ └── h [RISCV_FeatureStdExtZknh]
+ * │ ├── r [RISCV_FeatureStdExtZkr]
+ * │ ├── s [RISCV_FeatureStdExtZks]
+ * │ │ ├── e
+ * │ │ │ └── d [RISCV_FeatureStdExtZksed]
+ * │ │ └── h [RISCV_FeatureStdExtZksh]
+ * │ └── t [RISCV_FeatureStdExtZkt]
+ * ├── m
+ * │ └── m
+ * │ └── u
+ * │ └── l [RISCV_FeatureStdExtZmmul]
+ * ├── t
+ * │ └── s
+ * │ └── o [RISCV_FeatureStdExtZtso]
+ * └── v
+ * ├── b
+ * │ ├── b [RISCV_FeatureStdExtZvbb]
+ * │ └── c [RISCV_FeatureStdExtZvbc]
+ * ├── e
+ * │ ├── 3
+ * │ │ └── 2
+ * │ │ ├── f [RISCV_FeatureStdExtZve32f]
+ * │ │ └── x [RISCV_FeatureStdExtZve32x]
+ * │ └── 6
+ * │ └── 4
+ * │ ├── d [RISCV_FeatureStdExtZve64d]
+ * │ ├── f [RISCV_FeatureStdExtZve64f]
+ * │ └── x [RISCV_FeatureStdExtZve64x]
+ * ├── f
+ * │ ├── b
+ * │ │ └── f
+ * │ │ ├── m
+ * │ │ │ └── i
+ * │ │ │ └── n [RISCV_FeatureStdExtZvfbfmin]
+ * │ │ └── w
+ * │ │ └── m
+ * │ │ └── a [RISCV_FeatureStdExtZvfbfwma]
+ * │ └── h [RISCV_FeatureStdExtZvfh]
+ * │ └── m
+ * │ └── i
+ * │ └── n [RISCV_FeatureStdExtZvfhmin]
+ * ├── k
+ * │ ├── b [RISCV_FeatureStdExtZvkb]
+ * │ ├── g [RISCV_FeatureStdExtZvkg]
+ * │ ├── n [RISCV_FeatureStdExtZvkn]
+ * │ │ ├── c [RISCV_FeatureStdExtZvknc]
+ * │ │ ├── e
+ * │ │ │ └── d [RISCV_FeatureStdExtZvkned]
+ * │ │ ├── g [RISCV_FeatureStdExtZvkng]
+ * │ │ └── h
+ * │ │ ├── a [RISCV_FeatureStdExtZvknha]
+ * │ │ └── b [RISCV_FeatureStdExtZvknhb]
+ * │ ├── s [RISCV_FeatureStdExtZvks]
+ * │ │ ├── c [RISCV_FeatureStdExtZvksc]
+ * │ │ ├── e
+ * │ │ │ └── d [RISCV_FeatureStdExtZvksed]
+ * │ │ ├── g [RISCV_FeatureStdExtZvksg]
+ * │ │ └── h [RISCV_FeatureStdExtZvksh]
+ * │ └── t [RISCV_FeatureStdExtZvkt]
+ * └── l
+ * ├── 1
+ * │ ├── 0
+ * │ │ └── 2
+ * │ │ └── 4
+ * │ │ └── b [RISCV_FeatureStdExtZvl1024b]
+ * │ ├── 2
+ * │ │ └── 8
+ * │ │ └── b [RISCV_FeatureStdExtZvl128b]
+ * │ └── 6
+ * │ └── 3
+ * │ └── 8
+ * │ └── 4
+ * │ └── b [RISCV_FeatureStdExtZvl16384b]
+ * ├── 2
+ * │ ├── 0
+ * │ │ └── 4
+ * │ │ └── 8
+ * │ │ └── b [RISCV_FeatureStdExtZvl2048b]
+ * │ └── 5
+ * │ └── 6
+ * │ └── b [RISCV_FeatureStdExtZvl256b]
+ * ├── 3
+ * │ └── 2
+ * │ ├── 7
+ * │ │ └── 6
+ * │ │ └── 8
+ * │ │ └── b [RISCV_FeatureStdExtZvl32768b]
+ * │ └── b [RISCV_FeatureStdExtZvl32b]
+ * ├── 4
+ * │ └── 0
+ * │ └── 9
+ * │ └── 6
+ * │ └── b [RISCV_FeatureStdExtZvl4096b]
+ * ├── 5
+ * │ └── 1
+ * │ └── 2
+ * │ └── b [RISCV_FeatureStdExtZvl512b]
+ * ├── 6
+ * │ ├── 4
+ * │ │ └── b [RISCV_FeatureStdExtZvl64b]
+ * │ └── 5
+ * │ └── 5
+ * │ └── 3
+ * │ └── 6
+ * │ └── b [RISCV_FeatureStdExtZvl65536b]
+ * └── 8
+ * └── 1
+ * └── 9
+ * └── 2
+ * └── b [RISCV_FeatureStdExtZvl8192b]
+ */
+
+#define RISCV_FeatureStdExtA 0
+
+#define RISCV_FeatureStdExtC 1
+
+#define RISCV_FeatureStdExtD 2
+
+#define RISCV_FeatureStdExtF 3
+
+#define RISCV_FeatureStdExtH 4
+
+#define RISCV_FeatureStdExtI 5
+
+#define RISCV_FeatureStdExtM 6
+
+#define RISCV_FeatureStdExtSmaia 7
+
+#define RISCV_FeatureStdExtSmepmp 8
+
+#define RISCV_FeatureStdExtSsaia 9
+
+#define RISCV_FeatureStdExtSvinval 10
+
+#define RISCV_FeatureStdExtSvnapot 11
+
+#define RISCV_FeatureStdExtSvpbmt 12
+
+#define RISCV_FeatureStdExtV 13
+
+#define RISCV_FeatureStdExtZa64rs 14
+
+#define RISCV_FeatureStdExtZa128rs 15
+
+#define RISCV_FeatureStdExtZacas 16
+
+#define RISCV_FeatureStdExtZawrs 17
+
+#define RISCV_FeatureStdExtZba 18
+
+#define RISCV_FeatureStdExtZbb 19
+
+#define RISCV_FeatureStdExtZbc 20
+
+#define RISCV_FeatureStdExtZbkb 21
+
+#define RISCV_FeatureStdExtZbkc 22
+
+#define RISCV_FeatureStdExtZbkx 23
+
+#define RISCV_FeatureStdExtZbs 24
+
+#define RISCV_FeatureStdExtZca 25
+
+#define RISCV_FeatureStdExtZcb 26
+
+#define RISCV_FeatureStdExtZcd 27
+
+#define RISCV_FeatureStdExtZce 28
+
+#define RISCV_FeatureStdExtZcf 29
+
+#define RISCV_FeatureStdExtZcmop 30
+
+#define RISCV_FeatureStdExtZcmp 31
+
+#define RISCV_FeatureStdExtZcmt 32
+
+#define RISCV_FeatureStdExtZdinx 33
+
+#define RISCV_FeatureStdExtZfa 34
+
+#define RISCV_FeatureStdExtZfbfmin 35
+
+#define RISCV_FeatureStdExtZfh 36
+
+#define RISCV_FeatureStdExtZfhmin 37
+
+#define RISCV_FeatureStdExtZfinx 38
+
+#define RISCV_FeatureStdExtZhinx 39
+
+#define RISCV_FeatureStdExtZhinxmin 40
+
+#define RISCV_FeatureStdExtZic64b 41
+
+#define RISCV_FeatureStdExtZicbom 42
+
+#define RISCV_FeatureStdExtZicbop 43
+
+#define RISCV_FeatureStdExtZicboz 44
+
+#define RISCV_FeatureStdExtZiccamoa 45
+
+#define RISCV_FeatureStdExtZiccif 46
+
+#define RISCV_FeatureStdExtZicclsm 47
+
+#define RISCV_FeatureStdExtZiccrse 48
+
+#define RISCV_FeatureStdExtZicfilp 49
+
+#define RISCV_FeatureStdExtZicfiss 50
+
+#define RISCV_FeatureStdExtZicntr 51
+
+#define RISCV_FeatureStdExtZicond 52
+
+#define RISCV_FeatureStdExtZicsr 53
+
+#define RISCV_FeatureStdExtZifencei 54
+
+#define RISCV_FeatureStdExtZihintntl 55
+
+#define RISCV_FeatureStdExtZihintpause 56
+
+#define RISCV_FeatureStdExtZihpm 57
+
+#define RISCV_FeatureStdExtZimop 58
+
+#define RISCV_FeatureStdExtZk 59
+
+#define RISCV_FeatureStdExtZkn 60
+
+#define RISCV_FeatureStdExtZknd 61
+
+#define RISCV_FeatureStdExtZkne 62
+
+#define RISCV_FeatureStdExtZknh 63
+
+#define RISCV_FeatureStdExtZkr 64
+
+#define RISCV_FeatureStdExtZks 65
+
+#define RISCV_FeatureStdExtZksed 66
+
+#define RISCV_FeatureStdExtZksh 67
+
+#define RISCV_FeatureStdExtZkt 68
+
+#define RISCV_FeatureStdExtZmmul 69
+
+#define RISCV_FeatureStdExtZtso 70
+
+#define RISCV_FeatureStdExtZvbb 71
+
+#define RISCV_FeatureStdExtZvbc 72
+
+#define RISCV_FeatureStdExtZve32f 73
+
+#define RISCV_FeatureStdExtZve32x 74
+
+#define RISCV_FeatureStdExtZve64d 75
+
+#define RISCV_FeatureStdExtZve64f 76
+
+#define RISCV_FeatureStdExtZve64x 77
+
+#define RISCV_FeatureStdExtZvfbfmin 78
+
+#define RISCV_FeatureStdExtZvfbfwma 79
+
+#define RISCV_FeatureStdExtZvfh 80
+
+#define RISCV_FeatureStdExtZvfhmin 81
+
+#define RISCV_FeatureStdExtZvkb 82
+
+#define RISCV_FeatureStdExtZvkg 83
+
+#define RISCV_FeatureStdExtZvkn 84
+
+#define RISCV_FeatureStdExtZvknc 85
+
+#define RISCV_FeatureStdExtZvkned 86
+
+#define RISCV_FeatureStdExtZvkng 87
+
+#define RISCV_FeatureStdExtZvknha 88
+
+#define RISCV_FeatureStdExtZvknhb 89
+
+#define RISCV_FeatureStdExtZvks 90
+
+#define RISCV_FeatureStdExtZvksc 91
+
+#define RISCV_FeatureStdExtZvksed 92
+
+#define RISCV_FeatureStdExtZvksg 93
+
+#define RISCV_FeatureStdExtZvksh 94
+
+#define RISCV_FeatureStdExtZvkt 95
+
+#define RISCV_FeatureStdExtZvl32b 96
+
+#define RISCV_FeatureStdExtZvl64b 97
+
+#define RISCV_FeatureStdExtZvl128b 98
+
+#define RISCV_FeatureStdExtZvl256b 99
+
+#define RISCV_FeatureStdExtZvl512b 100
+
+#define RISCV_FeatureStdExtZvl1024b 101
+
+#define RISCV_FeatureStdExtZvl2048b 102
+
+#define RISCV_FeatureStdExtZvl4096b 103
+
+#define RISCV_FeatureStdExtZvl8192b 104
+
+#define RISCV_FeatureStdExtZvl16384b 105
+
+#define RISCV_FeatureStdExtZvl32768b 106
+
+#define RISCV_FeatureStdExtZvl65536b 107
+/* Parse result enum - indicates why parsing stopped */
+typedef enum {
+ RISCV_EXT_PARSE_END_OF_STRING, /* Stopped at '\0' - valid extension found */
+ RISCV_EXT_PARSE_STOPPED_AT_NUMBER, /* Stopped at a digit - valid extension found */
+ RISCV_EXT_PARSE_STOPPED_AT_UNDERSCORE, /* Stopped at '_' - valid extension found */
+ RISCV_EXT_PARSE_STOPPED_AT_UNEXPECTED, /* Stopped at unexpected char - valid extension found */
+ RISCV_EXT_PARSE_NO_MATCH_END_OF_STRING, /* Reached '\0' - no valid extension */
+ RISCV_EXT_PARSE_NO_MATCH_NUMBER, /* Hit number - no valid extension at this point */
+ RISCV_EXT_PARSE_NO_MATCH_UNDERSCORE, /* Hit underscore - no valid extension at this point */
+ RISCV_EXT_PARSE_NO_MATCH_UNEXPECTED, /* Hit unexpected char - no valid extension */
+} riscv_extension_parse_result_t;
+
+/* Macro: Stop parsing with a matched extension */
+#ifndef MATCH_CALLBACK
+#define MATCH_CALLBACK(feature_enum)
+#endif
+
+#ifndef FINI_EXT_CALLBACKS
+#define FINI_EXT_CALLBACKS()
+#endif
+
+#define STOP_WITH_MATCH(feature_enum) \
+ do { \
+ MATCH_CALLBACK(feature_enum); \
+ *idx = (size_t)(p - ext_name); \
+ *mode = feature_enum; \
+ FINI_EXT_CALLBACKS(); \
+ if (*p == '\0') { \
+ return RISCV_EXT_PARSE_END_OF_STRING; \
+ } else if (*p >= '0' && *p <= '9') { \
+ return RISCV_EXT_PARSE_STOPPED_AT_NUMBER; \
+ } else if (*p == '_') { \
+ return RISCV_EXT_PARSE_STOPPED_AT_UNDERSCORE; \
+ } else { \
+ return RISCV_EXT_PARSE_STOPPED_AT_UNEXPECTED; \
+ } \
+ } while (0)
+
+/* Macro: Stop parsing without a match */
+#define STOP_WITHOUT_MATCH() \
+ do { \
+ *idx = (size_t)(p - ext_name); \
+ if (*p == '\0') { \
+ return RISCV_EXT_PARSE_NO_MATCH_END_OF_STRING; \
+ } else if (*p >= '0' && *p <= '9') { \
+ return RISCV_EXT_PARSE_NO_MATCH_NUMBER; \
+ } else if (*p == '_') { \
+ return RISCV_EXT_PARSE_NO_MATCH_UNDERSCORE; \
+ } else { \
+ return RISCV_EXT_PARSE_NO_MATCH_UNEXPECTED; \
+ } \
+ } while (0)
+
+/**
+ * Main parse routine: Try to consume a RISC-V extension name from the architecture string at a given position.
+ *
+ * @param arch_str: The full architecture string
+ * @param idx: Pointer to current index (will be updated to show consumed length)
+ * @param mode: Pointer to the feature accumulator (will be ORed with the feature flag if extension found)
+ * @return: Parse result indicating why parsing stopped and whether a match was found
+ *
+ * Stopping conditions:
+ * - '\0' (end of string)
+ * - '0'-'9' (version number)
+ * - '_' (extension separator)
+ * - Any unexpected character
+ *
+ * The function uses a trie-based approach for efficient parsing.
+ * State comments show the current position in the trie:
+ * 'abc...' means we've matched 'abc' and are looking for more
+ * 'abc(!x)' means we've matched 'abc' but encountered unexpected char instead of 'x'
+ */
+#ifndef INIT_EXT_CALLBACKS
+#define INIT_EXT_CALLBACKS()
+#endif
+
+static inline riscv_extension_parse_result_t
+try_consume_riscv_ext_from(const char *ext_name, size_t *idx, ut64 *mode) {
+ if (!ext_name || !idx || !mode) {
+ return RISCV_EXT_PARSE_NO_MATCH_END_OF_STRING;
+ }
+
+ INIT_EXT_CALLBACKS();
+ const char *p = ext_name + *idx;
+
+ if (*p == '\0') {
+ return RISCV_EXT_PARSE_NO_MATCH_END_OF_STRING;
+ }
+
+ /* State: '' expecting [acdfhimsvz] */
+ if (*p == 'a') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtA);
+ } else if (*p == 'c') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtC);
+ } else if (*p == 'd') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtD);
+ } else if (*p == 'f') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtF);
+ } else if (*p == 'h') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtH);
+ } else if (*p == 'i') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtI);
+ } else if (*p == 'm') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtM);
+ } else if (*p == 's') {
+ p++;
+ /* State: 's' expecting [msv] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'sm' expecting [ae] */
+ if (*p == 'a') {
+ p++;
+ /* State: 'sma' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'smai' expecting [a] */
+ if (*p == 'a') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtSmaia);
+ } else {
+ /* Unexpected char at 'smai', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'sma', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'e') {
+ p++;
+ /* State: 'sme' expecting [p] */
+ if (*p == 'p') {
+ p++;
+ /* State: 'smep' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'smepm' expecting [p] */
+ if (*p == 'p') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtSmepmp);
+ } else {
+ /* Unexpected char at 'smepm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'smep', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'sme', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'sm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 's') {
+ p++;
+ /* State: 'ss' expecting [a] */
+ if (*p == 'a') {
+ p++;
+ /* State: 'ssa' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'ssai' expecting [a] */
+ if (*p == 'a') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtSsaia);
+ } else {
+ /* Unexpected char at 'ssai', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'ssa', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'ss', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'v') {
+ p++;
+ /* State: 'sv' expecting [inp] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'svi' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ /* State: 'svin' expecting [v] */
+ if (*p == 'v') {
+ p++;
+ /* State: 'svinv' expecting [a] */
+ if (*p == 'a') {
+ p++;
+ /* State: 'svinva' expecting [l] */
+ if (*p == 'l') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtSvinval);
+ } else {
+ /* Unexpected char at 'svinva', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'svinv', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'svin', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'svi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'n') {
+ p++;
+ /* State: 'svn' expecting [a] */
+ if (*p == 'a') {
+ p++;
+ /* State: 'svna' expecting [p] */
+ if (*p == 'p') {
+ p++;
+ /* State: 'svnap' expecting [o] */
+ if (*p == 'o') {
+ p++;
+ /* State: 'svnapo' expecting [t] */
+ if (*p == 't') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtSvnapot);
+ } else {
+ /* Unexpected char at 'svnapo', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'svnap', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'svna', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'svn', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'p') {
+ p++;
+ /* State: 'svp' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ /* State: 'svpb' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'svpbm' expecting [t] */
+ if (*p == 't') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtSvpbmt);
+ } else {
+ /* Unexpected char at 'svpbm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'svpb', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'svp', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'sv', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 's', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'v') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtV);
+ } else if (*p == 'z') {
+ p++;
+ /* State: 'z' expecting [abcdfhikmtv] */
+ if (*p == 'a') {
+ p++;
+ /* State: 'za' expecting [16cw] */
+ if (*p == '1') {
+ p++;
+ /* State: 'za1' expecting [2] */
+ if (*p == '2') {
+ p++;
+ /* State: 'za12' expecting [8] */
+ if (*p == '8') {
+ p++;
+ /* State: 'za128' expecting [r] */
+ if (*p == 'r') {
+ p++;
+ /* State: 'za128r' expecting [s] */
+ if (*p == 's') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZa128rs);
+ } else {
+ /* Unexpected char at 'za128r', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'za128', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'za12', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'za1', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '6') {
+ p++;
+ /* State: 'za6' expecting [4] */
+ if (*p == '4') {
+ p++;
+ /* State: 'za64' expecting [r] */
+ if (*p == 'r') {
+ p++;
+ /* State: 'za64r' expecting [s] */
+ if (*p == 's') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZa64rs);
+ } else {
+ /* Unexpected char at 'za64r', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'za64', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'za6', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'c') {
+ p++;
+ /* State: 'zac' expecting [a] */
+ if (*p == 'a') {
+ p++;
+ /* State: 'zaca' expecting [s] */
+ if (*p == 's') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZacas);
+ } else {
+ /* Unexpected char at 'zaca', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zac', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'w') {
+ p++;
+ /* State: 'zaw' expecting [r] */
+ if (*p == 'r') {
+ p++;
+ /* State: 'zawr' expecting [s] */
+ if (*p == 's') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZawrs);
+ } else {
+ /* Unexpected char at 'zawr', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zaw', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'za', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'b') {
+ p++;
+ /* State: 'zb' expecting [abcks] */
+ if (*p == 'a') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZba);
+ } else if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZbb);
+ } else if (*p == 'c') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZbc);
+ } else if (*p == 'k') {
+ p++;
+ /* State: 'zbk' expecting [bcx] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZbkb);
+ } else if (*p == 'c') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZbkc);
+ } else if (*p == 'x') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZbkx);
+ } else {
+ /* Unexpected char at 'zbk', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 's') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZbs);
+ } else {
+ /* Unexpected char at 'zb', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'c') {
+ p++;
+ /* State: 'zc' expecting [abdefm] */
+ if (*p == 'a') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZca);
+ } else if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZcb);
+ } else if (*p == 'd') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZcd);
+ } else if (*p == 'e') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZce);
+ } else if (*p == 'f') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZcf);
+ } else if (*p == 'm') {
+ p++;
+ /* State: 'zcm' expecting [opt] */
+ if (*p == 'o') {
+ p++;
+ /* State: 'zcmo' expecting [p] */
+ if (*p == 'p') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZcmop);
+ } else {
+ /* Unexpected char at 'zcmo', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'p') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZcmp);
+ } else if (*p == 't') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZcmt);
+ } else {
+ /* Unexpected char at 'zcm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zc', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'd') {
+ p++;
+ /* State: 'zd' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'zdi' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ /* State: 'zdin' expecting [x] */
+ if (*p == 'x') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZdinx);
+ } else {
+ /* Unexpected char at 'zdin', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zdi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zd', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'f') {
+ p++;
+ /* State: 'zf' expecting [abhi] */
+ if (*p == 'a') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZfa);
+ } else if (*p == 'b') {
+ p++;
+ /* State: 'zfb' expecting [f] */
+ if (*p == 'f') {
+ p++;
+ /* State: 'zfbf' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'zfbfm' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'zfbfmi' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZfbfmin);
+ } else {
+ /* Unexpected char at 'zfbfmi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zfbfm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zfbf', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zfb', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'h') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZfh);
+
+ /* State: 'zfh' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'zfhm' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'zfhmi' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZfhmin);
+ } else {
+ /* Unexpected char at 'zfhmi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zfhm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char, but 'zfh' was valid */
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZfh);
+ }
+ } else if (*p == 'i') {
+ p++;
+ /* State: 'zfi' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ /* State: 'zfin' expecting [x] */
+ if (*p == 'x') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZfinx);
+ } else {
+ /* Unexpected char at 'zfin', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zfi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zf', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'h') {
+ p++;
+ /* State: 'zh' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'zhi' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ /* State: 'zhin' expecting [x] */
+ if (*p == 'x') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZhinx);
+
+ /* State: 'zhinx' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'zhinxm' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'zhinxmi' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZhinxmin);
+ } else {
+ /* Unexpected char at 'zhinxmi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zhinxm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char, but 'zhinx' was valid */
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZhinx);
+ }
+ } else {
+ /* Unexpected char at 'zhin', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zhi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zh', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'i') {
+ p++;
+ /* State: 'zi' expecting [cfhm] */
+ if (*p == 'c') {
+ p++;
+ /* State: 'zic' expecting [6bcfnos] */
+ if (*p == '6') {
+ p++;
+ /* State: 'zic6' expecting [4] */
+ if (*p == '4') {
+ p++;
+ /* State: 'zic64' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZic64b);
+ } else {
+ /* Unexpected char at 'zic64', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zic6', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'b') {
+ p++;
+ /* State: 'zicb' expecting [o] */
+ if (*p == 'o') {
+ p++;
+ /* State: 'zicbo' expecting [mpz] */
+ if (*p == 'm') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZicbom);
+ } else if (*p == 'p') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZicbop);
+ } else if (*p == 'z') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZicboz);
+ } else {
+ /* Unexpected char at 'zicbo', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zicb', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'c') {
+ p++;
+ /* State: 'zicc' expecting [ailr] */
+ if (*p == 'a') {
+ p++;
+ /* State: 'zicca' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'ziccam' expecting [o] */
+ if (*p == 'o') {
+ p++;
+ /* State: 'ziccamo' expecting [a] */
+ if (*p == 'a') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZiccamoa);
+ } else {
+ /* Unexpected char at 'ziccamo', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'ziccam', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zicca', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'i') {
+ p++;
+ /* State: 'zicci' expecting [f] */
+ if (*p == 'f') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZiccif);
+ } else {
+ /* Unexpected char at 'zicci', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'l') {
+ p++;
+ /* State: 'ziccl' expecting [s] */
+ if (*p == 's') {
+ p++;
+ /* State: 'ziccls' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZicclsm);
+ } else {
+ /* Unexpected char at 'ziccls', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'ziccl', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'r') {
+ p++;
+ /* State: 'ziccr' expecting [s] */
+ if (*p == 's') {
+ p++;
+ /* State: 'ziccrs' expecting [e] */
+ if (*p == 'e') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZiccrse);
+ } else {
+ /* Unexpected char at 'ziccrs', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'ziccr', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zicc', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'f') {
+ p++;
+ /* State: 'zicf' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'zicfi' expecting [ls] */
+ if (*p == 'l') {
+ p++;
+ /* State: 'zicfil' expecting [p] */
+ if (*p == 'p') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZicfilp);
+ } else {
+ /* Unexpected char at 'zicfil', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 's') {
+ p++;
+ /* State: 'zicfis' expecting [s] */
+ if (*p == 's') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZicfiss);
+ } else {
+ /* Unexpected char at 'zicfis', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zicfi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zicf', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'n') {
+ p++;
+ /* State: 'zicn' expecting [t] */
+ if (*p == 't') {
+ p++;
+ /* State: 'zicnt' expecting [r] */
+ if (*p == 'r') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZicntr);
+ } else {
+ /* Unexpected char at 'zicnt', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zicn', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'o') {
+ p++;
+ /* State: 'zico' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ /* State: 'zicon' expecting [d] */
+ if (*p == 'd') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZicond);
+ } else {
+ /* Unexpected char at 'zicon', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zico', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 's') {
+ p++;
+ /* State: 'zics' expecting [r] */
+ if (*p == 'r') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZicsr);
+ } else {
+ /* Unexpected char at 'zics', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zic', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'f') {
+ p++;
+ /* State: 'zif' expecting [e] */
+ if (*p == 'e') {
+ p++;
+ /* State: 'zife' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ /* State: 'zifen' expecting [c] */
+ if (*p == 'c') {
+ p++;
+ /* State: 'zifenc' expecting [e] */
+ if (*p == 'e') {
+ p++;
+ /* State: 'zifence' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZifencei);
+ } else {
+ /* Unexpected char at 'zifence', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zifenc', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zifen', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zife', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zif', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'h') {
+ p++;
+ /* State: 'zih' expecting [ip] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'zihi' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ /* State: 'zihin' expecting [t] */
+ if (*p == 't') {
+ p++;
+ /* State: 'zihint' expecting [np] */
+ if (*p == 'n') {
+ p++;
+ /* State: 'zihintn' expecting [t] */
+ if (*p == 't') {
+ p++;
+ /* State: 'zihintnt' expecting [l] */
+ if (*p == 'l') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZihintntl);
+ } else {
+ /* Unexpected char at 'zihintnt', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zihintn', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'p') {
+ p++;
+ /* State: 'zihintp' expecting [a] */
+ if (*p == 'a') {
+ p++;
+ /* State: 'zihintpa' expecting [u] */
+ if (*p == 'u') {
+ p++;
+ /* State: 'zihintpau' expecting [s] */
+ if (*p == 's') {
+ p++;
+ /* State: 'zihintpaus' expecting [e] */
+ if (*p == 'e') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZihintpause);
+ } else {
+ /* Unexpected char at 'zihintpaus', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zihintpau', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zihintpa', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zihintp', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zihint', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zihin', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zihi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'p') {
+ p++;
+ /* State: 'zihp' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZihpm);
+ } else {
+ /* Unexpected char at 'zihp', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zih', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'm') {
+ p++;
+ /* State: 'zim' expecting [o] */
+ if (*p == 'o') {
+ p++;
+ /* State: 'zimo' expecting [p] */
+ if (*p == 'p') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZimop);
+ } else {
+ /* Unexpected char at 'zimo', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zim', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'k') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZk);
+
+ /* State: 'zk' expecting [nrst] */
+ if (*p == 'n') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZkn);
+
+ /* State: 'zkn' expecting [deh] */
+ if (*p == 'd') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZknd);
+ } else if (*p == 'e') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZkne);
+ } else if (*p == 'h') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZknh);
+ } else {
+ /* Unexpected char, but 'zkn' was valid */
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZkn);
+ }
+ } else if (*p == 'r') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZkr);
+ } else if (*p == 's') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZks);
+
+ /* State: 'zks' expecting [eh] */
+ if (*p == 'e') {
+ p++;
+ /* State: 'zkse' expecting [d] */
+ if (*p == 'd') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZksed);
+ } else {
+ /* Unexpected char at 'zkse', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'h') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZksh);
+ } else {
+ /* Unexpected char, but 'zks' was valid */
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZks);
+ }
+ } else if (*p == 't') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZkt);
+ } else {
+ /* Unexpected char, but 'zk' was valid */
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZk);
+ }
+ } else if (*p == 'm') {
+ p++;
+ /* State: 'zm' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'zmm' expecting [u] */
+ if (*p == 'u') {
+ p++;
+ /* State: 'zmmu' expecting [l] */
+ if (*p == 'l') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZmmul);
+ } else {
+ /* Unexpected char at 'zmmu', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zmm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 't') {
+ p++;
+ /* State: 'zt' expecting [s] */
+ if (*p == 's') {
+ p++;
+ /* State: 'zts' expecting [o] */
+ if (*p == 'o') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZtso);
+ } else {
+ /* Unexpected char at 'zts', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zt', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'v') {
+ p++;
+ /* State: 'zv' expecting [befkl] */
+ if (*p == 'b') {
+ p++;
+ /* State: 'zvb' expecting [bc] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvbb);
+ } else if (*p == 'c') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvbc);
+ } else {
+ /* Unexpected char at 'zvb', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'e') {
+ p++;
+ /* State: 'zve' expecting [36] */
+ if (*p == '3') {
+ p++;
+ /* State: 'zve3' expecting [2] */
+ if (*p == '2') {
+ p++;
+ /* State: 'zve32' expecting [fx] */
+ if (*p == 'f') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZve32f);
+ } else if (*p == 'x') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZve32x);
+ } else {
+ /* Unexpected char at 'zve32', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zve3', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '6') {
+ p++;
+ /* State: 'zve6' expecting [4] */
+ if (*p == '4') {
+ p++;
+ /* State: 'zve64' expecting [dfx] */
+ if (*p == 'd') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZve64d);
+ } else if (*p == 'f') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZve64f);
+ } else if (*p == 'x') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZve64x);
+ } else {
+ /* Unexpected char at 'zve64', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zve6', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zve', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'f') {
+ p++;
+ /* State: 'zvf' expecting [bh] */
+ if (*p == 'b') {
+ p++;
+ /* State: 'zvfb' expecting [f] */
+ if (*p == 'f') {
+ p++;
+ /* State: 'zvfbf' expecting [mw] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'zvfbfm' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'zvfbfmi' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvfbfmin);
+ } else {
+ /* Unexpected char at 'zvfbfmi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvfbfm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'w') {
+ p++;
+ /* State: 'zvfbfw' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'zvfbfwm' expecting [a] */
+ if (*p == 'a') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvfbfwma);
+ } else {
+ /* Unexpected char at 'zvfbfwm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvfbfw', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvfbf', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvfb', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'h') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvfh);
+
+ /* State: 'zvfh' expecting [m] */
+ if (*p == 'm') {
+ p++;
+ /* State: 'zvfhm' expecting [i] */
+ if (*p == 'i') {
+ p++;
+ /* State: 'zvfhmi' expecting [n] */
+ if (*p == 'n') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvfhmin);
+ } else {
+ /* Unexpected char at 'zvfhmi', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvfhm', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char, but 'zvfh' was valid */
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvfh);
+ }
+ } else {
+ /* Unexpected char at 'zvf', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'k') {
+ p++;
+ /* State: 'zvk' expecting [bgnst] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvkb);
+ } else if (*p == 'g') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvkg);
+ } else if (*p == 'n') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvkn);
+
+ /* State: 'zvkn' expecting [cegh] */
+ if (*p == 'c') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvknc);
+ } else if (*p == 'e') {
+ p++;
+ /* State: 'zvkne' expecting [d] */
+ if (*p == 'd') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvkned);
+ } else {
+ /* Unexpected char at 'zvkne', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'g') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvkng);
+ } else if (*p == 'h') {
+ p++;
+ /* State: 'zvknh' expecting [ab] */
+ if (*p == 'a') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvknha);
+ } else if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvknhb);
+ } else {
+ /* Unexpected char at 'zvknh', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char, but 'zvkn' was valid */
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvkn);
+ }
+ } else if (*p == 's') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvks);
+
+ /* State: 'zvks' expecting [cegh] */
+ if (*p == 'c') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvksc);
+ } else if (*p == 'e') {
+ p++;
+ /* State: 'zvkse' expecting [d] */
+ if (*p == 'd') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvksed);
+ } else {
+ /* Unexpected char at 'zvkse', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'g') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvksg);
+ } else if (*p == 'h') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvksh);
+ } else {
+ /* Unexpected char, but 'zvks' was valid */
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvks);
+ }
+ } else if (*p == 't') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvkt);
+ } else {
+ /* Unexpected char at 'zvk', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'l') {
+ p++;
+ /* State: 'zvl' expecting [1234568] */
+ if (*p == '1') {
+ p++;
+ /* State: 'zvl1' expecting [026] */
+ if (*p == '0') {
+ p++;
+ /* State: 'zvl10' expecting [2] */
+ if (*p == '2') {
+ p++;
+ /* State: 'zvl102' expecting [4] */
+ if (*p == '4') {
+ p++;
+ /* State: 'zvl1024' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl1024b);
+ } else {
+ /* Unexpected char at 'zvl1024', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl102', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl10', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '2') {
+ p++;
+ /* State: 'zvl12' expecting [8] */
+ if (*p == '8') {
+ p++;
+ /* State: 'zvl128' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl128b);
+ } else {
+ /* Unexpected char at 'zvl128', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl12', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '6') {
+ p++;
+ /* State: 'zvl16' expecting [3] */
+ if (*p == '3') {
+ p++;
+ /* State: 'zvl163' expecting [8] */
+ if (*p == '8') {
+ p++;
+ /* State: 'zvl1638' expecting [4] */
+ if (*p == '4') {
+ p++;
+ /* State: 'zvl16384' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl16384b);
+ } else {
+ /* Unexpected char at 'zvl16384', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl1638', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl163', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl16', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl1', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '2') {
+ p++;
+ /* State: 'zvl2' expecting [05] */
+ if (*p == '0') {
+ p++;
+ /* State: 'zvl20' expecting [4] */
+ if (*p == '4') {
+ p++;
+ /* State: 'zvl204' expecting [8] */
+ if (*p == '8') {
+ p++;
+ /* State: 'zvl2048' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl2048b);
+ } else {
+ /* Unexpected char at 'zvl2048', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl204', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl20', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '5') {
+ p++;
+ /* State: 'zvl25' expecting [6] */
+ if (*p == '6') {
+ p++;
+ /* State: 'zvl256' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl256b);
+ } else {
+ /* Unexpected char at 'zvl256', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl25', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl2', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '3') {
+ p++;
+ /* State: 'zvl3' expecting [2] */
+ if (*p == '2') {
+ p++;
+ /* State: 'zvl32' expecting [7b] */
+ if (*p == '7') {
+ p++;
+ /* State: 'zvl327' expecting [6] */
+ if (*p == '6') {
+ p++;
+ /* State: 'zvl3276' expecting [8] */
+ if (*p == '8') {
+ p++;
+ /* State: 'zvl32768' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl32768b);
+ } else {
+ /* Unexpected char at 'zvl32768', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl3276', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl327', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl32b);
+ } else {
+ /* Unexpected char at 'zvl32', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl3', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '4') {
+ p++;
+ /* State: 'zvl4' expecting [0] */
+ if (*p == '0') {
+ p++;
+ /* State: 'zvl40' expecting [9] */
+ if (*p == '9') {
+ p++;
+ /* State: 'zvl409' expecting [6] */
+ if (*p == '6') {
+ p++;
+ /* State: 'zvl4096' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl4096b);
+ } else {
+ /* Unexpected char at 'zvl4096', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl409', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl40', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl4', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '5') {
+ p++;
+ /* State: 'zvl5' expecting [1] */
+ if (*p == '1') {
+ p++;
+ /* State: 'zvl51' expecting [2] */
+ if (*p == '2') {
+ p++;
+ /* State: 'zvl512' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl512b);
+ } else {
+ /* Unexpected char at 'zvl512', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl51', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl5', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '6') {
+ p++;
+ /* State: 'zvl6' expecting [45] */
+ if (*p == '4') {
+ p++;
+ /* State: 'zvl64' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl64b);
+ } else {
+ /* Unexpected char at 'zvl64', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '5') {
+ p++;
+ /* State: 'zvl65' expecting [5] */
+ if (*p == '5') {
+ p++;
+ /* State: 'zvl655' expecting [3] */
+ if (*p == '3') {
+ p++;
+ /* State: 'zvl6553' expecting [6] */
+ if (*p == '6') {
+ p++;
+ /* State: 'zvl65536' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl65536b);
+ } else {
+ /* Unexpected char at 'zvl65536', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl6553', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl655', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl65', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl6', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else if (*p == '8') {
+ p++;
+ /* State: 'zvl8' expecting [1] */
+ if (*p == '1') {
+ p++;
+ /* State: 'zvl81' expecting [9] */
+ if (*p == '9') {
+ p++;
+ /* State: 'zvl819' expecting [2] */
+ if (*p == '2') {
+ p++;
+ /* State: 'zvl8192' expecting [b] */
+ if (*p == 'b') {
+ p++;
+ STOP_WITH_MATCH(RISCV_FeatureStdExtZvl8192b);
+ } else {
+ /* Unexpected char at 'zvl8192', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl819', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl81', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl8', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zvl', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'zv', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at 'z', no match */
+ STOP_WITHOUT_MATCH();
+ }
+ } else {
+ /* Unexpected char at '', no match */
+ STOP_WITHOUT_MATCH();
+ }
+
+ /* Should not reach here */
+ STOP_WITHOUT_MATCH();
+}
+
+/* Cleanup macros */
+#undef STOP_WITH_MATCH
+#undef STOP_WITHOUT_MATCH
+
+/* Example usage:
+ *
+ * ut64 features = 0;
+ * riscv_extension_parse_result_t result;
+ * size_t idx = 0;
+ * const char *arch = "i2p1_m2p0_zicsr";
+ *
+ * // Parse "i" from "i2p1_m2p0_zicsr"
+ * result = try_consume_riscv_ext_from(arch, &idx, &features);
+ * // idx is now 1, result is RISCV_EXT_PARSE_STOPPED_AT_NUMBER
+ *
+ * // Skip version "2p1_" by setting idx = 5
+ * idx = 5; // now at 'm'
+ * result = try_consume_riscv_ext_from(arch, &idx, &features);
+ * // idx is now 6, result is RISCV_EXT_PARSE_STOPPED_AT_NUMBER
+ *
+ * // Skip version "2p0_" by setting idx = 10
+ * idx = 10; // now at 'z'
+ * result = try_consume_riscv_ext_from(arch, &idx, &features);
+ * // idx is now 15, result is RISCV_EXT_PARSE_END_OF_STRING
+ */
diff --git a/librz/arch/p/asm/asm_riscv_cs.c b/librz/arch/p/asm/asm_riscv_cs.c
index a3b16f72ef6..21354fd4ef3 100644
--- a/librz/arch/p/asm/asm_riscv_cs.c
+++ b/librz/arch/p/asm/asm_riscv_cs.c
@@ -1,8 +1,10 @@
+// SPDX-FileCopyrightText: 2024-2026 moste00
// SPDX-FileCopyrightText: 2019 pancake
-// SPDX-License-Identifier: LGPL-3.0-only
+// SPDX-License-Identifier: BSD-3-Clause
#include
#include
+#include
#include "cs_helper.h"
CAPSTONE_DEFINE_PLUGIN_FUNCTIONS(riscv_asm);
@@ -13,6 +15,7 @@ static int riscv_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) {
int ret = -1;
cs_insn *insn;
cs_mode mode = (a->bits == 64) ? CS_MODE_RISCV64 : CS_MODE_RISCV32;
+ mode |= mode_from_arch_string(a->cpu);
op->size = 4;
if (ctx->omode != mode) {
cs_close(&ctx->handle);
@@ -49,11 +52,11 @@ static int riscv_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) {
}
RzAsmPlugin rz_asm_plugin_riscv_cs = {
- .name = "riscv.cs",
+ .name = "riscv",
.desc = "RISC-V Capstone-based disassembler",
.license = "BSD",
.arch = "riscv",
- .cpus = "",
+ .cpus = NULL,
.bits = 32 | 64,
.endian = RZ_SYS_ENDIAN_LITTLE | RZ_SYS_ENDIAN_BIG,
.init = riscv_asm_init,
diff --git a/librz/arch/p_gnu/analysis/analysis_riscv_gnu.c b/librz/arch/p_gnu/analysis/analysis_riscv_gnu.c
deleted file mode 100644
index 35d02f9c8ba..00000000000
--- a/librz/arch/p_gnu/analysis/analysis_riscv_gnu.c
+++ /dev/null
@@ -1,940 +0,0 @@
-// SPDX-FileCopyrightText: 2015-2019 qnix
-// SPDX-License-Identifier: LGPL-3.0-only
-
-#include
-#include
-#include
-#include
-#include
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
-#define RISCVARGSMAX (8)
-#define RISCVARGSIZE (64)
-#define RISCVARGN(x) ((x)->arg[(x)->num++])
-
-typedef struct riscv_args {
- int num;
- char arg[RISCVARGSMAX][RISCVARGSIZE];
-} riscv_args_t;
-
-static bool init_analysis = false;
-
-#define is_any(...) _is_any(o->name, __VA_ARGS__, NULL)
-static bool _is_any(const char *str, ...) {
- char *cur;
- va_list va;
- va_start(va, str);
- while (true) {
- cur = va_arg(va, char *);
- if (!cur) {
- break;
- }
- if (!strcmp(str, cur)) {
- va_end(va);
- return true;
- }
- }
- va_end(va);
- return false;
-}
-
-static void arg_p2(char *buf, unsigned long val, const char *const *array, size_t size) {
- const char *s = val >= size || array[val] ? array[val] : "unknown";
- snprintf(buf, RISCVARGSIZE, "%s", s);
-}
-
-static struct riscv_opcode *get_opcode_analysis(insn_t word) {
- struct riscv_opcode *op;
- static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1] = { 0 };
-
-#define OP_HASH_IDX(i) ((i) & (riscv_insn_length(i) == 2 ? 3 : OP_MASK_OP))
-
- if (!init_analysis) {
- for (op = riscv_opcodes; op < &riscv_opcodes[NUMOPCODES]; op++) {
- if (!riscv_hash[OP_HASH_IDX(op->match)]) {
- riscv_hash[OP_HASH_IDX(op->match)] = op;
- }
- }
- init_analysis = true;
- }
-
- return (struct riscv_opcode *)riscv_hash[OP_HASH_IDX(word)];
-}
-
-/* Print insn arguments for 32/64-bit code. */
-static void get_insn_args_analysis(riscv_args_t *args, const char *d, insn_t l, uint64_t pc) {
- int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
- int rd = (l >> OP_SH_RD) & OP_MASK_RD;
- uint64_t target;
- args->num = 0;
-
- for (; *d != '\0' && args->num < RISCVARGSMAX; d++) {
- switch (*d) {
- /* Xcustom */
- case '^':
- switch (*++d) {
- case 'd':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", rd);
- break;
- case 's':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", rs1);
- break;
- case 't':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_OPERAND(RS2, l));
- break;
- case 'j':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_OPERAND(CUSTOM_IMM, l));
- break;
- }
- break;
-
- case 'C': /* RVC */
- switch (*++d) {
- case 's': /* RS1 x8-x15 */
- case 'w': /* RS1 x8-x15 */
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s",
- riscv_gpr_names[EXTRACT_OPERAND(CRS1S, l) + 8]);
- break;
- case 't': /* RS2 x8-x15 */
- case 'x': /* RS2 x8-x15 */
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s",
- riscv_gpr_names[EXTRACT_OPERAND(CRS2S, l) + 8]);
- break;
- case 'U': /* RS1, constrained to equal RD in CI format*/
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s", riscv_gpr_names[rd]);
- break;
- case 'c': /* RS1, constrained to equal sp */
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s", riscv_gpr_names[X_SP]);
- break;
- case 'V': /* RS2 */
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s",
- riscv_gpr_names[EXTRACT_OPERAND(CRS2, l)]);
- break;
- case 'i':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_RVC_SIMM3(l));
- break;
- case 'j':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_RVC_IMM(l));
- break;
- case 'k':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_RVC_LW_IMM(l));
- break;
- case 'l':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_RVC_LD_IMM(l));
- break;
- case 'm':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_RVC_LWSP_IMM(l));
- break;
- case 'n':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_RVC_LDSP_IMM(l));
- break;
- case 'K':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_RVC_ADDI4SPN_IMM(l));
- break;
- case 'L':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_RVC_ADDI16SP_IMM(l));
- break;
- case 'M':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_RVC_SWSP_IMM(l));
- break;
- case 'N':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_RVC_SDSP_IMM(l));
- break;
- case 'p':
- target = EXTRACT_RVC_B_IMM(l) + pc;
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%" PFMT64x, (ut64)target);
- break;
- case 'a':
- target = EXTRACT_RVC_J_IMM(l) + pc;
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%" PFMT64x, (ut64)target);
- break;
- case 'u':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%x",
- (int)(EXTRACT_RVC_IMM(l) & (RISCV_BIGIMM_REACH - 1)));
- break;
- case '>':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%x", (int)EXTRACT_RVC_IMM(l) & 0x3f);
- break;
- case '<':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%x", (int)EXTRACT_RVC_IMM(l) & 0x1f);
- break;
- case 'T': /* floating-point RS2 */
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s",
- riscv_fpr_names[EXTRACT_OPERAND(CRS2, l)]);
- break;
- case 'D': /* floating-point RS2 x8-x15 */
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s",
- riscv_fpr_names[EXTRACT_OPERAND(CRS2S, l) + 8]);
- break;
- }
- break;
-
- case ',':
- case '(':
- case ')':
- case '[':
- case ']':
- break;
- case '0':
- /* Only print constant 0 if it is the last argument */
- if (!d[1]) {
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0");
- }
- break;
-
- case 'b':
- case 's':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s", riscv_gpr_names[rs1]);
- break;
-
- case 't':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s",
- riscv_gpr_names[EXTRACT_OPERAND(RS2, l)]);
- break;
-
- case 'u':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%x",
- (unsigned)EXTRACT_UTYPE_IMM(l) >> RISCV_IMM_BITS);
- break;
-
- case 'm':
- arg_p2(RISCVARGN(args), EXTRACT_OPERAND(RM, l),
- riscv_rm, ARRAY_SIZE(riscv_rm));
- break;
-
- case 'P':
- arg_p2(RISCVARGN(args), EXTRACT_OPERAND(PRED, l),
- riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
- break;
-
- case 'Q':
- arg_p2(RISCVARGN(args), EXTRACT_OPERAND(SUCC, l),
- riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
- break;
- case 'o':
- case 'j':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_ITYPE_IMM(l));
- break;
- case 'q':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", (int)EXTRACT_STYPE_IMM(l));
- break;
- case 'a':
- target = EXTRACT_UJTYPE_IMM(l) + pc;
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%" PFMT64x, (ut64)target);
- break;
- case 'p':
- target = EXTRACT_SBTYPE_IMM(l) + pc;
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%" PFMT64x, (ut64)target);
- break;
- case 'd':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s", riscv_gpr_names[rd]);
- break;
- case 'z':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s", riscv_gpr_names[0]);
- break;
- case '>':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%x", (int)EXTRACT_OPERAND(SHAMT, l));
- break;
- case '<':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%x", (int)EXTRACT_OPERAND(SHAMTW, l));
- break;
- case 'S':
- case 'U':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s", riscv_fpr_names[rs1]);
- break;
- case 'T':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s", riscv_fpr_names[EXTRACT_OPERAND(RS2, l)]);
- break;
- case 'D':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s", riscv_fpr_names[rd]);
- break;
- case 'R':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s", riscv_fpr_names[EXTRACT_OPERAND(RS3, l)]);
- break;
- case 'E': {
- const char *csr_name = NULL;
- unsigned int csr = EXTRACT_OPERAND(CSR, l);
- switch (csr) {
-#define DECLARE_CSR(name, num) \
- case num: \
- csr_name = #name; \
- break;
-#include
-#undef DECLARE_CSR
- }
- if (csr_name) {
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%s", csr_name);
- } else {
- snprintf(RISCVARGN(args), RISCVARGSIZE, "0x%x", csr);
- }
- break;
- }
- case 'Z':
- snprintf(RISCVARGN(args), RISCVARGSIZE, "%d", rs1);
- break;
- default:
- /* xgettext:c-format */
- snprintf(RISCVARGN(args), RISCVARGSIZE, "# internal error, undefined modifier (%c)",
- *d);
- return;
- }
- }
-}
-
-static const char *arg_n(riscv_args_t *args, int n) {
- if (n >= args->num || !strcmp(args->arg[n], "zero")) {
- return "0";
- }
- return args->arg[n];
-}
-
-static int riscv_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *data, int len, RzAnalysisOpMask mask) {
- const int no_alias = 1;
- riscv_args_t args = { 0 };
- ut64 word = 0;
- int xlen = analysis->bits;
- op->size = 4;
- op->addr = addr;
- op->type = RZ_ANALYSIS_OP_TYPE_UNK;
-
- if (len >= sizeof(ut64)) {
- word = rz_read_ble64(data, analysis->big_endian);
- } else if (len >= sizeof(ut16)) {
- word = rz_read_ble16(data, analysis->big_endian);
- } else {
- op->type = RZ_ANALYSIS_OP_TYPE_ILL;
- return -1;
- }
-
- struct riscv_opcode *o = get_opcode_analysis(word);
- for (; o && o < &riscv_opcodes[NUMOPCODES]; o++) {
- if (!(o->match_func)(o, word)) {
- continue;
- }
- if (no_alias && (o->pinfo & INSN_ALIAS)) {
- continue;
- }
- if (isdigit((ut8)o->subset[0]) && atoi(o->subset) != xlen) {
- continue;
- }
- if (o->name) {
- break;
- }
- op->type = RZ_ANALYSIS_OP_TYPE_ILL;
- return -1;
- }
- if (!o || o >= &riscv_opcodes[NUMOPCODES] || !o->name) {
- op->type = RZ_ANALYSIS_OP_TYPE_ILL;
- return -1;
- }
-
- if (mask & RZ_ANALYSIS_OP_MASK_DISASM) {
- op->mnemonic = rz_str_dup(o->name);
- }
-
- if (o->args) {
- const char *name = o->name;
- // Test for compressed instruction
- if (!strncmp("c.", o->name, 2)) {
- name += 2;
- op->size = 2;
- }
-#define ARG(x) (arg_n(&args, (x)))
- get_insn_args_analysis(&args, o->args, word, addr);
- if (!strcmp(name, "nop")) {
- esilprintf(op, ",");
- }
- // math
- else if (!strncmp(name, "addi16sp", 8)) {
- esilprintf(op, "%s,sp,+,%s,=", ARG(1), ARG(0));
- if (!strcmp(ARG(0), riscv_gpr_names[X_SP])) {
- op->stackop = RZ_ANALYSIS_STACK_INC;
- op->stackptr = rz_num_math(NULL, ARG(1));
- }
- } else if (!strncmp(name, "addiw", 5)) {
- rz_strbuf_appendf(&op->esil, "%s,0xffffffff,%s,&,", ARG(2), ARG(1));
- rz_strbuf_appendf(&op->esil, "+,%s,=,", ARG(0));
- rz_strbuf_appendf(&op->esil, "32,%s,~=", ARG(0));
- if (!strcmp(ARG(0), riscv_gpr_names[X_SP]) &&
- !strcmp(ARG(1), riscv_gpr_names[X_SP])) {
- op->stackop = RZ_ANALYSIS_STACK_INC;
- op->stackptr = rz_num_math(NULL, ARG(2));
- }
- } else if (!strncmp(name, "addw", 4)) {
- esilprintf(op, "0xffffffff,%s,&,", ARG(2));
- rz_strbuf_appendf(&op->esil, "0xffffffff,%s,&,", ARG(1));
- rz_strbuf_appendf(&op->esil, "+,%s,=,", ARG(0));
- rz_strbuf_appendf(&op->esil, "32,%s,~=", ARG(0));
- } else if (!strncmp(name, "add", 3)) {
- esilprintf(op, "%s,%s,+,%s,=", ARG(2), ARG(1), ARG(0));
- if (name[3] == 'i' && !strcmp(ARG(0), riscv_gpr_names[X_SP]) &&
- !strcmp(ARG(1), riscv_gpr_names[X_SP])) {
- op->stackop = RZ_ANALYSIS_STACK_INC;
- op->stackptr = -(signed)rz_num_math(NULL, ARG(2));
- }
- } else if (!strncmp(name, "subw", 4)) {
- esilprintf(op, "0xffffffff,%s,&,", ARG(2));
- rz_strbuf_appendf(&op->esil, "0xffffffff,%s,&,", ARG(1));
- rz_strbuf_appendf(&op->esil, "-,%s,=,", ARG(0));
- rz_strbuf_appendf(&op->esil, "32,%s,~=", ARG(0));
- } else if (!strncmp(name, "sub", 3)) {
- esilprintf(op, "%s,%s,-,%s,=", ARG(2), ARG(1), ARG(0));
- if (name[3] == 'i' && !strcmp(ARG(0), riscv_gpr_names[X_SP]) &&
- !strcmp(ARG(1), riscv_gpr_names[X_SP])) {
- op->stackop = RZ_ANALYSIS_STACK_INC;
- op->stackptr = rz_num_math(NULL, ARG(2));
- }
- } else if (!strncmp(name, "mulw", 4)) {
- esilprintf(op, "0xffffffff,%s,&,", ARG(2));
- rz_strbuf_appendf(&op->esil, "0xffffffff,%s,&,", ARG(1));
- rz_strbuf_appendf(&op->esil, "*,%s,=,", ARG(0));
- rz_strbuf_appendf(&op->esil, "32,%s,~=", ARG(0));
- } else if (!strncmp(name, "mul", 3)) {
- esilprintf(op, "%s,%s,*,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "div", 3)) {
- esilprintf(op, "%s,%s,/,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "rem", 3)) {
- esilprintf(op, "%s,%s,%%,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "xor", 3)) {
- esilprintf(op, "%s,%s,^,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "or", 2)) {
- esilprintf(op, "%s,%s,|,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "and", 3)) {
- esilprintf(op, "%s,%s,&,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strcmp(name, "auipc")) {
- esilprintf(op, "%s000,$$,+,%s,=", ARG(1), ARG(0));
- } else if (!strncmp(name, "sll", 3)) {
- esilprintf(op, "%s,%s,<<,%s,=", ARG(2), ARG(1), ARG(0));
- if (name[3] == 'w' || !strncmp(name, "slliw", 5)) {
- rz_strbuf_appendf(&op->esil, ",32,%s,~=", ARG(0));
- }
- } else if (!strcmp(name, "srlw") || !strcmp(name, "srliw")) {
- esilprintf(op, "%s,0xffffffff,%s,&,>>,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "srl", 3)) {
- esilprintf(op, "%s,%s,>>,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strcmp(name, "sraiw")) {
- esilprintf(op, "%s,%s,>>>>,%s,=,", ARG(2), ARG(1), ARG(0));
- rz_strbuf_appendf(&op->esil, "%s,64,-,%s,~=", ARG(2), ARG(0));
- } else if (!strncmp(name, "sra", 3)) {
- esilprintf(op, "%s,%s,>>>>,%s,=", ARG(2), ARG(1), ARG(0));
- }
- // assigns
- else if (!strcmp(name, "mv")) {
- esilprintf(op, "%s,%s,=", ARG(1), ARG(0));
- } else if (!strcmp(name, "li")) {
- esilprintf(op, "%s,%s,=", ARG(1), ARG(0));
- } else if (!strcmp(name, "lui")) {
- esilprintf(op, "%s000,%s,=", ARG(1), ARG(0));
- if (analysis->bits == 64) {
- rz_strbuf_appendf(&op->esil, ",32,%s,~=", ARG(0));
- }
- }
- // csr instrs
- // rd, rs1, CSR
- else if (!strncmp(name, "csrrw", 5)) {
- // Writes rs1 into CSR, places the old value in rd
- esilprintf(op, "%s,0,+,%s,%s,=,%s,=", ARG(1), ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "csrrs", 5)) {
- // Ors rs1 with CSR, places old value in rd
- esilprintf(op, "%s,0,+,%s,%s,|=,%s,=", ARG(1), ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "csrrc", 5)) {
- // Ands the inverse of rs1 with CSR, places old value in rd
- esilprintf(op, "%s,0,+,%s,1,+,0,-,%s,&=,%s,=", ARG(1), ARG(1), ARG(2), ARG(0));
- }
- // stores
- else if (!strcmp(name, "sd") || !strcmp(name, "sdsp")) {
- esilprintf(op, "%s,%s,%s,+,=[8]", ARG(0), ARG(2), ARG(1));
- } else if (!strcmp(name, "sw") || !strcmp(name, "swsp")) {
- esilprintf(op, "%s,%s,%s,+,=[4]", ARG(0), ARG(2), ARG(1));
- } else if (!strcmp(name, "sh") || !strcmp(name, "shsp")) {
- esilprintf(op, "%s,%s,%s,+,=[2]", ARG(0), ARG(2), ARG(1));
- } else if (!strcmp(name, "sb") || !strcmp(name, "sbsp")) {
- esilprintf(op, "%s,%s,%s,+,=[1]", ARG(0), ARG(2), ARG(1));
- } else if (!strcmp(name, "fsq") || !strcmp(name, "fsqsp")) {
- esilprintf(op, "%s,%s,+,[16],%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strcmp(name, "fsd") || !strcmp(name, "fsdsp")) {
- esilprintf(op, "%s,%s,%s,+,=[8]", ARG(0), ARG(2), ARG(1));
- } else if (!strcmp(name, "fsw") || !strcmp(name, "fswsp")) {
- esilprintf(op, "%s,%s,%s,+,=[4]", ARG(0), ARG(2), ARG(1));
- } else if (!strcmp(name, "fsh") || !strcmp(name, "fshsp")) {
- esilprintf(op, "%s,%s,%s,+,=[2]", ARG(0), ARG(2), ARG(1));
- } else if (!strcmp(name, "fsb") || !strcmp(name, "fsbsp")) {
- esilprintf(op, "%s,%s,%s,+,=[1]", ARG(0), ARG(2), ARG(1));
- }
- // loads
- else if (!strcmp(name, "ld") || !strcmp(name, "ldsp")) {
- esilprintf(op, "%s,%s,+,[8],%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strcmp(name, "lw") || !strcmp(name, "lwu") || !strcmp(name, "lwsp")) {
- esilprintf(op, "%s,%s,+,[4],%s,=", ARG(2), ARG(1), ARG(0));
- if ((analysis->bits == 64) && strcmp(name, "lwu")) {
- rz_strbuf_appendf(&op->esil, ",32,%s,~=", ARG(0));
- }
- } else if (!strcmp(name, "lh") || !strcmp(name, "lhu") || !strcmp(name, "lhsp")) {
- esilprintf(op, "%s,%s,+,[2],%s,=", ARG(2), ARG(1), ARG(0));
- if (strcmp(name, "lwu")) {
- rz_strbuf_appendf(&op->esil, ",16,%s,~=", ARG(0));
- }
- } else if (!strcmp(name, "lb") || !strcmp(name, "lbu") || !strcmp(name, "lbsp")) {
- esilprintf(op, "%s,%s,+,[1],%s,=", ARG(2), ARG(1), ARG(0));
- if (strcmp(name, "lbu")) {
- rz_strbuf_appendf(&op->esil, ",8,%s,~=", ARG(0));
- }
- } else if (!strcmp(name, "flq") || !strcmp(name, "flqsp")) {
- esilprintf(op, "%s,%s,+,[16],%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strcmp(name, "fld") || !strcmp(name, "fldsp")) {
- esilprintf(op, "%s,%s,+,[8],%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strcmp(name, "flw") || !strcmp(name, "flwsp")) {
- esilprintf(op, "%s,%s,+,[4],%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strcmp(name, "flh") || !strcmp(name, "flhsp")) {
- esilprintf(op, "%s,%s,+,[2],%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strcmp(name, "flb") || !strcmp(name, "flbsp")) {
- esilprintf(op, "%s,%s,+,[1],%s,=", ARG(2), ARG(1), ARG(0));
- }
- // jumps
- else if (!strcmp(name, "jalr")) {
- if (strcmp(ARG(0), "0")) {
- esilprintf(op, "%s,%s,+,pc,=,%d,$$,+,%s,=", ARG(2), ARG(1), op->size, ARG(0));
- } else {
- esilprintf(op, "%s,%s,+,pc,=", ARG(2), ARG(1));
- }
- } else if (!strcmp(name, "jal")) {
- if (strcmp(ARG(0), "0")) {
- if (args.num == 1) {
- esilprintf(op, "%d,$$,+,ra,=,%s,pc,=", op->size, ARG(0));
- } else {
- esilprintf(op, "%d,$$,+,%s,=,%s,pc,=", op->size, ARG(0), ARG(1));
- }
- } else {
- esilprintf(op, "%s,pc,=", ARG(1));
- }
- } else if (!strcmp(name, "jr") || !strcmp(name, "j")) {
- esilprintf(op, "%s,pc,=", ARG(0));
- } else if (!strcmp(name, "ecall") || !strcmp(name, "ebreak")) {
- esilprintf(op, "TRAP");
- }
- // Branches & cmps
- else if (!strcmp(name, "beq")) {
- esilprintf(op, "%s,%s,==,$z,?{,%s,pc,=,},", ARG(1), ARG(0), ARG(2));
- } else if (!strcmp(name, "bne")) {
- esilprintf(op, "%s,%s,==,$z,!,?{,%s,pc,=,},", ARG(1), ARG(0), ARG(2));
- } else if (!strcmp(name, "ble") || !strcmp(name, "bleu")) {
- esilprintf(op, "%s,%s,<=,?{,%s,pc,=,},", ARG(1), ARG(0), ARG(2));
- } else if (!strcmp(name, "blt") || !strcmp(name, "bltu")) {
- esilprintf(op, "%s,%s,<,?{,%s,pc,=,},", ARG(1), ARG(0), ARG(2));
- } else if (!strcmp(name, "bge") || !strcmp(name, "bgeu")) {
- esilprintf(op, "%s,%s,>=,?{,%s,pc,=,},", ARG(1), ARG(0), ARG(2));
- } else if (!strcmp(name, "bgt") || !strcmp(name, "bgtu")) {
- esilprintf(op, "%s,%s,>,?{,%s,pc,=,},", ARG(1), ARG(0), ARG(2));
- } else if (!strcmp(name, "beqz")) {
- esilprintf(op, "%s,0,==,$z,?{,%s,pc,=,},", ARG(0), ARG(1));
- } else if (!strcmp(name, "bnez")) {
- esilprintf(op, "%s,0,==,$z,!,?{,%s,pc,=,},", ARG(0), ARG(1));
- } else if (!strcmp(name, "blez")) {
- esilprintf(op, "%s,0,<=,?{,%s,pc,=,},", ARG(0), ARG(1));
- } else if (!strcmp(name, "bltz")) {
- esilprintf(op, "%s,0,<,?{,%s,pc,=,},", ARG(0), ARG(1));
- } else if (!strcmp(name, "bgez")) {
- esilprintf(op, "%s,0,>=,?{,%s,pc,=,},", ARG(0), ARG(1));
- } else if (!strcmp(name, "bgtz")) {
- esilprintf(op, "%s,0,>,?{,%s,pc,=,},", ARG(0), ARG(1));
- } else if (!strncmp(name, "seq", 3)) {
- esilprintf(op, "%s,%s,==,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "sne", 3)) {
- esilprintf(op, "%s,%s,!=,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "sle", 3)) {
- esilprintf(op, "%s,%s,<=,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "slt", 3)) {
- esilprintf(op, "%s,%s,<,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "sge", 3)) {
- esilprintf(op, "%s,%s,>=,%s,=", ARG(2), ARG(1), ARG(0));
- } else if (!strncmp(name, "sgt", 3)) {
- esilprintf(op, "%s,%s,>,%s,=", ARG(2), ARG(1), ARG(0));
- }
-#undef ARG
- }
-
- // branch/jumps/calls/rets
- if (is_any("jal")) {
- // decide whether it's jump or call
- int rd = (word >> OP_SH_RD) & OP_MASK_RD;
- op->type = (rd == 0) ? RZ_ANALYSIS_OP_TYPE_JMP : RZ_ANALYSIS_OP_TYPE_CALL;
- op->jump = EXTRACT_UJTYPE_IMM(word) + addr;
- op->fail = addr + op->size;
- } else if (is_any("c.jal")) {
- op->type = RZ_ANALYSIS_OP_TYPE_CALL;
- op->jump = EXTRACT_RVC_IMM(word) + addr;
- op->fail = addr + op->size;
- } else if (is_any("jr")) {
- op->type = RZ_ANALYSIS_OP_TYPE_JMP;
- } else if (is_any("c.j", "jump")) {
- op->type = RZ_ANALYSIS_OP_TYPE_JMP;
- op->jump = EXTRACT_RVC_J_IMM(word) + addr;
- } else if (is_any("jalr")) {
- // decide whether it's ret or call
- int rd = (word >> OP_SH_RD) & OP_MASK_RD;
- op->type = (rd == 0) ? RZ_ANALYSIS_OP_TYPE_RET : RZ_ANALYSIS_OP_TYPE_UCALL;
- if (rd != 0) {
- op->val = EXTRACT_ITYPE_IMM(word);
- }
- } else if (is_any("c.ret")) {
- op->type = RZ_ANALYSIS_OP_TYPE_RET;
- } else if (is_any("c.jalr")) {
- op->type = RZ_ANALYSIS_OP_TYPE_UCALL;
- } else if (is_any("c.jr")) {
- op->type = RZ_ANALYSIS_OP_TYPE_RET;
- } else if (is_any("beqz", "beq", "blez", "bgez", "ble",
- "bleu", "bge", "bgeu", "bltz", "bgtz", "blt", "bltu",
- "bgt", "bgtu", "bnez", "bne")) {
- op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
- op->jump = EXTRACT_SBTYPE_IMM(word) + addr;
- op->fail = addr + op->size;
- } else if (is_any("c.beqz", "c.bnez")) {
- op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
- op->jump = EXTRACT_RVC_B_IMM(word) + addr;
- op->fail = addr + op->size;
- // math
- } else if (is_any("c.addi", "c.addiw")) {
- op->type = RZ_ANALYSIS_OP_TYPE_ADD;
- op->val = EXTRACT_RVC_IMM(word);
- } else if (is_any("addi", "addiw")) {
- op->type = RZ_ANALYSIS_OP_TYPE_ADD;
- op->val = EXTRACT_ITYPE_IMM(word);
- } else if (is_any("c.addi4spn")) {
- op->type = RZ_ANALYSIS_OP_TYPE_ADD;
- op->val = EXTRACT_RVC_ADDI4SPN_IMM(word);
- } else if (is_any("c.addi16sp")) {
- op->type = RZ_ANALYSIS_OP_TYPE_ADD;
- op->val = EXTRACT_RVC_ADDI16SP_IMM(word);
- } else if (is_any("addw", "add", "c.addw", "c.add")) {
- op->type = RZ_ANALYSIS_OP_TYPE_ADD;
- } else if (is_any("auipc")) {
- op->type = RZ_ANALYSIS_OP_TYPE_ADD;
- op->val = EXTRACT_UTYPE_IMM(word);
- } else if (is_any("c.mv", "csrrw", "csrrc", "csrrs")) {
- op->type = RZ_ANALYSIS_OP_TYPE_MOV;
- } else if (is_any("subi", "subw", "sub", "c.sub", "c.subw")) {
- op->type = RZ_ANALYSIS_OP_TYPE_SUB;
- } else if (is_any("xori", "xor", "c.xor")) {
- op->type = RZ_ANALYSIS_OP_TYPE_XOR;
- } else if (is_any("andi", "and", "c.andi", "c.and")) {
- op->type = RZ_ANALYSIS_OP_TYPE_AND;
- } else if (is_any("ori", "or", "c.or")) {
- op->type = RZ_ANALYSIS_OP_TYPE_OR;
- } else if (is_any("not")) {
- op->type = RZ_ANALYSIS_OP_TYPE_NOT;
- } else if (is_any("c.nop")) {
- op->type = RZ_ANALYSIS_OP_TYPE_NOP;
- } else if (is_any("mul", "mulh", "mulhu", "mulhsu", "mulw")) {
- op->type = RZ_ANALYSIS_OP_TYPE_MUL;
- } else if (is_any("div", "divu", "divw", "divuw")) {
- op->type = RZ_ANALYSIS_OP_TYPE_DIV;
- } else if (is_any("sll", "slli", "sllw", "slliw", "c.slli")) {
- op->type = RZ_ANALYSIS_OP_TYPE_SHL;
- } else if (is_any("srl", "srlw", "srliw", "c.srli")) {
- op->type = RZ_ANALYSIS_OP_TYPE_SHR;
- } else if (is_any("sra", "srai", "sraiw", "c.srai")) {
- op->type = RZ_ANALYSIS_OP_TYPE_SAR;
- // memory
- } else if (is_any("sd", "sb", "sh", "sw", "c.sd", "c.sw",
- "c.swsp", "c.sdsp")) {
- op->type = RZ_ANALYSIS_OP_TYPE_STORE;
- } else if (is_any("ld", "lw", "lwu", "lb", "lbu", "lh",
- "lhu", "la", "lla", "c.ld", "c.lw", "c.lwsp")) {
- op->type = RZ_ANALYSIS_OP_TYPE_LOAD;
- } else if (is_any("lui")) {
- op->type = RZ_ANALYSIS_OP_TYPE_MOV;
- op->val = EXTRACT_UTYPE_IMM(word);
- } else if (is_any("c.lui")) {
- op->type = RZ_ANALYSIS_OP_TYPE_MOV;
- op->val = EXTRACT_RVC_IMM(word);
- } else if (is_any("li")) {
- op->type = RZ_ANALYSIS_OP_TYPE_MOV;
- op->val = EXTRACT_ITYPE_IMM(word);
- } else if (is_any("c.li")) {
- op->type = RZ_ANALYSIS_OP_TYPE_MOV;
- op->val = EXTRACT_RVC_IMM(word);
- }
- if (mask & RZ_ANALYSIS_OP_MASK_VAL && args.num) {
- op->dst = RZ_NEW0(RzAnalysisValue);
- char *argf = rz_str_dup(o->args);
- const char *comma = NULL;
- int dst_idx = 0, src_idx;
- if (op->type == RZ_ANALYSIS_OP_TYPE_STORE) {
- comma = rz_str_rchr(argf, argf + strlen(argf), ',');
- if (comma) {
- *(char *)comma++ = 0;
- if (strchr(comma, '(')) {
- dst_idx = args.num = args.num - 2;
- } else {
- dst_idx = args.num = args.num - 1;
- }
- }
- } else {
- comma = strtok(argf, ",");
- dst_idx = 0;
- }
- if (comma && strchr(comma, '(')) {
- op->dst->type = RZ_ANALYSIS_VAL_MEM;
- op->dst->delta = (st64)rz_num_get(NULL, args.arg[dst_idx++]);
- op->dst->reg = rz_reg_get(analysis->reg, args.arg[dst_idx], -1);
- src_idx = op->type == RZ_ANALYSIS_OP_TYPE_STORE ? 0 : 2;
- } else if (isdigit(args.arg[dst_idx][0])) {
- op->dst->type = RZ_ANALYSIS_VAL_IMM;
- op->dst->imm = rz_num_get(NULL, args.arg[dst_idx]);
- src_idx = op->type == RZ_ANALYSIS_OP_TYPE_STORE ? 0 : 1;
- } else {
- op->dst->type = RZ_ANALYSIS_VAL_REG;
- op->dst->reg = rz_reg_get(analysis->reg, args.arg[dst_idx], -1);
- src_idx = op->type == RZ_ANALYSIS_OP_TYPE_STORE ? 0 : 1;
- }
-
- comma = op->type == RZ_ANALYSIS_OP_TYPE_STORE
- ? strtok(argf, ",")
- : strtok(NULL, ",");
- int i;
- for (i = 0; src_idx < args.num; i++, src_idx++) {
- op->src[i] = RZ_NEW0(RzAnalysisValue);
- if (comma && strchr(comma, '(')) {
- op->src[i]->type = RZ_ANALYSIS_VAL_MEM;
- op->src[i]->delta = (st64)rz_num_get(NULL, args.arg[src_idx]);
- op->src[i]->reg = rz_reg_get(analysis->reg, args.arg[src_idx + 1], -1);
- src_idx++;
- } else if (isalpha(args.arg[src_idx][0])) {
- op->src[i]->type = RZ_ANALYSIS_VAL_REG;
- op->src[i]->reg = rz_reg_get(analysis->reg, args.arg[src_idx], -1);
- } else {
- op->src[i]->type = RZ_ANALYSIS_VAL_IMM;
- op->src[i]->imm = rz_num_get(NULL, args.arg[src_idx]);
- }
- comma = strtok(NULL, ",");
- }
- free(argf);
- }
- return op->size;
-}
-
-static char *get_reg_profile(RzAnalysis *analysis) {
- const char *p = NULL;
- switch (analysis->bits) {
- case 32:
- p =
- "=PC pc\n"
- "=A0 a0\n"
- "=A1 a1\n"
- "=A2 a2\n"
- "=A3 a3\n"
- "=A4 a4\n"
- "=A5 a5\n"
- "=A6 a6\n"
- "=A7 a7\n"
- "=R0 a0\n"
- "=R1 a1\n"
- "=SP sp\n" // ABI: stack pointer
- "=LR ra\n" // ABI: return address
- "=BP s0\n" // ABI: frame pointer
- "=SN a7\n" // ABI: syscall numer
- "gpr pc .32 0 0\n"
- // RV32I regs (ABI names)
- // From user-Level ISA Specification, section 2.1
- // "zero" has been left out as it ignores writes and always reads as zero
- "gpr ra .32 4 0\n" // =x1
- "gpr sp .32 8 0\n" // =x2
- "gpr gp .32 12 0\n" // =x3
- "gpr tp .32 16 0\n" // =x4
- "gpr t0 .32 20 0\n" // =x5
- "gpr t1 .32 24 0\n" // =x6
- "gpr t2 .32 28 0\n" // =x7
- "gpr s0 .32 32 0\n" // =x8
- "gpr s1 .32 36 0\n" // =x9
- "gpr a0 .32 40 0\n" // =x10
- "gpr a1 .32 44 0\n" // =x11
- "gpr a2 .32 48 0\n" // =x12
- "gpr a3 .32 52 0\n" // =x13
- "gpr a4 .32 56 0\n" // =x14
- "gpr a5 .32 60 0\n" // =x15
- "gpr a6 .32 64 0\n" // =x16
- "gpr a7 .32 68 0\n" // =x17
- "gpr s2 .32 72 0\n" // =x18
- "gpr s3 .32 76 0\n" // =x19
- "gpr s4 .32 80 0\n" // =x20
- "gpr s5 .32 84 0\n" // =x21
- "gpr s6 .32 88 0\n" // =x22
- "gpr s7 .32 92 0\n" // =x23
- "gpr s8 .32 96 0\n" // =x24
- "gpr s9 .32 100 0\n" // =x25
- "gpr s10 .32 104 0\n" // =x26
- "gpr s11 .32 108 0\n" // =x27
- "gpr t3 .32 112 0\n" // =x28
- "gpr t4 .32 116 0\n" // =x29
- "gpr t5 .32 120 0\n" // =x30
- "gpr t6 .32 124 0\n" // =x31
- // RV32F/D regs (ABI names)
- // From user-Level ISA Specification, section 8.1 and 9.1
- "fpu ft0 .64 128 0\n" // =f0
- "fpu ft1 .64 136 0\n" // =f1
- "fpu ft2 .64 144 0\n" // =f2
- "fpu ft3 .64 152 0\n" // =f3
- "fpu ft4 .64 160 0\n" // =f4
- "fpu ft5 .64 168 0\n" // =f5
- "fpu ft6 .64 176 0\n" // =f6
- "fpu ft7 .64 184 0\n" // =f7
- "fpu fs0 .64 192 0\n" // =f8
- "fpu fs1 .64 200 0\n" // =f9
- "fpu fa0 .64 208 0\n" // =f10
- "fpu fa1 .64 216 0\n" // =f11
- "fpu fa2 .64 224 0\n" // =f12
- "fpu fa3 .64 232 0\n" // =f13
- "fpu fa4 .64 240 0\n" // =f14
- "fpu fa5 .64 248 0\n" // =f15
- "fpu fa6 .64 256 0\n" // =f16
- "fpu fa7 .64 264 0\n" // =f17
- "fpu fs2 .64 272 0\n" // =f18
- "fpu fs3 .64 280 0\n" // =f19
- "fpu fs4 .64 288 0\n" // =f20
- "fpu fs5 .64 296 0\n" // =f21
- "fpu fs6 .64 304 0\n" // =f22
- "fpu fs7 .64 312 0\n" // =f23
- "fpu fs8 .64 320 0\n" // =f24
- "fpu fs9 .64 328 0\n" // =f25
- "fpu fs10 .64 336 0\n" // =f26
- "fpu fs11 .64 344 0\n" // =f27
- "fpu ft8 .64 352 0\n" // =f28
- "fpu ft9 .64 360 0\n" // =f29
- "fpu ft10 .64 368 0\n" // =f30
- "fpu ft11 .64 376 0\n" // =f31
- "fpu fcsr .32 384 0\n"
- "flg nx .1 3072 0\n"
- "flg uf .1 3073 0\n"
- "flg of .1 3074 0\n"
- "flg dz .1 3075 0\n"
- "flg nv .1 3076 0\n"
- "flg frm .3 3077 0\n";
-
- break;
- case 64:
- p =
- "=PC pc\n"
- "=SP sp\n" // ABI: stack pointer
- "=LR ra\n" // ABI: return address
- "=BP s0\n" // ABI: frame pointer
- "=A0 a0\n"
- "=A1 a1\n"
- "=A2 a2\n"
- "=A3 a3\n"
- "=A4 a4\n"
- "=A5 a5\n"
- "=A6 a6\n"
- "=A7 a7\n"
- "=R0 a0\n"
- "=R1 a1\n"
- "=SN a7\n" // ABI: syscall numer
- "gpr pc .64 0 0\n"
- // RV64I regs (ABI names)
- // From user-Level ISA Specification, section 2.1 and 4.1
- // "zero" has been left out as it ignores writes and always reads as zero
- "gpr ra .64 8 0\n" // =x1
- "gpr sp .64 16 0\n" // =x2
- "gpr gp .64 24 0\n" // =x3
- "gpr tp .64 32 0\n" // =x4
- "gpr t0 .64 40 0\n" // =x5
- "gpr t1 .64 48 0\n" // =x6
- "gpr t2 .64 56 0\n" // =x7
- "gpr s0 .64 64 0\n" // =x8
- "gpr s1 .64 72 0\n" // =x9
- "gpr a0 .64 80 0\n" // =x10
- "gpr a1 .64 88 0\n" // =x11
- "gpr a2 .64 96 0\n" // =x12
- "gpr a3 .64 104 0\n" // =x13
- "gpr a4 .64 112 0\n" // =x14
- "gpr a5 .64 120 0\n" // =x15
- "gpr a6 .64 128 0\n" // =x16
- "gpr a7 .64 136 0\n" // =x17
- "gpr s2 .64 144 0\n" // =x18
- "gpr s3 .64 152 0\n" // =x19
- "gpr s4 .64 160 0\n" // =x20
- "gpr s5 .64 168 0\n" // =x21
- "gpr s6 .64 176 0\n" // =x22
- "gpr s7 .64 184 0\n" // =x23
- "gpr s8 .64 192 0\n" // =x24
- "gpr s9 .64 200 0\n" // =x25
- "gpr s10 .64 208 0\n" // =x26
- "gpr s11 .64 216 0\n" // =x27
- "gpr t3 .64 224 0\n" // =x28
- "gpr t4 .64 232 0\n" // =x29
- "gpr t5 .64 240 0\n" // =x30
- "gpr t6 .64 248 0\n" // =x31
- // RV64F/D regs (ABI names)
- "fpu ft0 .64 256 0\n" // =f0
- "fpu ft1 .64 264 0\n" // =f1
- "fpu ft2 .64 272 0\n" // =f2
- "fpu ft3 .64 280 0\n" // =f3
- "fpu ft4 .64 288 0\n" // =f4
- "fpu ft5 .64 296 0\n" // =f5
- "fpu ft6 .64 304 0\n" // =f6
- "fpu ft7 .64 312 0\n" // =f7
- "fpu fs0 .64 320 0\n" // =f8
- "fpu fs1 .64 328 0\n" // =f9
- "fpu fa0 .64 336 0\n" // =f10
- "fpu fa1 .64 344 0\n" // =f11
- "fpu fa2 .64 352 0\n" // =f12
- "fpu fa3 .64 360 0\n" // =f13
- "fpu fa4 .64 368 0\n" // =f14
- "fpu fa5 .64 376 0\n" // =f15
- "fpu fa6 .64 384 0\n" // =f16
- "fpu fa7 .64 392 0\n" // =f17
- "fpu fs2 .64 400 0\n" // =f18
- "fpu fs3 .64 408 0\n" // =f19
- "fpu fs4 .64 416 0\n" // =f20
- "fpu fs5 .64 424 0\n" // =f21
- "fpu fs6 .64 432 0\n" // =f22
- "fpu fs7 .64 440 0\n" // =f23
- "fpu fs8 .64 448 0\n" // =f24
- "fpu fs9 .64 456 0\n" // =f25
- "fpu fs10 .64 464 0\n" // =f26
- "fpu fs11 .64 472 0\n" // =f27
- "fpu ft8 .64 480 0\n" // =f28
- "fpu ft9 .64 488 0\n" // =f29
- "fpu ft10 .64 496 0\n" // =f30
- "fpu ft11 .64 504 0\n" // =f31
- "fpu fcsr .32 512 0\n"
- "flg nx .1 4096 0\n"
- "flg uf .1 4097 0\n"
- "flg of .1 4098 0\n"
- "flg dz .1 4099 0\n"
- "flg nv .1 4100 0\n"
- "flg frm .3 4101 0\n";
-
- break;
- }
- return rz_str_dup(p);
-}
-
-static int archinfo(RzAnalysis *a, RzAnalysisInfoType query) {
- bool is_64_bits = a && a->bits == 64;
-
- switch (query) {
- case RZ_ANALYSIS_ARCHINFO_MIN_OP_SIZE:
- return is_64_bits ? 4 : 2;
- case RZ_ANALYSIS_ARCHINFO_MAX_OP_SIZE:
- return 6;
- case RZ_ANALYSIS_ARCHINFO_TEXT_ALIGN:
- /* fall-thru */
- case RZ_ANALYSIS_ARCHINFO_DATA_ALIGN:
- return 2;
- case RZ_ANALYSIS_ARCHINFO_CAN_USE_POINTERS:
- return true;
- default:
- return -1;
- }
-}
-
-RzAnalysisPlugin rz_analysis_plugin_riscv_gnu = {
- .name = "riscv",
- .desc = "RISC-V analysis plugin",
- .license = "LGPL",
- .arch = "riscv",
- .bits = 32 | 64,
- .archinfo = archinfo,
- .op = &riscv_op,
- .get_reg_profile = &get_reg_profile,
- .esil = true,
-};
diff --git a/librz/arch/p_gnu/arch_riscv.c b/librz/arch/p_gnu/arch_riscv.c
deleted file mode 100644
index 8e464619ea3..00000000000
--- a/librz/arch/p_gnu/arch_riscv.c
+++ /dev/null
@@ -1,15 +0,0 @@
-// SPDX-FileCopyrightText: 2024 RizinOrg
-// SPDX-FileCopyrightText: 2024 deroad
-// SPDX-License-Identifier: LGPL-3.0-only
-
-#include
-
-#include "../isa_gnu/riscv/riscv-opc.c"
-#include
-#include "../isa_gnu/riscv/riscv.c"
-
-#include "analysis/analysis_riscv_gnu.c"
-#include "asm/asm_riscv_gnu.c"
-#include "parse/parse_riscv_gnu.c"
-
-RZ_ARCH_WITH_PARSE_PLUGIN_DEFINE_DEPRECATED(riscv_gnu);
diff --git a/librz/arch/p_gnu/asm/asm_riscv_gnu.c b/librz/arch/p_gnu/asm/asm_riscv_gnu.c
deleted file mode 100644
index 130f8cd90a7..00000000000
--- a/librz/arch/p_gnu/asm/asm_riscv_gnu.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-FileCopyrightText: 2015-2021 qnix
-// SPDX-License-Identifier: LGPL-3.0-only
-
-#include
-#include
-#include
-#include
-
-static int riscv_gnu_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) {
- return op->size = riscv_dis(a, op, buf, len);
-}
-
-RzAsmPlugin rz_asm_plugin_riscv_gnu = {
- .name = "riscv",
- .desc = "RISC-V disassembler",
- .arch = "riscv",
- .bits = 32 | 64,
- .endian = RZ_SYS_ENDIAN_LITTLE | RZ_SYS_ENDIAN_BIG,
- .license = "GPL3",
- .disassemble = &riscv_gnu_disassemble,
-};
diff --git a/librz/arch/p_gnu/parse/parse_riscv_gnu.c b/librz/arch/p_gnu/parse/parse_riscv_gnu.c
deleted file mode 100644
index 9933ecc4154..00000000000
--- a/librz/arch/p_gnu/parse/parse_riscv_gnu.c
+++ /dev/null
@@ -1,226 +0,0 @@
-// SPDX-FileCopyrightText: 2020 Aswin C (officialcjunior)
-// SPDX-License-Identifier: LGPL-3.0-only
-
-#include
-#include
-#include
-#include
-
-static int replace(int argc, const char *argv[], char *newstr) {
-#define MAXPSEUDOOPS 10
- int i, j, k, d;
- char ch;
- struct {
- int narg;
- char *op;
- char *str;
- int args[MAXPSEUDOOPS];
- } ops[] = {
- { 0, "add", "# = # + #", { 1, 2, 3 } },
- { 0, "addi", "# = # + #", { 1, 2, 3 } },
- { 0, "and", "# = # & #", { 1, 2, 3 } },
- { 0, "andi", "# = # & #", { 1, 2, 3 } },
- { 0, "beq", "if (# == #) goto #", { 1, 2, 3 } },
- { 0, "bleu", "if (unsigned)# <= # goto #", { 1, 2, 3 } },
- { 0, "bltu", "if (unsigned)# < # goto #", { 1, 2, 3 } },
- { 0, "blt", "if (# < #) goto #", { 1, 2, 3 } },
- { 0, "beqz", "if (# == 0) goto #", { 1, 2 } },
- { 0, "bne", "if (# != #) goto #", { 1, 2, 3 } },
- { 0, "bnez", "if (# != 0) goto #", { 1, 2 } },
- { 0, "bgez", "if (# >= 0) goto #", { 1, 2 } },
- { 0, "bgtz", "if (# > 0) goto #", { 1, 2 } },
- { 0, "fld", "# = #", { 1, 2 } },
- { 0, "j", "jmp #", { 1 } },
- { 0, "jr", "jmp #", { 1 } },
- { 0, "jalr", "jmp #", { 1 } },
- { 0, "jal", "jmp #", { 1 } },
- { 0, "ld", "# = (double)[#]", { 1, 2 } },
- { 0, "li", "# = #", { 1, 2 } },
- { 0, "lh", "# = [#]", { 1, 2 } },
- { 0, "lui", "# = #", { 1, 2 } },
- { 0, "lbu", "# = (unsigned)[#]", { 1, 2 } },
- { 0, "lhu", "# = (unsigned)[#]", { 1, 2 } },
- { 0, "lw", "# = [#]", { 1, 2 } },
- { 0, "mv", "# = #", { 1, 2 } },
- { 0, "or", "# = # | #", { 1, 2, 3 } },
- { 0, "sd", "[#] = (double)#", { 2, 1 } },
- { 0, "sw", "[#] = #", { 2, 1 } },
- { 0, "sb", "[#] = #", { 2, 1 } },
- { 0, "sh", "[#] = #", { 2, 1 } },
- { 0, "sub", "# = # - #", { 1, 2, 3 } },
- { 0, NULL }
- };
- if (!newstr) {
- return false;
- }
-
- for (i = 0; ops[i].op; i++) {
- if (ops[i].narg) {
- if (argc - 1 != ops[i].narg) {
- continue;
- }
- }
- if (!strcmp(ops[i].op, argv[0])) {
- if (newstr) {
- d = 0;
- j = 0;
- ch = ops[i].str[j];
- for (j = 0, k = 0; ch != '\0'; j++, k++) {
- ch = ops[i].str[j];
- if (ch == '#') {
- if (d >= MAXPSEUDOOPS) {
- // XXX Shouldn't ever happen...
- continue;
- }
- int idx = ops[i].args[d];
- d++;
- if (idx <= 0) {
- // XXX Shouldn't ever happen...
- continue;
- }
- const char *w = argv[idx];
- if (w) {
- strcpy(newstr + k, w);
- k += strlen(w) - 1;
- }
- } else {
- newstr[k] = ch;
- }
- }
- newstr[k] = '\0';
- }
- rz_str_replace_char(newstr, '{', '(');
- rz_str_replace_char(newstr, '}', ')');
- return true;
- }
- }
-
- /* TODO: this is slow */
- newstr[0] = '\0';
- for (i = 0; i < argc; i++) {
- strcat(newstr, argv[i]);
- strcat(newstr, (!i || i == argc - 1) ? " " : ",");
- }
-
- rz_str_replace_char(newstr, '{', '(');
- rz_str_replace_char(newstr, '}', ')');
- return false;
-}
-
-static bool parse(RzParse *p, const char *data, RzStrBuf *sb) {
- char w0[256], w1[256], w2[256], w3[256];
- char str[1024] = { 0 };
- int i, len = strlen(data), n;
- char *buf, *ptr, *optr, *num;
-
- if (len >= sizeof(w0)) {
- return false;
- }
- // malloc can be slow here :?
- if (!(buf = malloc(len + 1))) {
- return false;
- }
- memcpy(buf, data, len + 1);
- if (*buf) {
- *w0 = *w1 = *w2 = *w3 = '\0';
- ptr = strchr(buf, ' ');
- if (!ptr) {
- ptr = strchr(buf, '\t');
- }
- if (ptr) {
- *ptr = '\0';
- for (++ptr; *ptr == ' '; ptr++) {
- ;
- }
- strncpy(w0, buf, sizeof(w0) - 1);
- strncpy(w1, ptr, sizeof(w1) - 1);
-
- optr = ptr;
- if (*ptr == '(') {
- ptr = strchr(ptr + 1, ')');
- }
- if (ptr && *ptr == '[') {
- ptr = strchr(ptr + 1, ']');
- }
- if (ptr && *ptr == '{') {
- ptr = strchr(ptr + 1, '}');
- }
- if (!ptr) {
- eprintf("Unbalanced bracket\n");
- free(buf);
- return false;
- }
- ptr = strchr(ptr, ',');
- if (ptr) {
- *ptr = '\0';
- for (++ptr; *ptr == ' '; ptr++) {
- ;
- }
- strncpy(w1, optr, sizeof(w1) - 1);
- strncpy(w2, ptr, sizeof(w2) - 1);
- optr = ptr;
- ptr = strchr(ptr, ',');
- if (ptr) {
- *ptr = '\0';
- for (++ptr; *ptr == ' '; ptr++) {
- ;
- }
- strncpy(w2, optr, sizeof(w2) - 1);
- strncpy(w3, ptr, sizeof(w3) - 1);
- }
- }
- ptr = strchr(buf, '(');
- if (ptr) {
- *ptr = 0;
- num = (char *)rz_str_lchr(buf, ' ');
- if (!num) {
- num = (char *)rz_str_lchr(buf, ',');
- }
- if (num) {
- n = atoi(num + 1);
- *ptr = '[';
- rz_str_cpy(num + 1, ptr);
- ptr = (char *)rz_str_lchr(buf, ']');
- if (n && ptr) {
- char *rest = rz_str_dup(ptr + 1);
- size_t dist = len + 1 - (ptr - buf);
- if (n > 0) {
- snprintf(ptr, dist, "+%d]%s", n, rest);
- } else {
- snprintf(ptr, dist, "%d]%s", n, rest);
- }
- free(rest);
- }
- } else {
- *ptr = '[';
- }
- }
- }
- {
- const char *wa[] = { w0, w1, w2, w3 };
- int nw = 0;
- for (i = 0; i < 4; i++) {
- if (wa[i][0]) {
- nw++;
- }
- }
- replace(nw, wa, str);
- }
- }
- {
- char *s = rz_str_dup(str);
- s = rz_str_replace(s, "+ -", "- ", 1);
- s = rz_str_replace(s, "- -", "+ ", 1);
- rz_strf(str, "%s", s);
- free(s);
- }
- free(buf);
- rz_strbuf_set(sb, str);
- return true;
-}
-
-RzParsePlugin rz_parse_plugin_riscv_gnu_pseudo = {
- .name = "riscv.pseudo",
- .desc = "riscv pseudo syntax",
- .parse = parse,
-};
diff --git a/librz/bin/format/elf/elf_info.c b/librz/bin/format/elf/elf_info.c
index 72f21ec00b5..55cb9f41026 100644
--- a/librz/bin/format/elf/elf_info.c
+++ b/librz/bin/format/elf/elf_info.c
@@ -6,6 +6,12 @@
#include "elf.h"
#include "elf/glibc_elf.h"
+#include "rz_bin.h"
+#include "rz_bp.h"
+#include "rz_util/rz_buf.h"
+#include "rz_util/rz_log.h"
+#include "rz_util/rz_str.h"
+#include "rz_util/rz_strbuf.h"
#define VERSYM_VERSION 0x7fff
@@ -733,6 +739,142 @@ static inline bool is_elf_class32(ELFOBJ *bin) {
return bin->ehdr.e_ident[EI_CLASS] == ELFCLASS32;
}
+static RzBuffer *get_riscv_attributes_section(ELFOBJ *bin) {
+ RzBinElfSection *section = Elf_(rz_bin_elf_get_section_with_name)(bin, ".riscv.attributes");
+ if (!section || section->type != SHT_RISCV_ATTRIBUTES /* shouldn't really be possible */) {
+ return NULL;
+ }
+ return rz_buf_new_slice(bin->b, section->offset, section->size);
+}
+
+/// All possible results of getting a riscv attribute of a given tag
+typedef enum {
+ RISCV_ATTR_NONE = 0, //< no attribute was found with the given tag or parsing error of the section format
+ RISCV_ATTR_TRUNCATED_NT_STRING = 1, //< attribute of type null-terminated string, too long to fit into result buffer
+ RISCV_ATTR_NT_STRING = 2, //< attribute of type null-terminated string
+ RISCV_ATTR_ULEB128 = 3, //< attribute of type uleb128 integer
+ RISCV_ATTR_TRUNCATED_ULEB128 = 4, //< attribute of type uleb128 integer, too big to fit into result buffer
+} riscv_attr_type;
+
+/**
+ * \brief Get a riscv attribute of a given tag from the .riscv.attributes section
+ * This section is defined in the RISC-V ELF psABI as a sequence of uleb128 encoded tags
+ * paired with either null-terminated string or uleb128 values.
+ *
+ * \param sec The .riscv.attributes section
+ * \param attr_tag The tag of the attribute to get
+ * \param result_maxlen The maximum capacity of the result buffer
+ * \param [out] result The result buffer
+ * \param [out] result_len The length of usable data in the result buffer, always <= result_maxlen
+ * \return riscv_attr_type The type of the found attribute, indicating whether it's a string or uleb128 integer and whether it was truncated
+ */
+static riscv_attr_type get_riscv_attribute_from_section(RzBuffer *sec, ut64 attr_tag, int result_maxlen, ut8 *result, int *result_len) {
+ // format:
+ /*
+ * */
+ /* =
+ * |
+ */
+ ut64 curr = 0;
+
+ // format byte
+ ut8 format;
+ if (!sec || !rz_buf_read8_offset(sec, &curr, &format) || format != 'A') {
+ RZ_LOG_ERROR("Can't read the format byte of the RISCV attrbiute section or found a different format (expected 'A' at section start)\n");
+ return RISCV_ATTR_NONE;
+ }
+
+ // subsection length
+ ut32 subsec_len;
+ if (!rz_buf_read_ble32_offset(sec, &curr, &subsec_len, /* big endian? */ false)) {
+ RZ_LOG_ERROR("Can't read the subsection length of the RISCV attribute section\n");
+ return RISCV_ATTR_NONE;
+ }
+
+ // skip vendor name
+ ut8 byte = 1;
+ while (byte != '\0') {
+ if (!rz_buf_read8_offset(sec, &curr, &byte)) {
+ RZ_LOG_ERROR("Can't read vendor name in RISCV attribute section\n");
+ return RISCV_ATTR_NONE;
+ }
+ }
+
+ // now parse the tag-value array
+ while (curr < rz_buf_size(sec)) {
+ ut64 tag;
+ ut32 num_bytes_read = rz_buf_uleb128_at(sec, curr, &tag);
+ curr += num_bytes_read;
+
+ if (num_bytes_read > 8) {
+ RZ_LOG_WARN("Can't interpret tag value between offsets %llu-%llu: "
+ "tag is too large at %d bytes, parser can only represent 64-bit tags (skipped)\n",
+ curr - num_bytes_read, curr, num_bytes_read);
+ continue;
+ }
+ if (tag != attr_tag) {
+ continue;
+ }
+
+ // RISCV ABI spec says that there are only 2 types of values associated with tags
+ // 1- Even tags: ULEB128 values (self-delimiting, no header length necessary)
+ // 2- Odd tags: Null-terminated strings (also self-delimiting)
+ // Like ARM but even simpler, no special cases for tags below 32
+ bool tag_is_odd = tag & 0x1;
+
+ int result_curr = 0;
+ // value is a null-terminated string
+ if (tag_is_odd) {
+ int string_starts_at = curr;
+ while (curr < rz_buf_size(sec) && result_curr < result_maxlen) {
+ bool succeeded = rz_buf_read8_offset(sec, &curr, &result[result_curr++]);
+ if (!succeeded) {
+ RZ_LOG_ERROR("Can't read the null-terminated string for tag %lld, starting at offset %d\n", tag, string_starts_at);
+ break;
+ }
+ // done
+ if (result[result_curr - 1] == '\0') {
+ break;
+ }
+ }
+
+ bool result_overflow = false;
+ // have we filled the buffer ?
+ if (result_curr == result_maxlen) {
+ result_overflow = result[result_maxlen - 1] != '\0';
+ // must force the last byte to null, in case the original string was too long
+ result[result_maxlen - 1] = '\0';
+ }
+ *result_len = result_curr;
+ return result_overflow ? RISCV_ATTR_TRUNCATED_NT_STRING : RISCV_ATTR_NT_STRING;
+ } else { // value is a self-delimiting ULEB128 integer
+ int uleb_starts_at = curr;
+ while (curr < rz_buf_size(sec) && result_curr < result_maxlen) {
+ bool succeeded = rz_buf_read8_offset(sec, &curr, &result[result_curr++]);
+ if (!succeeded) {
+ RZ_LOG_ERROR("Can't read the ULEB128 value for tag %lld, starting at offset %d\n", tag, uleb_starts_at);
+ break;
+ }
+ // last byte in the variable encoding, most-significant bit not set
+ if (!(result[result_curr - 1] & 0x80)) {
+ break;
+ }
+ }
+
+ bool result_overflow = false;
+ // have we filled the buffer ?
+ if (result_curr == result_maxlen) {
+ result_overflow = result[result_maxlen - 1] & 0x80;
+ // must force the last byte to a terminal byte, in case the original number was too long
+ result[result_maxlen - 1] = result[result_maxlen - 1] & 0x7F;
+ }
+ *result_len = result_curr;
+ return result_overflow ? RISCV_ATTR_TRUNCATED_ULEB128 : RISCV_ATTR_ULEB128;
+ }
+ }
+ return RISCV_ATTR_NONE;
+}
+
static int get_bits_mips(ELFOBJ *bin) {
if (is_elf_class64(bin)) {
return 64;
@@ -780,6 +922,10 @@ static bool arch_is_parisc(ELFOBJ *bin) {
return bin->ehdr.e_machine == EM_PARISC;
}
+static bool arch_is_riscv(ELFOBJ *bin) {
+ return bin->ehdr.e_machine == EM_RISCV;
+}
+
static char *read_elf_intrp(ELFOBJ *bin, ut64 addr, size_t size) {
char *str = malloc(size + 1);
if (!str) {
@@ -1945,7 +2091,7 @@ RZ_OWN char *Elf_(rz_bin_elf_get_arch)(RZ_NONNULL ELFOBJ *bin) {
* \param elf type
* \return allocated string
*
- * Only work on mips right now. Use the elf header to deduce the cpu
+ * Use the elf header to deduce the cpu
*/
RZ_OWN char *Elf_(rz_bin_elf_get_cpu)(RZ_NONNULL ELFOBJ *bin) {
rz_return_val_if_fail(bin, NULL);
@@ -1966,6 +2112,15 @@ RZ_OWN char *Elf_(rz_bin_elf_get_cpu)(RZ_NONNULL ELFOBJ *bin) {
return get_cpu_arm(bin);
} else if (arch_is_h8xx(bin)) {
return get_cpu_h8xx(bin);
+ } else if (arch_is_riscv(bin)) {
+ ut8 archstr[256];
+ int archstr_len;
+ riscv_attr_type typ = get_riscv_attribute_from_section(get_riscv_attributes_section(bin), T_RISCV_arch, 256, archstr, &archstr_len);
+ if (typ == RISCV_ATTR_NT_STRING) {
+ return rz_str_dup((const char *)archstr);
+ }
+ // some hardcoded fallback, the mafd + vector
+ return strdup("rv64i2p0_c2p0_m2p0_a2p0_f2p0_d2p0_v2p0");
}
return NULL;
}
diff --git a/librz/bin/format/elf/elf_relocs_patching.c b/librz/bin/format/elf/elf_relocs_patching.c
index bbcb7769925..d2d2dea0883 100644
--- a/librz/bin/format/elf/elf_relocs_patching.c
+++ b/librz/bin/format/elf/elf_relocs_patching.c
@@ -4,6 +4,11 @@
// SPDX-License-Identifier: LGPL-3.0-only
#include "elf.h"
+#include "elf/glibc_elf.h"
+#include "rz_types.h"
+#include "rz_types_base.h"
+#include "rz_util/rz_buf.h"
+#include "rz_util/rz_log.h"
typedef struct reloc_formular_symbols_t {
ut64 A; // Appendend
@@ -177,6 +182,20 @@ static void patch_val_over_mask_64(RZ_INOUT RzBuffer *buf_patched, bool big_endi
rz_buf_write_at(buf_patched, addr, buf, 8);
}
+/**
+ * \brief Does the same as patch_val_over_mask_32 but for 16bit values.
+ */
+static void patch_val_over_mask_16(RZ_INOUT RzBuffer *buf_patched, bool big_endian, const ut64 addr, const ut16 mask, const ut16 val) {
+ rz_return_if_fail(buf_patched);
+ ut8 buf[2] = { 0 };
+
+ rz_buf_read_at(buf_patched, addr, buf, 2);
+ ut16 opcode = rz_read_ble16(buf, big_endian) | rz_bits_spread(mask, val);
+
+ rz_write_ble16(buf, opcode, big_endian);
+ rz_buf_write_at(buf_patched, addr, buf, 2);
+}
+
#define UNHANDL(NAME) \
RZ_LOG_WARN("Unhandled " NAME " reloc\n"); \
return
@@ -2258,6 +2277,369 @@ static void patch_reloc_avr(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_add
break;
}
}
+// U-Type: 32-bit instructions that store a 20-bit immediate in their upper 20 bit
+static const ut32 RISCV_U_TYPE_IMM_MASK = ((1ULL << 20) - 1) << 12;
+// I-Type: 32-bit instructions that store a 12-bit immediate in their upper 12 bit
+static const ut32 RISCV_I_TYPE_IMM_MASK = ((1ULL << 12) - 1) << 20;
+// S-Type: 32-bit instructions that store a 12-bit immediate scattered over 2 places but still in relative order
+static const ut32 RISCV_S_TYPE_IMM_MASK = ((0x7F << 25) | (0x1F << 7));
+// B-TYPE: 32-bit instructions that store an 11-bit immediate scattered all over and out of order
+static const ut32 RISCV_B_TYPE_IMM_MASKS[] = {
+ 1ULL << 31, // bit 31: imm[12]
+ 0x3fULL << 25, // bits 30-25: imm[10:5]
+ 0xfULL << 8, // bits 11-8: imm[4:1]
+ 1ULL << 7 // bit 7: imm[11]
+};
+// J-TYPE: 32-bit instructions (JAL) that store a 20-bit immediate scattered all over and out of order
+static const ut32 RISCV_J_TYPE_IMM_MASKS[] = {
+ 1ULL << 31, // bit 31: imm[20]
+ 0x3ffULL << 21, // bits 30-21: imm[10:1]
+ 1ULL << 20, // bit 20: imm[11]
+ 0xffULL << 12 // bits 19-12: imm[19:12]
+};
+// CB-Type: 16-bit instructions that store an 8-bit immediate scattered all over and out of order
+// the immediate is effectively 9 bit with bit 0 implied and always zero
+static const ut16 RISCV_CB_TYPE_IMM_MASKS[] = {
+ (1 << 12), // bit 12: imm[8]
+ (3 << 10), // bits 11-10: imm[4:3]
+ (3 << 5), // bits 6-5: imm[7:6]
+ (3 << 3), // bits 4-3: imm[2:1]
+ (1 << 2) // bit 2: imm[5]
+};
+// CJ-Type: 16-bit instructions that store an 11-bit immediate scattered all over and out of order
+// the immediate is effectively 12 bit with bit 0 implied and always zero
+static const ut16 RISCV_CJ_TYPE_IMM_MASKS[] = {
+ (1 << 12), // bit 12: imm[11]
+ (1 << 11), // bit 11: imm[4]
+ (3 << 9), // bits 10:9: imm[9:8]
+ (1 << 8), // bit 8: imm[10]
+ (1 << 7), // bit 7: imm[6]
+ (1 << 6), // bit 6: imm[7]
+ (7 << 3), // bits 5:3: imm[3:1]
+ (1 << 2) // bit 2: imm[5]
+};
+// CI-type: 16-bit instructions that store a 6-bit immediate with the 6th bit scattered from the rest but still in relative order
+static const ut16 RISCV_CI_TYPE_IMM_MASK = (1 << 12) | (0x1f << 2);
+
+#define RISCV_HI20(i) ((i) + 0x800) >> 12
+#define RISCV_LO12(i) ((i) & 0xfff)
+#define RISCV_CHECK_NARROWING_32(i, w) \
+ if (w == 32) { \
+ i = ((ut32)i); \
+ }
+
+static void patch_reloc_riscv(RZ_INOUT RzBuffer *buf_patched, const ut64 patch_addr, const int rel_type, bool big_endian, const RelocFormularSymbols *fs, const int bits) {
+ rz_return_if_fail(buf_patched && fs);
+
+ ut64 val = 0;
+ // narrow address values for 32-bit binaries
+ ut64 S = (bits == 32) ? ((ut32)fs->S) : fs->S;
+ ut64 A = (bits == 32) ? ((ut32)fs->A) : fs->A;
+ ut64 B = (bits == 32) ? ((ut32)fs->B) : fs->B;
+ ut64 P = (bits == 32) ? ((ut32)fs->P) : fs->P;
+
+ switch (rel_type) {
+ case R_RISCV_NONE:
+ return;
+
+ case R_RISCV_32:
+ val = S + A;
+ rz_buf_write_ble32_at(buf_patched, patch_addr, val, big_endian);
+ break;
+
+ case R_RISCV_64:
+ val = S + A;
+ rz_buf_write_ble64_at(buf_patched, patch_addr, val, big_endian);
+ break;
+
+ case R_RISCV_RELATIVE:
+ val = A + B;
+ switch (bits) {
+ case 32:
+ rz_buf_write_ble32_at(buf_patched, patch_addr, val, big_endian);
+ break;
+ case 64:
+ rz_buf_write_ble64_at(buf_patched, patch_addr, val, big_endian);
+ break;
+ default:
+ RZ_LOG_WARN("Unsupported number of bits for R_RISCV_RELATIVE: %d, only 32 bits and 64 bits are supported", bits);
+ return;
+ }
+ break;
+
+ case R_RISCV_BRANCH: {
+ val = S + A - P;
+ ut64 imm12 = ((val >> 12) & 0x1); // inst[31] = imm[12]
+ ut64 imm10_5 = ((val >> 5) & 0x3f); // inst[30:25] = imm[10:5]
+ ut64 imm4_1 = ((val >> 1) & 0xf); // inst[11:8] = imm[4:1]
+ ut64 imm11 = ((val >> 11) & 0x1); // inst[7] = imm[11]
+ ut64 imms[4] = { imm12, imm10_5, imm4_1, imm11 };
+ for (int i = 0; i < sizeof(RISCV_B_TYPE_IMM_MASKS) / sizeof(RISCV_B_TYPE_IMM_MASKS[0]); i++) {
+ patch_val_over_mask_32(buf_patched, big_endian, patch_addr, RISCV_B_TYPE_IMM_MASKS[i], imms[i]);
+ }
+ break;
+ }
+
+ case R_RISCV_JAL: {
+ val = S + A - P;
+ RISCV_CHECK_NARROWING_32(val, bits);
+ ut64 imm20 = ((val >> 20) & 0x1); // inst[31] = imm[20]
+ ut64 imm10_1 = ((val >> 1) & 0x3ff); // inst[30:21] = imm[10:1]
+ ut64 imm11 = ((val >> 11) & 0x1); // inst[20] = imm[11]
+ ut64 imm19_12 = ((val >> 12) & 0xff); // inst[19:12] = imm[19:12]
+ ut64 imms[4] = { imm20, imm10_1, imm11, imm19_12 };
+ for (int i = 0; i < sizeof(RISCV_J_TYPE_IMM_MASKS) / sizeof(RISCV_J_TYPE_IMM_MASKS[0]); i++) {
+ patch_val_over_mask_32(buf_patched, big_endian, patch_addr, RISCV_J_TYPE_IMM_MASKS[i], imms[i]);
+ }
+ break;
+ }
+
+ // both handled by the same formula
+ // TODO: CALL_PLT is more complex if the symbol is outside the same object file
+ case R_RISCV_CALL:
+ case R_RISCV_CALL_PLT: {
+ ut64 result = S + A - P;
+
+ ut32 hi20 = RISCV_HI20(result);
+ ut32 lo12 = RISCV_LO12(result);
+
+ // the AUIPC part of the call sequence takes the upper 20 bits of the address
+ patch_val_over_mask_32(buf_patched, big_endian, patch_addr, RISCV_U_TYPE_IMM_MASK, hi20);
+ // the JALR part of the call sequence takes the lower 12 bits of the address;
+ patch_val_over_mask_32(buf_patched, big_endian, patch_addr + 4, RISCV_I_TYPE_IMM_MASK, lo12);
+ break;
+ }
+
+ case R_RISCV_JUMP_SLOT:
+ switch (bits) {
+ case 32:
+ rz_buf_write_ble32_at(buf_patched, patch_addr, S, big_endian);
+ break;
+ case 64:
+ rz_buf_write_ble64_at(buf_patched, patch_addr, S, big_endian);
+ break;
+ default:
+ RZ_LOG_WARN("Unsupported number of bits for R_RISCV_JUMP_SLOT: %d, only 32 bits and 64 bits are supported", bits);
+ break;
+ }
+ break;
+
+ case R_RISCV_32_PCREL:
+ val = S + A - P;
+ rz_buf_write_ble32_at(buf_patched, patch_addr, val, big_endian);
+ break;
+
+ case R_RISCV_GOT_HI20: {
+ val = fs->G + fs->GOT + A - P;
+ ut32 hi20 = RISCV_HI20(val);
+ patch_val_over_mask_32(buf_patched, big_endian, patch_addr, RISCV_U_TYPE_IMM_MASK, hi20);
+ break;
+ }
+ case R_RISCV_PCREL_HI20: {
+ val = S + A - P;
+ ut32 hi20 = RISCV_HI20(val);
+ patch_val_over_mask_32(buf_patched, big_endian, patch_addr, RISCV_U_TYPE_IMM_MASK, hi20);
+ break;
+ }
+
+ case R_RISCV_PCREL_LO12_I:
+ case R_RISCV_PCREL_LO12_S: {
+ val = S + A - P;
+ ut32 lo12 = RISCV_LO12(val);
+ patch_val_over_mask_32(buf_patched, big_endian, patch_addr, (rel_type == R_RISCV_PCREL_LO12_I) ? RISCV_I_TYPE_IMM_MASK : RISCV_S_TYPE_IMM_MASK, lo12);
+ break;
+ }
+
+ case R_RISCV_HI20: {
+ val = S + A;
+ patch_val_over_mask_32(buf_patched, big_endian, patch_addr, RISCV_U_TYPE_IMM_MASK, RISCV_HI20(val));
+ break;
+ }
+
+ case R_RISCV_LO12_I:
+ case R_RISCV_LO12_S: {
+ val = S + A;
+ patch_val_over_mask_32(buf_patched, big_endian, patch_addr, (rel_type == R_RISCV_LO12_I) ? RISCV_I_TYPE_IMM_MASK : RISCV_S_TYPE_IMM_MASK, RISCV_LO12(val));
+ break;
+ }
+
+ case R_RISCV_RVC_BRANCH: {
+ val = S + A - P;
+ uint16_t imms[] = {
+ ((val >> 8) & 0x1), // imm[8]
+ ((val >> 3) & 0x3), // imm[4:3]
+ ((val >> 6) & 0x3), // imm[7:6]
+ ((val >> 1) & 0x3), // imm[2:1]
+ ((val >> 5) & 0x1) // imm[5]
+ };
+ for (int i = 0; i < sizeof(RISCV_CB_TYPE_IMM_MASKS) / sizeof(RISCV_CB_TYPE_IMM_MASKS[0]); i++) {
+ patch_val_over_mask_16(buf_patched, big_endian, patch_addr, RISCV_CB_TYPE_IMM_MASKS[i], imms[i]);
+ }
+ break;
+ }
+
+ case R_RISCV_RVC_JUMP: {
+ val = S + A - P;
+ uint16_t imms[] = {
+ ((val >> 11) & 0x1), // imm[11]
+ ((val >> 4) & 0x1), // imm[4]
+ ((val >> 8) & 0x3), // imm[9:8]
+ ((val >> 10) & 0x1), // imm[10]
+ ((val >> 6) & 0x1), // imm[6]
+ ((val >> 7) & 0x1), // imm[7]
+ ((val >> 1) & 0x7), // imm[3:1]
+ ((val >> 5) & 0x1), // imm[5]
+ };
+ for (int i = 0; i < sizeof(RISCV_CJ_TYPE_IMM_MASKS) / sizeof(RISCV_CJ_TYPE_IMM_MASKS[0]); i++) {
+ patch_val_over_mask_16(buf_patched, big_endian, patch_addr, RISCV_CJ_TYPE_IMM_MASKS[i], imms[i]);
+ }
+ break;
+ }
+
+ case R_RISCV_RVC_LUI:
+ val = S + A;
+ patch_val_over_mask_16(buf_patched, big_endian, patch_addr, RISCV_CI_TYPE_IMM_MASK, val >> 12);
+ break;
+
+ case R_RISCV_ADD8: {
+ ut8 old_val = 0;
+ rz_buf_read_ble8_at(buf_patched, patch_addr, &old_val, big_endian);
+ ut64 result = ((ut64)old_val) + S + A;
+ unsigned long long addr = patch_addr;
+ rz_buf_write_ble8_offset(buf_patched, &addr, (ut8)result, big_endian);
+ break;
+ }
+
+ case R_RISCV_ADD16: {
+ ut16 old_val = 0;
+ rz_buf_read_ble16_at(buf_patched, patch_addr, &old_val, big_endian);
+ ut64 result = ((ut64)old_val) + S + A;
+ rz_buf_write_ble16_at(buf_patched, patch_addr, (ut16)result, big_endian);
+ break;
+ }
+
+ case R_RISCV_ADD32: {
+ ut32 old_val = 0;
+ rz_buf_read_ble32_at(buf_patched, patch_addr, &old_val, big_endian);
+ ut64 result = ((ut64)old_val) + S + A;
+ rz_buf_write_ble32_at(buf_patched, patch_addr, (ut32)result, big_endian);
+ break;
+ }
+
+ case R_RISCV_ADD64: {
+ ut64 old_val = 0;
+ rz_buf_read_ble64_at(buf_patched, patch_addr, &old_val, big_endian);
+ ut64 result = old_val + S + A;
+ rz_buf_write_ble64_at(buf_patched, patch_addr, result, big_endian);
+ break;
+ }
+
+ case R_RISCV_SUB8: {
+ ut8 old_val = 0;
+ rz_buf_read_ble8_at(buf_patched, patch_addr, &old_val, big_endian);
+ ut64 result = ((ut64)old_val) - S - A;
+ unsigned long long addr = patch_addr;
+ rz_buf_write_ble8_offset(buf_patched, &addr, (ut8)result, big_endian);
+ break;
+ }
+
+ case R_RISCV_SUB16: {
+ ut16 old_val = 0;
+ rz_buf_read_ble16_at(buf_patched, patch_addr, &old_val, big_endian);
+ ut64 result = ((ut64)old_val) - S - A;
+ rz_buf_write_ble16_at(buf_patched, patch_addr, (ut16)result, big_endian);
+ break;
+ }
+
+ case R_RISCV_SUB32: {
+ ut32 old_val = 0;
+ rz_buf_read_ble32_at(buf_patched, patch_addr, &old_val, big_endian);
+ ut64 result = ((ut64)old_val) - S - A;
+ rz_buf_write_ble32_at(buf_patched, patch_addr, (ut32)result, big_endian);
+ break;
+ }
+
+ case R_RISCV_SUB64: {
+ ut64 old_val = 0;
+ rz_buf_read_ble64_at(buf_patched, patch_addr, &old_val, big_endian);
+ ut64 result = ((ut64)old_val) - S - A;
+ rz_buf_write_ble64_at(buf_patched, patch_addr, result, big_endian);
+ break;
+ }
+
+ case R_RISCV_SET8: {
+ val = S + A;
+ unsigned long long addr = patch_addr;
+ rz_buf_write_ble8_offset(buf_patched, &addr, (ut8)val, big_endian);
+ break;
+ }
+ case R_RISCV_SET16: {
+ val = S + A;
+ rz_buf_write_ble16_at(buf_patched, patch_addr, (ut16)val, big_endian);
+ break;
+ }
+ case R_RISCV_SET32: {
+ val = S + A;
+ rz_buf_write_ble32_at(buf_patched, patch_addr, (ut32)val, big_endian);
+ break;
+ }
+
+ case R_RISCV_SET6:
+ case R_RISCV_SUB6: {
+ ut8 old_val = 0;
+ rz_buf_read_ble8_at(buf_patched, patch_addr, &old_val, big_endian);
+ val = S + A;
+ ut8 result = (rel_type == R_RISCV_SET6) ? val : ((old_val & 0x3F) - val);
+ rz_buf_write_ble8_at(buf_patched, patch_addr, (old_val & 0xC0) | (result & 0x3F), big_endian);
+ break;
+ }
+
+ /*************************************************** UNIMPLEMENTED ***************************************************/
+ case R_RISCV_TLS_DTPMOD32:
+ UNHANDL_DEF("RISCV", rel_type);
+ RZ_LOG_WARN("RISCV Relocations: TLS_DTPMOD32 UNIMPLEMENTED");
+ break;
+
+ case R_RISCV_TLS_DTPMOD64:
+ UNHANDL_DEF("RISCV", rel_type);
+ RZ_LOG_WARN("RISCV Relocations: TLS_DTPMOD64 UNIMPLEMENTED");
+ break;
+
+ case R_RISCV_TLS_TPREL32:
+ UNHANDL_DEF("RISCV", rel_type);
+ RZ_LOG_WARN("RISCV Relocations: TLS_TPREL32 UNIMPLEMENTED");
+ break;
+
+ case R_RISCV_TLS_TPREL64:
+ UNHANDL_DEF("RISCV", rel_type);
+ RZ_LOG_WARN("RISCV Relocations: TLS_TPREL64 UNIMPLEMENTED");
+ break;
+
+ case R_RISCV_TLS_GD_HI20:
+ UNHANDL_DEF("RISCV", rel_type);
+ RZ_LOG_WARN("RISCV Relocations: TLS_GD_HI20 UNIMPLEMENTED");
+ break;
+
+ case R_RISCV_TLS_GOT_HI20:
+ UNHANDL_DEF("RISCV", rel_type);
+ RZ_LOG_WARN("RISCV Relocations: TLS_GOT_HI20 UNIMPLEMENTED");
+ break;
+
+ case R_RISCV_TLS_DTPREL32:
+ UNHANDL_DEF("RISCV", rel_type);
+ RZ_LOG_WARN("RISCV Relocations: TLS_DTPREL32 UNIMPLEMENTED");
+ break;
+
+ case R_RISCV_TLS_DTPREL64:
+ UNHANDL_DEF("RISCV", rel_type);
+ RZ_LOG_WARN("RISCV Relocations: TLS_DTPREL64 UNIMPLEMENTED");
+ break;
+
+ default:
+ UNHANDL_DEF("RISC-V", rel_type);
+ return;
+ }
+}
#undef UNHANDL
#undef UNHANDL_DEF
@@ -2334,6 +2716,10 @@ void Elf_(rz_bin_elf_patch_relocation)(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RzBinE
case EM_AVR:
patch_reloc_avr(bin->buf_patched, patch_addr, rel->type, big_endian, &formular_sym);
break;
+ case EM_RISCV:
+ patch_reloc_riscv(bin->buf_patched, patch_addr, rel->type, big_endian, &formular_sym, bin->bits);
+ break;
+
case EM_M32: ARCH_MISSING("EM_M32");
case EM_68K: ARCH_MISSING("EM_68K");
case EM_88K: ARCH_MISSING("EM_88K");
@@ -2546,5 +2932,4 @@ void Elf_(rz_bin_elf_patch_relocation)(RZ_NONNULL ELFOBJ *bin, RZ_NONNULL RzBinE
return;
}
}
-
#undef ARCH_MISSING
diff --git a/librz/bin/format/elf/glibc_elf.h b/librz/bin/format/elf/glibc_elf.h
index 876f812683c..c459192ea43 100644
--- a/librz/bin/format/elf/glibc_elf.h
+++ b/librz/bin/format/elf/glibc_elf.h
@@ -4125,6 +4125,17 @@ ARM32 relocations:
#define R_RISCV_NUM 59
+/* RISCV Tags */
+#define T_RISCV_stack_align 4
+#define T_RISCV_arch 5
+#define T_RISCV_unaligned_access 6
+#define T_RISCV_priv_spec 8
+#define T_RISCV_priv_spec_minor 10
+#define T_RISCV_priv_spec_revision 12
+
+/* RISCV-specific section types */
+#define SHT_RISCV_ATTRIBUTES 0x70000003
+
/* BPF specific declarations. */
#define R_BPF_NONE 0 /* No reloc */
diff --git a/librz/bin/p/bin_elf.inc b/librz/bin/p/bin_elf.inc
index 3619d0c7231..6c8fa0fff72 100644
--- a/librz/bin/p/bin_elf.inc
+++ b/librz/bin/p/bin_elf.inc
@@ -15,6 +15,7 @@
#include "../i/private.h"
#include "elf/elf.h"
#include "elf/glibc_elf.h"
+#include "rz_vector.h"
#include
#include
diff --git a/librz/include/rz_analysis.h b/librz/include/rz_analysis.h
index 638bd875d50..bf5bd77a3f2 100644
--- a/librz/include/rz_analysis.h
+++ b/librz/include/rz_analysis.h
@@ -338,6 +338,9 @@ typedef enum {
RZ_ANALYSIS_OP_TYPE_CPL = 45, /* complement */
RZ_ANALYSIS_OP_TYPE_CRYPTO = 46,
RZ_ANALYSIS_OP_TYPE_SYNC = 47,
+ RZ_ANALYSIS_OP_TYPE_BCNT = 48, /* bit-counting operations like pop count */
+ RZ_ANALYSIS_OP_TYPE_REV = 49, /* byte-reversal and bit-reversal operations */
+ RZ_ANALYSIS_OP_TYPE_REDUCE = 50, /* instructions that reduce a sequence, like string operations or vector sum */
// RZ_ANALYSIS_OP_TYPE_DEBUG = 43, // monitor/trace/breakpoint
#if 0
RZ_ANALYSIS_OP_TYPE_PRIV = 40, /* privileged instruction */
diff --git a/subprojects/capstone-next.wrap b/subprojects/capstone-next.wrap
index be49428420b..6fc9a8649e4 100644
--- a/subprojects/capstone-next.wrap
+++ b/subprojects/capstone-next.wrap
@@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/capstone-engine/capstone.git
-revision = 9539045d675a30eed43869325f7f51cfc26de0b7
+revision = 3533a9c8d0713eac0d39532d91f6c7acfa23b3d6
directory = capstone-next
patch_directory = capstone-next
depth = 1
diff --git a/subprojects/capstone-v6.wrap b/subprojects/capstone-v6.wrap
index 9b4a1673752..7fe0caa1f3f 100644
--- a/subprojects/capstone-v6.wrap
+++ b/subprojects/capstone-v6.wrap
@@ -1,6 +1,6 @@
[wrap-file]
-source_url = https://github.com/capstone-engine/capstone/releases/download/6.0.0-Alpha6/capstone-6.0.0-Alpha6.tar.xz
-source_filename = capstone-6.0.0-Alpha6.tar.xz
-source_hash = 8ad244c35508b28d6c0751e3610a25380f34ddd892c968212794ed6a90d8e3cb
-directory = capstone-6.0.0-Alpha6
-patch_directory = capstone-6.0.0-alpha6
+source_url = https://github.com/capstone-engine/capstone/releases/download/6.0.0-Alpha7/capstone-6.0.0-Alpha7.tar.xz
+source_filename = capstone-6.0.0-Alpha7.tar.xz
+source_hash = 6864bf6cff06f2698fd30854cc2097b6d41cd10b5454be67e8b56ad0cfc686ec
+directory = capstone-6.0.0-Alpha7
+patch_directory = capstone-6.0.0-alpha7
diff --git a/subprojects/packagefiles/capstone-6.0.0-alpha6/meson.build b/subprojects/packagefiles/capstone-6.0.0-alpha7/meson.build
similarity index 94%
rename from subprojects/packagefiles/capstone-6.0.0-alpha6/meson.build
rename to subprojects/packagefiles/capstone-6.0.0-alpha7/meson.build
index a6f0fddc93c..47ce09660c6 100644
--- a/subprojects/packagefiles/capstone-6.0.0-alpha6/meson.build
+++ b/subprojects/packagefiles/capstone-6.0.0-alpha7/meson.build
@@ -55,6 +55,12 @@ cs_files = [
'arch/PowerPC/PPCInstPrinter.c',
'arch/PowerPC/PPCMapping.c',
'arch/PowerPC/PPCModule.c',
+ 'arch/RISCV/RISCVDisassembler.c',
+ 'arch/RISCV/RISCVDisassemblerExtension.c',
+ 'arch/RISCV/RISCVInstPrinter.c',
+ 'arch/RISCV/RISCVBaseInfo.c',
+ 'arch/RISCV/RISCVMapping.c',
+ 'arch/RISCV/RISCVModule.c',
'arch/Sparc/SparcDisassembler.c',
'arch/Sparc/SparcDisassemblerExtension.c',
'arch/Sparc/SparcInstPrinter.c',
@@ -123,6 +129,7 @@ libcapstone_c_args = [
'-DCAPSTONE_HAS_X86',
'-DCAPSTONE_HAS_XCORE',
'-DCAPSTONE_HAS_XTENSA',
+ '-DCAPSTONE_HAS_RISCV',
]
if meson.get_compiler('c').has_argument('-Wmaybe-uninitialized')
diff --git a/subprojects/packagefiles/capstone-next/meson.build b/subprojects/packagefiles/capstone-next/meson.build
index a6f0fddc93c..47ce09660c6 100644
--- a/subprojects/packagefiles/capstone-next/meson.build
+++ b/subprojects/packagefiles/capstone-next/meson.build
@@ -55,6 +55,12 @@ cs_files = [
'arch/PowerPC/PPCInstPrinter.c',
'arch/PowerPC/PPCMapping.c',
'arch/PowerPC/PPCModule.c',
+ 'arch/RISCV/RISCVDisassembler.c',
+ 'arch/RISCV/RISCVDisassemblerExtension.c',
+ 'arch/RISCV/RISCVInstPrinter.c',
+ 'arch/RISCV/RISCVBaseInfo.c',
+ 'arch/RISCV/RISCVMapping.c',
+ 'arch/RISCV/RISCVModule.c',
'arch/Sparc/SparcDisassembler.c',
'arch/Sparc/SparcDisassemblerExtension.c',
'arch/Sparc/SparcInstPrinter.c',
@@ -123,6 +129,7 @@ libcapstone_c_args = [
'-DCAPSTONE_HAS_X86',
'-DCAPSTONE_HAS_XCORE',
'-DCAPSTONE_HAS_XTENSA',
+ '-DCAPSTONE_HAS_RISCV',
]
if meson.get_compiler('c').has_argument('-Wmaybe-uninitialized')
diff --git a/sys/riscv_extension_parser_generator.py b/sys/riscv_extension_parser_generator.py
new file mode 100644
index 00000000000..97154b5464f
--- /dev/null
+++ b/sys/riscv_extension_parser_generator.py
@@ -0,0 +1,392 @@
+#!/usr/bin/env python3
+# SPDX-FileCopyrightText: 2024-2026 moste00
+# SPDX-License-Identifier: BSD-3-Clause
+
+"""
+RISC-V Extension Trie-Based Parser Generator
+
+Given a list of RISCV_FeatureStdExt* enums, generates C code that:
+1. Parses extension names using a trie data structure
+2. ORs the corresponding enum value with a running accumulator
+3. Includes an ASCII art tree visualization of the trie
+4. Annotates branches with parse state
+5. Uses macros to reduce boilerplate
+"""
+
+import sys
+import os
+from typing import Dict, List, Optional, Tuple
+from dataclasses import dataclass
+
+
+@dataclass
+class TrieNode:
+ children: Dict[str, "TrieNode"]
+ enum_name: Optional[str] = None
+
+ def __init__(self):
+ self.children = {}
+ self.enum_name = None
+
+
+class Trie:
+ def __init__(self):
+ self.root = TrieNode()
+
+ def insert(self, ext_name: str, enum_name: str):
+ """Insert an extension name into the trie"""
+ node = self.root
+ for char in ext_name:
+ if char not in node.children:
+ node.children[char] = TrieNode()
+ node = node.children[char]
+ node.enum_name = enum_name
+
+ def generate_ascii_tree(
+ self,
+ node: Optional[TrieNode] = None,
+ prefix: str = "",
+ is_last: bool = True,
+ char: str = "ROOT",
+ ) -> List[str]:
+ """Generate ASCII tree representation"""
+ if node is None:
+ node = self.root
+
+ lines = []
+
+ # Current node
+ connector = "└── " if is_last else "├── "
+ if char == "ROOT":
+ line = "ROOT"
+ else:
+ line = prefix + connector + char
+ if node.enum_name:
+ line += f" [{node.enum_name}]"
+ lines.append(line)
+
+ # Children
+ if node.children:
+ sorted_children = sorted(node.children.items())
+ for i, (ch, child) in enumerate(sorted_children):
+ is_last_child = i == len(sorted_children) - 1
+
+ if char == "ROOT":
+ child_prefix = ""
+ else:
+ extension = " " if is_last else "│ "
+ child_prefix = prefix + extension
+
+ lines.extend(
+ self.generate_ascii_tree(child, child_prefix, is_last_child, ch)
+ )
+
+ return lines
+
+
+def parse_enum_definitions(enum_text: str) -> List[Tuple[str, str]]:
+ """Parse enum definitions and extract extension names"""
+ results = []
+
+ for line in enum_text.strip().split("\n"):
+ line = line.strip()
+ if not line or not line.startswith("RISCV_FeatureStdExt"):
+ continue
+
+ # Remove trailing comma and split
+ enum_name = line.rstrip(",").split("=")[0].strip()
+
+ # Extract extension name (part after FeatureStdExt)
+ if "FeatureStdExt" in enum_name:
+ ext_name = enum_name.split("FeatureStdExt")[1].lower()
+ if ext_name: # Skip empty names
+ results.append((ext_name, enum_name))
+
+ return results
+
+
+# pylint: disable=too-many-statements
+def generate_c_code(trie: Trie, extensions: List[Tuple[str, str]]) -> str:
+ """Generate the complete C parsing function"""
+
+ # Generate ASCII tree
+ tree_lines = trie.generate_ascii_tree()
+ tree_comment = "\n".join(f" * {line}" for line in tree_lines)
+
+ # Generate function body
+ code_lines = []
+
+ def generate_node_code(node: TrieNode, depth: int, path: str) -> List[str]:
+ """Recursively generate parsing code for trie nodes"""
+ lines = []
+ indent = " " * depth
+
+ if not node.children:
+ # Leaf node
+ if node.enum_name:
+ lines.append(f"{indent}STOP_WITH_MATCH({node.enum_name});")
+ else:
+ lines.append(f"{indent}STOP_WITHOUT_MATCH();")
+ return lines
+
+ # Non-leaf node - check if this is also a valid end point
+ if node.enum_name:
+ lines.append(f"{indent}STOP_WITH_MATCH({node.enum_name});")
+ lines.append("")
+
+ # Process children - add state comment only before branching
+ sorted_children = sorted(node.children.items())
+ expected_chars = [c for c, _ in sorted_children]
+ expected_str = "".join(expected_chars)
+
+ lines.append(f"{indent}/* State: '{path}' expecting [{expected_str}] */")
+
+ for i, (char, child) in enumerate(sorted_children):
+ if i == 0:
+ lines.append(f"{indent}if (*p == '{char}') {{")
+ else:
+ lines.append(f"{indent}}} else if (*p == '{char}') {{")
+
+ lines.append(f"{indent} p++;")
+ lines.extend(generate_node_code(child, depth + 1, path + char))
+
+ lines.append(f"{indent}}} else {{")
+
+ # In the else branch, we have an unexpected character
+ if node.enum_name:
+ # There was a valid match at the previous state
+ lines.append(f"{indent} /* Unexpected char, but '{path}' was valid */")
+ lines.append(f"{indent} STOP_WITH_MATCH({node.enum_name});")
+ else:
+ # No valid match at this point
+ lines.append(f"{indent} /* Unexpected char at '{path}', no match */")
+ lines.append(f"{indent} STOP_WITHOUT_MATCH();")
+
+ lines.append(f"{indent}}}")
+
+ return lines
+
+ # Start with root's children
+ if trie.root.children:
+ code_lines.extend(generate_node_code(trie.root, 1, ""))
+ code_lines.append("")
+ code_lines.append(" /* Should not reach here */")
+ code_lines.append(" STOP_WITHOUT_MATCH();")
+
+ # Build the complete function
+ full_code = "// SPDX-FileCopyrightText: 2024-2026 moste00 \n"
+ full_code += "// " + "SPDX" + "-License-Identifier: BSD-3-Clause"
+ full_code += "\n\n/*\n"
+ full_code += " * \n \n *********************************************** AUTO-GENERATED CODE, DO NOT EDIT BY HAND! "
+ full_code += " * *********************************************** \n \n"
+ full_code += " * RISC-V Extension Parser Using a Trie trick\n"
+ full_code += (
+ " * Generated from arch/RISCV/RISCVGenSubtargetInfo.inc in Capstone sources \n"
+ )
+ full_code += " * \n"
+ full_code += " * This function parses a single RISC-V extension name and ORs the corresponding\n"
+ full_code += " * feature flags with an accumulator 'mode'.\n"
+ full_code += " * \n"
+ full_code += " * Trie Diagram:\n"
+ full_code += tree_comment + "\n"
+ full_code += " */\n\n"
+
+ flags_defs = "\n".join(
+ [f"#define {member} {i} \n" for i, (_, member) in enumerate(extensions)]
+ )
+ full_code += flags_defs
+
+ full_code += "/* Parse result enum - indicates why parsing stopped */\n"
+ full_code += "typedef enum {\n"
+ full_code += (
+ " RISCV_EXT_PARSE_END_OF_STRING, "
+ "/* Stopped at '\\0' - valid extension found */\n"
+ )
+ full_code += (
+ " RISCV_EXT_PARSE_STOPPED_AT_NUMBER, "
+ "/* Stopped at a digit - valid extension found */\n"
+ )
+ full_code += (
+ " RISCV_EXT_PARSE_STOPPED_AT_UNDERSCORE, "
+ "/* Stopped at '_' - valid extension found */\n"
+ )
+ full_code += (
+ " RISCV_EXT_PARSE_STOPPED_AT_UNEXPECTED, "
+ "/* Stopped at unexpected char - valid extension found */\n"
+ )
+ full_code += (
+ " RISCV_EXT_PARSE_NO_MATCH_END_OF_STRING, "
+ "/* Reached '\\0' - no valid extension */\n"
+ )
+ full_code += (
+ " RISCV_EXT_PARSE_NO_MATCH_NUMBER, "
+ "/* Hit number - no valid extension at this point */\n"
+ )
+ full_code += (
+ " RISCV_EXT_PARSE_NO_MATCH_UNDERSCORE, "
+ "/* Hit underscore - no valid extension at this point */\n"
+ )
+ full_code += (
+ " RISCV_EXT_PARSE_NO_MATCH_UNEXPECTED, "
+ "/* Hit unexpected char - no valid extension */\n"
+ )
+ full_code += "} riscv_extension_parse_result_t;\n\n"
+
+ full_code += "/* Macro: Stop parsing with a matched extension */\n"
+ full_code += "#ifndef MATCH_CALLBACK\n"
+ full_code += "#define MATCH_CALLBACK(feature_enum)\n"
+ full_code += "#endif\n\n"
+ full_code += "#ifndef FINI_EXT_CALLBACKS\n"
+ full_code += "#define FINI_EXT_CALLBACKS()\n"
+ full_code += "#endif\n\n"
+ full_code += "#define STOP_WITH_MATCH(feature_enum) \\\n"
+ full_code += " do { \\\n"
+ full_code += " MATCH_CALLBACK(feature_enum); \\\n"
+ full_code += " *idx = (size_t)(p - ext_name); \\\n"
+ full_code += " *mode = feature_enum; \\\n"
+ full_code += " FINI_EXT_CALLBACKS(); \\\n"
+ full_code += " if (*p == '\\0') { \\\n"
+ full_code += " return RISCV_EXT_PARSE_END_OF_STRING; \\\n"
+ full_code += " } else if (*p >= '0' && *p <= '9') { \\\n"
+ full_code += " return RISCV_EXT_PARSE_STOPPED_AT_NUMBER; \\\n"
+ full_code += " } else if (*p == '_') { \\\n"
+ full_code += " return RISCV_EXT_PARSE_STOPPED_AT_UNDERSCORE; \\\n"
+ full_code += " } else { \\\n"
+ full_code += " return RISCV_EXT_PARSE_STOPPED_AT_UNEXPECTED; \\\n"
+ full_code += " } \\\n"
+ full_code += " } while (0)\n\n"
+
+ full_code += "/* Macro: Stop parsing without a match */\n"
+ full_code += "#define STOP_WITHOUT_MATCH() \\\n"
+ full_code += " do { \\\n"
+ full_code += " *idx = (size_t)(p - ext_name); \\\n"
+ full_code += " if (*p == '\\0') { \\\n"
+ full_code += " return RISCV_EXT_PARSE_NO_MATCH_END_OF_STRING; \\\n"
+ full_code += " } else if (*p >= '0' && *p <= '9') { \\\n"
+ full_code += " return RISCV_EXT_PARSE_NO_MATCH_NUMBER; \\\n"
+ full_code += " } else if (*p == '_') { \\\n"
+ full_code += " return RISCV_EXT_PARSE_NO_MATCH_UNDERSCORE; \\\n"
+ full_code += " } else { \\\n"
+ full_code += " return RISCV_EXT_PARSE_NO_MATCH_UNEXPECTED; \\\n"
+ full_code += " } \\\n"
+ full_code += " } while (0)\n\n"
+
+ full_code += "/**\n"
+ full_code += (
+ " * Main parse routine: Try to consume a RISC-V extension name "
+ "from the architecture string at a given position.\n"
+ )
+ full_code += " * \n"
+ full_code += " * @param arch_str: The full architecture string\n"
+ full_code += (
+ " * @param idx: Pointer to current index "
+ "(will be updated to show consumed length)\n"
+ )
+ full_code += (
+ " * @param mode: Pointer to the feature accumulator "
+ "(will be ORed with the feature flag if extension found)\n"
+ )
+ full_code += " * @return: Parse result indicating why parsing stopped and whether a match was found\n"
+ full_code += " * \n"
+ full_code += " * Stopping conditions:\n"
+ full_code += " * - '\\0' (end of string)\n"
+ full_code += " * - '0'-'9' (version number)\n"
+ full_code += " * - '_' (extension separator)\n"
+ full_code += " * - Any unexpected character\n"
+ full_code += " * \n"
+ full_code += " * The function uses a trie-based approach for efficient parsing.\n"
+ full_code += " * State comments show the current position in the trie:\n"
+ full_code += " * 'abc...' means we've matched 'abc' and are looking for more\n"
+ full_code += " * 'abc(!x)' means we've matched 'abc' but encountered unexpected char instead of 'x'\n"
+ full_code += " */\n"
+ full_code += "#ifndef INIT_EXT_CALLBACKS\n"
+ full_code += "#define INIT_EXT_CALLBACKS()\n"
+ full_code += "#endif\n\n"
+ full_code += "static inline riscv_extension_parse_result_t\n"
+ full_code += (
+ "try_consume_riscv_ext_from(const char *ext_name, size_t *idx, ut64 *mode)\n"
+ )
+ full_code += "{\n"
+ full_code += " if (!ext_name || !idx || !mode) {\n"
+ full_code += " return RISCV_EXT_PARSE_NO_MATCH_END_OF_STRING;\n"
+ full_code += " }\n"
+ full_code += " \n"
+ full_code += " INIT_EXT_CALLBACKS();\n"
+ full_code += " const char *p = ext_name + *idx;\n"
+ full_code += " \n"
+ full_code += " if (*p == '\\0') {\n"
+ full_code += " return RISCV_EXT_PARSE_NO_MATCH_END_OF_STRING;\n"
+ full_code += " }\n\n"
+
+ full_code += "\n".join(code_lines)
+ full_code += "\n}\n\n"
+
+ full_code += "/* Cleanup macros */\n"
+ full_code += "#undef STOP_WITH_MATCH\n"
+ full_code += "#undef STOP_WITHOUT_MATCH\n\n"
+
+ # Add example usage
+ full_code += "/* Example usage:\n"
+ full_code += " *\n"
+ full_code += " * ut64 features = 0;\n"
+ full_code += " * riscv_extension_parse_result_t result;\n"
+ full_code += " * size_t idx = 0;\n"
+ full_code += ' * const char *arch = "i2p1_m2p0_zicsr";\n'
+ full_code += " * \n"
+ full_code += ' * // Parse "i" from "i2p1_m2p0_zicsr"\n'
+ full_code += " * result = try_consume_riscv_ext_from(arch, &idx, &features);\n"
+ full_code += " * // idx is now 1, result is RISCV_EXT_PARSE_STOPPED_AT_NUMBER\n"
+ full_code += " * \n"
+ full_code += ' * // Skip version "2p1_" by setting idx = 5\n'
+ full_code += " * idx = 5; // now at 'm'\n"
+ full_code += " * result = try_consume_riscv_ext_from(arch, &idx, &features);\n"
+ full_code += " * // idx is now 6, result is RISCV_EXT_PARSE_STOPPED_AT_NUMBER\n"
+ full_code += " * \n"
+ full_code += ' * // Skip version "2p0_" by setting idx = 10\n'
+ full_code += " * idx = 10; // now at 'z'\n"
+ full_code += " * result = try_consume_riscv_ext_from(arch, &idx, &features);\n"
+ full_code += " * // idx is now 15, result is RISCV_EXT_PARSE_END_OF_STRING\n"
+ full_code += " */\n"
+
+ return full_code
+
+
+def main():
+
+ if len(sys.argv) < 3:
+ print(f"Usage: {sys.argv[0]} ")
+ sys.exit(1)
+
+ input_header = sys.argv[1]
+ output_file = sys.argv[2]
+
+ if not os.path.exists(input_header):
+ print(f"Error: Input file {input_header} not found")
+ sys.exit(1)
+
+ with open(input_header, "r", encoding="utf-8") as f:
+ enum_text = "\n".join(
+ [line for line in f if line.strip().startswith("RISCV_FeatureStdExt")]
+ )
+
+ # Parse enum definitions
+ extensions = parse_enum_definitions(enum_text)
+
+ if not extensions:
+ print(f"Warning: No extensions found in {input_header}")
+
+ # Build trie
+ trie = Trie()
+ for ext_name, enum_name in extensions:
+ trie.insert(ext_name, enum_name)
+
+ # Generate C code
+ c_code = generate_c_code(trie, extensions)
+
+ # Output to file
+ with open(output_file, "w", encoding="utf-8") as f:
+ f.write(c_code)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/test/db/analysis/alpha b/test/db/analysis/alpha
index b8f1141e445..ee3c3c0468e 100644
--- a/test/db/analysis/alpha
+++ b/test/db/analysis/alpha
@@ -51,7 +51,7 @@ opex:
- type: "reg"
value: "$2"
- type: "imm"
- value: 536982352
+ value: 4831949648
jump: 0x12001b350
fail: 0x12001b340
cond: al
diff --git a/test/db/analysis/riscv b/test/db/analysis/riscv
index 5ffe90624ea..05fe7cb83c6 100644
--- a/test/db/analysis/riscv
+++ b/test/db/analysis/riscv
@@ -19,7 +19,7 @@ wx 21a001009d06aa858146
pd 5
EOF
EXPECT=< 0x00000002 8280 ret
:`-> 0x00000004 9d06 addi a3, a3, 7
- `==< 0x00000006 f5fe bnez a3, 0x2
- 0x00000008 0000 illegal
+ `==< 0x00000006 f5fe bnez a3, 2
+ 0x00000008 0000 unimp
EOF
RUN
-NAME=asm pseudo for riscv
-FILE=bins/elf/analysis/guess-number-riscv64
+NAME=vector addition of 2 arrays
+FILE=bins/elf/riscv_vec_arrsum
+CMDS=< 0x00010c86 07e10702 vle32.v v2, (a5) ; arg6
+| :: 0x00010c8a c107 addi a5, a5, 0x10 ; arg6
+| :: 0x00010c8c d7001102 vadd.vv v1, v1, v2
+| `==< 0x00010c90 e39bd7ff bne a5, t4, 0x10c86
+| : 0x00010c94 f32620c2 csrr a3, vlenb
+| : 0x00010c98 8a96 add a3, a3, sp ; arg4
+| : 0x00010c9a a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x00010c9e 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x00010ca2 d730005e vmv.v.i v1, 0
+| : 0x00010ca6 1147 li a4, 4
+| .--> 0x00010ca8 d7770709 vsetvli a5, a4, e0x20, m1, tu, ma ; arg6
+| :: 0x00010cac 07e10602 vle32.v v2, (a3) ; arg4
+| :: 0x00010cb0 13982700 slli a6, a5, 2 ; arg6
+| :: 0x00010cb4 1d8f sub a4, a4, a5 ; arg6
+| :: 0x00010cb6 c296 add a3, a3, a6 ; arg4
+| :: 0x00010cb8 d7802002 vadd.vv v1, v2, v1
+| `==< 0x00010cbc 75f7 bnez a4, 0x10ca8
+| : 0x00010cbe d777000d vsetvli a5, zero, e0x20, m1, ta, ma ; arg6
+| : 0x00010cc2 57610042 vmv.s.x v2, zero
+| : 0x00010cc6 f32720c2 csrr a5, vlenb
+| : 0x00010cca d7201102 vredsum.vs v1, v1, v2
+| : 0x00010cce c107 addi a5, a5, 0x10 ; arg6
+| : 0x00010cd0 37070080 lui a4, 0x80000
+| : 0x00010cd4 3308f100 add a6, sp, a5 ; arg6
+| : 0x00010cd8 5741075e vmv.v.x v2, a4
+| : 0x00010cdc c286 mv a3, a6
+| : 0x00010cde 1147 li a4, 4
+| : 0x00010ce0 d7281042 vmv.x.s a7, v1
+| .--> 0x00010ce4 d777670c vsetvli a5, a4, e8, mf4, ta, ma ; arg6
+| :: 0x00010ce8 27e10602 vse32.v v2, (a3) ; arg4
+| :: 0x00010cec 1d8f sub a4, a4, a5 ; arg6
+| :: 0x00010cee 8a07 slli a5, a5, 2
+| :: 0x00010cf0 be96 add a3, a3, a5 ; arg6
+| `==< 0x00010cf2 6dfb bnez a4, 0x10ce4
+| : 0x00010cf4 577002cd vsetivli zero, 4, e0x20, m1, ta, ma
+| : 0x00010cf8 87600802 vle32.v v1, (a6)
+| .--> 0x00010cfc 07610502 vle32.v v2, (a0) ; arg1
+| :: 0x00010d00 4105 addi a0, a0, 0x10 ; arg1
+| :: 0x00010d02 d700111e vmax.vv v1, v1, v2
+| `==< 0x00010d06 e39baefe bne t4, a0, 0x10cfc
+| : 0x00010d0a a7600802 vse32.v v1, (a6)
+| : 0x00010d0e d777000d vsetvli a5, zero, e0x20, m1, ta, ma ; arg6
+| : 0x00010d12 d7400e5e vmv.v.x v1, t3
+| : 0x00010d16 c286 mv a3, a6
+| : 0x00010d18 1147 li a4, 4
+| : 0x00010d1a 5731109e vmv1r.v v2, v1
+| .--> 0x00010d1e d7770709 vsetvli a5, a4, e0x20, m1, tu, ma ; arg6
+| :: 0x00010d22 07e20602 vle32.v v4, (a3) ; arg4
+| :: 0x00010d26 13952700 slli a0, a5, 2 ; arg6
+| :: 0x00010d2a 1d8f sub a4, a4, a5 ; arg6
+| :: 0x00010d2c aa96 add a3, a3, a0 ; arg4
+| :: 0x00010d2e 5701411e vmax.vv v2, v4, v2
+| `==< 0x00010d32 75f7 bnez a4, 0x10d1e
+| : 0x00010d34 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x00010d38 b7070080 lui a5, 0x80000
+| : 0x00010d3c 57e20742 vmv.s.x v4, a5
+| : 0x00010d40 fd37 addiw a5, a5, -1 ; arg6
+| : 0x00010d42 5721221e vredmax.vs v2, v2, v4
+| : 0x00010d46 57c2075e vmv.v.x v4, a5
+| : 0x00010d4a f32720c2 csrr a5, vlenb
+| : 0x00010d4e 93870702 addi a5, a5, 0x20 ; arg6
+| : 0x00010d52 3305f100 add a0, sp, a5 ; arg6
+| : 0x00010d56 aa86 mv a3, a0
+| : 0x00010d58 1147 li a4, 4
+| : 0x00010d5a 572e2042 vmv.x.s t3, v2
+| .--> 0x00010d5e d777670c vsetvli a5, a4, e8, mf4, ta, ma ; arg6
+| :: 0x00010d62 27e20602 vse32.v v4, (a3) ; arg4
+| :: 0x00010d66 1d8f sub a4, a4, a5 ; arg6
+| :: 0x00010d68 8a07 slli a5, a5, 2
+| :: 0x00010d6a be96 add a3, a3, a5 ; arg6
+| `==< 0x00010d6c 6dfb bnez a4, 0x10d5e
+| : 0x00010d6e 577002cd vsetivli zero, 4, e0x20, m1, ta, ma
+| : 0x00010d72 07610502 vle32.v v2, (a0)
+| .--> 0x00010d76 07620302 vle32.v v4, (t1)
+| :: 0x00010d7a 4103 addi t1, t1, 0x10
+| :: 0x00010d7c 57012216 vmin.vv v2, v2, v4
+| `==< 0x00010d80 e39b6efe bne t4, t1, 0x10d76
+| : 0x00010d84 27610502 vse32.v v2, (a0)
+| : 0x00010d88 aa86 mv a3, a0
+| : 0x00010d8a 1147 li a4, 4
+| .--> 0x00010d8c d7770709 vsetvli a5, a4, e0x20, m1, tu, ma ; arg6
+| :: 0x00010d90 07e10602 vle32.v v2, (a3) ; arg4
+| :: 0x00010d94 13952700 slli a0, a5, 2 ; arg6
+| :: 0x00010d98 1d8f sub a4, a4, a5 ; arg6
+| :: 0x00010d9a aa96 add a3, a3, a0 ; arg4
+| :: 0x00010d9c d7802016 vmin.vv v1, v2, v1
+| `==< 0x00010da0 75f7 bnez a4, 0x10d8c
+| : 0x00010da2 b7070080 lui a5, 0x80000
+| : 0x00010da6 577002cd vsetivli zero, 4, e0x20, m1, ta, ma
+| : 0x00010daa fd37 addiw a5, a5, -1 ; arg6
+| : 0x00010dac 57e20742 vmv.s.x v4, a5
+| : 0x00010db0 57b10f5e vmv.v.i v2, -1
+| : 0x00010db4 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x00010db8 d7201216 vredmin.vs v1, v1, v4
+| : 0x00010dbc 0563 lui t1, 1
+| : 0x00010dbe 2e93 add t1, t1, a1 ; arg2
+| : 0x00010dc0 2e85 mv a0, a1
+| : 0x00010dc2 ae87 mv a5, a1
+| : 0x00010dc4 d7261042 vmv.x.s a3, v1
+| : 0x00010dc8 577002cd vsetivli zero, 4, e0x20, m1, ta, ma
+| .--> 0x00010dcc 87e00702 vle32.v v1, (a5) ; arg6
+| :: 0x00010dd0 c107 addi a5, a5, 0x10 ; arg6
+| :: 0x00010dd2 57812026 vand.vv v2, v2, v1
+| `==< 0x00010dd6 e39b67fe bne a5, t1, 0x10dcc
+| : 0x00010dda f32720c2 csrr a5, vlenb
+| : 0x00010dde 93870703 addi a5, a5, 0x30 ; arg6
+| : 0x00010de2 3308f100 add a6, sp, a5 ; arg6
+| : 0x00010de6 27610802 vse32.v v2, (a6)
+| : 0x00010dea 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x00010dee d7b00f5e vmv.v.i v1, -1
+| : 0x00010df2 1147 li a4, 4
+| .--> 0x00010df4 d7770709 vsetvli a5, a4, e0x20, m1, tu, ma ; arg6
+| :: 0x00010df8 07610802 vle32.v v2, (a6)
+| :: 0x00010dfc 939e2700 slli t4, a5, 2 ; arg6
+| :: 0x00010e00 1d8f sub a4, a4, a5 ; arg6
+| :: 0x00010e02 7698 add a6, a6, t4
+| :: 0x00010e04 d7802026 vand.vv v1, v2, v1
+| `==< 0x00010e08 75f7 bnez a4, 0x10df4
+| : 0x00010e0a 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x00010e0e fd57 li a5, -1
+| : 0x00010e10 57e20742 vmv.s.x v4, a5
+| : 0x00010e14 5731309e vmv1r.v v2, v3
+| : 0x00010e18 d7201206 vredand.vs v1, v1, v4
+| : 0x00010e1c 57271042 vmv.x.s a4, v1
+| : 0x00010e20 577002cd vsetivli zero, 4, e0x20, m1, ta, ma
+| .--> 0x00010e24 87e00502 vle32.v v1, (a1) ; arg2
+| :: 0x00010e28 c105 addi a1, a1, 0x10 ; arg2
+| :: 0x00010e2a 5781202a vor.vv v2, v2, v1
+| `==< 0x00010e2e e39b65fe bne a1, t1, 0x10e24
+| : 0x00010e32 f32720c2 csrr a5, vlenb
+| : 0x00010e36 93870704 addi a5, a5, 0x40 ; arg6
+| : 0x00010e3a 3308f100 add a6, sp, a5 ; arg6
+| : 0x00010e3e 27610802 vse32.v v2, (a6)
+| : 0x00010e42 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x00010e46 d730005e vmv.v.i v1, 0
+| : 0x00010e4a 9145 li a1, 4
+| .--> 0x00010e4c d7f70509 vsetvli a5, a1, e0x20, m1, tu, ma ; arg6
+| :: 0x00010e50 07610802 vle32.v v2, (a6)
+| :: 0x00010e54 939e2700 slli t4, a5, 2 ; arg6
+| :: 0x00010e58 9d8d sub a1, a1, a5 ; arg6
+| :: 0x00010e5a 7698 add a6, a6, t4
+| :: 0x00010e5c d780202a vor.vv v1, v2, v1
+| `==< 0x00010e60 f5f5 bnez a1, 0x10e4c
+| : 0x00010e62 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x00010e66 57620042 vmv.s.x v4, zero
+| : 0x00010e6a 5731309e vmv1r.v v2, v3
+| : 0x00010e6e d720120a vredor.vs v1, v1, v4
+| : 0x00010e72 d7271042 vmv.x.s a5, v1
+| : 0x00010e76 577002cd vsetivli zero, 4, e0x20, m1, ta, ma
+| .--> 0x00010e7a 87600502 vle32.v v1, (a0)
+| :: 0x00010e7e 4105 addi a0, a0, 0x10
+| :: 0x00010e80 5781202e vxor.vv v2, v2, v1
+| `==< 0x00010e84 e31b65fe bne a0, t1, 0x10e7a
+| : 0x00010e88 f32520c2 csrr a1, vlenb
+| : 0x00010e8c 93850505 addi a1, a1, 0x50 ; arg2
+| : 0x00010e90 3308b100 add a6, sp, a1 ; arg2
+| : 0x00010e94 27610802 vse32.v v2, (a6)
+| : 0x00010e98 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x00010e9c d730005e vmv.v.i v1, 0
+| : 0x00010ea0 9145 li a1, 4
+| .--> 0x00010ea2 57f50509 vsetvli a0, a1, e0x20, m1, tu, ma ; arg2
+| :: 0x00010ea6 07610802 vle32.v v2, (a6)
+| :: 0x00010eaa 13132500 slli t1, a0, 2
+| :: 0x00010eae 898d sub a1, a1, a0 ; arg2
+| :: 0x00010eb0 1a98 add a6, a6, t1
+| :: 0x00010eb2 d780202e vxor.vv v1, v2, v1
+| `==< 0x00010eb6 f5f5 bnez a1, 0x10ea2
+| : 0x00010eb8 577002cd vsetivli zero, 4, e0x20, m1, ta, ma
+| : 0x00010ebc d7610042 vmv.s.x v3, zero
+| : 0x00010ec0 5731005e vmv.v.i v2, 0
+| : 0x00010ec4 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x00010ec8 d7a0110e vredxor.vs v1, v1, v3
+| : 0x00010ecc 856f lui t6, 1
+| : 0x00010ece b29f add t6, t6, a2 ; arg3
+| : 0x00010ed0 328f mv t5, a2
+| : 0x00010ed2 b285 mv a1, a2
+| : 0x00010ed4 57281042 vmv.x.s a6, v1
+| : 0x00010ed8 577002cd vsetivli zero, 4, e0x20, m1, ta, ma
+| .--> 0x00010edc 87e00502 vle32.v v1, (a1) ; arg2
+| :: 0x00010ee0 c105 addi a1, a1, 0x10 ; arg2
+| :: 0x00010ee2 57912002 vfadd.vv v2, v2, v1
+| `==< 0x00010ee6 e39bbffe bne t6, a1, 0x10edc
+| : 0x00010eea f32520c2 csrr a1, vlenb
+| : 0x00010eee 93850506 addi a1, a1, 0x60 ; arg2
+| : 0x00010ef2 3303b100 add t1, sp, a1 ; arg2
+| : 0x00010ef6 27610302 vse32.v v2, (t1)
+| : 0x00010efa 530400f0 fmv.w.x fs0, zero
+| : 0x00010efe 9145 li a1, 4
+| .--> 0x00010f00 57f5650c vsetvli a0, a1, e8, mf4, ta, ma ; arg2
+| :: 0x00010f04 07610302 vle32.v v2, (t1)
+| :: 0x00010f08 57f000cd vsetivli zero, 1, e0x20, m1, ta, ma
+| :: 0x00010f0c d7500442 vfmv.s.f v1, fs0
+| :: 0x00010f10 5770050d vsetvli zero, a0, e0x20, m1, ta, ma
+| :: 0x00010f14 931e2500 slli t4, a0, 2
+| :: 0x00010f18 898d sub a1, a1, a0 ; arg2
+| :: 0x00010f1a d790200e vfredosum.vs v1, v2, v1
+| :: 0x00010f1e 7693 add t1, t1, t4
+| :: 0x00010f20 57141042 vfmv.f.s fs0, v1
+| `==< 0x00010f24 f1fd bnez a1, 0x10f00
+| : 0x00010f26 cd62 lui t0, 0x13 ; 0x13000 ; "P\U00000005\U00000001"
+| : 0x00010f28 07a78202 flw fa4, 0x28(t0)
+| : 0x00010f2c d775000d vsetvli a1, zero, e0x20, m1, ta, ma ; arg2
+| : 0x00010f30 732520c2 csrr a0, vlenb
+| : 0x00010f34 13050507 addi a0, a0, 0x70
+| : 0x00010f38 d750075e vfmv.v.f v1, fa4
+| : 0x00010f3c b30ea100 add t4, sp, a0
+| : 0x00010f40 7683 mv t1, t4
+| : 0x00010f42 9145 li a1, 4
+| .--> 0x00010f44 57f5650c vsetvli a0, a1, e8, mf4, ta, ma ; arg2
+| :: 0x00010f48 a7600302 vse32.v v1, (t1)
+| :: 0x00010f4c 898d sub a1, a1, a0 ; arg2
+| :: 0x00010f4e 0a05 slli a0, a0, 2
+| :: 0x00010f50 2a93 add t1, t1, a0
+| `==< 0x00010f52 edf9 bnez a1, 0x10f44
+| : 0x00010f54 577002cd vsetivli zero, 4, e0x20, m1, ta, ma
+| : 0x00010f58 87e00e02 vle32.v v1, (t4)
+| : 0x00010f5c 3285 mv a0, a2
+| .--> 0x00010f5e 07610502 vle32.v v2, (a0)
+| :: 0x00010f62 4105 addi a0, a0, 0x10
+| :: 0x00010f64 5710116e vmflt.vv v0, v1, v2
+| :: 0x00010f68 d700115c vmerge.vvm v1, v1, v2, v0
+| `==< 0x00010f6c e399affe bne t6, a0, 0x10f5e
+| : 0x00010f70 a7e00e02 vse32.v v1, (t4)
+| : 0x00010f74 5776000d vsetvli a2, zero, e0x20, m1, ta, ma ; arg3
+| : 0x00010f78 d7d0075e vfmv.v.f v1, fa5
+| : 0x00010f7c f685 mv a1, t4
+| : 0x00010f7e 1146 li a2, 4
+| : 0x00010f80 5731109e vmv1r.v v2, v1
+| .--> 0x00010f84 57750609 vsetvli a0, a2, e0x20, m1, tu, ma ; arg3
+| :: 0x00010f88 87e10502 vle32.v v3, (a1) ; arg2
+| :: 0x00010f8c 13132500 slli t1, a0, 2
+| :: 0x00010f90 098e sub a2, a2, a0 ; arg3
+| :: 0x00010f92 9a95 add a1, a1, t1 ; arg2
+| :: 0x00010f94 5711311a vfmax.vv v2, v3, v2
+| `==< 0x00010f98 75f6 bnez a2, 0x10f84
+| : 0x00010f9a 07a78202 flw fa4, 0x28(t0)
+| : 0x00010f9e 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x00010fa2 cd64 lui s1, 0x13 ; 0x13000 ; "P\U00000005\U00000001"
+| : 0x00010fa4 57520742 vfmv.s.f v4, fa4
+| : 0x00010fa8 87a7c402 flw fa5, 0x2c(s1)
+| : 0x00010fac 5711221e vfredmax.vs v2, v2, v4
+| : 0x00010fb0 732620c2 csrr a2, vlenb
+| : 0x00010fb4 13060608 addi a2, a2, 0x80 ; arg3
+| : 0x00010fb8 d7d1075e vfmv.v.f v3, fa5
+| : 0x00010fbc 0a96 add a2, a2, sp ; arg3
+| : 0x00010fbe 3283 mv t1, a2
+| : 0x00010fc0 9145 li a1, 4
+| : 0x00010fc2 d7142042 vfmv.f.s fs1, v2
+| .--> 0x00010fc6 57f5650c vsetvli a0, a1, e8, mf4, ta, ma ; arg2
+| :: 0x00010fca a7610302 vse32.v v3, (t1)
+| :: 0x00010fce 898d sub a1, a1, a0 ; arg2
+| :: 0x00010fd0 0a05 slli a0, a0, 2
+| :: 0x00010fd2 2a93 add t1, t1, a0
+| `==< 0x00010fd4 edf9 bnez a1, 0x10fc6
+| : 0x00010fd6 577002cd vsetivli zero, 4, e0x20, m1, ta, ma
+| : 0x00010fda 07610602 vle32.v v2, (a2) ; arg3
+| .--> 0x00010fde 87610f02 vle32.v v3, (t5)
+| :: 0x00010fe2 410f addi t5, t5, 0x10
+| :: 0x00010fe4 5710316e vmflt.vv v0, v3, v2
+| :: 0x00010fe8 5781215c vmerge.vvm v2, v2, v3, v0
+| `==< 0x00010fec e319ffff bne t5, t6, 0x10fde
+| : 0x00010ff0 27610602 vse32.v v2, (a2) ; arg3
+| : 0x00010ff4 9145 li a1, 4
+| .--> 0x00010ff6 57f50509 vsetvli a0, a1, e0x20, m1, tu, ma ; arg2
+| :: 0x00010ffa 07610602 vle32.v v2, (a2) ; arg3
+| :: 0x00010ffe 13132500 slli t1, a0, 2
+| :: 0x00011002 898d sub a1, a1, a0 ; arg2
+| :: 0x00011004 1a96 add a2, a2, t1 ; arg3
+| :: 0x00011006 d7101112 vfmin.vv v1, v1, v2
+| `==< 0x0001100a f5f5 bnez a1, 0x10ff6
+| : 0x0001100c 4965 lui a0, 0x12
+| : 0x0001100e 7286 mv a2, t3
+| : 0x00011010 c685 mv a1, a7
+| : 0x00011012 1305859c addi a0, a0, -0x638
+| : 0x00011016 a7008102 vs1r.v v1, (sp)
+| : 0x0001101a eff06fd8 jal sym.imp.printf ; int printf(const char *format)
+| : 0x0001101e 87608102 vl1re32.v v1, (sp)
+| : 0x00011022 87a7c402 flw fa5, 0x2c(s1)
+| : 0x00011026 5774000d vsetvli s0, zero, e0x20, m1, ta, ma
+| : 0x0001102a 53870442 fcvt.d.s fa4, fs1
+| : 0x0001102e 57d10742 vfmv.s.f v2, fa5
+| : 0x00011032 f32220c2 csrr t0, vlenb
+| : 0x00011036 d7101116 vfredmin.vs v1, v1, v2
+| : 0x0001103a 530607e2 fmv.x.d a2, fa4
+| : 0x0001103e 53070442 fcvt.d.s fa4, fs0
+| : 0x00011042 1691 add sp, sp, t0
+| : 0x00011044 ea70 ld ra, 0xb8(sp)
+| : 0x00011046 4a74 ld s0, 0xb0(sp)
+| : 0x00011048 aa74 ld s1, 0xa8(sp)
+| : 0x0001104a d7171042 vfmv.f.s fa5, v1
+| : 0x0001104e 6a24 fld fs0, 0x98(sp)
+| : 0x00011050 d3870742 fcvt.d.s fa5, fa5
+| : 0x00011054 ca24 fld fs1, 0x90(sp)
+| : 0x00011056 d30507e2 fmv.x.d a1, fa4
+| : 0x0001105a d38607e2 fmv.x.d a3, fa5
+| : 0x0001105e 4965 lui a0, 0x12
+| : 0x00011060 130505a0 addi a0, a0, -0x600
+| : 0x00011064 2961 addi sp, sp, 0xc0
+\ `=< 0x00011066 6ff0afd3 j sym.imp.printf
+EOF
+RUN
+
+
+NAME=Vector instructions: vector sign injection
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x0001156e d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011572 87e00802 vle32.v v1, (a7) ; arg8
+| : 0x00011576 07e10502 vle32.v v2, (a1) ; arg2
+| : 0x0001157a 13982700 slli a6, a5, 2 ; arg6
+| : 0x0001157e 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011580 c298 add a7, a7, a6 ; arg8
+| : 0x00011582 c295 add a1, a1, a6 ; arg2
+| : 0x00011584 d7101122 vfsgnj.vv v1, v1, v2
+| : 0x00011588 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x0001158c c296 add a3, a3, a6 ; arg4
+| `=< 0x0001158e 65f3 bnez a4, 0x1156e
+| 0x00011590 b286 mv a3, a2
+| 0x00011592 aa85 mv a1, a0
+| 0x00011594 13070040 li a4, 0x400
+| .-> 0x00011598 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x0001159c 87e00502 vle32.v v1, (a1) ; arg2
+| : 0x000115a0 13982700 slli a6, a5, 2 ; arg6
+| : 0x000115a4 1d8f sub a4, a4, a5 ; arg6
+| : 0x000115a6 c295 add a1, a1, a6 ; arg2
+| : 0x000115a8 d790102a vfabs.v v1, v1
+| : 0x000115ac a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000115b0 c296 add a3, a3, a6 ; arg4
+| `=< 0x000115b2 7df3 bnez a4, 0x11598
+| 0x000115b4 87a7c180 flw fa5, -0x7f4(gp)
+| 0x000115b8 d777000d vsetvli a5, zero, e0x20, m1, ta, ma ; arg6
+| 0x000115bc 13070040 li a4, 0x400
+| 0x000115c0 57d1075e vfmv.v.f v2, fa5
+| .-> 0x000115c4 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000115c8 87600502 vle32.v v1, (a0) ; arg1
+| : 0x000115cc 93962700 slli a3, a5, 2 ; arg6
+| : 0x000115d0 1d8f sub a4, a4, a5 ; arg6
+| : 0x000115d2 3695 add a0, a0, a3 ; arg1
+| : 0x000115d4 d7101122 vfsgnj.vv v1, v1, v2
+| : 0x000115d8 a7600602 vse32.v v1, (a2) ; arg3
+| : 0x000115dc 3696 add a2, a2, a3 ; arg3
+| `=< 0x000115de 7df3 bnez a4, 0x115c4
+\ 0x000115e0 8280 ret
+EOF
+RUN
+
+
+NAME=Vector instructions: vector saturating
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x0001126e d777f70c vsetvli a5, a4, e0x10, mf2, ta, ma ; arg6
+| : 0x00011272 87520302 vle16.v v5, (t1)
+| : 0x00011276 07d20802 vle16.v v4, (a7) ; arg8
+| : 0x0001127a 13981700 slli a6, a5, 1 ; arg6
+| : 0x0001127e 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011280 c298 add a7, a7, a6 ; arg8
+| : 0x00011282 4293 add t1, t1, a6
+| : 0x00011284 d72052c6 vwadd.vv v1, v5, v4
+| : 0x00011288 5770000d vsetvli zero, zero, e0x20, m1, ta, ma
+| : 0x0001128c d780111e vmax.vv v1, v1, v3
+| : 0x00011290 d7001116 vmin.vv v1, v1, v2
+| : 0x00011294 5770f00c vsetvli zero, zero, e0x10, mf2, ta, ma
+| : 0x00011298 d73010b2 vnsrl.wi v1, v1, 0
+| : 0x0001129c a7d00602 vse16.v v1, (a3) ; arg4
+| : 0x000112a0 c296 add a3, a3, a6 ; arg4
+| `=< 0x000112a2 71f7 bnez a4, 0x1126e
+| 0x000112a4 13070040 li a4, 0x400
+| .-> 0x000112a8 d777f70c vsetvli a5, a4, e0x10, mf2, ta, ma ; arg6
+| : 0x000112ac 87520502 vle16.v v5, (a0) ; arg1
+| : 0x000112b0 07d20502 vle16.v v4, (a1) ; arg2
+| : 0x000112b4 93961700 slli a3, a5, 1 ; arg6
+| : 0x000112b8 1d8f sub a4, a4, a5 ; arg6
+| : 0x000112ba 3695 add a0, a0, a3 ; arg1
+| : 0x000112bc b695 add a1, a1, a3 ; arg2
+| : 0x000112be d72052ce vwsub.vv v1, v5, v4
+| : 0x000112c2 5770000d vsetvli zero, zero, e0x20, m1, ta, ma
+| : 0x000112c6 d780111e vmax.vv v1, v1, v3
+| : 0x000112ca d7001116 vmin.vv v1, v1, v2
+| : 0x000112ce 5770f00c vsetvli zero, zero, e0x10, mf2, ta, ma
+| : 0x000112d2 d73010b2 vnsrl.wi v1, v1, 0
+| : 0x000112d6 a7500602 vse16.v v1, (a2) ; arg3
+| : 0x000112da 3696 add a2, a2, a3 ; arg3
+| `=< 0x000112dc 71f7 bnez a4, 0x112a8
+\ 0x000112de 8280 ret
+EOF
+RUN
+
+
+NAME=Vector instructions: vector unsigned operations
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x0001190a d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x0001190e 07e10802 vle32.v v2, (a7) ; arg8
+| : 0x00011912 87600302 vle32.v v1, (t1)
+| : 0x00011916 13982700 slli a6, a5, 2 ; arg6
+| : 0x0001191a 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001191c c298 add a7, a7, a6 ; arg8
+| : 0x0001191e 4293 add t1, t1, a6
+| : 0x00011920 d700111a vmaxu.vv v1, v1, v2
+| : 0x00011924 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x00011928 c296 add a3, a3, a6 ; arg4
+| `=< 0x0001192a 65f3 bnez a4, 0x1190a
+| 0x0001192c 13070040 li a4, 0x400
+| .-> 0x00011930 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011934 07e10502 vle32.v v2, (a1) ; arg2
+| : 0x00011938 87600502 vle32.v v1, (a0) ; arg1
+| : 0x0001193c 93962700 slli a3, a5, 2 ; arg6
+| : 0x00011940 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011942 b695 add a1, a1, a3 ; arg2
+| : 0x00011944 3695 add a0, a0, a3 ; arg1
+| : 0x00011946 d7001112 vminu.vv v1, v1, v2
+| : 0x0001194a a7600602 vse32.v v1, (a2) ; arg3
+| : 0x0001194e 3696 add a2, a2, a3 ; arg3
+| `=< 0x00011950 65f3 bnez a4, 0x11930
+\ 0x00011952 8280 ret
+EOF
+RUN
+
+
+NAME=Vector instructions: vector minmax
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x000118b6 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000118ba 07e10802 vle32.v v2, (a7) ; arg8
+| : 0x000118be 87600302 vle32.v v1, (t1)
+| : 0x000118c2 13982700 slli a6, a5, 2 ; arg6
+| : 0x000118c6 1d8f sub a4, a4, a5 ; arg6
+| : 0x000118c8 c298 add a7, a7, a6 ; arg8
+| : 0x000118ca 4293 add t1, t1, a6
+| : 0x000118cc d700111e vmax.vv v1, v1, v2
+| : 0x000118d0 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000118d4 c296 add a3, a3, a6 ; arg4
+| `=< 0x000118d6 65f3 bnez a4, 0x118b6
+| 0x000118d8 13070040 li a4, 0x400
+| .-> 0x000118dc d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000118e0 07e10502 vle32.v v2, (a1) ; arg2
+| : 0x000118e4 87600502 vle32.v v1, (a0) ; arg1
+| : 0x000118e8 93962700 slli a3, a5, 2 ; arg6
+| : 0x000118ec 1d8f sub a4, a4, a5 ; arg6
+| : 0x000118ee b695 add a1, a1, a3 ; arg2
+| : 0x000118f0 3695 add a0, a0, a3 ; arg1
+| : 0x000118f2 d7001116 vmin.vv v1, v1, v2
+| : 0x000118f6 a7600602 vse32.v v1, (a2) ; arg3
+| : 0x000118fa 3696 add a2, a2, a3 ; arg3
+| `=< 0x000118fc 65f3 bnez a4, 0x118dc
+\ 0x000118fe 8280 ret
+EOF
+RUN
+
+
+NAME=Vector instructions: vector fused multiply-add
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x00011422 d777080d vsetvli a5, a6, e0x20, m1, ta, ma ; arg6
+| : 0x00011426 87600302 vle32.v v1, (t1)
+| : 0x0001142a 87610e02 vle32.v v3, (t3)
+| : 0x0001142e 07e10e02 vle32.v v2, (t4)
+| : 0x00011432 13972700 slli a4, a5, 2 ; arg6
+| : 0x00011436 3308f840 sub a6, a6, a5 ; arg6
+| : 0x0001143a 3a93 add t1, t1, a4
+| : 0x0001143c 3a9e add t3, t3, a4
+| : 0x0001143e ba9e add t4, t4, a4
+| : 0x00011440 d79021a2 vfmadd.vv v1, v3, v2
+| : 0x00011444 a7e00802 vse32.v v1, (a7) ; arg8
+| : 0x00011448 ba98 add a7, a7, a4 ; arg8
+| `=< 0x0001144a e31c08fc bnez a6, 0x11422
+| 0x0001144e b688 mv a7, a3
+| 0x00011450 b28e mv t4, a2
+| 0x00011452 2e8e mv t3, a1
+| 0x00011454 2a83 mv t1, a0
+| 0x00011456 13080040 li a6, 0x400
+| .-> 0x0001145a d777080d vsetvli a5, a6, e0x20, m1, ta, ma ; arg6
+| : 0x0001145e 87610302 vle32.v v3, (t1)
+| : 0x00011462 87600e02 vle32.v v1, (t3)
+| : 0x00011466 07e10e02 vle32.v v2, (t4)
+| : 0x0001146a 13972700 slli a4, a5, 2 ; arg6
+| : 0x0001146e 3308f840 sub a6, a6, a5 ; arg6
+| : 0x00011472 3a93 add t1, t1, a4
+| : 0x00011474 3a9e add t3, t3, a4
+| : 0x00011476 ba9e add t4, t4, a4
+| : 0x00011478 d79021aa vfmsub.vv v1, v3, v2
+| : 0x0001147c a7e00802 vse32.v v1, (a7) ; arg8
+| : 0x00011480 ba98 add a7, a7, a4 ; arg8
+| `=< 0x00011482 e31c08fc bnez a6, 0x1145a
+| 0x00011486 13080040 li a6, 0x400
+| .-> 0x0001148a d777080d vsetvli a5, a6, e0x20, m1, ta, ma ; arg6
+| : 0x0001148e 07610602 vle32.v v2, (a2) ; arg3
+| : 0x00011492 87610502 vle32.v v3, (a0) ; arg1
+| : 0x00011496 87e00502 vle32.v v1, (a1) ; arg2
+| : 0x0001149a 13972700 slli a4, a5, 2 ; arg6
+| : 0x0001149e 3308f840 sub a6, a6, a5 ; arg6
+| : 0x000114a2 3a96 add a2, a2, a4 ; arg3
+| : 0x000114a4 3a95 add a0, a0, a4 ; arg1
+| : 0x000114a6 ba95 add a1, a1, a4 ; arg2
+| : 0x000114a8 d79021ae vfnmsub.vv v1, v3, v2
+| : 0x000114ac a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000114b0 ba96 add a3, a3, a4 ; arg4
+| `=< 0x000114b2 e31c08fc bnez a6, 0x1148a
+\ 0x000114b6 8280 ret
+EOF
+RUN
+
+
+NAME=Vector instructions: vector float operations
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x0001136c d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011370 87e00802 vle32.v v1, (a7) ; arg8
+| : 0x00011374 07610302 vle32.v v2, (t1)
+| : 0x00011378 13982700 slli a6, a5, 2 ; arg6
+| : 0x0001137c 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001137e c298 add a7, a7, a6 ; arg8
+| : 0x00011380 4293 add t1, t1, a6
+| : 0x00011382 d7101102 vfadd.vv v1, v1, v2
+| : 0x00011386 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x0001138a c296 add a3, a3, a6 ; arg4
+| `=< 0x0001138c 65f3 bnez a4, 0x1136c
+| 0x0001138e b286 mv a3, a2
+| 0x00011390 2e83 mv t1, a1
+| 0x00011392 aa88 mv a7, a0
+| 0x00011394 13070040 li a4, 0x400
+| .-> 0x00011398 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x0001139c 87e00802 vle32.v v1, (a7) ; arg8
+| : 0x000113a0 07610302 vle32.v v2, (t1)
+| : 0x000113a4 13982700 slli a6, a5, 2 ; arg6
+| : 0x000113a8 1d8f sub a4, a4, a5 ; arg6
+| : 0x000113aa c298 add a7, a7, a6 ; arg8
+| : 0x000113ac 4293 add t1, t1, a6
+| : 0x000113ae d710110a vfsub.vv v1, v1, v2
+| : 0x000113b2 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000113b6 c296 add a3, a3, a6 ; arg4
+| `=< 0x000113b8 65f3 bnez a4, 0x11398
+| 0x000113ba b286 mv a3, a2
+| 0x000113bc aa88 mv a7, a0
+| 0x000113be 13070040 li a4, 0x400
+| .-> 0x000113c2 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000113c6 87e00802 vle32.v v1, (a7) ; arg8
+| : 0x000113ca 07e10502 vle32.v v2, (a1) ; arg2
+| : 0x000113ce 13982700 slli a6, a5, 2 ; arg6
+| : 0x000113d2 1d8f sub a4, a4, a5 ; arg6
+| : 0x000113d4 c298 add a7, a7, a6 ; arg8
+| : 0x000113d6 c295 add a1, a1, a6 ; arg2
+| : 0x000113d8 d7101182 vfdiv.vv v1, v1, v2
+| : 0x000113dc a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000113e0 c296 add a3, a3, a6 ; arg4
+| `=< 0x000113e2 65f3 bnez a4, 0x113c2
+| 0x000113e4 d777000d vsetvli a5, zero, e0x20, m1, ta, ma ; arg6
+| 0x000113e8 5731005e vmv.v.i v2, 0
+| 0x000113ec 13070040 li a4, 0x400
+| .-> 0x000113f0 d7770705 vsetvli a5, a4, e0x20, m1, ta, mu ; arg6
+| : 0x000113f4 87600502 vle32.v v1, (a0) ; arg1
+| : 0x000113f8 d731209e vmv1r.v v3, v2
+| : 0x000113fc 93962700 slli a3, a5, 2 ; arg6
+| : 0x00011400 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011402 3695 add a0, a0, a3 ; arg1
+| : 0x00011404 5790206e vmflt.vv v0, v2, v1
+| : 0x00011408 d711104c vfsqrt.v v3, v1, v0.t
+| : 0x0001140c a7610602 vse32.v v3, (a2) ; arg3
+| : 0x00011410 3696 add a2, a2, a3 ; arg3
+| `=< 0x00011412 79ff bnez a4, 0x113f0
+\ 0x00011414 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: floating point operations
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x0001136c d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011370 87e00802 vle32.v v1, (a7) ; arg8
+| : 0x00011374 07610302 vle32.v v2, (t1)
+| : 0x00011378 13982700 slli a6, a5, 2 ; arg6
+| : 0x0001137c 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001137e c298 add a7, a7, a6 ; arg8
+| : 0x00011380 4293 add t1, t1, a6
+| : 0x00011382 d7101102 vfadd.vv v1, v1, v2
+| : 0x00011386 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x0001138a c296 add a3, a3, a6 ; arg4
+| `=< 0x0001138c 65f3 bnez a4, 0x1136c
+| 0x0001138e b286 mv a3, a2
+| 0x00011390 2e83 mv t1, a1
+| 0x00011392 aa88 mv a7, a0
+| 0x00011394 13070040 li a4, 0x400
+| .-> 0x00011398 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x0001139c 87e00802 vle32.v v1, (a7) ; arg8
+| : 0x000113a0 07610302 vle32.v v2, (t1)
+| : 0x000113a4 13982700 slli a6, a5, 2 ; arg6
+| : 0x000113a8 1d8f sub a4, a4, a5 ; arg6
+| : 0x000113aa c298 add a7, a7, a6 ; arg8
+| : 0x000113ac 4293 add t1, t1, a6
+| : 0x000113ae d710110a vfsub.vv v1, v1, v2
+| : 0x000113b2 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000113b6 c296 add a3, a3, a6 ; arg4
+| `=< 0x000113b8 65f3 bnez a4, 0x11398
+| 0x000113ba b286 mv a3, a2
+| 0x000113bc aa88 mv a7, a0
+| 0x000113be 13070040 li a4, 0x400
+| .-> 0x000113c2 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000113c6 87e00802 vle32.v v1, (a7) ; arg8
+| : 0x000113ca 07e10502 vle32.v v2, (a1) ; arg2
+| : 0x000113ce 13982700 slli a6, a5, 2 ; arg6
+| : 0x000113d2 1d8f sub a4, a4, a5 ; arg6
+| : 0x000113d4 c298 add a7, a7, a6 ; arg8
+| : 0x000113d6 c295 add a1, a1, a6 ; arg2
+| : 0x000113d8 d7101182 vfdiv.vv v1, v1, v2
+| : 0x000113dc a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000113e0 c296 add a3, a3, a6 ; arg4
+| `=< 0x000113e2 65f3 bnez a4, 0x113c2
+| 0x000113e4 d777000d vsetvli a5, zero, e0x20, m1, ta, ma ; arg6
+| 0x000113e8 5731005e vmv.v.i v2, 0
+| 0x000113ec 13070040 li a4, 0x400
+| .-> 0x000113f0 d7770705 vsetvli a5, a4, e0x20, m1, ta, mu ; arg6
+| : 0x000113f4 87600502 vle32.v v1, (a0) ; arg1
+| : 0x000113f8 d731209e vmv1r.v v3, v2
+| : 0x000113fc 93962700 slli a3, a5, 2 ; arg6
+| : 0x00011400 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011402 3695 add a0, a0, a3 ; arg1
+| : 0x00011404 5790206e vmflt.vv v0, v2, v1
+| : 0x00011408 d711104c vfsqrt.v v3, v1, v0.t
+| : 0x0001140c a7610602 vse32.v v3, (a2) ; arg3
+| : 0x00011410 3696 add a2, a2, a3 ; arg3
+| `=< 0x00011412 79ff bnez a4, 0x113f0
+\ 0x00011414 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: widening operations
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x000112ea d777f70c vsetvli a5, a4, e0x10, mf2, ta, ma ; arg6
+| : 0x000112ee 87d10802 vle16.v v3, (a7) ; arg8
+| : 0x000112f2 07510802 vle16.v v2, (a6) ; arg7
+| : 0x000112f6 13931700 slli t1, a5, 1 ; arg6
+| : 0x000112fa 139e2700 slli t3, a5, 2 ; arg6
+| : 0x000112fe 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011300 1a98 add a6, a6, t1 ; arg7
+| : 0x00011302 9a98 add a7, a7, t1 ; arg8
+| : 0x00011304 d72031c6 vwadd.vv v1, v3, v2
+| : 0x00011308 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x0001130c f296 add a3, a3, t3 ; arg4
+| `=< 0x0001130e 71ff bnez a4, 0x112ea
+| 0x00011310 13070040 li a4, 0x400
+| .-> 0x00011314 d777f70c vsetvli a5, a4, e0x10, mf2, ta, ma ; arg6
+| : 0x00011318 87d10502 vle16.v v3, (a1) ; arg2
+| : 0x0001131c 07510502 vle16.v v2, (a0) ; arg1
+| : 0x00011320 93961700 slli a3, a5, 1 ; arg6
+| : 0x00011324 13982700 slli a6, a5, 2 ; arg6
+| : 0x00011328 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001132a 3695 add a0, a0, a3 ; arg1
+| : 0x0001132c b695 add a1, a1, a3 ; arg2
+| : 0x0001132e d72031ee vwmul.vv v1, v3, v2
+| : 0x00011332 a7600602 vse32.v v1, (a2) ; arg3
+| : 0x00011336 4296 add a2, a2, a6 ; arg3
+| `=< 0x00011338 71ff bnez a4, 0x11314
+\ 0x0001133a 8280 ret
+EOF
+RUN
+
+
+NAME=Vector instructions: comparisons
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x00011074 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011078 07e10802 vle32.v v2, (a7) ; arg8
+| : 0x0001107c 87600302 vle32.v v1, (t1)
+| : 0x00011080 13982700 slli a6, a5, 2 ; arg6
+| : 0x00011084 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011086 c298 add a7, a7, a6 ; arg8
+| : 0x00011088 4293 add t1, t1, a6
+| : 0x0001108a d7001116 vmin.vv v1, v1, v2
+| : 0x0001108e a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x00011092 c296 add a3, a3, a6 ; arg4
+| `=< 0x00011094 65f3 bnez a4, 0x11074
+| 0x00011096 5773000d vsetvli t1, zero, e0x20, m1, ta, ma
+| 0x0001109a 5731005e vmv.v.i v2, 0
+| 0x0001109e b286 mv a3, a2
+| 0x000110a0 aa88 mv a7, a0
+| 0x000110a2 13070040 li a4, 0x400
+| .-> 0x000110a6 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000110aa 87e00802 vle32.v v1, (a7) ; arg8
+| : 0x000110ae 07e00502 vle32.v v0, (a1) ; arg2
+| : 0x000110b2 13982700 slli a6, a5, 2 ; arg6
+| : 0x000110b6 1d8f sub a4, a4, a5 ; arg6
+| : 0x000110b8 c295 add a1, a1, a6 ; arg2
+| : 0x000110ba c298 add a7, a7, a6 ; arg8
+| : 0x000110bc 57800062 vmseq.vv v0, v0, v1
+| : 0x000110c0 d7b0205c vmerge.vim v1, v2, 1, v0
+| : 0x000110c4 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000110c8 c296 add a3, a3, a6 ; arg4
+| `=< 0x000110ca 71ff bnez a4, 0x110a6
+| 0x000110cc d777000d vsetvli a5, zero, e0x20, m1, ta, ma ; arg6
+| 0x000110d0 5731005e vmv.v.i v2, 0
+| 0x000110d4 13073006 li a4, 0x63
+| 0x000110d8 d741075e vmv.v.x v3, a4
+| 0x000110dc 13070040 li a4, 0x400
+| .-> 0x000110e0 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000110e4 87600502 vle32.v v1, (a0) ; arg1
+| : 0x000110e8 93962700 slli a3, a5, 2 ; arg6
+| : 0x000110ec 1d8f sub a4, a4, a5 ; arg6
+| : 0x000110ee 3695 add a0, a0, a3 ; arg1
+| : 0x000110f0 5780306e vmslt.vv v0, v3, v1
+| : 0x000110f4 d780205c vmerge.vvm v1, v2, v1, v0
+| : 0x000110f8 a7600602 vse32.v v1, (a2) ; arg3
+| : 0x000110fc 3696 add a2, a2, a3 ; arg3
+| `=< 0x000110fe 6df3 bnez a4, 0x110e0
+\ 0x00011100 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: clipping
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x00011840 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011844 87600502 vle32.v v1, (a0) ; arg1
+| : 0x00011848 93962700 slli a3, a5, 2 ; arg6
+| : 0x0001184c 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001184e 3695 add a0, a0, a3 ; arg1
+| : 0x00011850 d780111e vmax.vv v1, v1, v3
+| : 0x00011854 d7001116 vmin.vv v1, v1, v2
+| : 0x00011858 a7e00502 vse32.v v1, (a1) ; arg2
+| : 0x0001185c b695 add a1, a1, a3 ; arg2
+| `=< 0x0001185e 6df3 bnez a4, 0x11840
+\ 0x00011860 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: conversions
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x00011528 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x0001152c 87600502 vle32.v v1, (a0) ; arg1
+| : 0x00011530 13982700 slli a6, a5, 2 ; arg6
+| : 0x00011534 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011536 4295 add a0, a0, a6 ; arg1
+| : 0x00011538 d790114a vfcvt.f.x.v v1, v1
+| : 0x0001153c a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x00011540 c296 add a3, a3, a6 ; arg4
+| `=< 0x00011542 7df3 bnez a4, 0x11528
+| 0x00011544 13070040 li a4, 0x400
+| .-> 0x00011548 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x0001154c 87e00502 vle32.v v1, (a1) ; arg2
+| : 0x00011550 93962700 slli a3, a5, 2 ; arg6
+| : 0x00011554 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011556 b695 add a1, a1, a3 ; arg2
+| : 0x00011558 d790134a vfcvt.rtz.x.f.v v1, v1
+| : 0x0001155c a7600602 vse32.v v1, (a2) ; arg3
+| : 0x00011560 3696 add a2, a2, a3 ; arg3
+| `=< 0x00011562 7df3 bnez a4, 0x11548
+\ 0x00011564 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: narrowing
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x00011340 d777f70c vsetvli a5, a4, e0x10, mf2, ta, ma ; arg6
+| : 0x00011344 87600502 vle32.v v1, (a0) ; arg1
+| : 0x00011348 13962700 slli a2, a5, 2 ; arg6
+| : 0x0001134c 93961700 slli a3, a5, 1 ; arg6
+| : 0x00011350 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011352 3295 add a0, a0, a2 ; arg1
+| : 0x00011354 d73014b6 vnsra.wi v1, v1, 8
+| : 0x00011358 a7d00502 vse16.v v1, (a1) ; arg2
+| : 0x0001135c b695 add a1, a1, a3 ; arg2
+| `=< 0x0001135e 6df3 bnez a4, 0x11340
+\ 0x00011360 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: average
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x0001180c d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011810 07610502 vle32.v v2, (a0) ; arg1
+| : 0x00011814 87e00502 vle32.v v1, (a1) ; arg2
+| : 0x00011818 93962700 slli a3, a5, 2 ; arg6
+| : 0x0001181c 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001181e 3695 add a0, a0, a3 ; arg1
+| : 0x00011820 b695 add a1, a1, a3 ; arg2
+| : 0x00011822 d7201122 vaaddu.vv v1, v1, v2
+| : 0x00011826 a7600602 vse32.v v1, (a2) ; arg3
+| : 0x0001182a 3696 add a2, a2, a3 ; arg3
+| `=< 0x0001182c 65f3 bnez a4, 0x1180c
+\ 0x0001182e 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: segment access
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x00011746 d777080d vsetvli a5, a6, e0x20, m1, ta, ma ; arg6
+| : 0x0001174a 87610502 vle32.v v3, (a0) ; arg1
+| : 0x0001174e 07e10502 vle32.v v2, (a1) ; arg2
+| : 0x00011752 87600602 vle32.v v1, (a2) ; arg3
+| : 0x00011756 13972700 slli a4, a5, 2 ; arg6
+| : 0x0001175a 3308f840 sub a6, a6, a5 ; arg6
+| : 0x0001175e 3a95 add a0, a0, a4 ; arg1
+| : 0x00011760 ba95 add a1, a1, a4 ; arg2
+| : 0x00011762 57912102 vfadd.vv v2, v2, v3
+| : 0x00011766 3a96 add a2, a2, a4 ; arg3
+| : 0x00011768 d7101102 vfadd.vv v1, v1, v2
+| : 0x0001176c a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x00011770 ba96 add a3, a3, a4 ; arg4
+| `=< 0x00011772 e31a08fc bnez a6, 0x11746
+\ 0x00011776 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: floating point comparisons
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x000114c2 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000114c6 07e10802 vle32.v v2, (a7) ; arg8
+| : 0x000114ca 87600302 vle32.v v1, (t1)
+| : 0x000114ce 13982700 slli a6, a5, 2 ; arg6
+| : 0x000114d2 1d8f sub a4, a4, a5 ; arg6
+| : 0x000114d4 c298 add a7, a7, a6 ; arg8
+| : 0x000114d6 4293 add t1, t1, a6
+| : 0x000114d8 5790206e vmflt.vv v0, v2, v1
+| : 0x000114dc d700115c vmerge.vvm v1, v1, v2, v0
+| : 0x000114e0 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000114e4 c296 add a3, a3, a6 ; arg4
+| `=< 0x000114e6 71ff bnez a4, 0x114c2
+| 0x000114e8 577e000d vsetvli t3, zero, e0x20, m1, ta, ma
+| 0x000114ec d731005e vmv.v.i v3, 0
+| 0x000114f0 13070040 li a4, 0x400
+| .-> 0x000114f4 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000114f8 07610502 vle32.v v2, (a0) ; arg1
+| : 0x000114fc 07e00502 vle32.v v0, (a1) ; arg2
+| : 0x00011500 87a78180 flw fa5, -0x7f8(gp)
+| : 0x00011504 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011506 93962700 slli a3, a5, 2 ; arg6
+| : 0x0001150a d7d0075e vfmv.v.f v1, fa5
+| : 0x0001150e 57100162 vmfeq.vv v0, v0, v2
+| : 0x00011512 b695 add a1, a1, a3 ; arg2
+| : 0x00011514 3695 add a0, a0, a3 ; arg1
+| : 0x00011516 d780305c vmerge.vvm v1, v3, v1, v0
+| : 0x0001151a a7600602 vse32.v v1, (a2) ; arg3
+| : 0x0001151e 3696 add a2, a2, a3 ; arg3
+| `=< 0x00011520 71fb bnez a4, 0x114f4
+\ 0x00011522 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: multi byte
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x0001177c d777870d vsetvli a5, a4, e0x40, m1, ta, ma ; arg6
+| : 0x00011780 07710502 vle64.v v2, (a0) ; arg1
+| : 0x00011784 87f00502 vle64.v v1, (a1) ; arg2
+| : 0x00011788 93963700 slli a3, a5, 3 ; arg6
+| : 0x0001178c 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001178e 3695 add a0, a0, a3 ; arg1
+| : 0x00011790 b695 add a1, a1, a3 ; arg2
+| : 0x00011792 d7001102 vadd.vv v1, v1, v2
+| : 0x00011796 a7700602 vse64.v v1, (a2) ; arg3
+| : 0x0001179a 3696 add a2, a2, a3 ; arg3
+| `=< 0x0001179c 65f3 bnez a4, 0x1177c
+\ 0x0001179e 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: shifts
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x0001110a d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x0001110e 87600802 vle32.v v1, (a6) ; arg7
+| : 0x00011112 93982700 slli a7, a5, 2 ; arg6
+| : 0x00011116 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011118 4698 add a6, a6, a7 ; arg7
+| : 0x0001111a d7b01196 vsll.vi v1, v1, 3
+| : 0x0001111e a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x00011122 c696 add a3, a3, a7 ; arg4
+| `=< 0x00011124 7df3 bnez a4, 0x1110a
+| 0x00011126 b286 mv a3, a2
+| 0x00011128 2a88 mv a6, a0
+| 0x0001112a 13070040 li a4, 0x400
+| .-> 0x0001112e d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011132 87600802 vle32.v v1, (a6) ; arg7
+| : 0x00011136 93982700 slli a7, a5, 2 ; arg6
+| : 0x0001113a 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001113c 4698 add a6, a6, a7 ; arg7
+| : 0x0001113e d73011a2 vsrl.vi v1, v1, 2
+| : 0x00011142 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x00011146 c696 add a3, a3, a7 ; arg4
+| `=< 0x00011148 7df3 bnez a4, 0x1112e
+| 0x0001114a b286 mv a3, a2
+| 0x0001114c 13070040 li a4, 0x400
+| .-> 0x00011150 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011154 87e00502 vle32.v v1, (a1) ; arg2
+| : 0x00011158 13982700 slli a6, a5, 2 ; arg6
+| : 0x0001115c 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001115e c295 add a1, a1, a6 ; arg2
+| : 0x00011160 d73012a6 vsra.vi v1, v1, 4
+| : 0x00011164 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x00011168 c296 add a3, a3, a6 ; arg4
+| `=< 0x0001116a 7df3 bnez a4, 0x11150
+| 0x0001116c d777000d vsetvli a5, zero, e0x20, m1, ta, ma ; arg6
+| 0x00011170 57a10852 vid.v v2
+| 0x00011174 13070040 li a4, 0x400
+| .-> 0x00011178 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x0001117c 87600502 vle32.v v1, (a0) ; arg1
+| : 0x00011180 57b22326 vand.vi v4, v2, 7
+| : 0x00011184 d775000d vsetvli a1, zero, e0x20, m1, ta, ma ; arg2
+| : 0x00011188 d7c1075e vmv.v.x v3, a5
+| : 0x0001118c 57f0070d vsetvli zero, a5, e0x20, m1, ta, ma ; arg6
+| : 0x00011190 93952700 slli a1, a5, 2 ; arg6
+| : 0x00011194 d7001296 vsll.vv v1, v1, v4
+| : 0x00011198 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001119a 2e95 add a0, a0, a1 ; arg1
+| : 0x0001119c a7600602 vse32.v v1, (a2) ; arg3
+| : 0x000111a0 d777000d vsetvli a5, zero, e0x20, m1, ta, ma ; arg6
+| : 0x000111a4 57812102 vadd.vv v2, v2, v3
+| : 0x000111a8 2e96 add a2, a2, a1 ; arg3
+| `=< 0x000111aa 79f7 bnez a4, 0x11178
+\ 0x000111ac 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: strided access
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x000115ea d777670c vsetvli a5, a4, e8, mf4, ta, ma ; arg6
+| : 0x000115ee 07610622 vlseg2e32.v v2, (a2) ; arg3
+| : 0x000115f2 93983700 slli a7, a5, 3 ; arg6
+| : 0x000115f6 13982700 slli a6, a5, 2 ; arg6
+| : 0x000115fa 1d8f sub a4, a4, a5 ; arg6
+| : 0x000115fc 4696 add a2, a2, a7 ; arg3
+| : 0x000115fe 27e10602 vse32.v v2, (a3) ; arg4
+| : 0x00011602 c296 add a3, a3, a6 ; arg4
+| `=< 0x00011604 7df3 bnez a4, 0x115ea
+| 0x00011606 0567 lui a4, 1
+| 0x00011608 b307e500 add a5, a0, a4 ; arg1
+| 0x0001160c 87a787ff flw fa5, -8(a5)
+| 0x00011610 732620c2 csrr a2, vlenb
+| 0x00011614 93582600 srli a7, a2, 2 ; arg3
+| 0x00011618 9387f8ff addi a5, a7, -1
+| 0x0001161c 27aef57e fsw fa5, 0x7fc(a1) ; arg2
+| 0x00011620 1b880700 sext.w a6, a5
+| 0x00011624 9306f03f li a3, 0x3ff
+| ,=< 0x00011628 63e80611 bltu a3, a6, 0x11738
+| | 0x0001162c 5773000d vsetvli t1, zero, e0x20, m1, ta, ma
+| | 0x00011630 d7a10852 vid.v v3
+| | 0x00011634 118f sub a4, a4, a2 ; arg3
+| | 0x00011636 33081041 neg a6, a7
+| | 0x0001163a d7c1370e vrsub.vx v3, v3, a5
+| | 0x0001163e 2e97 add a4, a4, a1 ; arg2
+| | 0x00011640 1b080840 addiw a6, a6, 0x400
+| | 0x00011644 aa86 mv a3, a0
+| | 0x00011646 8147 li a5, 0
+| .--> 0x00011648 07e18602 vl1re32.v v2, (a3)
+| :| 0x0001164c bb871701 addw a5, a5, a7
+| :| 0x00011650 b296 add a3, a3, a2 ; arg3
+| :| 0x00011652 d7802132 vrgather.vv v1, v2, v3
+| :| 0x00011656 a7008702 vs1r.v v1, (a4)
+| :| 0x0001165a 118f sub a4, a4, a2 ; arg3
+| `==< 0x0001165c e376f8fe bgeu a6, a5, 0x11648
+| | 0x00011660 93060040 li a3, 0x400
+| ,==< 0x00011664 6389d70c beq a5, a3, 0x11736
+| || 0x00011668 bb8ef640 subw t4, a3, a5
+| || 0x0001166c 3e88 mv a6, a5
+| || ; CODE XREF from sym.test_strided_access @ 0x11740
+| .---> 0x0001166e 732320c2 csrr t1, vlenb
+| :|| 0x00011672 93563300 srli a3, t1, 3
+| :|| 0x00011676 9388f6ff addi a7, a3, -1
+| :|| 0x0001167a 1307f03f li a4, 0x3ff
+| :|| 0x0001167e 1b860800 sext.w a2, a7
+| :|| 0x00011682 1d9f subw a4, a4, a5
+| ,====< 0x00011684 636cc706 bltu a4, a2, 0x116fc
+| |:|| 0x00011688 13970702 slli a4, a5, 0x20
+| |:|| 0x0001168c 135ee701 srli t3, a4, 0x1e
+| |:|| 0x00011690 5776700d vsetvli a2, zero, e0x20, mf2, ta, ma
+| |:|| 0x00011694 330fc501 add t5, a0, t3 ; arg1
+| |:|| 0x00011698 87610f02 vle32.v v3, (t5)
+| |:|| 0x0001169c d7a00852 vid.v v1
+| |:|| 0x000116a0 935f1300 srli t6, t1, 1
+| |:|| 0x000116a4 d7c0180e vrsub.vx v1, v1, a7
+| |:|| 0x000116a8 0567 lui a4, 1
+| |:|| 0x000116aa 3307f741 sub a4, a4, t6
+| |:|| 0x000116ae 57813032 vrgather.vv v2, v3, v1
+| |:|| 0x000116b2 3307c741 sub a4, a4, t3
+| |:|| 0x000116b6 2e97 add a4, a4, a1 ; arg2
+| |:|| 0x000116b8 27610702 vse32.v v2, (a4)
+| |:|| 0x000116bc b308d040 neg a7, a3
+| |:|| 0x000116c0 93880840 addi a7, a7, 0x400
+| |:|| 0x000116c4 bb88f840 subw a7, a7, a5
+| |:|| 0x000116c8 130e0040 li t3, 0x400
+| |:|| 0x000116cc 8126 sext.w a3, a3
+| |:|| 0x000116ce bb07fe40 subw a5, t3, a5
+| ,=====< 0x000116d2 63efd800 bltu a7, a3, 0x116f0
+| ||:|| 0x000116d6 7e9f add t5, t5, t6
+| ||:|| 0x000116d8 87610f02 vle32.v v3, (t5)
+| ||:|| 0x000116dc 3307f741 sub a4, a4, t6
+| ||:|| 0x000116e0 13532300 srli t1, t1, 2
+| ||:|| 0x000116e4 9b060300 sext.w a3, t1
+| ||:|| 0x000116e8 57813032 vrgather.vv v2, v3, v1
+| ||:|| 0x000116ec 27610702 vse32.v v2, (a4)
+| ,`-----> 0x000116f0 6383d704 beq a5, a3, 0x11736
+| | |:|| 0x000116f4 3b880601 addw a6, a3, a6
+| | |:|| 0x000116f8 bb8ede40 subw t4, t4, a3
+| | `----> 0x000116fc 9b86feff addiw a3, t4, -1
+| | :|| 0x00011700 1387f57f addi a4, a1, 0x7ff ; arg2
+| | :|| 0x00011704 0a08 slli a6, a6, 2
+| | :|| 0x00011706 1307977f addi a4, a4, 0x7f9
+| | :|| 0x0001170a 13960602 slli a2, a3, 0x20
+| | :|| 0x0001170e 9387f57f addi a5, a1, 0x7ff ; arg2
+| | :|| 0x00011712 9356e601 srli a3, a2, 0x1e
+| | :|| 0x00011716 33070741 sub a4, a4, a6
+| | :|| 0x0001171a 9387d77f addi a5, a5, 0x7fd
+| | :|| 0x0001171e 4295 add a0, a0, a6 ; arg1
+| | :|| 0x00011720 158f sub a4, a4, a3
+| | :|| 0x00011722 b3870741 sub a5, a5, a6
+| | .----> 0x00011726 87270500 flw fa5, 0(a0) ; arg1
+| | ::|| 0x0001172a f117 addi a5, a5, -4
+| | ::|| 0x0001172c 1105 addi a0, a0, 4 ; arg1
+| | ::|| 0x0001172e 27a2f700 fsw fa5, 4(a5)
+| | `====< 0x00011732 e31af7fe bne a4, a5, 0x11726
+| `---`--> 0x00011736 8280 ret
+| : `-> 0x00011738 8147 li a5, 0
+| : 0x0001173a 930e0040 li t4, 0x400
+| : 0x0001173e 0148 li a6, 0
+\ `===< 0x00011740 3db7 j 0x1166e
+EOF
+RUN
+
+NAME=Vector instructions: absolute value and negation
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x0001186a d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x0001186e 87600602 vle32.v v1, (a2) ; arg3
+| : 0x00011872 13982700 slli a6, a5, 2 ; arg6
+| : 0x00011876 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011878 4296 add a2, a2, a6 ; arg3
+| : 0x0001187a 5731100e vrsub.vi v2, v1, 0
+| : 0x0001187e d700111e vmax.vv v1, v1, v2
+| : 0x00011882 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x00011886 c296 add a3, a3, a6 ; arg4
+| `=< 0x00011888 6df3 bnez a4, 0x1186a
+| 0x0001188a 13070040 li a4, 0x400
+| .-> 0x0001188e d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011892 87600502 vle32.v v1, (a0) ; arg1
+| : 0x00011896 93962700 slli a3, a5, 2 ; arg6
+| : 0x0001189a 1d8f sub a4, a4, a5 ; arg6
+| : 0x0001189c 3695 add a0, a0, a3 ; arg1
+| : 0x0001189e d730100e vrsub.vi v1, v1, 0
+| : 0x000118a2 a7e00502 vse32.v v1, (a1) ; arg2
+| : 0x000118a6 b695 add a1, a1, a3 ; arg2
+| `=< 0x000118a8 7df3 bnez a4, 0x1188e
+\ 0x000118aa 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: main function
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x000105f2 0566 lui a2, 1
+| 0x000105f4 93050004 li a1, 0x40
+| 0x000105f8 0819 addi a0, sp, 0xb0
+| 0x000105fa eff07ff8 jal sym.imp.posix_memalign
+| 0x000105fe 014b li s6, 0
+| ,=< 0x00010600 11e1 bnez a0, 0x10604
+| | 0x00010602 4a7b ld s6, 0xb0(sp)
+| `-> 0x00010604 0566 lui a2, 1
+| 0x00010606 93050004 li a1, 0x40
+| 0x0001060a 2811 addi a0, sp, 0xa8
+| 0x0001060c eff05ff7 jal sym.imp.posix_memalign
+| 0x00010610 02f0 sd zero, 0x20(sp)
+| ,=< 0x00010612 19e1 bnez a0, 0x10618
+| | 0x00010614 aa77 ld a5, 0xa8(sp)
+| | 0x00010616 3ef0 sd a5, 0x20(sp)
+| `-> 0x00010618 0566 lui a2, 1
+| 0x0001061a 93050004 li a1, 0x40
+| 0x0001061e 0811 addi a0, sp, 0xa0
+| 0x00010620 eff01ff6 jal sym.imp.posix_memalign
+| 0x00010624 014a li s4, 0
+| ,=< 0x00010626 11e1 bnez a0, 0x1062a
+| | 0x00010628 0a7a ld s4, 0xa0(sp)
+| `-> 0x0001062a 0566 lui a2, 1
+| 0x0001062c 13060680 addi a2, a2, -0x800
+| 0x00010630 93050004 li a1, 0x40
+| 0x00010634 2809 addi a0, sp, 0x98
+| 0x00010636 eff0bff4 jal sym.imp.posix_memalign
+| 0x0001063a 814c li s9, 0
+| ,=< 0x0001063c 11e1 bnez a0, 0x10640
+| | 0x0001063e ea6c ld s9, 0x98(sp)
+| `-> 0x00010640 0566 lui a2, 1
+| 0x00010642 13060680 addi a2, a2, -0x800
+| 0x00010646 93050004 li a1, 0x40
+| 0x0001064a 0809 addi a0, sp, 0x90
+| 0x0001064c eff05ff3 jal sym.imp.posix_memalign
+| 0x00010650 814d li s11, 0
+| ,=< 0x00010652 11e1 bnez a0, 0x10656
+| | 0x00010654 ca6d ld s11, 0x90(sp)
+| `-> 0x00010656 0566 lui a2, 1
+| 0x00010658 13060680 addi a2, a2, -0x800
+| 0x0001065c 93050004 li a1, 0x40
+| 0x00010660 2801 addi a0, sp, 0x88
+| 0x00010662 eff0fff1 jal sym.imp.posix_memalign
+| 0x00010666 02ec sd zero, 0x18(sp)
+| ,=< 0x00010668 19e1 bnez a0, 0x1066e
+| | 0x0001066a aa67 ld a5, 0x88(sp)
+| | 0x0001066c 3eec sd a5, 0x18(sp)
+| `-> 0x0001066e 13060040 li a2, 0x400
+| 0x00010672 93050004 li a1, 0x40
+| 0x00010676 0801 addi a0, sp, 0x80
+| 0x00010678 eff09ff0 jal sym.imp.posix_memalign
+| 0x0001067c 02e8 sd zero, 0x10(sp)
+| ,=< 0x0001067e 19e1 bnez a0, 0x10684
+| | 0x00010680 8a67 ld a5, 0x80(sp)
+| | 0x00010682 3ee8 sd a5, 0x10(sp)
+| `-> 0x00010684 0966 lui a2, 2
+| 0x00010686 93050004 li a1, 0x40
+| 0x0001068a a818 addi a0, sp, 0x78
+| 0x0001068c eff05fef jal sym.imp.posix_memalign
+| 0x00010690 02e4 sd zero, 8(sp)
+| ,=< 0x00010692 19e1 bnez a0, 0x10698
+| | 0x00010694 e677 ld a5, 0x78(sp)
+| | 0x00010696 3ee4 sd a5, 8(sp)
+| `-> 0x00010698 0966 lui a2, 2
+| 0x0001069a 93050004 li a1, 0x40
+| 0x0001069e 8818 addi a0, sp, 0x70
+| 0x000106a0 eff01fee jal sym.imp.posix_memalign
+| 0x000106a4 02e0 sd zero, 0(sp)
+| ,=< 0x000106a6 19e1 bnez a0, 0x106ac
+| | 0x000106a8 c677 ld a5, 0x70(sp)
+| | 0x000106aa 3ee0 sd a5, 0(sp)
+| `-> 0x000106ac 0966 lui a2, 2
+| 0x000106ae 93050004 li a1, 0x40
+| 0x000106b2 a810 addi a0, sp, 0x68
+| 0x000106b4 eff0dfec jal sym.imp.posix_memalign
+| 0x000106b8 02f4 sd zero, 0x28(sp)
+| ,=< 0x000106ba 19e1 bnez a0, 0x106c0
+| | 0x000106bc a677 ld a5, 0x68(sp)
+| | 0x000106be 3ef4 sd a5, 0x28(sp)
+| `-> 0x000106c0 0566 lui a2, 1
+| 0x000106c2 93050004 li a1, 0x40
+| 0x000106c6 8810 addi a0, sp, 0x60
+| 0x000106c8 eff09feb jal sym.imp.posix_memalign
+| 0x000106cc 8144 li s1, 0
+| ,=< 0x000106ce 11e1 bnez a0, 0x106d2
+| | 0x000106d0 8674 ld s1, 0x60(sp)
+| `-> 0x000106d2 0566 lui a2, 1
+| 0x000106d4 93050004 li a1, 0x40
+| 0x000106d8 a808 addi a0, sp, 0x58
+| 0x000106da eff07fea jal sym.imp.posix_memalign
+| 0x000106de 8149 li s3, 0
+| ,=< 0x000106e0 11e1 bnez a0, 0x106e4
+| | 0x000106e2 e669 ld s3, 0x58(sp)
+| `-> 0x000106e4 0566 lui a2, 1
+| 0x000106e6 93050004 li a1, 0x40
+| 0x000106ea 8808 addi a0, sp, 0x50
+| 0x000106ec eff05fe9 jal sym.imp.posix_memalign
+| 0x000106f0 014d li s10, 0
+| ,=< 0x000106f2 11e1 bnez a0, 0x106f6
+| | 0x000106f4 466d ld s10, 0x50(sp)
+| `-> 0x000106f6 0566 lui a2, 1
+| 0x000106f8 93050004 li a1, 0x40
+| 0x000106fc a800 addi a0, sp, 0x48
+| 0x000106fe eff03fe8 jal sym.imp.posix_memalign
+| 0x00010702 0149 li s2, 0
+| ,=< 0x00010704 11e1 bnez a0, 0x10708
+| | 0x00010706 2669 ld s2, 0x48(sp)
+| `-> 0x00010708 93050004 li a1, 0x40
+| 0x0001070c 0566 lui a2, 1
+| 0x0001070e 3305b100 add a0, sp, a1
+| 0x00010712 eff0ffe6 jal sym.imp.posix_memalign
+| 0x00010716 814a li s5, 0
+| ,=< 0x00010718 11e1 bnez a0, 0x1071c
+| | 0x0001071a 866a ld s5, 0x40(sp)
+| `-> 0x0001071c 0566 lui a2, 1
+| 0x0001071e 93050004 li a1, 0x40
+| 0x00010722 2818 addi a0, sp, 0x38
+| 0x00010724 eff0dfe5 jal sym.imp.posix_memalign
+| 0x00010728 014c li s8, 0
+| ,=< 0x0001072a 11e1 bnez a0, 0x1072e
+| | 0x0001072c 627c ld s8, 0x38(sp)
+| `-> 0x0001072e 0566 lui a2, 1
+| 0x00010730 93050004 li a1, 0x40
+| 0x00010734 0818 addi a0, sp, 0x30
+| 0x00010736 eff0bfe4 jal sym.imp.posix_memalign
+| 0x0001073a 814b li s7, 0
+| ,=< 0x0001073c 11e1 bnez a0, 0x10740
+| | 0x0001073e c27b ld s7, 0x30(sp)
+| `-> 0x00010740 5777000d vsetvli a4, zero, e0x20, m1, ta, ma
+| 0x00010744 93064006 li a3, 0x64
+| 0x00010748 57c4065e vmv.v.x v8, a3
+| 0x0001074c 93060040 li a3, 0x400
+| 0x00010750 57c9065e vmv.v.x v18, a3
+| 0x00010754 9306f007 li a3, 0x7f
+| 0x00010758 d7c8065e vmv.v.x v17, a3
+| 0x0001075c b787eb51 lui a5, 0x51eb8
+| 0x00010760 930600e0 li a3, -0x200
+| 0x00010764 57c8065e vmv.v.x v16, a3
+| 0x00010768 9b87f751 addiw a5, a5, 0x51f
+| 0x0001076c 9306f00f li a3, 0xff
+| 0x00010770 d7c7065e vmv.v.x v15, a3
+| 0x00010774 d7c9075e vmv.v.x v19, a5
+| 0x00010778 930600e0 li a3, -0x200
+| 0x0001077c 5770f00c vsetvli zero, zero, e0x10, mf2, ta, ma
+| 0x00010780 57c7065e vmv.v.x v14, a3
+| 0x00010784 9306f007 li a3, 0x7f
+| 0x00010788 5770600c vsetvli zero, zero, e8, mf4, ta, ma
+| 0x0001078c d7c6065e vmv.v.x v13, a3
+| 0x00010790 87a70181 flw fa5, -0x7f0(gp)
+| 0x00010794 5770000d vsetvli zero, zero, e0x20, m1, ta, ma
+| 0x00010798 07a78180 flw fa4, -0x7f8(gp)
+| 0x0001079c d7b5015e vmv.v.i v11, 3
+| 0x000107a0 57b5035e vmv.v.i v10, 7
+| 0x000107a4 d7b4065e vmv.v.i v9, 0xd
+| 0x000107a8 4263 ld t1, 0x10(sp)
+| 0x000107aa 0275 ld a0, 0x20(sp)
+| 0x000107ac c546 li a3, 0x11
+| 0x000107ae d7a00852 vid.v v1
+| 0x000107b2 57c6065e vmv.v.x v12, a3
+| 0x000107b6 e282 mv t0, s8
+| 0x000107b8 d68f mv t6, s5
+| 0x000107ba 6a8f mv t5, s10
+| 0x000107bc ce8e mv t4, s3
+| 0x000107be 268e mv t3, s1
+| 0x000107c0 ee88 mv a7, s11
+| 0x000107c2 6688 mv a6, s9
+| 0x000107c4 da85 mv a1, s6
+| 0x000107c6 2286 mv a2, s0
+| 0x000107c8 93060040 li a3, 0x400
+| .-> 0x000107cc d7f7060d vsetvli a5, a3, e0x20, m1, ta, ma
+| : 0x000107d0 d7011802 vadd.vv v3, v1, v16
+| : 0x000107d4 57211596 vmul.vv v2, v1, v10
+| : 0x000107d8 d7a31596 vmul.vv v7, v1, v11
+| : 0x000107dc a7610602 vse32.v v3, (a2)
+| : 0x000107e0 5770f00c vsetvli zero, zero, e0x10, mf2, ta, ma
+| : 0x000107e4 d73110b2 vnsrl.wi v3, v1, 0
+| : 0x000107e8 5770000d vsetvli zero, zero, e0x20, m1, ta, ma
+| : 0x000107ec 57812726 vand.vv v2, v2, v15
+| : 0x000107f0 d7837826 vand.vv v7, v7, v17
+| : 0x000107f4 d792114a vfcvt.f.x.v v5, v1
+| : 0x000107f8 5770f00c vsetvli zero, zero, e0x10, mf2, ta, ma
+| : 0x000107fc 27e10502 vse32.v v2, (a1)
+| : 0x00010800 d70a3702 vadd.vv v21, v3, v14
+| : 0x00010804 5770000d vsetvli zero, zero, e0x20, m1, ta, ma
+| : 0x00010808 5783200b vsub.vv v6, v18, v1
+| : 0x0001080c 57a1199e vmulh.vv v2, v1, v19
+| : 0x00010810 d7d25782 vfdiv.vf v5, v5, fa5
+| : 0x00010814 5770f00c vsetvli zero, zero, e0x10, mf2, ta, ma
+| : 0x00010818 573a70b2 vnsrl.wi v20, v7, 0
+| : 0x0001081c 5770000d vsetvli zero, zero, e0x20, m1, ta, ma
+| : 0x00010820 a7630502 vse32.v v7, (a0)
+| : 0x00010824 a75a0802 vse16.v v21, (a6)
+| : 0x00010828 5792614a vfcvt.f.x.v v4, v6
+| : 0x0001082c 57b122a6 vsra.vi v2, v2, 5
+| : 0x00010830 13972700 slli a4, a5, 2
+| : 0x00010834 57d24782 vfdiv.vf v4, v4, fa5
+| : 0x00010838 5770600c vsetvli zero, zero, e8, mf4, ta, ma
+| : 0x0001083c d73130b2 vnsrl.wi v3, v3, 0
+| : 0x00010840 5770000d vsetvli zero, zero, e0x20, m1, ta, ma
+| : 0x00010844 27da0802 vse16.v v20, (a7)
+| : 0x00010848 572114ae vnmsub.vv v2, v8, v1
+| : 0x0001084c d7a31496 vmul.vv v7, v1, v9
+| : 0x00010850 5770600c vsetvli zero, zero, e8, mf4, ta, ma
+| : 0x00010854 d7813626 vand.vv v3, v3, v13
+| : 0x00010858 5770000d vsetvli zero, zero, e0x20, m1, ta, ma
+| : 0x0001085c 5791214a vfcvt.f.x.v v2, v2
+| : 0x00010860 a7010302 vse8.v v3, (t1)
+| : 0x00010864 d7525702 vfadd.vf v5, v5, fa4
+| : 0x00010868 57d12782 vfdiv.vf v2, v2, fa5
+| : 0x0001086c 57236696 vmul.vv v6, v6, v12
+| : 0x00010870 d773000d vsetvli t2, zero, e0x20, m1, ta, ma
+| : 0x00010874 57ca075e vmv.v.x v20, a5
+| : 0x00010878 57f0070d vsetvli zero, a5, e0x20, m1, ta, ma
+| : 0x0001087c a7620e02 vse32.v v5, (t3)
+| : 0x00010880 d7514702 vfadd.vf v3, v4, fa4
+| : 0x00010884 d773000d vsetvli t2, zero, e0x20, m1, ta, ma
+| : 0x00010888 d7001a02 vadd.vv v1, v1, v20
+| : 0x0001088c 57f0070d vsetvli zero, a5, e0x20, m1, ta, ma
+| : 0x00010890 93931700 slli t2, a5, 1
+| : 0x00010894 a7e10e02 vse32.v v3, (t4)
+| : 0x00010898 9d8e sub a3, a3, a5
+| : 0x0001089a 3e93 add t1, t1, a5
+| : 0x0001089c 3a96 add a2, a2, a4
+| : 0x0001089e ba95 add a1, a1, a4
+| : 0x000108a0 3a95 add a0, a0, a4
+| : 0x000108a2 27610f02 vse32.v v2, (t5)
+| : 0x000108a6 a7e30f02 vse32.v v7, (t6)
+| : 0x000108aa 3a9e add t3, t3, a4
+| : 0x000108ac ba9e add t4, t4, a4
+| : 0x000108ae 3a9f add t5, t5, a4
+| : 0x000108b0 ba9f add t6, t6, a4
+| : 0x000108b2 1e98 add a6, a6, t2
+| : 0x000108b4 27e30202 vse32.v v6, (t0)
+| : 0x000108b8 9e98 add a7, a7, t2
+| : 0x000108ba ba92 add t0, t0, a4
+| `=< 0x000108bc 81fa bnez a3, 0x107cc
+| 0x000108be d777700d vsetvli a5, zero, e0x20, mf2, ta, ma
+| 0x000108c2 1307803e li a4, 0x3e8
+| 0x000108c6 0266 ld a2, 0(sp)
+| 0x000108c8 a266 ld a3, 8(sp)
+| 0x000108ca d741075e vmv.v.x v3, a4
+| 0x000108ce d7a00852 vid.v v1
+| 0x000108d2 13070040 li a4, 0x400
+| 0x000108d6 5743075e vmv.v.x v6, a4
+| 0x000108da 13070020 li a4, 0x200
+| .-> 0x000108de d777770d vsetvli a5, a4, e0x20, mf2, ta, ma
+| : 0x000108e2 57a21196 vmul.vv v4, v1, v3
+| : 0x000108e6 5781600a vsub.vv v2, v6, v1
+| : 0x000108ea 5770800d vsetvli zero, zero, e0x40, m1, ta, ma
+| : 0x000108ee 13953700 slli a0, a5, 3
+| : 0x000108f2 d7a2434a vsext.vf2 v5, v4
+| : 0x000108f6 5770700d vsetvli zero, zero, e0x20, mf2, ta, ma
+| : 0x000108fa 57a12196 vmul.vv v2, v2, v3
+| : 0x000108fe d775700d vsetvli a1, zero, e0x20, mf2, ta, ma
+| : 0x00010902 57c2075e vmv.v.x v4, a5
+| : 0x00010906 57f0870d vsetvli zero, a5, e0x40, m1, ta, ma
+| : 0x0001090a a7f20602 vse64.v v5, (a3)
+| : 0x0001090e d7a2234a vsext.vf2 v5, v2
+| : 0x00010912 1d8f sub a4, a4, a5
+| : 0x00010914 aa96 add a3, a3, a0
+| : 0x00010916 a7720602 vse64.v v5, (a2)
+| : 0x0001091a d775700d vsetvli a1, zero, e0x20, mf2, ta, ma
+| : 0x0001091e d7001202 vadd.vv v1, v1, v4
+| : 0x00010922 2a96 add a2, a2, a0
+| `=< 0x00010924 4dff bnez a4, 0x108de
+| 0x00010926 4965 lui a0, 0x12
+| 0x00010928 130585a2 addi a0, a0, -0x5d8
+| 0x0001092c eff05fc6 jal sym.imp.puts ; int puts(const char *s)
+| 0x00010930 ce86 mv a3, s3
+| 0x00010932 2686 mv a2, s1
+| 0x00010934 da85 mv a1, s6
+| 0x00010936 2285 mv a0, s0
+| 0x00010938 ef00e031 jal sym.test_reductions
+| 0x0001093c 5286 mv a2, s4
+| 0x0001093e da85 mv a1, s6
+| 0x00010940 2285 mv a0, s0
+| 0x00010942 ef008072 jal sym.test_comparisons
+| 0x00010946 5e86 mv a2, s7
+| 0x00010948 a285 mv a1, s0
+| 0x0001094a 5685 mv a0, s5
+| 0x0001094c ef00607b jal sym.test_shifts
+| 0x00010950 5e86 mv a2, s7
+| 0x00010952 e285 mv a1, s8
+| 0x00010954 5685 mv a0, s5
+| 0x00010956 ef009005 jal sym.test_bitwise
+| 0x0001095a 6266 ld a2, 0x18(sp)
+| 0x0001095c ee85 mv a1, s11
+| 0x0001095e 6685 mv a0, s9
+| 0x00010960 ef00300f jal sym.test_saturating
+| 0x00010964 5286 mv a2, s4
+| 0x00010966 ee85 mv a1, s11
+| 0x00010968 6685 mv a0, s9
+| 0x0001096a ef007017 jal sym.test_widening
+| 0x0001096e e266 ld a3, 0x18(sp)
+| 0x00010970 2286 mv a2, s0
+| 0x00010972 13070040 li a4, 0x400
+| .-> 0x00010976 d777f70c vsetvli a5, a4, e0x10, mf2, ta, ma
+| : 0x0001097a 87600602 vle32.v v1, (a2)
+| : 0x0001097e 13952700 slli a0, a5, 2
+| : 0x00010982 93951700 slli a1, a5, 1
+| : 0x00010986 1d8f sub a4, a4, a5
+| : 0x00010988 2a96 add a2, a2, a0
+| : 0x0001098a d73014b6 vnsra.wi v1, v1, 8
+| : 0x0001098e a7d00602 vse16.v v1, (a3)
+| : 0x00010992 ae96 add a3, a3, a1
+| `=< 0x00010994 6df3 bnez a4, 0x10976
+| 0x00010996 4a86 mv a2, s2
+| 0x00010998 ce85 mv a1, s3
+| 0x0001099a 2685 mv a0, s1
+| 0x0001099c ef00701c jal sym.test_float_ops
+| 0x000109a0 ca86 mv a3, s2
+| 0x000109a2 6a86 mv a2, s10
+| 0x000109a4 ce85 mv a1, s3
+| 0x000109a6 2685 mv a0, s1
+| 0x000109a8 ef00f026 jal sym.test_fma
+| 0x000109ac 4a86 mv a2, s2
+| 0x000109ae ce85 mv a1, s3
+| 0x000109b0 2685 mv a0, s1
+| 0x000109b2 ef007030 jal sym.test_float_comparisons
+| 0x000109b6 ca86 mv a3, s2
+| 0x000109b8 2286 mv a2, s0
+| 0x000109ba 13070040 li a4, 0x400
+| .-> 0x000109be d777070d vsetvli a5, a4, e0x20, m1, ta, ma
+| : 0x000109c2 87600602 vle32.v v1, (a2)
+| : 0x000109c6 93952700 slli a1, a5, 2
+| : 0x000109ca 1d8f sub a4, a4, a5
+| : 0x000109cc 2e96 add a2, a2, a1
+| : 0x000109ce d790114a vfcvt.f.x.v v1, v1
+| : 0x000109d2 a7e00602 vse32.v v1, (a3)
+| : 0x000109d6 ae96 add a3, a3, a1
+| `=< 0x000109d8 7df3 bnez a4, 0x109be
+| 0x000109da d286 mv a3, s4
+| 0x000109dc 2686 mv a2, s1
+| 0x000109de 13070040 li a4, 0x400
+| .-> 0x000109e2 d777070d vsetvli a5, a4, e0x20, m1, ta, ma
+| : 0x000109e6 87600602 vle32.v v1, (a2)
+| : 0x000109ea 93952700 slli a1, a5, 2
+| : 0x000109ee 1d8f sub a4, a4, a5
+| : 0x000109f0 2e96 add a2, a2, a1
+| : 0x000109f2 d790134a vfcvt.rtz.x.f.v v1, v1
+| : 0x000109f6 a7e00602 vse32.v v1, (a3)
+| : 0x000109fa ae96 add a3, a3, a1
+| `=< 0x000109fc 7df3 bnez a4, 0x109e2
+| 0x000109fe 4a86 mv a2, s2
+| 0x00010a00 ce85 mv a1, s3
+| 0x00010a02 2685 mv a0, s1
+| 0x00010a04 ef003036 jal sym.test_sign_injection
+| 0x00010a08 ca85 mv a1, s2
+| 0x00010a0a 2685 mv a0, s1
+| 0x00010a0c ef00703d jal sym.test_strided_access
+| 0x00010a10 4a86 mv a2, s2
+| 0x00010a12 6a88 mv a6, s10
+| 0x00010a14 4e85 mv a0, s3
+| 0x00010a16 a685 mv a1, s1
+| 0x00010a18 93060040 li a3, 0x400
+| .-> 0x00010a1c d7f7060d vsetvli a5, a3, e0x20, m1, ta, ma
+| : 0x00010a20 87e10502 vle32.v v3, (a1)
+| : 0x00010a24 07610502 vle32.v v2, (a0)
+| : 0x00010a28 87600802 vle32.v v1, (a6)
+| : 0x00010a2c 13972700 slli a4, a5, 2
+| : 0x00010a30 9d8e sub a3, a3, a5
+| : 0x00010a32 ba95 add a1, a1, a4
+| : 0x00010a34 3a95 add a0, a0, a4
+| : 0x00010a36 57912102 vfadd.vv v2, v2, v3
+| : 0x00010a3a 3a98 add a6, a6, a4
+| : 0x00010a3c d7101102 vfadd.vv v1, v1, v2
+| : 0x00010a40 a7600602 vse32.v v1, (a2)
+| : 0x00010a44 3a96 add a2, a2, a4
+| `=< 0x00010a46 f9fa bnez a3, 0x10a1c
+| 0x00010a48 a276 ld a3, 0x28(sp)
+| 0x00010a4a 0265 ld a0, 0(sp)
+| 0x00010a4c a265 ld a1, 8(sp)
+| 0x00010a4e 13070020 li a4, 0x200
+| .-> 0x00010a52 d777870d vsetvli a5, a4, e0x40, m1, ta, ma
+| : 0x00010a56 07f10502 vle64.v v2, (a1)
+| : 0x00010a5a 87700502 vle64.v v1, (a0)
+| : 0x00010a5e 13963700 slli a2, a5, 3
+| : 0x00010a62 1d8f sub a4, a4, a5
+| : 0x00010a64 b295 add a1, a1, a2
+| : 0x00010a66 3295 add a0, a0, a2
+| : 0x00010a68 d7001102 vadd.vv v1, v1, v2
+| : 0x00010a6c a7f00602 vse64.v v1, (a3)
+| : 0x00010a70 b296 add a3, a3, a2
+| `=< 0x00010a72 65f3 bnez a4, 0x10a52
+| 0x00010a74 4265 ld a0, 0x10(sp)
+| 0x00010a76 2286 mv a2, s0
+| 0x00010a78 e685 mv a1, s9
+| 0x00010a7a ef007052 jal sym.test_mixed_width
+| 0x00010a7e 13064006 li a2, 0x64
+| 0x00010a82 d777000d vsetvli a5, zero, e0x20, m1, ta, ma
+| 0x00010a86 5744065e vmv.v.x v8, a2
+| 0x00010a8a de86 mv a3, s7
+| 0x00010a8c 6285 mv a0, s8
+| 0x00010a8e d685 mv a1, s5
+| 0x00010a90 13070040 li a4, 0x400
+| .-> 0x00010a94 d777070d vsetvli a5, a4, e0x20, m1, ta, ma
+| : 0x00010a98 07e10502 vle32.v v2, (a1)
+| : 0x00010a9c 87600502 vle32.v v1, (a0)
+| : 0x00010aa0 13962700 slli a2, a5, 2
+| : 0x00010aa4 1d8f sub a4, a4, a5
+| : 0x00010aa6 b295 add a1, a1, a2
+| : 0x00010aa8 3295 add a0, a0, a2
+| : 0x00010aaa d7201122 vaaddu.vv v1, v1, v2
+| : 0x00010aae a7e00602 vse32.v v1, (a3)
+| : 0x00010ab2 b296 add a3, a3, a2
+| `=< 0x00010ab4 65f3 bnez a4, 0x10a94
+| 0x00010ab6 1307c0f9 li a4, -0x64
+| 0x00010aba d777000d vsetvli a5, zero, e0x20, m1, ta, ma
+| 0x00010abe 5741075e vmv.v.x v2, a4
+| 0x00010ac2 d286 mv a3, s4
+| 0x00010ac4 2286 mv a2, s0
+| 0x00010ac6 13070040 li a4, 0x400
+| .-> 0x00010aca d777070d vsetvli a5, a4, e0x20, m1, ta, ma
+| : 0x00010ace 87600602 vle32.v v1, (a2)
+| : 0x00010ad2 93952700 slli a1, a5, 2
+| : 0x00010ad6 1d8f sub a4, a4, a5
+| : 0x00010ad8 2e96 add a2, a2, a1
+| : 0x00010ada d700111e vmax.vv v1, v1, v2
+| : 0x00010ade d7001416 vmin.vv v1, v1, v8
+| : 0x00010ae2 a7e00602 vse32.v v1, (a3)
+| : 0x00010ae6 ae96 add a3, a3, a1
+| `=< 0x00010ae8 6df3 bnez a4, 0x10aca
+| 0x00010aea d285 mv a1, s4
+| 0x00010aec 2285 mv a0, s0
+| 0x00010aee ef005057 jal sym.test_abs_neg
+| 0x00010af2 5286 mv a2, s4
+| 0x00010af4 da85 mv a1, s6
+| 0x00010af6 2285 mv a0, s0
+| 0x00010af8 ef00505b jal sym.test_minmax
+| 0x00010afc 5e86 mv a2, s7
+| 0x00010afe e285 mv a1, s8
+| 0x00010b00 5685 mv a0, s5
+| 0x00010b02 ef00f05f jal sym.test_unsigned_ops
+| 0x00010b06 0276 ld a2, 0x20(sp)
+| 0x00010b08 d286 mv a3, s4
+| 0x00010b0a da85 mv a1, s6
+| 0x00010b0c 2285 mv a0, s0
+| 0x00010b0e ef007064 jal sym.test_madd
+| 0x00010b12 4965 lui a0, 0x12
+| 0x00010b14 130505a7 addi a0, a0, -0x590
+| 0x00010b18 eff09fa7 jal sym.imp.puts ; int puts(const char *s)
+| 0x00010b1c 2285 mv a0, s0
+| 0x00010b1e eff03fa9 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b22 5a85 mv a0, s6
+| 0x00010b24 eff0dfa8 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b28 0275 ld a0, 0x20(sp)
+| 0x00010b2a eff07fa8 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b2e 5285 mv a0, s4
+| 0x00010b30 eff01fa8 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b34 6685 mv a0, s9
+| 0x00010b36 eff0bfa7 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b3a 6e85 mv a0, s11
+| 0x00010b3c eff05fa7 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b40 6265 ld a0, 0x18(sp)
+| 0x00010b42 eff0ffa6 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b46 4265 ld a0, 0x10(sp)
+| 0x00010b48 eff09fa6 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b4c 2265 ld a0, 8(sp)
+| 0x00010b4e eff03fa6 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b52 0265 ld a0, 0(sp)
+| 0x00010b54 eff0dfa5 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b58 2275 ld a0, 0x28(sp)
+| 0x00010b5a eff07fa5 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b5e 2685 mv a0, s1
+| 0x00010b60 eff01fa5 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b64 4e85 mv a0, s3
+| 0x00010b66 eff0bfa4 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b6a 6a85 mv a0, s10
+| 0x00010b6c eff05fa4 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b70 4a85 mv a0, s2
+| 0x00010b72 eff0ffa3 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b76 5685 mv a0, s5
+| 0x00010b78 eff09fa3 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b7c 6285 mv a0, s8
+| 0x00010b7e eff03fa3 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b82 5e85 mv a0, s7
+| 0x00010b84 eff0dfa2 jal sym.imp.free ; void free(void *ptr)
+| 0x00010b88 b270 ld ra, 0x128(sp)
+| 0x00010b8a 1274 ld s0, 0x120(sp)
+| 0x00010b8c f264 ld s1, 0x118(sp)
+| 0x00010b8e 5269 ld s2, 0x110(sp)
+| 0x00010b90 b269 ld s3, 0x108(sp)
+| 0x00010b92 126a ld s4, 0x100(sp)
+| 0x00010b94 ee7a ld s5, 0xf8(sp)
+| 0x00010b96 4e7b ld s6, 0xf0(sp)
+| 0x00010b98 ae7b ld s7, 0xe8(sp)
+| 0x00010b9a 0e7c ld s8, 0xe0(sp)
+| 0x00010b9c ee6c ld s9, 0xd8(sp)
+| 0x00010b9e 4e6d ld s10, 0xd0(sp)
+| 0x00010ba0 ae6d ld s11, 0xc8(sp)
+| 0x00010ba2 0145 li a0, 0
+| 0x00010ba4 5561 addi sp, sp, 0x130
+\ 0x00010ba6 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: madd
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x00011960 d777080d vsetvli a5, a6, e0x20, m1, ta, ma ; arg6
+| : 0x00011964 87610302 vle32.v v3, (t1)
+| : 0x00011968 87600e02 vle32.v v1, (t3)
+| : 0x0001196c 07e10e02 vle32.v v2, (t4)
+| : 0x00011970 13972700 slli a4, a5, 2 ; arg6
+| : 0x00011974 3308f840 sub a6, a6, a5 ; arg6
+| : 0x00011978 3a93 add t1, t1, a4
+| : 0x0001197a 3a9e add t3, t3, a4
+| : 0x0001197c ba9e add t4, t4, a4
+| : 0x0001197e d7a021a6 vmadd.vv v1, v3, v2
+| : 0x00011982 a7e00802 vse32.v v1, (a7) ; arg8
+| : 0x00011986 ba98 add a7, a7, a4 ; arg8
+| `=< 0x00011988 e31c08fc bnez a6, 0x11960
+| 0x0001198c 13080040 li a6, 0x400
+| .-> 0x00011990 d777080d vsetvli a5, a6, e0x20, m1, ta, ma ; arg6
+| : 0x00011994 87610602 vle32.v v3, (a2) ; arg3
+| : 0x00011998 07610502 vle32.v v2, (a0) ; arg1
+| : 0x0001199c 87e00502 vle32.v v1, (a1) ; arg2
+| : 0x000119a0 13972700 slli a4, a5, 2 ; arg6
+| : 0x000119a4 3308f840 sub a6, a6, a5 ; arg6
+| : 0x000119a8 3a96 add a2, a2, a4 ; arg3
+| : 0x000119aa 3a95 add a0, a0, a4 ; arg1
+| : 0x000119ac ba95 add a1, a1, a4 ; arg2
+| : 0x000119ae d72031ae vnmsub.vv v1, v2, v3
+| : 0x000119b2 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000119b6 ba96 add a3, a3, a4 ; arg4
+| `=< 0x000119b8 e31c08fc bnez a6, 0x11990
+\ 0x000119bc 8280 ret
+EOF
+RUN
+
+NAME=Vector instructions: bitwise
+FILE=bins/elf/riscv_vec_arith
+CMDS=< 0x000111b8 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000111bc 07e10802 vle32.v v2, (a7) ; arg8
+| : 0x000111c0 87600302 vle32.v v1, (t1)
+| : 0x000111c4 13982700 slli a6, a5, 2 ; arg6
+| : 0x000111c8 1d8f sub a4, a4, a5 ; arg6
+| : 0x000111ca c298 add a7, a7, a6 ; arg8
+| : 0x000111cc 4293 add t1, t1, a6
+| : 0x000111ce d7001126 vand.vv v1, v1, v2
+| : 0x000111d2 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x000111d6 c296 add a3, a3, a6 ; arg4
+| `=< 0x000111d8 65f3 bnez a4, 0x111b8
+| 0x000111da b286 mv a3, a2
+| 0x000111dc 2e83 mv t1, a1
+| 0x000111de aa88 mv a7, a0
+| 0x000111e0 13070040 li a4, 0x400
+| .-> 0x000111e4 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x000111e8 07e10802 vle32.v v2, (a7) ; arg8
+| : 0x000111ec 87600302 vle32.v v1, (t1)
+| : 0x000111f0 13982700 slli a6, a5, 2 ; arg6
+| : 0x000111f4 1d8f sub a4, a4, a5 ; arg6
+| : 0x000111f6 c298 add a7, a7, a6 ; arg8
+| : 0x000111f8 4293 add t1, t1, a6
+| : 0x000111fa d700112a vor.vv v1, v1, v2
+| : 0x000111fe a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x00011202 c296 add a3, a3, a6 ; arg4
+| `=< 0x00011204 65f3 bnez a4, 0x111e4
+| 0x00011206 b286 mv a3, a2
+| 0x00011208 aa88 mv a7, a0
+| 0x0001120a 13070040 li a4, 0x400
+| .-> 0x0001120e d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011212 07e10802 vle32.v v2, (a7) ; arg8
+| : 0x00011216 87e00502 vle32.v v1, (a1) ; arg2
+| : 0x0001121a 13982700 slli a6, a5, 2 ; arg6
+| : 0x0001121e 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011220 c298 add a7, a7, a6 ; arg8
+| : 0x00011222 c295 add a1, a1, a6 ; arg2
+| : 0x00011224 d700112e vxor.vv v1, v1, v2
+| : 0x00011228 a7e00602 vse32.v v1, (a3) ; arg4
+| : 0x0001122c c296 add a3, a3, a6 ; arg4
+| `=< 0x0001122e 65f3 bnez a4, 0x1120e
+| 0x00011230 13070040 li a4, 0x400
+| .-> 0x00011234 d777070d vsetvli a5, a4, e0x20, m1, ta, ma ; arg6
+| : 0x00011238 87600502 vle32.v v1, (a0) ; arg1
+| : 0x0001123c 93962700 slli a3, a5, 2 ; arg6
+| : 0x00011240 1d8f sub a4, a4, a5 ; arg6
+| : 0x00011242 3695 add a0, a0, a3 ; arg1
+| : 0x00011244 d7b01f2e vnot.v v1, v1
+| : 0x00011248 a7600602 vse32.v v1, (a2) ; arg3
+| : 0x0001124c 3696 add a2, a2, a3 ; arg3
+| `=< 0x0001124e 7df3 bnez a4, 0x11234
+\ 0x00011250 8280 ret
+EOF
+RUN
+
+NAME=rotate_right_var
+FILE=bins/elf/riscv_bitmanip
+CMDS=< 0x00010554 13050008 li a0, 0x80
+| |||,==< 0x00010558 638a0600 beqz a3, 0x1056c
+| ||||| 0x0001055c 13051000 li a0, 1
+| ||||| 0x00010560 67800000 ret
+| ||`---> 0x00010564 13050004 li a0, 0x40
+| ||,===< 0x00010568 63940600 bnez a3, 0x10570
+| .`--`--> 0x0001056c 67800000 ret
+| : |`---> 0x00010570 13052000 li a0, 2
+| : | | 0x00010574 67800000 ret
+| : `----> 0x00010578 13050002 li a0, 0x20
+| `======< 0x0001057c e38806fe beqz a3, 0x1056c
+| | 0x00010580 13054000 li a0, 4
+| | 0x00010584 67800000 ret
+| `-> 0x00010588 13050030 li a0, 0x300
+\ 0x0001058c 67800000 ret
+EOF
+RUN
+
+
+NAME=fclass_h
+FILE=bins/elf/riscv_float_rounding
+CMDS=< 0x000105d8 13050008 li a0, 0x80
+| ||,==< 0x000105dc 63880700 beqz a5, 0x105ec
+| |||| 0x000105e0 13051000 li a0, 1
+| |||| 0x000105e4 67800000 ret
+| |||`-> 0x000105e8 13050030 li a0, 0x300
+| .`-`.-> 0x000105ec 67800000 ret
+| : `---> 0x000105f0 d30700f0 fmv.w.x fa5, zero
+| : : 0x000105f4 530707f0 fmv.w.x fa4, a4
+| : : 0x000105f8 5327f7a0 feq.s a4, fa4, fa5
+| : ,==< 0x000105fc 630a0700 beqz a4, 0x10610
+| : |: 0x00010600 13050001 li a0, 0x10
+| `=====< 0x00010604 e38407fe beqz a5, 0x105ec
+| |: 0x00010608 13058000 li a0, 8
+| |: 0x0001060c 67800000 ret
+| `--> 0x00010610 13050002 li a0, 0x20
+| `=< 0x00010614 e38c07fc beqz a5, 0x105ec
+| 0x00010618 13054000 li a0, 4
+\ 0x0001061c 67800000 ret
+EOF
+RUN
+
+
+NAME=fround_d_attr
+FILE=bins/elf/riscv_float_rounding
+CMDS=< 0x000104cc 13050008 li a0, 0x80
+| |||,==< 0x000104d0 638a0700 beqz a5, 0x104e4
+| ||||| 0x000104d4 13051000 li a0, 1
+| ||||| 0x000104d8 67800000 ret
+| ||`---> 0x000104dc 13050004 li a0, 0x40
+| ||,===< 0x000104e0 63940700 bnez a5, 0x104e8
+| .`--`--> 0x000104e4 67800000 ret
+| : |`---> 0x000104e8 13052000 li a0, 2
+| : | | 0x000104ec 67800000 ret
+| : `----> 0x000104f0 13050002 li a0, 0x20
+| `======< 0x000104f4 e38807fe beqz a5, 0x104e4
+| | 0x000104f8 13054000 li a0, 4
+| | 0x000104fc 67800000 ret
+| `-> 0x00010500 13050030 li a0, 0x300
+\ 0x00010504 67800000 ret
+EOF
+RUN
+
+NAME=fround_s
+FILE=bins/elf/riscv_float_rounding
+CMDS=< 0x00010170 b7170200 lui a5, 0x21
-| :: 0x00010174 1385874f addi a0, a5, 1272
-| :: 0x00010178 ef00c01f jal ra, sym.printf
-| :: 0x0001017c 930784fe addi a5, s0, -24
+| :: 0x00010174 1385874f addi a0, a5, 0x4f8
+| :: 0x00010178 ef00c01f jal sym.printf
+| :: 0x0001017c 930784fe addi a5, s0, -0x18
| :: 0x00010180 93850700 mv a1, a5
| :: 0x00010184 b7170200 lui a5, 0x21
-| :: 0x00010188 13850751 addi a0, a5, 1296
-| :: 0x0001018c ef00402f jal ra, sym.scanf
-| :: 0x00010190 032784fe lw a4, -24(s0)
-| :: 0x00010194 8327c4fe lw a5, -20(s0)
+| :: 0x00010188 13850751 addi a0, a5, 0x510
+| :: 0x0001018c ef00402f jal sym.scanf
+| :: 0x00010190 032784fe lw a4, -0x18(s0)
+| :: 0x00010194 8327c4fe lw a5, -0x14(s0)
| ,===< 0x00010198 631cf700 bne a4, a5, 0x101b0
| |:: 0x0001019c b7170200 lui a5, 0x21
-| |:: 0x000101a0 13858751 addi a0, a5, 1304
-| |:: 0x000101a4 ef00002d jal ra, sym.puts
+| |:: 0x000101a0 13858751 addi a0, a5, 0x518
+| |:: 0x000101a4 ef00002d jal sym.puts
| |:: 0x000101a8 93070000 li a5, 0
| ,====< 0x000101ac 6f000003 j 0x101dc
-| |`---> 0x000101b0 032784fe lw a4, -24(s0)
-| | :: 0x000101b4 8327c4fe lw a5, -20(s0)
-| |,===< 0x000101b8 635af700 ble a5, a4, 0x101cc
+| |`---> 0x000101b0 032784fe lw a4, -0x18(s0)
+| | :: 0x000101b4 8327c4fe lw a5, -0x14(s0)
+| |,===< 0x000101b8 635af700 bge a4, a5, 0x101cc
| ||:: 0x000101bc b7170200 lui a5, 0x21
-| ||:: 0x000101c0 13858752 addi a0, a5, 1320
-| ||:: 0x000101c4 ef00002b jal ra, sym.puts
+| ||:: 0x000101c0 13858752 addi a0, a5, 0x528
+| ||:: 0x000101c4 ef00002b jal sym.puts
| ||`==< 0x000101c8 6ff09ffa j 0x10170
| |`---> 0x000101cc b7170200 lui a5, 0x21
-| | : 0x000101d0 13858753 addi a0, a5, 1336
-| | : 0x000101d4 ef00002a jal ra, sym.puts
+| | : 0x000101d0 13858753 addi a0, a5, 0x538
+| | : 0x000101d4 ef00002a jal sym.puts
| | `=< 0x000101d8 6ff09ff9 j 0x10170
| | ; CODE XREF from main @ 0x101ac
| `----> 0x000101dc 13850700 mv a0, a5
-| 0x000101e0 83308101 ld ra, 24(sp)
-| 0x000101e4 03340101 ld s0, 16(sp)
-| 0x000101e8 13010102 addi sp, sp, 32
+| 0x000101e0 83308101 ld ra, 0x18(sp)
+| 0x000101e4 03340101 ld s0, 0x10(sp)
+| 0x000101e8 13010102 addi sp, sp, 0x20
\ 0x000101ec 67800000 ret
EOF
RUN
@@ -520,47 +520,47 @@ EXPECT=< 0x00010170 b7170200 lui a5, 0x21
-| :: 0x00010174 1385874f addi a0, a5, 1272 ; const char *fmt
-| :: 0x00010178 ef00c01f jal ra, dbg.printf
-| :: 0x0001017c 930784fe addi a5, s0, -24
+| :: 0x00010174 1385874f addi a0, a5, 0x4f8
+| :: 0x00010178 ef00c01f jal dbg.printf
+| :: 0x0001017c 930784fe addi a5, s0, -0x18
| :: 0x00010180 93850700 mv a1, a5
| :: 0x00010184 b7170200 lui a5, 0x21
-| :: 0x00010188 13850751 addi a0, a5, 1296 ; const char *fmt
-| :: 0x0001018c ef00402f jal ra, dbg.scanf
-| :: 0x00010190 032784fe lw a4, -24(s0)
-| :: 0x00010194 8327c4fe lw a5, -20(s0)
+| :: 0x00010188 13850751 addi a0, a5, 0x510
+| :: 0x0001018c ef00402f jal dbg.scanf
+| :: 0x00010190 032784fe lw a4, -0x18(s0)
+| :: 0x00010194 8327c4fe lw a5, -0x14(s0)
| ,===< 0x00010198 631cf700 bne a4, a5, 0x101b0
| |:: 0x0001019c b7170200 lui a5, 0x21
-| |:: 0x000101a0 13858751 addi a0, a5, 1304 ; const char *s
-| |:: 0x000101a4 ef00002d jal ra, dbg.puts
+| |:: 0x000101a0 13858751 addi a0, a5, 0x518
+| |:: 0x000101a4 ef00002d jal dbg.puts
| |:: 0x000101a8 93070000 li a5, 0
| ,====< 0x000101ac 6f000003 j 0x101dc
-| |`---> 0x000101b0 032784fe lw a4, -24(s0)
-| | :: 0x000101b4 8327c4fe lw a5, -20(s0)
-| |,===< 0x000101b8 635af700 ble a5, a4, 0x101cc
+| |`---> 0x000101b0 032784fe lw a4, -0x18(s0)
+| | :: 0x000101b4 8327c4fe lw a5, -0x14(s0)
+| |,===< 0x000101b8 635af700 bge a4, a5, 0x101cc
| ||:: 0x000101bc b7170200 lui a5, 0x21
-| ||:: 0x000101c0 13858752 addi a0, a5, 1320 ; const char *s
-| ||:: 0x000101c4 ef00002b jal ra, dbg.puts
+| ||:: 0x000101c0 13858752 addi a0, a5, 0x528
+| ||:: 0x000101c4 ef00002b jal dbg.puts
| ||`==< 0x000101c8 6ff09ffa j 0x10170
| |`---> 0x000101cc b7170200 lui a5, 0x21
-| | : 0x000101d0 13858753 addi a0, a5, 1336 ; const char *s
-| | : 0x000101d4 ef00002a jal ra, dbg.puts
+| | : 0x000101d0 13858753 addi a0, a5, 0x538
+| | : 0x000101d4 ef00002a jal dbg.puts
| | `=< 0x000101d8 6ff09ff9 j 0x10170
| | ; CODE XREF from main @ 0x101ac
| `----> 0x000101dc 13850700 mv a0, a5
-| 0x000101e0 83308101 ld ra, 24(sp)
-| 0x000101e4 03340101 ld s0, 16(sp)
-| 0x000101e8 13010102 addi sp, sp, 32
+| 0x000101e0 83308101 ld ra, 0x18(sp)
+| 0x000101e4 03340101 ld s0, 0x10(sp)
+| 0x000101e8 13010102 addi sp, sp, 0x20
\ 0x000101ec 67800000 ret
EOF
RUN
diff --git a/test/db/formats/elf/riscv-relocs b/test/db/formats/elf/riscv-relocs
new file mode 100644
index 00000000000..79057c0e767
--- /dev/null
+++ b/test/db/formats/elf/riscv-relocs
@@ -0,0 +1,928 @@
+NAME=ADD8/16/32/64 and SUB8/16/32/64 relocs
+FILE=bins/elf/riscv_relocs_add
+CMDS=< 0x08000038 jal loc._x.0 ; RELOC 0 bar @ 0x08000034
+nth paddr vaddr bind type size lib name
+--------------------------------------------------------
+ 1 0x00000038 0x08000038 LOCAL NOTYPE 0 foo
+ 2 0x00000034 0x08000034 LOCAL NOTYPE 0 $x.0
+ 3 0x00000034 0x08000034 LOCAL NOTYPE 0 bar
+ 4 0x00000034 0x08000034 GLOBAL NOTYPE 0 _start
+ vaddr paddr target type name
+--------------------------------------------------
+0x08000034 0x00000034 0x08000038 R_RISCV_JAL foo
+0x08000038 0x00000038 0x08000034 R_RISCV_JAL bar
+EOF
+RUN
+
+NAME=JAL relocs (64 bits near)
+FILE=bins/elf/riscv_relocs_jal_near_64
+CMDS=< 0x08000044 jal loc._x.0 ; RELOC 0 bar @ 0x08000040
+nth paddr vaddr bind type size lib name
+--------------------------------------------------------
+ 1 0x00000044 0x08000044 LOCAL NOTYPE 0 foo
+ 2 0x00000040 0x08000040 LOCAL NOTYPE 0 $x.0
+ 3 0x00000040 0x08000040 LOCAL NOTYPE 0 bar
+ 4 0x00000040 0x08000040 GLOBAL NOTYPE 0 _start
+ vaddr paddr target type name
+--------------------------------------------------
+0x08000040 0x00000040 0x08000044 R_RISCV_JAL foo
+0x08000044 0x00000044 0x08000040 R_RISCV_JAL bar
+EOF
+RUN
+
+NAME=JAL relocs (32 bits far)
+FILE=bins/elf/riscv_relocs_jal_far_32
+CMDS=< 0x0800003e addi a0, a0, 1 ; RELOC TARGET 0 .LBB0_2 @ 0x0800003e
+ 0x08000040 ret
+nth paddr vaddr bind type size lib name
+----------------------------------------------------------------
+ 1 ---------- 0x00000000 LOCAL FILE 0 riscv_branch.c
+ 2 0x00000034 0x08000034 LOCAL NOTYPE 0 $x.0
+ 3 0x0000003e 0x0800003e LOCAL NOTYPE 0 .LBB0_2
+ 4 0x00000042 0x08000042 LOCAL NOTYPE 0 $d.1
+ 5 0x0000006a 0x0800006a LOCAL NOTYPE 0 $d.2
+ 6 0x00000034 0x08000034 GLOBAL FUNC 14 test
+ vaddr paddr target type name
+--------------------------------------------------------
+0x08000036 0x00000036 0x0800003e R_RISCV_BRANCH .LBB0_2
+EOF
+RUN
+
+NAME=BRANCH relocs (64 bits near)
+FILE=bins/elf/riscv_relocs_branch_near_64
+CMDS=< 0x0800004a addiw a0, a0, 1 ; RELOC TARGET 0 .LBB0_2 @ 0x0800004a
+ 0x0800004c ret
+nth paddr vaddr bind type size lib name
+----------------------------------------------------------------
+ 1 ---------- 0x00000000 LOCAL FILE 0 riscv_branch.c
+ 2 0x00000040 0x08000040 LOCAL NOTYPE 0 $x.0
+ 3 0x0000004a 0x0800004a LOCAL NOTYPE 0 .LBB0_2
+ 4 0x0000004e 0x0800004e LOCAL NOTYPE 0 $d.1
+ 5 0x00000076 0x08000076 LOCAL NOTYPE 0 $d.2
+ 6 0x00000040 0x08000040 GLOBAL FUNC 14 test
+ vaddr paddr target type name
+--------------------------------------------------------
+0x08000042 0x00000042 0x0800004a R_RISCV_BRANCH .LBB0_2
+EOF
+RUN
+
+
+NAME=BRANCH relocs (32 bits far forward)
+FILE=bins/elf/riscv_relocs_branch_far_32
+CMDS=< 0x08001032 li a0, 1 ; RELOC TARGET 0 .LBB0_2 @ 0x08001032
+\ 0x08001034 ret
+nth paddr vaddr bind type size lib name
+--------------------------------------------------------------------
+ 1 ---------- 0x00000000 LOCAL FILE 0 riscv_branch_far.c
+ 2 0x00000034 0x08000034 LOCAL NOTYPE 0 $x.0
+ 3 0x00001032 0x08001032 LOCAL NOTYPE 0 .LBB0_2
+ 4 0x00002038 0x08002038 LOCAL NOTYPE 0 .LBB1_2
+ 5 0x0000203c 0x0800203c LOCAL NOTYPE 0 .LBB2_1
+ 6 0x00003044 0x08003044 LOCAL NOTYPE 0 .LBB3_1
+ 7 0x00004050 0x08004050 LOCAL NOTYPE 0 $d.1
+ 8 0x00004078 0x08004078 LOCAL NOTYPE 0 $d.2
+ 9 0x00000034 0x08000034 GLOBAL FUNC 4098 test_forward_max
+ 10 0x00001036 0x08001036 GLOBAL FUNC 4102 test_forward_over
+ 11 0x0000203c 0x0800203c GLOBAL FUNC 4104 test_backward_max
+ 12 0x00003044 0x08003044 GLOBAL FUNC 4108 test_backward_over
+ vaddr paddr target type name
+--------------------------------------------------------
+0x08000034 0x00000034 0x08001032 R_RISCV_BRANCH .LBB0_2
+0x08001038 0x00001038 0x08002038 R_RISCV_JAL .LBB1_2
+0x0800303c 0x0000303c 0x0800203c R_RISCV_BRANCH .LBB2_1
+0x08004048 0x00004048 0x08003044 R_RISCV_JAL .LBB3_1
+EOF
+RUN
+
+NAME=BRANCH relocs (64 bits far forward)
+FILE=bins/elf/riscv_relocs_branch_far_64
+CMDS=< 0x0800103e li a0, 1 ; RELOC TARGET 0 .LBB0_2 @ 0x0800103e
+\ 0x08001040 ret
+nth paddr vaddr bind type size lib name
+--------------------------------------------------------------------
+ 1 ---------- 0x00000000 LOCAL FILE 0 riscv_branch_far.c
+ 2 0x00000040 0x08000040 LOCAL NOTYPE 0 $x.0
+ 3 0x0000103e 0x0800103e LOCAL NOTYPE 0 .LBB0_2
+ 4 0x00002044 0x08002044 LOCAL NOTYPE 0 .LBB1_2
+ 5 0x00002048 0x08002048 LOCAL NOTYPE 0 .LBB2_1
+ 6 0x00003050 0x08003050 LOCAL NOTYPE 0 .LBB3_1
+ 7 0x0000405c 0x0800405c LOCAL NOTYPE 0 $d.1
+ 8 0x00004084 0x08004084 LOCAL NOTYPE 0 $d.2
+ 9 0x00000040 0x08000040 GLOBAL FUNC 4098 test_forward_max
+ 10 0x00001042 0x08001042 GLOBAL FUNC 4102 test_forward_over
+ 11 0x00002048 0x08002048 GLOBAL FUNC 4104 test_backward_max
+ 12 0x00003050 0x08003050 GLOBAL FUNC 4108 test_backward_over
+ vaddr paddr target type name
+--------------------------------------------------------
+0x08000040 0x00000040 0x0800103e R_RISCV_BRANCH .LBB0_2
+0x08001044 0x00001044 0x08002044 R_RISCV_JAL .LBB1_2
+0x08003048 0x00003048 0x08002048 R_RISCV_BRANCH .LBB2_1
+0x08004054 0x00004054 0x08003050 R_RISCV_JAL .LBB3_1
+EOF
+RUN
+
+NAME=BRANCH relocs (32 bits far backward)
+FILE=bins/elf/riscv_relocs_branch_far_32
+CMDS=< 0x0800004e addi a0, a0, 0xf ; RELOC TARGET 0 .LBB0_2 @ 0x0800004e
+| | ; CODE XREF from loc._x.0 @ 0x800004c
+| | ;-- .LBB0_3:
+| `--> 0x08000050 lw ra, 0xc(sp) ; RELOC TARGET 0 .LBB0_3 @ 0x08000050
+| 0x08000052 lw s0, 8(sp)
+| 0x08000054 addi sp, sp, 0x10
+\ 0x08000056 ret
+nth paddr vaddr bind type size lib name
+--------------------------------------------------------------------------------
+ 1 ---------- 0x00000000 LOCAL FILE 0 riscv_branch_compressed_near.c
+ 2 0x00000034 0x08000034 LOCAL NOTYPE 0 $x.0
+ 3 0x0000004e 0x0800004e LOCAL NOTYPE 0 .LBB0_2
+ 4 0x00000050 0x08000050 LOCAL NOTYPE 0 .LBB0_3
+ 5 0x00000058 0x08000058 LOCAL NOTYPE 0 $d.1
+ 6 0x00000080 0x08000080 LOCAL NOTYPE 0 $d.2
+ 7 0x00000034 0x08000034 GLOBAL FUNC 36 test
+ 8 ---------- ---------- GLOBAL NOTYPE 0 imp.__mulsi3
+ vaddr paddr target type name
+-------------------------------------------------------------
+0x08000040 0x00000040 0x00000000 R_RISCV_RELAX
+0x08000040 0x00000040 0x08000210 R_RISCV_CALL_PLT __mulsi3
+0x08000048 0x00000048 0x0800004e R_RISCV_RVC_BRANCH .LBB0_2
+0x0800004c 0x0000004c 0x08000050 R_RISCV_RVC_JUMP .LBB0_3
+EOF
+RUN
+
+NAME=RVC BRANCH (near 64-bits)
+FILE=bins/elf/riscv_relocs_rvc_branch_near_64
+CMDS=< 0x0800005a addiw a0, a0, 0xf ; RELOC TARGET 0 .LBB0_2 @ 0x0800005a ; arg1
+| | ; CODE XREF from loc._x.0 @ 0x8000058
+| | ;-- .LBB0_3:
+| `--> 0x0800005c ld ra, 8(sp) ; RELOC TARGET 0 .LBB0_3 @ 0x0800005c
+| 0x0800005e ld s0, 0(sp)
+| 0x08000060 addi sp, sp, 0x10
+\ 0x08000062 ret
+nth paddr vaddr bind type size lib name
+--------------------------------------------------------------------------------
+ 1 ---------- 0x00000000 LOCAL FILE 0 riscv_branch_compressed_near.c
+ 2 0x00000040 0x08000040 LOCAL NOTYPE 0 $x.0
+ 3 0x0000005a 0x0800005a LOCAL NOTYPE 0 .LBB0_2
+ 4 0x0000005c 0x0800005c LOCAL NOTYPE 0 .LBB0_3
+ 5 0x00000064 0x08000064 LOCAL NOTYPE 0 $d.1
+ 6 0x0000008c 0x0800008c LOCAL NOTYPE 0 $d.2
+ 7 0x00000040 0x08000040 GLOBAL FUNC 36 test
+ 8 ---------- ---------- GLOBAL NOTYPE 0 imp.__muldi3
+ vaddr paddr target type name
+-------------------------------------------------------------
+0x0800004c 0x0000004c 0x00000000 R_RISCV_RELAX
+0x0800004c 0x0000004c 0x08000298 R_RISCV_CALL_PLT __muldi3
+0x08000054 0x00000054 0x0800005a R_RISCV_RVC_BRANCH .LBB0_2
+0x08000058 0x00000058 0x0800005c R_RISCV_RVC_JUMP .LBB0_3
+EOF
+RUN
+
+NAME=RVC BRANCH (far forward 32-bits)
+FILE=bins/elf/riscv_relocs_rvc_branch_far_32
+CMDS=< 0x08000132 li a0, 1 ; RELOC TARGET 0 .LBB0_2 @ 0x08000132
+\ 0x08000134 ret
+nth paddr vaddr bind type size lib name
+-------------------------------------------------------------------------------
+ 1 ---------- 0x00000000 LOCAL FILE 0 riscv_branch_compressed_far.c
+ 2 0x00000034 0x08000034 LOCAL NOTYPE 0 $x.0
+ 3 0x00000132 0x08000132 LOCAL NOTYPE 0 .LBB0_2
+ 4 0x00000238 0x08000238 LOCAL NOTYPE 0 .LBB1_2
+ 5 0x0000023c 0x0800023c LOCAL NOTYPE 0 .LBB2_1
+ 6 0x00000342 0x08000342 LOCAL NOTYPE 0 .LBB3_1
+ 7 0x0000044c 0x0800044c LOCAL NOTYPE 0 $d.1
+ 8 0x00000474 0x08000474 LOCAL NOTYPE 0 $d.2
+ 9 0x00000034 0x08000034 GLOBAL FUNC 258 test_forward_max
+ 10 0x00000136 0x08000136 GLOBAL FUNC 262 test_forward_over
+ 11 0x0000023c 0x0800023c GLOBAL FUNC 262 test_backward_max
+ 12 0x00000342 0x08000342 GLOBAL FUNC 266 test_backward_over
+ vaddr paddr target type name
+------------------------------------------------------------
+0x08000034 0x00000034 0x08000132 R_RISCV_RVC_BRANCH .LBB0_2
+0x08000136 0x00000136 0x08000238 R_RISCV_BRANCH .LBB1_2
+0x0800033c 0x0000033c 0x0800023c R_RISCV_RVC_BRANCH .LBB2_1
+0x08000444 0x00000444 0x08000342 R_RISCV_BRANCH .LBB3_1
+EOF
+RUN
+
+NAME=RVC BRANCH (far backward 32-bits)
+FILE=bins/elf/riscv_relocs_rvc_branch_far_32
+CMDS=< 0x0800013e li a0, 1 ; RELOC TARGET 0 .LBB0_2 @ 0x0800013e
+\ 0x08000140 ret
+nth paddr vaddr bind type size lib name
+-------------------------------------------------------------------------------
+ 1 ---------- 0x00000000 LOCAL FILE 0 riscv_branch_compressed_far.c
+ 2 0x00000040 0x08000040 LOCAL NOTYPE 0 $x.0
+ 3 0x0000013e 0x0800013e LOCAL NOTYPE 0 .LBB0_2
+ 4 0x00000244 0x08000244 LOCAL NOTYPE 0 .LBB1_2
+ 5 0x00000248 0x08000248 LOCAL NOTYPE 0 .LBB2_1
+ 6 0x0000034e 0x0800034e LOCAL NOTYPE 0 .LBB3_1
+ 7 0x00000458 0x08000458 LOCAL NOTYPE 0 $d.1
+ 8 0x00000480 0x08000480 LOCAL NOTYPE 0 $d.2
+ 9 0x00000040 0x08000040 GLOBAL FUNC 258 test_forward_max
+ 10 0x00000142 0x08000142 GLOBAL FUNC 262 test_forward_over
+ 11 0x00000248 0x08000248 GLOBAL FUNC 262 test_backward_max
+ 12 0x0000034e 0x0800034e GLOBAL FUNC 266 test_backward_over
+ vaddr paddr target type name
+------------------------------------------------------------
+0x08000040 0x00000040 0x0800013e R_RISCV_RVC_BRANCH .LBB0_2
+0x08000142 0x00000142 0x08000244 R_RISCV_BRANCH .LBB1_2
+0x08000348 0x00000348 0x08000248 R_RISCV_RVC_BRANCH .LBB2_1
+0x08000450 0x00000450 0x0800034e R_RISCV_BRANCH .LBB3_1
+EOF
+RUN
+
+NAME=RVC BRANCH (far backward 64-bits)
+FILE=bins/elf/riscv_relocs_rvc_branch_far_64
+CMDS=<regdelta->name, "r3", "Source reg base should be r3");
rz_analysis_op_fini(&op);
-#if WITH_GPL
SWITCH_TO_ARCH_BITS("riscv", 32);
+ rz_analysis_set_cpu(analysis, "rv32i2p0_c2p0");
// lw s10, 64(sp)
rz_analysis_op_init(&op);
len = rz_analysis_op(analysis, &op, 0, (const ut8 *)"\x06\x4d", 2, RZ_ANALYSIS_OP_MASK_VAL);
@@ -94,13 +94,12 @@ bool test_rz_analysis_op_val() {
rz_analysis_op_init(&op);
len = rz_analysis_op(analysis, &op, 0, (const ut8 *)"\x22\xc5", 2, RZ_ANALYSIS_OP_MASK_VAL);
mu_assert_eq(len, 2, "Op is of size 2");
- mu_assert_eq(op.dst->type, RZ_ANALYSIS_VAL_MEM, "Destination should be reg");
+ mu_assert_eq(op.dst->type, RZ_ANALYSIS_VAL_MEM, "Destination should be mem");
mu_assert_streq(op.dst->reg->name, "sp", "Dst reg should be s10");
mu_assert_eq(op.dst->delta, 136, "Source delta should be 64");
mu_assert_eq(op.src[0]->type, RZ_ANALYSIS_VAL_REG, "Source should be reg");
mu_assert_streq(op.src[0]->reg->name, "s0", "Source reg base should be s0");
rz_analysis_op_fini(&op);
-#endif
rz_analysis_free(analysis);
mu_end;