Rizin
unix-like reverse engineering framework and cli tools
riscv.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <ctype.h>
#include <stdarg.h>
#include <rz_asm.h>
#include <rz_lib.h>
#include <string.h>
#include "riscv-opc.h"
#include "riscv.h"

Go to the source code of this file.

Macros

#define ARRAY_SIZE(a)   (sizeof(a) / sizeof(*a))
 
#define DECLARE_CSR(name, num)   case num: csr_name = #name; break;
 
#define OP_HASH_IDX(i)   ((i) & (riscv_insn_length (i) == 2 ? 3 : OP_MASK_OP))
 

Functions

static void arg_p (char *buf, unsigned long val, const char *const *array, size_t size)
 
static void get_insn_args (char *buf, const char *d, insn_t l, uint64_t pc)
 
static struct riscv_opcodeget_opcode (insn_t word)
 
static int riscv_disassemble (RzAsm *a, RzAsmOp *rop, insn_t word, int xlen, int len)
 
static int riscv_dis (RzAsm *a, RzAsmOp *rop, const ut8 *buf, ut64 len)
 

Variables

static const char *constriscv_gpr_names = riscv_gpr_names_abi
 
static const char *constriscv_fpr_names = riscv_fpr_names_abi
 
static int init = 0
 

Macro Definition Documentation

◆ ARRAY_SIZE

#define ARRAY_SIZE (   a)    (sizeof(a) / sizeof(*a))

Definition at line 36 of file riscv.c.

◆ DECLARE_CSR

#define DECLARE_CSR (   name,
  num 
)    case num: csr_name = #name; break;

◆ OP_HASH_IDX

#define OP_HASH_IDX (   i)    ((i) & (riscv_insn_length (i) == 2 ? 3 : OP_MASK_OP))

Function Documentation

◆ arg_p()

static void arg_p ( char *  buf,
unsigned long  val,
const char *const array,
size_t  size 
)
static

Definition at line 43 of file riscv.c.

43  {
44  const char *s = val >= size || array[val] ? array[val] : "unknown";
45  sprintf (buf+strlen (buf), "%s", s);
46 }
ut16 val
Definition: armass64_const.h:6
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
sprintf
Definition: kernel.h:365
static RzSocket * s
Definition: rtr.c:28

References s, sprintf, and val.

Referenced by get_insn_args().

◆ get_insn_args()

static void get_insn_args ( char *  buf,
const char *  d,
insn_t  l,
uint64_t  pc 
)
static

Definition at line 49 of file riscv.c.

