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