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