riscv-dis.c revision 1.2 1 /* RISC-V disassembler
2 Copyright 2011-2014 Free Software Foundation, Inc.
3
4 Contributed by Andrew Waterman (waterman (at) cs.berkeley.edu) at UC Berkeley.
5 Based on MIPS target.
6
7 This file is part of the GNU opcodes library.
8
9 This library is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 It is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
23
24 #include "sysdep.h"
25 #include "dis-asm.h"
26 #include "libiberty.h"
27 #include "opcode/riscv.h"
28 #include "opintl.h"
29 #include "elf-bfd.h"
30 #include "elf/riscv.h"
31
32 #include <stdint.h>
33 #include <assert.h>
34
35 /* FIXME: These should be shared with gdb somehow. */
36
37 static const char * const riscv_gpr_names_numeric[32] =
38 {
39 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
40 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
41 "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
42 "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31"
43 };
44
45 static const char * const riscv_gpr_names_abi[32] = {
46 "zero", "ra", "s0", "s1", "s2", "s3", "s4", "s5",
47 "s6", "s7", "s8", "s9", "s10", "s11", "sp", "tp",
48 "v0", "v1", "a0", "a1", "a2", "a3", "a4", "a5",
49 "a6", "a7", "t0", "t1", "t2", "t3", "t4", "gp"
50 };
51
52
53 static const char * const riscv_fpr_names_numeric[32] =
54 {
55 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
56 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
57 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
58 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
59 };
60
61 static const char * const riscv_fpr_names_abi[32] = {
62 "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
63 "fs8", "fs9", "fs10", "fs11", "fs12", "fs13", "fs14", "fs15",
64 "fv0", "fv1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
65 "fa6", "fa7", "ft0", "ft1", "ft2", "ft3", "ft4", "ft5"
66 };
67
68 static const char * const riscv_vgr_reg_names_riscv[32] =
69 {
70 "vx0", "vx1", "vx2", "vx3", "vx4", "vx5", "vx6", "vx7",
71 "vx8", "vx9", "vx10", "vx11", "vx12", "vx13", "vx14", "vx15",
72 "vx16", "vx17", "vx18", "vx19", "vx20", "vx21", "vx22", "vx23",
73 "vx24", "vx25", "vx26", "vx27", "vx28", "vx29", "vx30", "vx31"
74 };
75
76 static const char * const riscv_vfp_reg_names_riscv[32] =
77 {
78 "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7",
79 "vf8", "vf9", "vf10", "vf11", "vf12", "vf13", "vf14", "vf15",
80 "vf16", "vf17", "vf18", "vf19", "vf20", "vf21", "vf22", "vf23",
81 "vf24", "vf25", "vf26", "vf27", "vf28", "vf29", "vf30", "vf31"
82 };
83
84 struct riscv_abi_choice
85 {
86 const char * name;
87 const char * const *gpr_names;
88 const char * const *fpr_names;
89 };
90
91 struct riscv_abi_choice riscv_abi_choices[] =
92 {
93 { "numeric", riscv_gpr_names_numeric, riscv_fpr_names_numeric },
94 { "32", riscv_gpr_names_abi, riscv_fpr_names_abi },
95 { "64", riscv_gpr_names_abi, riscv_fpr_names_abi },
96 };
97
98 struct riscv_arch_choice
99 {
100 const char *name;
101 int bfd_mach_valid;
102 unsigned long bfd_mach;
103 };
104
105 const struct riscv_arch_choice riscv_arch_choices[] =
106 {
107 { "numeric", 0, 0 },
108 { "rv32", 1, bfd_mach_riscv32 },
109 { "rv64", 1, bfd_mach_riscv64 },
110 };
111
112 struct riscv_private_data
113 {
114 bfd_vma gp;
115 bfd_vma print_addr;
116 bfd_vma hi_addr[OP_MASK_RD + 1];
117 };
118
119 /* ISA and processor type to disassemble for, and register names to use.
120 set_default_riscv_dis_options and parse_riscv_dis_options fill in these
121 values. */
122 static const char * const *riscv_gpr_names;
123 static const char * const *riscv_fpr_names;
124
125 /* Other options */
126 static int no_aliases; /* If set disassemble as most general inst. */
127
128 static const struct riscv_abi_choice *
130 choose_abi_by_name (const char *name, unsigned int namelen)
131 {
132 const struct riscv_abi_choice *c;
133 unsigned int i;
134
135 for (i = 0, c = NULL; i < ARRAY_SIZE (riscv_abi_choices) && c == NULL; i++)
136 if (strncmp (riscv_abi_choices[i].name, name, namelen) == 0
137 && strlen (riscv_abi_choices[i].name) == namelen)
138 c = &riscv_abi_choices[i];
139
140 return c;
141 }
142
143 static void
144 set_default_riscv_dis_options (struct disassemble_info *info ATTRIBUTE_UNUSED)
145 {
146 riscv_gpr_names = riscv_gpr_names_abi;
147 riscv_fpr_names = riscv_fpr_names_abi;
148 no_aliases = 0;
149 }
150
151 static void
152 parse_riscv_dis_option (const char *option, unsigned int len)
153 {
154 unsigned int i, optionlen, vallen;
155 const char *val;
156 const struct riscv_abi_choice *chosen_abi;
157
158 /* Try to match options that are simple flags */
159 if (CONST_STRNEQ (option, "no-aliases"))
160 {
161 no_aliases = 1;
162 return;
163 }
164
165 /* Look for the = that delimits the end of the option name. */
166 for (i = 0; i < len; i++)
167 if (option[i] == '=')
168 break;
169
170 if (i == 0) /* Invalid option: no name before '='. */
171 return;
172 if (i == len) /* Invalid option: no '='. */
173 return;
174 if (i == (len - 1)) /* Invalid option: no value after '='. */
175 return;
176
177 optionlen = i;
178 val = option + (optionlen + 1);
179 vallen = len - (optionlen + 1);
180
181 if (strncmp ("gpr-names", option, optionlen) == 0
182 && strlen ("gpr-names") == optionlen)
183 {
184 chosen_abi = choose_abi_by_name (val, vallen);
185 if (chosen_abi != NULL)
186 riscv_gpr_names = chosen_abi->gpr_names;
187 return;
188 }
189
190 if (strncmp ("fpr-names", option, optionlen) == 0
191 && strlen ("fpr-names") == optionlen)
192 {
193 chosen_abi = choose_abi_by_name (val, vallen);
194 if (chosen_abi != NULL)
195 riscv_fpr_names = chosen_abi->fpr_names;
196 return;
197 }
198
199 /* Invalid option. */
200 }
201
202 static void
203 parse_riscv_dis_options (const char *options)
204 {
205 const char *option_end;
206
207 if (options == NULL)
208 return;
209
210 while (*options != '\0')
211 {
212 /* Skip empty options. */
213 if (*options == ',')
214 {
215 options++;
216 continue;
217 }
218
219 /* We know that *options is neither NUL or a comma. */
220 option_end = options + 1;
221 while (*option_end != ',' && *option_end != '\0')
222 option_end++;
223
224 parse_riscv_dis_option (options, option_end - options);
225
226 /* Go on to the next one. If option_end points to a comma, it
227 will be skipped above. */
228 options = option_end;
229 }
230 }
231
232 /* Print one argument from an array. */
233
234 static void
235 arg_print (struct disassemble_info *info, unsigned long val,
236 const char* const* array, size_t size)
237 {
238 const char *s = val >= size || array[val] == NULL ? "unknown" : array[val];
239 (*info->fprintf_func) (info->stream, "%s", s);
240 }
241
242 static void
243 maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset)
244 {
245 if (pd->hi_addr[base_reg] != (bfd_vma)-1)
246 {
247 pd->print_addr = pd->hi_addr[base_reg] + offset;
248 pd->hi_addr[base_reg] = -1;
249 }
250 else if (base_reg == GP_REG && pd->gp != (bfd_vma)-1)
251 pd->print_addr = pd->gp + offset;
252 else if (base_reg == TP_REG)
253 pd->print_addr = offset;
254 }
255
256 /* Print insn arguments for 32/64-bit code. */
257
258 static void
259 print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
260 {
261 struct riscv_private_data *pd = info->private_data;
262 int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
263 int rd = (l >> OP_SH_RD) & OP_MASK_RD;
264
265 if (*d != '\0')
266 (*info->fprintf_func) (info->stream, "\t");
267
268 for (; *d != '\0'; d++)
269 {
270 switch (*d)
271 {
272 /* Xcustom */
273 case '^':
274 switch (*++d)
275 {
276 case 'd':
277 (*info->fprintf_func) (info->stream, "%d", rd);
278 break;
279 case 's':
280 (*info->fprintf_func) (info->stream, "%d", rs1);
281 break;
282 case 't':
283 (*info->fprintf_func)
284 ( info->stream, "%d", (int)((l >> OP_SH_RS2) & OP_MASK_RS2));
285 break;
286 case 'j':
287 (*info->fprintf_func)
288 ( info->stream, "%d", (int)((l >> OP_SH_CUSTOM_IMM) & OP_MASK_CUSTOM_IMM));
289 break;
290 }
291 break;
292
293 /* Xhwacha */
294 case '#':
295 switch ( *++d ) {
296 case 'g':
297 (*info->fprintf_func)
298 ( info->stream, "%d",
299 (int)((l >> OP_SH_IMMNGPR) & OP_MASK_IMMNGPR));
300 break;
301 case 'f':
302 (*info->fprintf_func)
303 ( info->stream, "%d",
304 (int)((l >> OP_SH_IMMNFPR) & OP_MASK_IMMNFPR));
305 break;
306 case 'p':
307 (*info->fprintf_func)
308 ( info->stream, "%d",
309 (int)((l >> OP_SH_CUSTOM_IMM) & OP_MASK_CUSTOM_IMM));
310 break;
311 case 'n':
312 (*info->fprintf_func)
313 ( info->stream, "%d",
314 (int)(((l >> OP_SH_IMMSEGNELM) & OP_MASK_IMMSEGNELM) + 1));
315 break;
316 case 'd':
317 (*info->fprintf_func)
318 ( info->stream, "%s",
319 riscv_vgr_reg_names_riscv[(l >> OP_SH_VRD) & OP_MASK_VRD]);
320 break;
321 case 's':
322 (*info->fprintf_func)
323 ( info->stream, "%s",
324 riscv_vgr_reg_names_riscv[(l >> OP_SH_VRS) & OP_MASK_VRS]);
325 break;
326 case 't':
327 (*info->fprintf_func)
328 ( info->stream, "%s",
329 riscv_vgr_reg_names_riscv[(l >> OP_SH_VRT) & OP_MASK_VRT]);
330 break;
331 case 'r':
332 (*info->fprintf_func)
333 ( info->stream, "%s",
334 riscv_vgr_reg_names_riscv[(l >> OP_SH_VRR) & OP_MASK_VRR]);
335 break;
336 case 'D':
337 (*info->fprintf_func)
338 ( info->stream, "%s",
339 riscv_vfp_reg_names_riscv[(l >> OP_SH_VFD) & OP_MASK_VFD]);
340 break;
341 case 'S':
342 (*info->fprintf_func)
343 ( info->stream, "%s",
344 riscv_vfp_reg_names_riscv[(l >> OP_SH_VFS) & OP_MASK_VFS]);
345 break;
346 case 'T':
347 (*info->fprintf_func)
348 ( info->stream, "%s",
349 riscv_vfp_reg_names_riscv[(l >> OP_SH_VFT) & OP_MASK_VFT]);
350 break;
351 case 'R':
352 (*info->fprintf_func)
353 ( info->stream, "%s",
354 riscv_vfp_reg_names_riscv[(l >> OP_SH_VFR) & OP_MASK_VFR]);
355 break;
356 }
357 break;
358
359 case ',':
360 case '(':
361 case ')':
362 case '[':
363 case ']':
364 (*info->fprintf_func) (info->stream, "%c", *d);
365 break;
366
367 case '0':
368 break;
369
370 case 'b':
371 case 's':
372 (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[rs1]);
373 break;
374
375 case 't':
376 (*info->fprintf_func) (info->stream, "%s",
377 riscv_gpr_names[(l >> OP_SH_RS2) & OP_MASK_RS2]);
378 break;
379
380 case 'u':
381 (*info->fprintf_func) (info->stream, "0x%x", (unsigned)EXTRACT_UTYPE_IMM (l) << RISCV_IMM_BITS >> RISCV_IMM_BITS);
382 break;
383
384 case 'm':
385 arg_print(info, (l >> OP_SH_RM) & OP_MASK_RM,
386 riscv_rm, ARRAY_SIZE(riscv_rm));
387 break;
388
389 case 'P':
390 arg_print(info, (l >> OP_SH_PRED) & OP_MASK_PRED,
391 riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
392 break;
393
394 case 'Q':
395 arg_print(info, (l >> OP_SH_SUCC) & OP_MASK_SUCC,
396 riscv_pred_succ, ARRAY_SIZE(riscv_pred_succ));
397 break;
398
399 case 'o':
400 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
401 case 'j':
402 if ((l & MASK_ADDI) == MATCH_ADDI || (l & MASK_JALR) == MATCH_JALR)
403 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
404 (*info->fprintf_func) (info->stream, "%d", (int)EXTRACT_ITYPE_IMM (l));
405 break;
406
407 case 'q':
408 maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l));
409 (*info->fprintf_func) (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
410 break;
411
412 case 'a':
413 info->target = EXTRACT_UJTYPE_IMM (l) + pc;
414 (*info->print_address_func) (info->target, info);
415 break;
416
417 case 'p':
418 info->target = EXTRACT_SBTYPE_IMM (l) + pc;
419 (*info->print_address_func) (info->target, info);
420 break;
421
422 case 'd':
423 if ((l & MASK_AUIPC) == MATCH_AUIPC)
424 pd->hi_addr[rd] = pc + (EXTRACT_UTYPE_IMM (l) << RISCV_IMM_BITS);
425 else if ((l & MASK_LUI) == MATCH_LUI)
426 pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l) << RISCV_IMM_BITS;
427 (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[rd]);
428 break;
429
430 case 'z':
431 (*info->fprintf_func) (info->stream, "%s", riscv_gpr_names[0]);
432 break;
433
434 case '>':
435 (*info->fprintf_func) (info->stream, "0x%x",
436 (unsigned)((l >> OP_SH_SHAMT) & OP_MASK_SHAMT));
437 break;
438
439 case '<':
440 (*info->fprintf_func) (info->stream, "0x%x",
441 (unsigned)((l >> OP_SH_SHAMTW) & OP_MASK_SHAMTW));
442 break;
443
444 case 'S':
445 case 'U':
446 (*info->fprintf_func) (info->stream, "%s", riscv_fpr_names[rs1]);
447 break;
448
449 case 'T':
450 (*info->fprintf_func) (info->stream, "%s",
451 riscv_fpr_names[(l >> OP_SH_RS2) & OP_MASK_RS2]);
452 break;
453
454 case 'D':
455 (*info->fprintf_func) (info->stream, "%s", riscv_fpr_names[rd]);
456 break;
457
458 case 'R':
459 (*info->fprintf_func) (info->stream, "%s",
460 riscv_fpr_names[(l >> OP_SH_RS3) & OP_MASK_RS3]);
461 break;
462
463 case 'E':
464 {
465 const char* csr_name = "unknown";
466 switch ((l >> OP_SH_CSR) & OP_MASK_CSR)
467 {
468 #define DECLARE_CSR(name, num) case num: csr_name = #name; break;
469 #include "opcode/riscv-opc.h"
470 #undef DECLARE_CSR
471 }
472 (*info->fprintf_func) (info->stream, "%s", csr_name);
473 break;
474 }
475
476 case 'Z':
477 (*info->fprintf_func) (info->stream, "%d", rs1);
478 break;
479
480 default:
481 /* xgettext:c-format */
482 (*info->fprintf_func) (info->stream,
483 _("# internal error, undefined modifier (%c)"),
484 *d);
485 return;
486 }
487 }
488 }
489
490 #if 0
491 static unsigned long
492 riscv_rvc_uncompress(unsigned long rvc_insn)
493 {
494 #define IS_INSN(x, op) (((x) & MASK_##op) == MATCH_##op)
495 #define EXTRACT_OPERAND(x, op) (((x) >> OP_SH_##op) & OP_MASK_##op)
496
497 int crd = EXTRACT_OPERAND(rvc_insn, CRD);
498 int crs1 = EXTRACT_OPERAND(rvc_insn, CRS1);
499 int crs2 = EXTRACT_OPERAND(rvc_insn, CRS2);
500 int crds = EXTRACT_OPERAND(rvc_insn, CRDS);
501 int crs1s = EXTRACT_OPERAND(rvc_insn, CRS1S);
502 int crs2s = EXTRACT_OPERAND(rvc_insn, CRS2S);
503 int crs2bs = EXTRACT_OPERAND(rvc_insn, CRS2BS);
504
505 int cimm6 = EXTRACT_OPERAND(rvc_insn, CIMM6);
506 int imm6 = ((int32_t)cimm6 << 26 >> 26) & (RISCV_IMM_REACH-1);
507 int imm6x4 = (((int32_t)cimm6 << 26 >> 26)*4) & (RISCV_IMM_REACH-1);
508 int imm6x4lo = imm6x4 & ((1<<RISCV_IMMLO_BITS)-1);
509 int imm6x4hi = (imm6x4 >> RISCV_IMMLO_BITS) & ((1<<RISCV_IMMHI_BITS)-1);
510 int imm6x8 = (((int32_t)cimm6 << 26 >> 26)*8) & (RISCV_IMM_REACH-1);
511 int imm6x8lo = imm6x8 & ((1<<RISCV_IMMLO_BITS)-1);
512 int imm6x8hi = (imm6x8 >> RISCV_IMMLO_BITS) & ((1<<RISCV_IMMHI_BITS)-1);
513
514 int cimm5 = EXTRACT_OPERAND(rvc_insn, CIMM5);
515 int imm5 = ((int32_t)cimm5 << 27 >> 27) & (RISCV_IMM_REACH-1);
516 int imm5lo = imm5 & ((1<<RISCV_IMMLO_BITS)-1);
517 int imm5hi = (imm5 >> RISCV_IMMLO_BITS) & ((1<<RISCV_IMMHI_BITS)-1);
518 int imm5x4 = (((int32_t)cimm5 << 27 >> 27)*4) & (RISCV_IMM_REACH-1);
519 int imm5x4lo = imm5x4 & ((1<<RISCV_IMMLO_BITS)-1);
520 int imm5x4hi = (imm5x4 >> RISCV_IMMLO_BITS) & ((1<<RISCV_IMMHI_BITS)-1);
521 int imm5x8 = (((int32_t)cimm5 << 27 >> 27)*8) & (RISCV_IMM_REACH-1);
522 int imm5x8lo = imm5x8 & ((1<<RISCV_IMMLO_BITS)-1);
523 int imm5x8hi = (imm5x8 >> RISCV_IMMLO_BITS) & ((1<<RISCV_IMMHI_BITS)-1);
524
525 int cimm10 = EXTRACT_OPERAND(rvc_insn, CIMM10);
526 int jt10 = ((int32_t)cimm10 << 22 >> 22) & ((1<<RISCV_JUMP_BITS)-1);
527
528 if(IS_INSN(rvc_insn, C_ADDI))
529 {
530 if(crd == 0)
531 {
532 if(imm6 & 0x20)
533 return MATCH_JALR | (LINK_REG << OP_SH_RD) | (crs1 << OP_SH_RS1);
534 else
535 return MATCH_JALR | (crs1 << OP_SH_RS1);
536 }
537 return MATCH_ADDI | (crd << OP_SH_RD) | (crd << OP_SH_RS1) |
538 (imm6 << OP_SH_IMMEDIATE);
539 }
540 if(IS_INSN(rvc_insn, C_ADDIW))
541 return MATCH_ADDIW | (crd << OP_SH_RD) | (crd << OP_SH_RS1) | (imm6 << OP_SH_IMMEDIATE);
542 if(IS_INSN(rvc_insn, C_LI))
543 return MATCH_ADDI | (crd << OP_SH_RD) | (imm6 << OP_SH_IMMEDIATE);
544 if(IS_INSN(rvc_insn, C_MOVE))
545 return MATCH_ADDI | (crd << OP_SH_RD) | (crs1 << OP_SH_RS1);
546 if(IS_INSN(rvc_insn, C_SLLI))
547 return MATCH_SLLI | (cimm5 << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
548 if(IS_INSN(rvc_insn, C_SLLI32))
549 return MATCH_SLLI | ((cimm5+32) << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
550 if(IS_INSN(rvc_insn, C_SRLI))
551 return MATCH_SRLI | (cimm5 << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
552 if(IS_INSN(rvc_insn, C_SRLI32))
553 return MATCH_SRLI | ((cimm5+32) << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
554 if(IS_INSN(rvc_insn, C_SRAI))
555 return MATCH_SRAI | (cimm5 << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
556 if(IS_INSN(rvc_insn, C_SRAI32))
557 return MATCH_SRAI | ((cimm5+32) << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
558 if(IS_INSN(rvc_insn, C_SLLIW))
559 return MATCH_SLLIW | (cimm5 << OP_SH_SHAMT) | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rd_regmap[crds] << OP_SH_RS1);
560 if(IS_INSN(rvc_insn, C_ADD))
561 return MATCH_ADD | (crd << OP_SH_RD) | (crs1 << OP_SH_RS1) | (crd << OP_SH_RS2);
562 if(IS_INSN(rvc_insn, C_SUB))
563 return MATCH_SUB | (crd << OP_SH_RD) | (crs1 << OP_SH_RS1) | (crd << OP_SH_RS2);
564 if(IS_INSN(rvc_insn, C_ADD3))
565 return MATCH_ADD | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2b_regmap[crs2bs] << OP_SH_RS2);
566 if(IS_INSN(rvc_insn, C_SUB3))
567 return MATCH_SUB | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2b_regmap[crs2bs] << OP_SH_RS2);
568 if(IS_INSN(rvc_insn, C_AND3))
569 return MATCH_AND | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2b_regmap[crs2bs] << OP_SH_RS2);
570 if(IS_INSN(rvc_insn, C_OR3))
571 return MATCH_OR | (rvc_rd_regmap[crds] << OP_SH_RD) | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2b_regmap[crs2bs] << OP_SH_RS2);
572 if(IS_INSN(rvc_insn, C_J))
573 return MATCH_JAL | (jt10 << OP_SH_TARGET);
574 if(IS_INSN(rvc_insn, C_BEQ))
575 return MATCH_BEQ | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5lo << OP_SH_IMMLO) | (imm5hi << OP_SH_IMMHI);
576 if(IS_INSN(rvc_insn, C_BNE))
577 return MATCH_BNE | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5lo << OP_SH_IMMLO) | (imm5hi << OP_SH_IMMHI);
578 if(IS_INSN(rvc_insn, C_LDSP))
579 return MATCH_LD | (30 << OP_SH_RS1) | (crd << OP_SH_RD) | (imm6x8 << OP_SH_IMMEDIATE);
580 if(IS_INSN(rvc_insn, C_LWSP))
581 return MATCH_LW | (30 << OP_SH_RS1) | (crd << OP_SH_RD) | (imm6x4 << OP_SH_IMMEDIATE);
582 if(IS_INSN(rvc_insn, C_SDSP))
583 return MATCH_SD | (30 << OP_SH_RS1) | (crs2 << OP_SH_RS2) | (imm6x8lo << OP_SH_IMMLO) | (imm6x8hi << OP_SH_IMMHI);
584 if(IS_INSN(rvc_insn, C_SWSP))
585 return MATCH_SW | (30 << OP_SH_RS1) | (crs2 << OP_SH_RS2) | (imm6x4lo << OP_SH_IMMLO) | (imm6x4hi << OP_SH_IMMHI);
586 if(IS_INSN(rvc_insn, C_LD))
587 return MATCH_LD | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rd_regmap[crds] << OP_SH_RD) | (imm5x8 << OP_SH_IMMEDIATE);
588 if(IS_INSN(rvc_insn, C_LW))
589 return MATCH_LW | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rd_regmap[crds] << OP_SH_RD) | (imm5x4 << OP_SH_IMMEDIATE);
590 if(IS_INSN(rvc_insn, C_SD))
591 return MATCH_SD | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5x8lo << OP_SH_IMMLO) | (imm5x8hi << OP_SH_IMMHI);
592 if(IS_INSN(rvc_insn, C_SW))
593 return MATCH_SW | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5x4lo << OP_SH_IMMLO) | (imm5x4hi << OP_SH_IMMHI);
594 if(IS_INSN(rvc_insn, C_LD0))
595 return MATCH_LD | (crs1 << OP_SH_RS1) | (crd << OP_SH_RD);
596 if(IS_INSN(rvc_insn, C_LW0))
597 return MATCH_LW | (crs1 << OP_SH_RS1) | (crd << OP_SH_RD);
598 if(IS_INSN(rvc_insn, C_FLD))
599 return MATCH_FLD | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rd_regmap[crds] << OP_SH_RD) | (imm5x8 << OP_SH_IMMEDIATE);
600 if(IS_INSN(rvc_insn, C_FLW))
601 return MATCH_FLW | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rd_regmap[crds] << OP_SH_RD) | (imm5x4 << OP_SH_IMMEDIATE);
602 if(IS_INSN(rvc_insn, C_FSD))
603 return MATCH_FSD | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5x8lo << OP_SH_IMMLO) | (imm5x8hi << OP_SH_IMMHI);
604 if(IS_INSN(rvc_insn, C_FSW))
605 return MATCH_FSW | (rvc_rs1_regmap[crs1s] << OP_SH_RS1) | (rvc_rs2_regmap[crs2s] << OP_SH_RS2) | (imm5x4lo << OP_SH_IMMLO) | (imm5x4hi << OP_SH_IMMHI);
606
607 return rvc_insn;
608 }
609 #endif
610
611 /* Print the RISC-V instruction at address MEMADDR in debugged memory,
612 on using INFO. Returns length of the instruction, in bytes.
613 BIGENDIAN must be 1 if this is big-endian code, 0 if
614 this is little-endian code. */
615
616 static int
617 riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
618 {
619 const struct riscv_opcode *op;
620 static bfd_boolean init = 0;
621 static const char *extension = NULL;
622 static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
623 struct riscv_private_data *pd;
624 int insnlen;
625
626 /* Build a hash table to shorten the search time. */
627 if (! init)
628 {
629 unsigned int i;
630 unsigned int e_flags = elf_elfheader (info->section->owner)->e_flags;
631 extension = riscv_elf_flag_to_name(EF_GET_RISCV_EXT(e_flags));
632
633 for (i = 0; i <= OP_MASK_OP; i++)
634 for (op = riscv_opcodes; op < &riscv_opcodes[NUMOPCODES]; op++)
635 if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
636 {
637 riscv_hash[i] = op;
638 break;
639 }
640
641 init = 1;
642 }
643
644 if (info->private_data == NULL)
645 {
646 int i;
647
648 pd = info->private_data = calloc(1, sizeof (struct riscv_private_data));
649 pd->gp = -1;
650 pd->print_addr = -1;
651 for (i = 0; i < (int) ARRAY_SIZE(pd->hi_addr); i++)
652 pd->hi_addr[i] = -1;
653
654 for (i = 0; i < info->symtab_size; i++)
655 if (strcmp (bfd_asymbol_name (info->symtab[i]), "_gp") == 0)
656 pd->gp = bfd_asymbol_value (info->symtab[i]);
657 }
658 else
659 pd = info->private_data;
660
661 insnlen = riscv_insn_length (word);
662
663 #if 0
664 if (insnlen == 2)
665 word = riscv_rvc_uncompress(word);
666 #endif
667
668 info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
669 info->bytes_per_line = 8;
670 info->display_endian = info->endian;
671 info->insn_info_valid = 1;
672 info->branch_delay_insns = 0;
673 info->data_size = 0;
674 info->insn_type = dis_nonbranch;
675 info->target = 0;
676 info->target2 = 0;
677
678 op = riscv_hash[(word >> OP_SH_OP) & OP_MASK_OP];
679 if (op != NULL)
680 {
681 for (; op < &riscv_opcodes[NUMOPCODES]; op++)
682 {
683 if ((op->match_func) (op, word)
684 && !(no_aliases && (op->pinfo & INSN_ALIAS))
685 && !(op->subset[0] == 'X' && strcmp(op->subset, extension)))
686 {
687 (*info->fprintf_func) (info->stream, "%s", op->name);
688 print_insn_args (op->args, word, memaddr, info);
689 if (pd->print_addr != (bfd_vma)-1)
690 {
691 info->target = pd->print_addr;
692 (*info->fprintf_func) (info->stream, " # ");
693 (*info->print_address_func) (info->target, info);
694 pd->print_addr = -1;
695 }
696 return insnlen;
697 }
698 }
699 }
700
701 /* Handle undefined instructions. */
702 info->insn_type = dis_noninsn;
703 (*info->fprintf_func) (info->stream, "0x%llx", (unsigned long long)word);
704 return insnlen;
705 }
706
707 int
708 print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
709 {
710 uint16_t i2;
711 insn_t insn = 0;
712 bfd_vma n;
713 int status;
714
715 set_default_riscv_dis_options (info);
716 parse_riscv_dis_options (info->disassembler_options);
717
718 /* Instructions are a sequence of 2-byte packets in little-endian order. */
719 for (n = 0; n < sizeof(insn) && n < riscv_insn_length (insn); n += 2)
720 {
721 status = (*info->read_memory_func) (memaddr + n, (bfd_byte*)&i2, 2, info);
722 if (status != 0)
723 {
724 if (n > 0) /* Don't fail just because we fell off the end. */
725 break;
726 (*info->memory_error_func) (status, memaddr, info);
727 return status;
728 }
729
730 i2 = bfd_getl16 (&i2);
731 insn |= (insn_t)i2 << (8*n);
732 }
733
734 return riscv_disassemble_insn (memaddr, insn, info);
735 }
736
737 void
738 print_riscv_disassembler_options (FILE *stream)
739 {
740 unsigned int i;
741
742 fprintf (stream, _("\n\
743 The following RISC-V-specific disassembler options are supported for use\n\
744 with the -M switch (multiple options should be separated by commas):\n"));
745
746 fprintf (stream, _("\n\
747 gpr-names=ABI Print GPR names according to specified ABI.\n\
748 Default: based on binary being disassembled.\n"));
749
750 fprintf (stream, _("\n\
751 fpr-names=ABI Print FPR names according to specified ABI.\n\
752 Default: numeric.\n"));
753
754 fprintf (stream, _("\n\
755 For the options above, the following values are supported for \"ABI\":\n\
756 "));
757 for (i = 0; i < ARRAY_SIZE (riscv_abi_choices); i++)
758 fprintf (stream, " %s", riscv_abi_choices[i].name);
759 fprintf (stream, _("\n"));
760
761 fprintf (stream, _("\n"));
762 }
763