1 /* radare2 - LGPL - Copyright 2013-2020 - pancake */
2
3 #include <r_asm.h>
4 #include <r_lib.h>
5
6 #include <capstone.h>
7 #if CS_API_MAJOR >= 5
8 #include <riscv.h>
9
10 // http://www.mrc.uidaho.edu/mrc/people/jff/digital/RISCVir.html
11
12 #define OPERAND(x) insn->detail->riscv.operands[x]
13 #define REGID(x) insn->detail->riscv.operands[x].reg
14 #define REG(x) cs_reg_name (*handle, insn->detail->riscv.operands[x].reg)
15 #define IMM(x) insn->detail->riscv.operands[x].imm
16 #define MEMBASE(x) cs_reg_name(*handle, insn->detail->riscv.operands[x].mem.base)
17 #define MEMINDEX(x) insn->detail->riscv.operands[x].mem.index
18 #define MEMDISP(x) insn->detail->riscv.operands[x].mem.disp
19 #define OPCOUNT() insn->detail->riscv.op_count
20 // TODO scale and disp
21
22 #define SET_VAL(op,i) \
23 if ((i)<OPCOUNT() && OPERAND(i).type == RISCV_OP_IMM) {\
24 (op)->val = OPERAND(i).imm;\
25 }
26
27 #define CREATE_SRC_DST_3(op) \
28 (op)->src[0] = r_anal_value_new ();\
29 (op)->src[1] = r_anal_value_new ();\
30 (op)->dst = r_anal_value_new ();
31
32 #define CREATE_SRC_DST_2(op) \
33 (op)->src[0] = r_anal_value_new ();\
34 (op)->dst = r_anal_value_new ();
35
36 #define SET_SRC_DST_3_REGS(op) \
37 CREATE_SRC_DST_3 (op);\
38 (op)->dst->reg = r_reg_get (anal->reg, REG (0), R_REG_TYPE_GPR);\
39 (op)->src[0]->reg = r_reg_get (anal->reg, REG (1), R_REG_TYPE_GPR);\
40 (op)->src[1]->reg = r_reg_get (anal->reg, REG (2), R_REG_TYPE_GPR);
41
42 #define SET_SRC_DST_3_IMM(op) \
43 CREATE_SRC_DST_3 (op);\
44 (op)->dst->reg = r_reg_get (anal->reg, REG (0), R_REG_TYPE_GPR);\
45 (op)->src[0]->reg = r_reg_get (anal->reg, REG (1), R_REG_TYPE_GPR);\
46 (op)->src[1]->imm = IMM (2);
47
48 #define SET_SRC_DST_2_REGS(op) \
49 CREATE_SRC_DST_2 (op);\
50 (op)->dst->reg = r_reg_get (anal->reg, REG (0), R_REG_TYPE_GPR);\
51 (op)->src[0]->reg = r_reg_get (anal->reg, REG (1), R_REG_TYPE_GPR);
52
53 #define SET_SRC_DST_3_REG_OR_IMM(op) \
54 if (OPERAND(2).type == RISCV_OP_IMM) {\
55 SET_SRC_DST_3_IMM (op);\
56 } else if (OPERAND(2).type == RISCV_OP_REG) {\
57 SET_SRC_DST_3_REGS (op);\
58 }
59
60
61 // ESIL macros:
62
63 // put the sign bit on the stack
64 #define ES_IS_NEGATIVE(arg) "1,"arg",<<<,1,&"
65
66
67 // call with delay slot
68 #define ES_CALL_DR(ra, addr) "pc,4,+,"ra",=,"ES_J(addr)
69 #define ES_CALL_D(addr) ES_CALL_DR("ra", addr)
70
71 // call without delay slot
72 #define ES_CALL_NDR(ra, addr) "pc,"ra",=,"ES_J(addr)
73 #define ES_CALL_ND(addr) ES_CALL_NDR("ra", addr)
74
75 #define USE_DS 0
76 #if USE_DS
77 // emit ERR trap if executed in a delay slot
78 #define ES_TRAP_DS() "$ds,!,!,?{,$$,1,TRAP,BREAK,},"
79 // jump to address
80 #define ES_J(addr) addr",SETJT,1,SETD"
81 #else
82 #define ES_TRAP_DS() ""
83 #define ES_J(addr) addr",pc,="
84 #endif
85
86 // sign extend 32 -> 64
87 #define ES_SIGN_EXT64(arg) \
88 arg",0x80000000,&,0,<,?{,"\
89 "0xffffffff00000000,"arg",|=,"\
90 "}"
91
92 #define PROTECT_ZERO() \
93 if (REG(0)[0]=='z'){\
94 r_strbuf_appendf (&op->esil, ",");\
95 } else
96
97 #define ESIL_LOAD(size) \
98 PROTECT_ZERO () {\
99 r_strbuf_appendf (&op->esil, "%s,["size"],%s,=",\
100 ARG(1), REG(0));\
101 }
102
opex(RStrBuf * buf,csh handle,cs_insn * insn)103 static void opex(RStrBuf *buf, csh handle, cs_insn *insn) {
104 int i;
105 PJ *pj = pj_new ();
106 if (!pj) {
107 return;
108 }
109 pj_o (pj);
110 pj_ka (pj, "operands");
111 cs_riscv *x = &insn->detail->riscv;
112 for (i = 0; i < x->op_count; i++) {
113 cs_riscv_op *op = x->operands + i;
114 pj_o (pj);
115 switch (op->type) {
116 case RISCV_OP_REG:
117 pj_ks (pj, "type", "reg");
118 pj_ks (pj, "value", cs_reg_name (handle, op->reg));
119 break;
120 case RISCV_OP_IMM:
121 pj_ks (pj, "type", "imm");
122 pj_kN (pj, "value", op->imm);
123 break;
124 case RISCV_OP_MEM:
125 pj_ks (pj, "type", "mem");
126 if (op->mem.base != RISCV_REG_INVALID) {
127 pj_ks (pj, "base", cs_reg_name (handle, op->mem.base));
128 }
129 pj_kN (pj, "disp", op->mem.disp);
130 break;
131 default:
132 pj_ks (pj, "type", "invalid");
133 break;
134 }
135 pj_end (pj); /* o operand */
136 }
137 pj_end (pj); /* a operands */
138 pj_end (pj);
139
140 r_strbuf_init (buf);
141 r_strbuf_append (buf, pj_string (pj));
142 pj_free (pj);
143 }
144
arg(csh * handle,cs_insn * insn,char * buf,int n)145 static const char *arg(csh *handle, cs_insn *insn, char *buf, int n) {
146 *buf = 0;
147 switch (insn->detail->riscv.operands[n].type) {
148 case RISCV_OP_INVALID:
149 break;
150 case RISCV_OP_REG:
151 sprintf (buf, "%s",
152 cs_reg_name (*handle,
153 insn->detail->riscv.operands[n].reg));
154 break;
155 case RISCV_OP_IMM:
156 {
157 st64 x = (st64)insn->detail->riscv.operands[n].imm;
158 sprintf (buf, "%"PFMT64d, x);
159 break;
160 }
161 case RISCV_OP_MEM:
162 {
163 st64 disp = insn->detail->riscv.operands[n].mem.disp;
164 if (disp < 0) {
165 sprintf (buf, "%"PFMT64d",%s,-",
166 (ut64)-insn->detail->riscv.operands[n].mem.disp,
167 cs_reg_name (*handle,
168 insn->detail->riscv.operands[n].mem.base));
169 } else {
170 sprintf (buf, "0x%"PFMT64x",%s,+",
171 insn->detail->riscv.operands[n].mem.disp,
172 cs_reg_name (*handle,
173 insn->detail->riscv.operands[n].mem.base));
174 }
175 break;
176 }
177 }
178 return buf;
179 }
180
181 #define ARG(x) (*str[x]!=0)?str[x]:arg(handle, insn, str[x], x)
182
analop_esil(RAnal * a,RAnalOp * op,ut64 addr,const ut8 * buf,int len,csh * handle,cs_insn * insn)183 static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) {
184 char str[8][32] = {{0}};
185 int i;
186
187 r_strbuf_init (&op->esil);
188 r_strbuf_set (&op->esil, "");
189
190 if (insn) {
191 // caching operands
192 for (i = 0; i < insn->detail->riscv.op_count && i < 8; i++) {
193 *str[i] = 0;
194 ARG (i);
195 }
196 }
197
198 switch (insn->id) {
199 //case RISCV_INS_NOP:
200 // r_strbuf_setf (&op->esil, ",");
201 // break;
202 }
203 return 0;
204 }
205
parse_reg_name(RRegItem * reg,csh handle,cs_insn * insn,int reg_num)206 static int parse_reg_name(RRegItem *reg, csh handle, cs_insn *insn, int reg_num) {
207 if (!reg) {
208 return -1;
209 }
210 switch (OPERAND (reg_num).type) {
211 case RISCV_OP_REG:
212 reg->name = (char *)cs_reg_name (handle, OPERAND (reg_num).reg);
213 break;
214 case RISCV_OP_MEM:
215 if (OPERAND (reg_num).mem.base != RISCV_REG_INVALID) {
216 reg->name = (char *)cs_reg_name (handle, OPERAND (reg_num).mem.base);
217 }
218 default:
219 break;
220 }
221 return 0;
222 }
223
op_fillval(RAnal * anal,RAnalOp * op,csh * handle,cs_insn * insn)224 static void op_fillval(RAnal *anal, RAnalOp *op, csh *handle, cs_insn *insn) {
225 static RRegItem reg;
226 switch (op->type & R_ANAL_OP_TYPE_MASK) {
227 case R_ANAL_OP_TYPE_LOAD:
228 if (OPERAND(1).type == RISCV_OP_MEM) {
229 ZERO_FILL (reg);
230 op->src[0] = r_anal_value_new ();
231 op->src[0]->reg = ®
232 parse_reg_name (op->src[0]->reg, *handle, insn, 1);
233 op->src[0]->delta = OPERAND(1).mem.disp;
234 }
235 break;
236 case R_ANAL_OP_TYPE_STORE:
237 if (OPERAND(1).type == RISCV_OP_MEM) {
238 ZERO_FILL (reg);
239 op->dst = r_anal_value_new ();
240 op->dst->reg = ®
241 parse_reg_name (op->dst->reg, *handle, insn, 1);
242 op->dst->delta = OPERAND(1).mem.disp;
243 }
244 break;
245 case R_ANAL_OP_TYPE_SHL:
246 case R_ANAL_OP_TYPE_SHR:
247 case R_ANAL_OP_TYPE_SAR:
248 case R_ANAL_OP_TYPE_XOR:
249 case R_ANAL_OP_TYPE_SUB:
250 case R_ANAL_OP_TYPE_AND:
251 case R_ANAL_OP_TYPE_ADD:
252 case R_ANAL_OP_TYPE_OR:
253 SET_SRC_DST_3_REG_OR_IMM (op);
254 break;
255 case R_ANAL_OP_TYPE_MOV:
256 SET_SRC_DST_3_REG_OR_IMM (op);
257 break;
258 case R_ANAL_OP_TYPE_DIV: // UDIV
259 #if 0
260 capstone bug
261 ------------
262 $ r2 -a riscv -e cfg.bigendian=1 -c "wx 0083001b" -
263 // should be 3 regs, right?
264 [0x00000000]> aoj~{}
265 [
266 {
267 "opcode": "divu zero, a0, v1",
268 "disasm": "divu zero, a0, v1",
269 "mnemonic": "divu",
270 "sign": false,
271 "prefix": 0,
272 "id": 192,
273 "opex": {
274 "operands": [
275 {
276 "type": "reg",
277 "value": "a0"
278 },
279 {
280 "type": "reg",
281 "value": "v1"
282 }
283 ]
284 },
285 #endif
286 if (OPERAND(0).type == RISCV_OP_REG && OPERAND(1).type == RISCV_OP_REG && OPERAND(2).type == RISCV_OP_REG) {
287 SET_SRC_DST_3_REGS (op);
288 } else if (OPERAND(0).type == RISCV_OP_REG && OPERAND(1).type == RISCV_OP_REG) {
289 SET_SRC_DST_2_REGS (op);
290 } else {
291 eprintf ("Unknown div at 0x%08"PFMT64x"\n", op->addr);
292 }
293 break;
294 }
295 if (insn && (insn->id == RISCV_INS_SLTI || insn->id == RISCV_INS_SLTIU)) {
296 SET_SRC_DST_3_IMM (op);
297 }
298 }
299
300 static void set_opdir(RAnalOp *op) {
301 switch (op->type & R_ANAL_OP_TYPE_MASK) {
302 case R_ANAL_OP_TYPE_LOAD:
303 op->direction = R_ANAL_OP_DIR_READ;
304 break;
305 case R_ANAL_OP_TYPE_STORE:
306 op->direction = R_ANAL_OP_DIR_WRITE;
307 break;
308 case R_ANAL_OP_TYPE_LEA:
309 op->direction = R_ANAL_OP_DIR_REF;
310 break;
311 case R_ANAL_OP_TYPE_CALL:
312 case R_ANAL_OP_TYPE_JMP:
313 case R_ANAL_OP_TYPE_UJMP:
314 case R_ANAL_OP_TYPE_UCALL:
315 op->direction = R_ANAL_OP_DIR_EXEC;
316 break;
317 default:
318 break;
319 }
320 }
321
322 static int analop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
323 int n, ret, opsize = -1;
324 static csh hndl = 0;
325 static int omode = -1;
326 static int obits = 32;
327 cs_insn* insn;
328 int mode = (anal->bits==64)? CS_MODE_RISCV64: CS_MODE_RISCV32;
329 if (mode != omode || anal->bits != obits) {
330 cs_close (&hndl);
331 hndl = 0;
332 omode = mode;
333 obits = anal->bits;
334 }
335 // XXX no arch->cpu ?!?! CS_MODE_MICRO, N64
336 op->addr = addr;
337 if (len < 4) {
338 return -1;
339 }
340 op->size = 4;
341 if (hndl == 0) {
342 ret = cs_open (CS_ARCH_RISCV, mode, &hndl);
343 if (ret != CS_ERR_OK) {
344 goto fin;
345 }
346 cs_option (hndl, CS_OPT_DETAIL, CS_OPT_ON);
347 }
348 n = cs_disasm (hndl, (ut8*)buf, len, addr, 1, &insn);
349 if (n < 1 || insn->size < 1) {
350 goto beach;
351 }
352 op->id = insn->id;
353 opsize = op->size = insn->size;
354 switch (insn->id) {
355 case RISCV_INS_C_NOP:
356 op->type = R_ANAL_OP_TYPE_NOP;
357 break;
358 case RISCV_INS_INVALID:
359 op->type = R_ANAL_OP_TYPE_ILL;
360 break;
361 case RISCV_INS_C_JALR:
362 op->type = R_ANAL_OP_TYPE_UCALL;
363 break;
364 case RISCV_INS_C_JR:
365 op->type = R_ANAL_OP_TYPE_UJMP;
366 break;
367 case RISCV_INS_C_MV:
368 op->type = R_ANAL_OP_TYPE_MOV;
369 break;
370 case RISCV_INS_JAL:
371 op->type = R_ANAL_OP_TYPE_CALL;
372 op->jump = IMM(0);
373 op->fail = op->addr + op->size;
374 break;
375 case RISCV_INS_MRET:
376 case RISCV_INS_SRET:
377 case RISCV_INS_URET:
378 op->type = R_ANAL_OP_TYPE_RET;
379 break;
380 }
381 beach:
382 set_opdir (op);
383 if (insn && mask & R_ANAL_OP_MASK_OPEX) {
384 opex (&op->opex, hndl, insn);
385 }
386 if (mask & R_ANAL_OP_MASK_ESIL) {
387 if (analop_esil (anal, op, addr, buf, len, &hndl, insn) != 0) {
388 r_strbuf_fini (&op->esil);
389 }
390 }
391 if (mask & R_ANAL_OP_MASK_VAL) {
392 op_fillval (anal, op, &hndl, insn);
393 }
394 cs_free (insn, n);
395 //cs_close (&handle);
396 fin:
397 return opsize;
398 }
399
400 static char *get_reg_profile(RAnal *anal) {
401 const char *p = NULL;
402 switch (anal->bits) {
403 case 32: p =
404 "=PC pc\n"
405 "=SP sp\n" // ABI: stack pointer
406 "=LR ra\n" // ABI: return address
407 "=BP s0\n" // ABI: frame pointer
408 "=A0 a0\n"
409 "=A1 a1\n"
410
411 "gpr pc .32 0 0\n"
412 // RV32I regs (ABI names)
413 // From user-Level ISA Specification, section 2.1
414 // "zero" has been left out as it ignores writes and always reads as zero
415 "gpr ra .32 4 0\n" // =x1
416 "gpr sp .32 8 0\n" // =x2
417 "gpr gp .32 12 0\n" // =x3
418 "gpr tp .32 16 0\n" // =x4
419 "gpr t0 .32 20 0\n" // =x5
420 "gpr t1 .32 24 0\n" // =x6
421 "gpr t2 .32 28 0\n" // =x7
422 "gpr s0 .32 32 0\n" // =x8
423 "gpr s1 .32 36 0\n" // =x9
424 "gpr a0 .32 40 0\n" // =x10
425 "gpr a1 .32 44 0\n" // =x11
426 "gpr a2 .32 48 0\n" // =x12
427 "gpr a3 .32 52 0\n" // =x13
428 "gpr a4 .32 56 0\n" // =x14
429 "gpr a5 .32 60 0\n" // =x15
430 "gpr a6 .32 64 0\n" // =x16
431 "gpr a7 .32 68 0\n" // =x17
432 "gpr s2 .32 72 0\n" // =x18
433 "gpr s3 .32 76 0\n" // =x19
434 "gpr s4 .32 80 0\n" // =x20
435 "gpr s5 .32 84 0\n" // =x21
436 "gpr s6 .32 88 0\n" // =x22
437 "gpr s7 .32 92 0\n" // =x23
438 "gpr s8 .32 96 0\n" // =x24
439 "gpr s9 .32 100 0\n" // =x25
440 "gpr s10 .32 104 0\n" // =x26
441 "gpr s11 .32 108 0\n" // =x27
442 "gpr t3 .32 112 0\n" // =x28
443 "gpr t4 .32 116 0\n" // =x29
444 "gpr t5 .32 120 0\n" // =x30
445 "gpr t6 .32 124 0\n" // =x31
446 // RV32F/D regs (ABI names)
447 // From user-Level ISA Specification, section 8.1 and 9.1
448 "gpr ft0 .64 128 0\n" // =f0
449 "gpr ft1 .64 136 0\n" // =f1
450 "gpr ft2 .64 144 0\n" // =f2
451 "gpr ft3 .64 152 0\n" // =f3
452 "gpr ft4 .64 160 0\n" // =f4
453 "gpr ft5 .64 168 0\n" // =f5
454 "gpr ft6 .64 176 0\n" // =f6
455 "gpr ft7 .64 184 0\n" // =f7
456 "gpr fs0 .64 192 0\n" // =f8
457 "gpr fs1 .64 200 0\n" // =f9
458 "gpr fa0 .64 208 0\n" // =f10
459 "gpr fa1 .64 216 0\n" // =f11
460 "gpr fa2 .64 224 0\n" // =f12
461 "gpr fa3 .64 232 0\n" // =f13
462 "gpr fa4 .64 240 0\n" // =f14
463 "gpr fa5 .64 248 0\n" // =f15
464 "gpr fa6 .64 256 0\n" // =f16
465 "gpr fa7 .64 264 0\n" // =f17
466 "gpr fs2 .64 272 0\n" // =f18
467 "gpr fs3 .64 280 0\n" // =f19
468 "gpr fs4 .64 288 0\n" // =f20
469 "gpr fs5 .64 296 0\n" // =f21
470 "gpr fs6 .64 304 0\n" // =f22
471 "gpr fs7 .64 312 0\n" // =f23
472 "gpr fs8 .64 320 0\n" // =f24
473 "gpr fs9 .64 328 0\n" // =f25
474 "gpr fs10 .64 336 0\n" // =f26
475 "gpr fs11 .64 344 0\n" // =f27
476 "gpr ft8 .64 352 0\n" // =f28
477 "gpr ft9 .64 360 0\n" // =f29
478 "gpr ft10 .64 368 0\n" // =f30
479 "gpr ft11 .64 376 0\n" // =f31
480 "gpr fcsr .32 384 0\n"
481 "flg nx .1 3072 0\n"
482 "flg uf .1 3073 0\n"
483 "flg of .1 3074 0\n"
484 "flg dz .1 3075 0\n"
485 "flg nv .1 3076 0\n"
486 "flg frm .3 3077 0\n"
487 ;
488
489 break;
490 case 64: p =
491 "=PC pc\n"
492 "=SP sp\n" // ABI: stack pointer
493 "=LR ra\n" // ABI: return address
494 "=BP s0\n" // ABI: frame pointer
495 "=A0 a0\n"
496 "=A1 a1\n"
497
498 "gpr pc .64 0 0\n"
499 // RV64I regs (ABI names)
500 // From user-Level ISA Specification, section 2.1 and 4.1
501 // "zero" has been left out as it ignores writes and always reads as zero
502 "gpr ra .64 8 0\n" // =x1
503 "gpr sp .64 16 0\n" // =x2
504 "gpr gp .64 24 0\n" // =x3
505 "gpr tp .64 32 0\n" // =x4
506 "gpr t0 .64 40 0\n" // =x5
507 "gpr t1 .64 48 0\n" // =x6
508 "gpr t2 .64 56 0\n" // =x7
509 "gpr s0 .64 64 0\n" // =x8
510 "gpr s1 .64 72 0\n" // =x9
511 "gpr a0 .64 80 0\n" // =x10
512 "gpr a1 .64 88 0\n" // =x11
513 "gpr a2 .64 96 0\n" // =x12
514 "gpr a3 .64 104 0\n" // =x13
515 "gpr a4 .64 112 0\n" // =x14
516 "gpr a5 .64 120 0\n" // =x15
517 "gpr a6 .64 128 0\n" // =x16
518 "gpr a7 .64 136 0\n" // =x17
519 "gpr s2 .64 144 0\n" // =x18
520 "gpr s3 .64 152 0\n" // =x19
521 "gpr s4 .64 160 0\n" // =x20
522 "gpr s5 .64 168 0\n" // =x21
523 "gpr s6 .64 176 0\n" // =x22
524 "gpr s7 .64 184 0\n" // =x23
525 "gpr s8 .64 192 0\n" // =x24
526 "gpr s9 .64 200 0\n" // =x25
527 "gpr s10 .64 208 0\n" // =x26
528 "gpr s11 .64 216 0\n" // =x27
529 "gpr t3 .64 224 0\n" // =x28
530 "gpr t4 .64 232 0\n" // =x29
531 "gpr t5 .64 240 0\n" // =x30
532 "gpr t6 .64 248 0\n" // =x31
533 // RV64F/D regs (ABI names)
534 "gpr ft0 .64 256 0\n" // =f0
535 "gpr ft1 .64 264 0\n" // =f1
536 "gpr ft2 .64 272 0\n" // =f2
537 "gpr ft3 .64 280 0\n" // =f3
538 "gpr ft4 .64 288 0\n" // =f4
539 "gpr ft5 .64 296 0\n" // =f5
540 "gpr ft6 .64 304 0\n" // =f6
541 "gpr ft7 .64 312 0\n" // =f7
542 "gpr fs0 .64 320 0\n" // =f8
543 "gpr fs1 .64 328 0\n" // =f9
544 "gpr fa0 .64 336 0\n" // =f10
545 "gpr fa1 .64 344 0\n" // =f11
546 "gpr fa2 .64 352 0\n" // =f12
547 "gpr fa3 .64 360 0\n" // =f13
548 "gpr fa4 .64 368 0\n" // =f14
549 "gpr fa5 .64 376 0\n" // =f15
550 "gpr fa6 .64 384 0\n" // =f16
551 "gpr fa7 .64 392 0\n" // =f17
552 "gpr fs2 .64 400 0\n" // =f18
553 "gpr fs3 .64 408 0\n" // =f19
554 "gpr fs4 .64 416 0\n" // =f20
555 "gpr fs5 .64 424 0\n" // =f21
556 "gpr fs6 .64 432 0\n" // =f22
557 "gpr fs7 .64 440 0\n" // =f23
558 "gpr fs8 .64 448 0\n" // =f24
559 "gpr fs9 .64 456 0\n" // =f25
560 "gpr fs10 .64 464 0\n" // =f26
561 "gpr fs11 .64 472 0\n" // =f27
562 "gpr ft8 .64 480 0\n" // =f28
563 "gpr ft9 .64 488 0\n" // =f29
564 "gpr ft10 .64 496 0\n" // =f30
565 "gpr ft11 .64 504 0\n" // =f31
566 "gpr fcsr .32 512 0\n"
567 "flg nx .1 4096 0\n"
568 "flg uf .1 4097 0\n"
569 "flg of .1 4098 0\n"
570 "flg dz .1 4099 0\n"
571 "flg nv .1 4100 0\n"
572 "flg frm .3 4101 0\n"
573 ;
574
575 break;
576 }
577 return (p && *p)? strdup (p): NULL;
578 }
579
580 static int archinfo(RAnal *anal, int q) {
581 switch (q) {
582 case R_ANAL_ARCHINFO_ALIGN:
583 return 4;
584 case R_ANAL_ARCHINFO_MAX_OP_SIZE:
585 return 4;
586 case R_ANAL_ARCHINFO_MIN_OP_SIZE:
587 if (anal->bits == 64) {
588 return 4;
589 }
590 return 2;
591 }
592 return 0;
593 }
594
595 RAnalPlugin r_anal_plugin_riscv_cs = {
596 .name = "riscv.cs",
597 .desc = "Capstone RISCV analyzer",
598 .license = "BSD",
599 .esil = true,
600 .arch = "riscv",
601 .get_reg_profile = get_reg_profile,
602 .archinfo = archinfo,
603 .bits = 32|64,
604 .op = &analop,
605 };
606
607 #ifndef R2_PLUGIN_INCORE
608 R_API RLibStruct radare_plugin = {
609 .type = R_LIB_TYPE_ANAL,
610 .data = &r_anal_plugin_riscv_cs,
611 .version = R2_VERSION
612 };
613 #endif
614
615 #else
616 RAnalPlugin r_anal_plugin_riscv_cs = {0};
617 #ifndef R2_PLUGIN_INCORE
618 R_API RLibStruct radare_plugin = {
619 .type = R_LIB_TYPE_ANAL,
620 .version = R2_VERSION
621 };
622 #endif
623 #endif
624