riscv-dis.c revision 1.4 1 1.1 matt /* RISC-V disassembler
2 1.4 christos Copyright (C) 2011-2018 Free Software Foundation, Inc.
3 1.1 matt
4 1.4 christos Contributed by Andrew Waterman (andrew (at) sifive.com).
5 1.1 matt Based on MIPS target.
6 1.1 matt
7 1.1 matt This file is part of the GNU opcodes library.
8 1.1 matt
9 1.1 matt This library is free software; you can redistribute it and/or modify
10 1.1 matt it under the terms of the GNU General Public License as published by
11 1.1 matt the Free Software Foundation; either version 3, or (at your option)
12 1.1 matt any later version.
13 1.1 matt
14 1.1 matt It is distributed in the hope that it will be useful, but WITHOUT
15 1.1 matt ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 1.1 matt or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 1.1 matt License for more details.
18 1.1 matt
19 1.1 matt You should have received a copy of the GNU General Public License
20 1.4 christos along with this program; see the file COPYING3. If not,
21 1.4 christos see <http://www.gnu.org/licenses/>. */
22 1.1 matt
23 1.1 matt #include "sysdep.h"
24 1.4 christos #include "disassemble.h"
25 1.1 matt #include "libiberty.h"
26 1.1 matt #include "opcode/riscv.h"
27 1.1 matt #include "opintl.h"
28 1.1 matt #include "elf-bfd.h"
29 1.1 matt #include "elf/riscv.h"
30 1.1 matt
31 1.1 matt #include <stdint.h>
32 1.4 christos
33 1.4 christos #include <ctype.h>
34 1.1 matt
35 1.1 matt struct riscv_private_data
36 1.1 matt {
37 1.1 matt bfd_vma gp;
38 1.1 matt bfd_vma print_addr;
39 1.1 matt bfd_vma hi_addr[OP_MASK_RD + 1];
40 1.1 matt };
41 1.1 matt
42 1.1 matt static const char * const *riscv_gpr_names;
43 1.1 matt static const char * const *riscv_fpr_names;
44 1.1 matt
45 1.4 christos /* Other options. */
46 1.1 matt static int no_aliases; /* If set disassemble as most general inst. */
47 1.1 matt
48 1.1 matt static void
49 1.3 matt set_default_riscv_dis_options (void)
50 1.1 matt {
51 1.1 matt riscv_gpr_names = riscv_gpr_names_abi;
52 1.1 matt riscv_fpr_names = riscv_fpr_names_abi;
53 1.1 matt no_aliases = 0;
54 1.1 matt }
55 1.1 matt
56 1.1 matt static void
57 1.3 matt parse_riscv_dis_option (const char *option)
58 1.1 matt {
59 1.4 christos if (strcmp (option, "no-aliases") == 0)
60 1.3 matt no_aliases = 1;
61 1.4 christos else if (strcmp (option, "numeric") == 0)
62 1.1 matt {
63 1.3 matt riscv_gpr_names = riscv_gpr_names_numeric;
64 1.3 matt riscv_fpr_names = riscv_fpr_names_numeric;
65 1.1 matt }
66 1.4 christos else
67 1.4 christos {
68 1.4 christos /* Invalid option. */
69 1.4 christos fprintf (stderr, _("Unrecognized disassembler option: %s\n"), option);
70 1.4 christos }
71 1.1 matt }
72 1.1 matt
73 1.1 matt static void
74 1.3 matt parse_riscv_dis_options (const char *opts_in)
75 1.1 matt {
76 1.3 matt char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts;
77 1.1 matt
78 1.3 matt set_default_riscv_dis_options ();
79 1.1 matt
80 1.3 matt for ( ; opt_end != NULL; opt = opt_end + 1)
81 1.1 matt {
82 1.3 matt if ((opt_end = strchr (opt, ',')) != NULL)
83 1.3 matt *opt_end = 0;
84 1.3 matt parse_riscv_dis_option (opt);
85 1.3 matt }
86 1.1 matt
87 1.3 matt free (opts);
88 1.1 matt }
89 1.1 matt
90 1.4 christos /* Print one argument from an array. */
91 1.1 matt
92 1.1 matt static void
93 1.1 matt arg_print (struct disassemble_info *info, unsigned long val,
94 1.1 matt const char* const* array, size_t size)
95 1.1 matt {
96 1.1 matt const char *s = val >= size || array[val] == NULL ? "unknown" : array[val];
97 1.1 matt (*info->fprintf_func) (info->stream, "%s", s);
98 1.1 matt }
99 1.1 matt
100 1.1 matt static void
101 1.1 matt maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset)
102 1.1 matt {
103 1.1 matt if (pd->hi_addr[base_reg] != (bfd_vma)-1)
104 1.1 matt {
105 1.4 christos pd->print_addr = (base_reg != 0 ? pd->hi_addr[base_reg] : 0) + offset;
106 1.1 matt pd->hi_addr[base_reg] = -1;
107 1.1 matt }
108 1.3 matt else if (base_reg == X_GP && pd->gp != (bfd_vma)-1)
109 1.1 matt pd->print_addr = pd->gp + offset;
110 1.4 christos else if (base_reg == X_TP || base_reg == 0)
111 1.1 matt pd->print_addr = offset;
112 1.1 matt }
113 1.1 matt
114 1.1 matt /* Print insn arguments for 32/64-bit code. */
115 1.1 matt
116 1.1 matt static void
117 1.1 matt print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
118 1.1 matt {
119 1.1 matt struct riscv_private_data *pd = info->private_data;
120 1.1 matt int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
121 1.1 matt int rd = (l >> OP_SH_RD) & OP_MASK_RD;
122 1.4 christos fprintf_ftype print = info->fprintf_func;
123 1.1 matt
124 1.1 matt if (*d != '\0')
125 1.4 christos print (info->stream, "\t");
126 1.1 matt
127 1.1 matt for (; *d != '\0'; d++)
128 1.1 matt {
129 1.1 matt switch (*d)
130 1.1 matt {
131 1.4 christos case 'C': /* RVC */
132 1.4 christos switch (*++d)
133 1.4 christos {
134 1.4 christos case 's': /* RS1 x8-x15 */
135 1.4 christos case 'w': /* RS1 x8-x15 */
136 1.4 christos print (info->stream, "%s",
137 1.4 christos riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
138 1.4 christos break;
139 1.4 christos case 't': /* RS2 x8-x15 */
140 1.4 christos case 'x': /* RS2 x8-x15 */
141 1.4 christos print (info->stream, "%s",
142 1.4 christos riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
143 1.4 christos break;
144 1.4 christos case 'U': /* RS1, constrained to equal RD */
145 1.4 christos print (info->stream, "%s", riscv_gpr_names[rd]);
146 1.4 christos break;
147 1.4 christos case 'c': /* RS1, constrained to equal sp */
148 1.4 christos print (info->stream, "%s", riscv_gpr_names[X_SP]);
149 1.4 christos break;
150 1.4 christos case 'V': /* RS2 */
151 1.4 christos print (info->stream, "%s",
152 1.4 christos riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
153 1.4 christos break;
154 1.4 christos case 'i':
155 1.4 christos print (info->stream, "%d", (int)EXTRACT_RVC_SIMM3 (l));
156 1.4 christos break;
157 1.4 christos case 'o':
158 1.4 christos case 'j':
159 1.4 christos print (info->stream, "%d", (int)EXTRACT_RVC_IMM (l));
160 1.4 christos break;
161 1.4 christos case 'k':
162 1.4 christos print (info->stream, "%d", (int)EXTRACT_RVC_LW_IMM (l));
163 1.4 christos break;
164 1.4 christos case 'l':
165 1.4 christos print (info->stream, "%d", (int)EXTRACT_RVC_LD_IMM (l));
166 1.4 christos break;
167 1.4 christos case 'm':
168 1.4 christos print (info->stream, "%d", (int)EXTRACT_RVC_LWSP_IMM (l));
169 1.4 christos break;
170 1.4 christos case 'n':
171 1.4 christos print (info->stream, "%d", (int)EXTRACT_RVC_LDSP_IMM (l));
172 1.4 christos break;
173 1.4 christos case 'K':
174 1.4 christos print (info->stream, "%d", (int)EXTRACT_RVC_ADDI4SPN_IMM (l));
175 1.4 christos break;
176 1.4 christos case 'L':
177 1.4 christos print (info->stream, "%d", (int)EXTRACT_RVC_ADDI16SP_IMM (l));
178 1.4 christos break;
179 1.4 christos case 'M':
180 1.4 christos print (info->stream, "%d", (int)EXTRACT_RVC_SWSP_IMM (l));
181 1.4 christos break;
182 1.4 christos case 'N':
183 1.4 christos print (info->stream, "%d", (int)EXTRACT_RVC_SDSP_IMM (l));
184 1.4 christos break;
185 1.4 christos case 'p':
186 1.4 christos info->target = EXTRACT_RVC_B_IMM (l) + pc;
187 1.4 christos (*info->print_address_func) (info->target, info);
188 1.4 christos break;
189 1.4 christos case 'a':
190 1.4 christos info->target = EXTRACT_RVC_J_IMM (l) + pc;
191 1.4 christos (*info->print_address_func) (info->target, info);
192 1.4 christos break;
193 1.4 christos case 'u':
194 1.4 christos print (info->stream, "0x%x",
195 1.4 christos (int)(EXTRACT_RVC_IMM (l) & (RISCV_BIGIMM_REACH-1)));
196 1.4 christos break;
197 1.4 christos case '>':
198 1.4 christos print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x3f);
199 1.4 christos break;
200 1.4 christos case '<':
201 1.4 christos print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x1f);
202 1.4 christos break;
203 1.4 christos case 'T': /* floating-point RS2 */
204 1.4 christos print (info->stream, "%s",
205 1.4 christos riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
206 1.4 christos break;
207 1.4 christos case 'D': /* floating-point RS2 x8-x15 */
208 1.4 christos print (info->stream, "%s",
209 1.4 christos riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
210 1.4 christos break;
211 1.4 christos }
212 1.4 christos break;
213 1.1 matt
214 1.1 matt case ',':
215 1.1 matt case '(':
216 1.1 matt case ')':
217 1.1 matt case '[':
218 1.1 matt case ']':
219 1.4 christos print (info->stream, "%c", *d);
220 1.1 matt break;
221 1.1 matt
222 1.1 matt case '0':
223 1.4 christos /* Only print constant 0 if it is the last argument */
224 1.4 christos if (!d[1])
225 1.4 christos print (info->stream, "0");
226 1.1 matt break;
227 1.1 matt
228 1.1 matt case 'b':
229 1.1 matt case 's':
230 1.4 christos if ((l & MASK_JALR) == MATCH_JALR)
231 1.4 christos maybe_print_address (pd, rs1, 0);
232 1.4 christos print (info->stream, "%s", riscv_gpr_names[rs1]);
233 1.1 matt break;
234 1.1 matt
235 1.1 matt case 't':
236 1.4 christos print (info->stream, "%s",
237 1.4 christos riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
238 1.1 matt break;
239 1.1 matt
240 1.1 matt case 'u':
241 1.4 christos print (info->stream, "0x%x",
242 1.4 christos (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
243 1.1 matt break;
244 1.1 matt
245 1.1 matt case 'm':
246 1.4 christos arg_print (info, EXTRACT_OPERAND (RM, l),
247 1.4 christos riscv_rm, ARRAY_SIZE (riscv_rm));
248 1.1 matt break;
249 1.1 matt
250 1.1 matt case 'P':
251 1.4 christos arg_print (info, EXTRACT_OPERAND (PRED, l),
252 1.4 christos riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
253 1.1 matt break;
254 1.1 matt
255 1.1 matt case 'Q':
256 1.4 christos arg_print (info, EXTRACT_OPERAND (SUCC, l),
257 1.4 christos riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
258 1.1 matt break;
259 1.1 matt
260 1.1 matt case 'o':
261 1.1 matt maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
262 1.4 christos /* Fall through. */
263 1.1 matt case 'j':
264 1.4 christos if (((l & MASK_ADDI) == MATCH_ADDI && rs1 != 0)
265 1.4 christos || (l & MASK_JALR) == MATCH_JALR)
266 1.1 matt maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
267 1.4 christos print (info->stream, "%d", (int)EXTRACT_ITYPE_IMM (l));
268 1.1 matt break;
269 1.1 matt
270 1.1 matt case 'q':
271 1.1 matt maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l));
272 1.4 christos print (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
273 1.1 matt break;
274 1.1 matt
275 1.1 matt case 'a':
276 1.1 matt info->target = EXTRACT_UJTYPE_IMM (l) + pc;
277 1.1 matt (*info->print_address_func) (info->target, info);
278 1.1 matt break;
279 1.1 matt
280 1.1 matt case 'p':
281 1.1 matt info->target = EXTRACT_SBTYPE_IMM (l) + pc;
282 1.1 matt (*info->print_address_func) (info->target, info);
283 1.1 matt break;
284 1.1 matt
285 1.1 matt case 'd':
286 1.1 matt if ((l & MASK_AUIPC) == MATCH_AUIPC)
287 1.3 matt pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l);
288 1.1 matt else if ((l & MASK_LUI) == MATCH_LUI)
289 1.3 matt pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
290 1.4 christos else if ((l & MASK_C_LUI) == MATCH_C_LUI)
291 1.4 christos pd->hi_addr[rd] = EXTRACT_RVC_LUI_IMM (l);
292 1.4 christos print (info->stream, "%s", riscv_gpr_names[rd]);
293 1.1 matt break;
294 1.1 matt
295 1.1 matt case 'z':
296 1.4 christos print (info->stream, "%s", riscv_gpr_names[0]);
297 1.1 matt break;
298 1.1 matt
299 1.1 matt case '>':
300 1.4 christos print (info->stream, "0x%x", (int)EXTRACT_OPERAND (SHAMT, l));
301 1.1 matt break;
302 1.1 matt
303 1.1 matt case '<':
304 1.4 christos print (info->stream, "0x%x", (int)EXTRACT_OPERAND (SHAMTW, l));
305 1.1 matt break;
306 1.1 matt
307 1.1 matt case 'S':
308 1.1 matt case 'U':
309 1.4 christos print (info->stream, "%s", riscv_fpr_names[rs1]);
310 1.1 matt break;
311 1.1 matt
312 1.1 matt case 'T':
313 1.4 christos print (info->stream, "%s", riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
314 1.1 matt break;
315 1.1 matt
316 1.1 matt case 'D':
317 1.4 christos print (info->stream, "%s", riscv_fpr_names[rd]);
318 1.1 matt break;
319 1.1 matt
320 1.1 matt case 'R':
321 1.4 christos print (info->stream, "%s", riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
322 1.1 matt break;
323 1.1 matt
324 1.1 matt case 'E':
325 1.1 matt {
326 1.3 matt const char* csr_name = NULL;
327 1.4 christos unsigned int csr = EXTRACT_OPERAND (CSR, l);
328 1.3 matt switch (csr)
329 1.1 matt {
330 1.4 christos #define DECLARE_CSR(name, num) case num: csr_name = #name; break;
331 1.4 christos #include "opcode/riscv-opc.h"
332 1.4 christos #undef DECLARE_CSR
333 1.1 matt }
334 1.3 matt if (csr_name)
335 1.4 christos print (info->stream, "%s", csr_name);
336 1.3 matt else
337 1.4 christos print (info->stream, "0x%x", csr);
338 1.1 matt break;
339 1.1 matt }
340 1.1 matt
341 1.1 matt case 'Z':
342 1.4 christos print (info->stream, "%d", rs1);
343 1.1 matt break;
344 1.1 matt
345 1.1 matt default:
346 1.1 matt /* xgettext:c-format */
347 1.4 christos print (info->stream, _("# internal error, undefined modifier (%c)"),
348 1.4 christos *d);
349 1.1 matt return;
350 1.1 matt }
351 1.1 matt }
352 1.1 matt }
353 1.1 matt
354 1.1 matt /* Print the RISC-V instruction at address MEMADDR in debugged memory,
355 1.1 matt on using INFO. Returns length of the instruction, in bytes.
356 1.1 matt BIGENDIAN must be 1 if this is big-endian code, 0 if
357 1.1 matt this is little-endian code. */
358 1.1 matt
359 1.1 matt static int
360 1.1 matt riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
361 1.1 matt {
362 1.1 matt const struct riscv_opcode *op;
363 1.1 matt static bfd_boolean init = 0;
364 1.1 matt static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
365 1.1 matt struct riscv_private_data *pd;
366 1.1 matt int insnlen;
367 1.1 matt
368 1.4 christos #define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP))
369 1.4 christos
370 1.1 matt /* Build a hash table to shorten the search time. */
371 1.1 matt if (! init)
372 1.1 matt {
373 1.4 christos for (op = riscv_opcodes; op->name; op++)
374 1.4 christos if (!riscv_hash[OP_HASH_IDX (op->match)])
375 1.4 christos riscv_hash[OP_HASH_IDX (op->match)] = op;
376 1.1 matt
377 1.1 matt init = 1;
378 1.1 matt }
379 1.1 matt
380 1.1 matt if (info->private_data == NULL)
381 1.1 matt {
382 1.1 matt int i;
383 1.1 matt
384 1.4 christos pd = info->private_data = xcalloc (1, sizeof (struct riscv_private_data));
385 1.1 matt pd->gp = -1;
386 1.1 matt pd->print_addr = -1;
387 1.4 christos for (i = 0; i < (int)ARRAY_SIZE (pd->hi_addr); i++)
388 1.1 matt pd->hi_addr[i] = -1;
389 1.1 matt
390 1.1 matt for (i = 0; i < info->symtab_size; i++)
391 1.4 christos if (strcmp (bfd_asymbol_name (info->symtab[i]), RISCV_GP_SYMBOL) == 0)
392 1.1 matt pd->gp = bfd_asymbol_value (info->symtab[i]);
393 1.1 matt }
394 1.1 matt else
395 1.1 matt pd = info->private_data;
396 1.1 matt
397 1.1 matt insnlen = riscv_insn_length (word);
398 1.1 matt
399 1.1 matt info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
400 1.1 matt info->bytes_per_line = 8;
401 1.1 matt info->display_endian = info->endian;
402 1.1 matt info->insn_info_valid = 1;
403 1.1 matt info->branch_delay_insns = 0;
404 1.1 matt info->data_size = 0;
405 1.1 matt info->insn_type = dis_nonbranch;
406 1.1 matt info->target = 0;
407 1.1 matt info->target2 = 0;
408 1.1 matt
409 1.4 christos op = riscv_hash[OP_HASH_IDX (word)];
410 1.1 matt if (op != NULL)
411 1.1 matt {
412 1.4 christos int xlen = 0;
413 1.4 christos
414 1.4 christos /* If XLEN is not known, get its value from the ELF class. */
415 1.4 christos if (info->mach == bfd_mach_riscv64)
416 1.4 christos xlen = 64;
417 1.4 christos else if (info->mach == bfd_mach_riscv32)
418 1.4 christos xlen = 32;
419 1.4 christos else if (info->section != NULL)
420 1.1 matt {
421 1.4 christos Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
422 1.4 christos xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
423 1.4 christos }
424 1.4 christos
425 1.4 christos for (; op->name; op++)
426 1.4 christos {
427 1.4 christos /* Does the opcode match? */
428 1.4 christos if (! (op->match_func) (op, word))
429 1.4 christos continue;
430 1.4 christos /* Is this a pseudo-instruction and may we print it as such? */
431 1.4 christos if (no_aliases && (op->pinfo & INSN_ALIAS))
432 1.4 christos continue;
433 1.4 christos /* Is this instruction restricted to a certain value of XLEN? */
434 1.4 christos if (isdigit (op->subset[0]) && atoi (op->subset) != xlen)
435 1.4 christos continue;
436 1.4 christos
437 1.4 christos /* It's a match. */
438 1.4 christos (*info->fprintf_func) (info->stream, "%s", op->name);
439 1.4 christos print_insn_args (op->args, word, memaddr, info);
440 1.4 christos
441 1.4 christos /* Try to disassemble multi-instruction addressing sequences. */
442 1.4 christos if (pd->print_addr != (bfd_vma)-1)
443 1.1 matt {
444 1.4 christos info->target = pd->print_addr;
445 1.4 christos (*info->fprintf_func) (info->stream, " # ");
446 1.4 christos (*info->print_address_func) (info->target, info);
447 1.4 christos pd->print_addr = -1;
448 1.1 matt }
449 1.4 christos
450 1.4 christos return insnlen;
451 1.1 matt }
452 1.1 matt }
453 1.1 matt
454 1.4 christos /* We did not find a match, so just print the instruction bits. */
455 1.1 matt info->insn_type = dis_noninsn;
456 1.1 matt (*info->fprintf_func) (info->stream, "0x%llx", (unsigned long long)word);
457 1.1 matt return insnlen;
458 1.1 matt }
459 1.1 matt
460 1.1 matt int
461 1.1 matt print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
462 1.1 matt {
463 1.4 christos bfd_byte packet[2];
464 1.1 matt insn_t insn = 0;
465 1.1 matt bfd_vma n;
466 1.1 matt int status;
467 1.1 matt
468 1.3 matt if (info->disassembler_options != NULL)
469 1.3 matt {
470 1.3 matt parse_riscv_dis_options (info->disassembler_options);
471 1.3 matt /* Avoid repeatedly parsing the options. */
472 1.3 matt info->disassembler_options = NULL;
473 1.3 matt }
474 1.3 matt else if (riscv_gpr_names == NULL)
475 1.3 matt set_default_riscv_dis_options ();
476 1.1 matt
477 1.1 matt /* Instructions are a sequence of 2-byte packets in little-endian order. */
478 1.4 christos for (n = 0; n < sizeof (insn) && n < riscv_insn_length (insn); n += 2)
479 1.1 matt {
480 1.4 christos status = (*info->read_memory_func) (memaddr + n, packet, 2, info);
481 1.1 matt if (status != 0)
482 1.1 matt {
483 1.4 christos /* Don't fail just because we fell off the end. */
484 1.4 christos if (n > 0)
485 1.1 matt break;
486 1.1 matt (*info->memory_error_func) (status, memaddr, info);
487 1.1 matt return status;
488 1.1 matt }
489 1.1 matt
490 1.4 christos insn |= ((insn_t) bfd_getl16 (packet)) << (8 * n);
491 1.1 matt }
492 1.1 matt
493 1.1 matt return riscv_disassemble_insn (memaddr, insn, info);
494 1.1 matt }
495 1.1 matt
496 1.1 matt void
497 1.1 matt print_riscv_disassembler_options (FILE *stream)
498 1.1 matt {
499 1.1 matt fprintf (stream, _("\n\
500 1.1 matt The following RISC-V-specific disassembler options are supported for use\n\
501 1.1 matt with the -M switch (multiple options should be separated by commas):\n"));
502 1.1 matt
503 1.1 matt fprintf (stream, _("\n\
504 1.4 christos numeric Print numeric register names, rather than ABI names.\n"));
505 1.1 matt
506 1.1 matt fprintf (stream, _("\n\
507 1.3 matt no-aliases Disassemble only into canonical instructions, rather\n\
508 1.3 matt than into pseudoinstructions.\n"));
509 1.1 matt
510 1.1 matt fprintf (stream, _("\n"));
511 1.1 matt }
512