49  {
50  int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
51  int rd = (l >> OP_SH_RD) & OP_MASK_RD;
52  uint64_t target;
53 
54  if (*d != '\0') {
55  sprintf (buf+strlen (buf), " ");
56  }
57 
58  for (; *d != '\0'; d++) {
59  switch (*d) {
60  /* Xcustom */
61  case '^':
62  switch (*++d) {
63  case 'd':
64  sprintf (buf+strlen (buf), "%d", rd);
65  break;
66  case 's':
67  sprintf (buf+strlen (buf), "%d", rs1);
68  break;
69  case 't':
70  sprintf (buf+strlen (buf), "%d", (int) EXTRACT_OPERAND (RS2, l));
71  break;
72  case 'j':
73  sprintf (buf+strlen (buf), "%d", (int) EXTRACT_OPERAND (CUSTOM_IMM, l));
74  break;
75  }
76  break;
77 
78  case 'C': /* RVC */
79  switch (*++d) {
80  case 's': /* RS1 x8-x15 */
81  case 'w': /* RS1 x8-x15 */
82  sprintf (buf+strlen (buf), "%s",
83  riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
84  break;
85  case 't': /* RS2 x8-x15 */
86  case 'x': /* RS2 x8-x15 */
87  sprintf (buf+strlen (buf), "%s",
88  riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
89  break;
90  case 'U': /* RS1, constrained to equal RD */
91  sprintf (buf+strlen (buf), "%s", riscv_gpr_names[rd]);
92  break;
93  case 'c': /* RS1, constrained to equal sp */
94  sprintf (buf+strlen (buf), "%s", riscv_gpr_names[X_SP]);
95  break;
96  case 'V': /* RS2 */
97  sprintf (buf+strlen (buf), "%s",
98  riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
99  break;
100  case 'i':
101  sprintf (buf+strlen (buf), "%d", (int)EXTRACT_RVC_SIMM3 (l));
102  break;
103  case 'j':
104  sprintf (buf+strlen (buf), "%d", (int)EXTRACT_RVC_IMM (l));
105  break;
106  case 'k':
107  sprintf (buf+strlen (buf), "%d", (int)EXTRACT_RVC_LW_IMM (l));
108  break;
109  case 'l':
110  sprintf (buf+strlen (buf), "%d", (int)EXTRACT_RVC_LD_IMM (l));
111  break;
112  case 'm':
113  sprintf (buf+strlen (buf), "%d", (int)EXTRACT_RVC_LWSP_IMM (l));
114  break;
115  case 'n':
116  sprintf (buf+strlen (buf), "%d", (int)EXTRACT_RVC_LDSP_IMM (l));
117  break;
118  case 'K':
119  sprintf (buf+strlen (buf), "%d", (int)EXTRACT_RVC_ADDI4SPN_IMM (l));
120  break;
121  case 'L':
122  sprintf (buf+strlen (buf), "%d", (int)EXTRACT_RVC_ADDI16SP_IMM (l));
123  break;
124  case 'M':
125  sprintf (buf+strlen (buf), "%d", (int)EXTRACT_RVC_SWSP_IMM (l));
126  break;
127  case 'N':
128  sprintf (buf+strlen (buf), "%d", (int)EXTRACT_RVC_SDSP_IMM (l));
129  break;
130  case 'p':
131  target = EXTRACT_RVC_B_IMM (l) + pc;
132  sprintf (buf+strlen (buf), "0x%"PFMT64x, (ut64) target);
133  break;
134  case 'a':
135  target = EXTRACT_RVC_J_IMM (l) + pc;
136  sprintf (buf+strlen (buf), "0x%"PFMT64x, (ut64)target);
137  break;
138  case 'u':
139  sprintf (buf+strlen (buf), "0x%x",
140  (int) (EXTRACT_RVC_IMM (l) & (RISCV_BIGIMM_REACH-1)));
141  break;
142  case '>':
143  sprintf (buf+strlen (buf), "0x%x", (int) EXTRACT_RVC_IMM (l) & 0x3f);
144  break;
145  case '<':
146  sprintf (buf+strlen (buf), "0x%x", (int) EXTRACT_RVC_IMM (l) & 0x1f);
147  break;
148  case 'T': /* floating-point RS2 */
149  sprintf (buf+strlen (buf), "%s",
150  riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
151  break;
152  case 'D': /* floating-point RS2 x8-x15 */
153  sprintf (buf+strlen (buf), "%s",
154  riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
155  break;
156  }
157  break;
158 
159  case ',':
160  sprintf (buf+strlen (buf), "%c ", *d);
161  break;
162  case '(':
163  case ')':
164  case '[':
165  case ']':
166  sprintf (buf+strlen (buf), "%c", *d);
167  break;
168  case '0':
169  /* Only print constant 0 if it is the last argument */
170  if (!d[1]) {
171  sprintf (buf+strlen (buf), "0");
172  }
173  break;
174 
175  case 'b':
176  case 's':
177  sprintf (buf+strlen (buf), "%s", riscv_gpr_names[rs1]);
178  break;
179 
180  case 't':
181  sprintf (buf+strlen (buf), "%s",
183  break;
184 
185  case 'u':
186  sprintf (buf+strlen (buf), "0x%x",
187  (unsigned) EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
188  break;
189 
190  case 'm':
191  arg_p (buf, EXTRACT_OPERAND (RM, l),
193  break;
194 
195  case 'P':
196  arg_p (buf, EXTRACT_OPERAND (PRED, l),
198  break;
199 
200  case 'Q':
201  arg_p (buf, EXTRACT_OPERAND (SUCC, l),
203  break;
204  case 'o':
205  case 'j':
206  sprintf (buf+strlen (buf), "%d", (int) EXTRACT_ITYPE_IMM (l));
207  break;
208  case 'q':
209  sprintf (buf+strlen (buf), "%d", (int) EXTRACT_STYPE_IMM (l));
210  break;
211  case 'a':
212  target = EXTRACT_UJTYPE_IMM (l) + pc;
213  sprintf (buf+strlen (buf), "0x%"PFMT64x, (ut64)target);
214  break;
215  case 'p':
216  target = EXTRACT_SBTYPE_IMM (l) + pc;
217  sprintf (buf+strlen (buf), "0x%"PFMT64x, (ut64)target);
218  break;
219  case 'd':
220  sprintf (buf+strlen (buf), "%s", riscv_gpr_names[rd]);
221  break;
222  case 'z':
223  sprintf (buf+strlen (buf), "%s", riscv_gpr_names[0]);
224  break;
225  case '>':
226  sprintf (buf+strlen (buf), "0x%x", (int) EXTRACT_OPERAND (SHAMT, l));
227  break;
228  case '<':
229  sprintf (buf+strlen (buf), "0x%x", (int) EXTRACT_OPERAND (SHAMTW, l));
230  break;
231  case 'S':
232  case 'U':
233  sprintf (buf+strlen (buf), "%s", riscv_fpr_names[rs1]);
234  break;
235  case 'T':
236  sprintf (buf+strlen (buf), "%s", riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
237  break;
238  case 'D':
239  sprintf (buf+strlen (buf), "%s", riscv_fpr_names[rd]);
240  break;
241  case 'R':
242  sprintf (buf+strlen (buf), "%s", riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
243  break;
244  case 'E':
245  {
246  const char* csr_name = NULL;
247  unsigned int csr = EXTRACT_OPERAND (CSR, l);
248  switch (csr)
249  {
250 #define DECLARE_CSR(name, num) case num: csr_name = #name; break;
251 #include "riscv-opc.h"
252 #undef DECLARE_CSR
253  }
254  if (csr_name) {
255  sprintf (buf+strlen (buf), "%s", csr_name);
256  } else {
257  sprintf (buf+strlen (buf), "0x%x", csr);
258  }
259  break;
260  }
261  case 'Z':
262  sprintf (buf+strlen (buf), "%d", rs1);
263  break;
264  default:
265  /* xgettext:c-format */
266  sprintf (buf+strlen (buf), "# internal error, undefined modifier (%c)",
267  *d);
268  return;
269  }
270  }
271 }
#define rd()
#define NULL
Definition: cris-opc.c:27
#define OP_MASK_RD
Definition: mips.h:84
#define OP_SH_RD
Definition: mips.h:85
#define RS2(x)
Definition: sparc.h:203
static const char *const * riscv_fpr_names
Definition: riscv.c:40
#define ARRAY_SIZE(a)
Definition: riscv.c:36
static void arg_p(char *buf, unsigned long val, const char *const *array, size_t size)
Definition: riscv.c:43
static const char *const * riscv_gpr_names
Definition: riscv.c:39
#define EXTRACT_RVC_LD_IMM(x)
Definition: riscv.h:89
#define EXTRACT_RVC_J_IMM(x)
Definition: riscv.h:101
#define EXTRACT_RVC_LDSP_IMM(x)
Definition: riscv.h:93
#define EXTRACT_SBTYPE_IMM(x)
Definition: riscv.h:71
#define EXTRACT_STYPE_IMM(x)
Definition: riscv.h:69
#define X_SP
Definition: riscv.h:241
#define EXTRACT_RVC_IMM(x)
Definition: riscv.h:77
#define EXTRACT_RVC_SWSP_IMM(x)
Definition: riscv.h:95
#define EXTRACT_UTYPE_IMM(x)
Definition: riscv.h:73
#define RISCV_BIGIMM_REACH
Definition: riscv.h:190
#define EXTRACT_RVC_SDSP_IMM(x)
Definition: riscv.h:97
static const char *const riscv_rm[8]
Definition: riscv.h:47
#define EXTRACT_RVC_LWSP_IMM(x)
Definition: riscv.h:91
#define OP_SH_RS1
Definition: riscv.h:204
#define EXTRACT_UJTYPE_IMM(x)
Definition: riscv.h:75
#define OP_MASK_RS1
Definition: riscv.h:203
#define EXTRACT_RVC_B_IMM(x)
Definition: riscv.h:99
#define EXTRACT_ITYPE_IMM(x)
Definition: riscv.h:67
#define EXTRACT_OPERAND(FIELD, INSN)
Definition: riscv.h:264
#define EXTRACT_RVC_SIMM3(x)
Definition: riscv.h:81
#define EXTRACT_RVC_ADDI4SPN_IMM(x)
Definition: riscv.h:83
#define EXTRACT_RVC_ADDI16SP_IMM(x)
Definition: riscv.h:85
#define EXTRACT_RVC_LW_IMM(x)
Definition: riscv.h:87
#define RISCV_IMM_BITS
Definition: riscv.h:187
static const char *const riscv_pred_succ[16]
Definition: riscv.h:52
#define PFMT64x
Definition: rz_types.h:393
unsigned long uint64_t
Definition: sftypes.h:28
#define d(i)
Definition: sha256.c:44
ut64(WINAPI *w32_GetEnabledXStateFeatures)()

References arg_p(), ARRAY_SIZE, d, EXTRACT_ITYPE_IMM, EXTRACT_OPERAND, EXTRACT_RVC_ADDI16SP_IMM, EXTRACT_RVC_ADDI4SPN_IMM, EXTRACT_RVC_B_IMM, EXTRACT_RVC_IMM, EXTRACT_RVC_J_IMM, EXTRACT_RVC_LD_IMM, EXTRACT_RVC_LDSP_IMM, EXTRACT_RVC_LW_IMM, EXTRACT_RVC_LWSP_IMM, EXTRACT_RVC_SDSP_IMM, EXTRACT_RVC_SIMM3, EXTRACT_RVC_SWSP_IMM, EXTRACT_SBTYPE_IMM, EXTRACT_STYPE_IMM, EXTRACT_UJTYPE_IMM, EXTRACT_UTYPE_IMM, NULL, OP_MASK_RD, OP_MASK_RS1, OP_SH_RD, OP_SH_RS1, pc, PFMT64x, rd, RISCV_BIGIMM_REACH, riscv_fpr_names, riscv_gpr_names, RISCV_IMM_BITS, riscv_pred_succ, riscv_rm, RS2, sprintf, ut64(), and X_SP.

Referenced by riscv_disassemble().

◆ get_opcode()

static struct riscv_opcode* get_opcode ( insn_t  word)
static

Definition at line 273 of file riscv.c.

273  {
274  struct riscv_opcode *op;
275  static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1] = {0};
276 
277 #define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 3 : OP_MASK_OP))
278 
279  if (!init) {
280  for (op=riscv_opcodes; op < &riscv_opcodes[NUMOPCODES]; op++) {
281  if (!riscv_hash[OP_HASH_IDX (op->match)]) {
282  riscv_hash[OP_HASH_IDX (op->match)] = op;
283  }
284  }
285  init = 1;
286  }
287 
288  return (struct riscv_opcode *)riscv_hash[OP_HASH_IDX (word)];
289 }
ut8 op
Definition: 6502dis.c:13
#define NUMOPCODES
Definition: hppa.h:1079
#define OP_MASK_OP
Definition: mips.h:64
static struct riscv_opcode * riscv_opcodes
Definition: riscv-opc.c:685
static int init
Definition: riscv.c:41
#define OP_HASH_IDX(i)
Definition: dis.c:32

References init, NUMOPCODES, op, OP_HASH_IDX, OP_MASK_OP, and riscv_opcodes.

Referenced by riscv_disassemble().

◆ riscv_dis()

static int riscv_dis ( RzAsm a,
RzAsmOp rop,
const ut8 buf,
ut64  len 
)
static

Definition at line 318 of file riscv.c.

318  {
319  insn_t insn = {0};
320  if (len < 2) {
321  return -1;
322  }
323  memcpy (&insn, buf, RZ_MIN (sizeof (insn), len));
324  int insn_len = riscv_insn_length(insn);
325  if (len < insn_len) {
326  return -1;
327  }
328  riscv_disassemble (a, rop, insn, a->bits, len);
329  return insn_len;
330 }
size_t len
Definition: 6502dis.c:15
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
static int riscv_disassemble(RzAsm *a, RzAsmOp *rop, insn_t word, int xlen, int len)
Definition: riscv.c:291
static unsigned int riscv_insn_length(insn_t insn)
Definition: riscv.h:33
#define RZ_MIN(x, y)
#define a(i)
Definition: sha256.c:41

References a, len, memcpy(), riscv_disassemble(), riscv_insn_length(), and RZ_MIN.

Referenced by disassemble().

◆ riscv_disassemble()

static int riscv_disassemble ( RzAsm a,
RzAsmOp rop,
insn_t  word,
int  xlen,
int  len 
)
static

Definition at line 291 of file riscv.c.

291  {
292  const bool no_alias = false;
293  const struct riscv_opcode *op = get_opcode (word);
294  if (!op) {
295  return -1;
296  }
297  for (; op < &riscv_opcodes[NUMOPCODES]; op++) {
298  if ( !(op->match_func)(op, word) ) {
299  continue;
300  }
301  if (no_alias && (op->pinfo & INSN_ALIAS)) {
302  continue;
303  }
304  if (isdigit ((ut8)op->subset[0]) && atoi (op->subset) != xlen ) {
305  continue;
306  }
307  if (op->name && op->args) {
308  rz_asm_op_set_asm (rop, op->name);
309  get_insn_args (rz_asm_op_get_asm (rop), op->args, word, a->pc);
310  return 0;
311  }
312  rz_asm_op_set_asm (rop, sdb_fmt ("invalid word(%"PFMT64x")", (ut64)word));
313  return -1;
314  }
315  return 0;
316 }
RZ_API void rz_asm_op_set_asm(RzAsmOp *op, const char *str)
Definition: aop.c:53
RZ_API char * rz_asm_op_get_asm(RzAsmOp *op)
Definition: aop.c:37
RZ_API char * sdb_fmt(const char *fmt,...)
Definition: fmt.c:26
uint8_t ut8
Definition: lh5801.h:11
static void get_insn_args(char *buf, const char *d, insn_t l, uint64_t pc)
Definition: riscv.c:49
static struct riscv_opcode * get_opcode(insn_t word)
Definition: riscv.c:273
#define INSN_ALIAS
Definition: riscv.h:297
#define isdigit(c)
Definition: safe-ctype.h:131

References a, get_insn_args(), get_opcode(), INSN_ALIAS, isdigit, NUMOPCODES, PFMT64x, riscv_opcodes, rz_asm_op_get_asm(), rz_asm_op_set_asm(), sdb_fmt(), and ut64().

Referenced by riscv_dis().

Variable Documentation

◆ init

int init ( void  ) = 0
static

Definition at line 41 of file riscv.c.

Referenced by get_opcode().

◆ riscv_fpr_names

const char* const* riscv_fpr_names = riscv_fpr_names_abi
static

Definition at line 40 of file riscv.c.

Referenced by get_insn_args().

◆ riscv_gpr_names

const char* const* riscv_gpr_names = riscv_gpr_names_abi
static

Definition at line 39 of file riscv.c.

Referenced by get_insn_args().