Fix extraction of signed constants in nios2 disassembler (again).
[deliverable/binutils-gdb.git] / opcodes / riscv-dis.c
CommitLineData
e23eba97 1/* RISC-V disassembler
b3adc24a 2 Copyright (C) 2011-2020 Free Software Foundation, Inc.
e23eba97
NC
3
4 Contributed by Andrew Waterman (andrew@sifive.com).
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; see the file COPYING3. If not,
21 see <http://www.gnu.org/licenses/>. */
22
23#include "sysdep.h"
88c1242d 24#include "disassemble.h"
e23eba97
NC
25#include "libiberty.h"
26#include "opcode/riscv.h"
27#include "opintl.h"
28#include "elf-bfd.h"
29#include "elf/riscv.h"
30
2d5d5a8f 31#include "bfd_stdint.h"
e23eba97
NC
32#include <ctype.h>
33
8f595e9b
NC
34static enum riscv_priv_spec_class default_priv_spec = PRIV_SPEC_CLASS_NONE;
35
e23eba97
NC
36struct riscv_private_data
37{
38 bfd_vma gp;
39 bfd_vma print_addr;
40 bfd_vma hi_addr[OP_MASK_RD + 1];
41};
42
43static const char * const *riscv_gpr_names;
44static const char * const *riscv_fpr_names;
45
46/* Other options. */
47static int no_aliases; /* If set disassemble as most general inst. */
48
49static void
50set_default_riscv_dis_options (void)
51{
52 riscv_gpr_names = riscv_gpr_names_abi;
53 riscv_fpr_names = riscv_fpr_names_abi;
54 no_aliases = 0;
55}
56
8f595e9b
NC
57static bfd_boolean
58parse_riscv_dis_option_without_args (const char *option)
e23eba97
NC
59{
60 if (strcmp (option, "no-aliases") == 0)
61 no_aliases = 1;
62 else if (strcmp (option, "numeric") == 0)
63 {
64 riscv_gpr_names = riscv_gpr_names_numeric;
65 riscv_fpr_names = riscv_fpr_names_numeric;
66 }
8f595e9b
NC
67 else
68 return FALSE;
69 return TRUE;
70}
71
72static void
73parse_riscv_dis_option (const char *option)
74{
75 char *equal, *value;
76
77 if (parse_riscv_dis_option_without_args (option))
78 return;
79
80 equal = strchr (option, '=');
81 if (equal == NULL)
82 {
83 /* The option without '=' should be defined above. */
84 opcodes_error_handler (_("unrecognized disassembler option: %s"), option);
85 return;
86 }
87 if (equal == option
88 || *(equal + 1) == '\0')
89 {
90 /* Invalid options with '=', no option name before '=',
91 and no value after '='. */
92 opcodes_error_handler (_("unrecognized disassembler option with '=': %s"),
93 option);
94 return;
95 }
96
97 *equal = '\0';
98 value = equal + 1;
99 if (strcmp (option, "priv-spec") == 0)
100 {
101 if (!riscv_get_priv_spec_class (value, &default_priv_spec))
102 opcodes_error_handler (_("unknown privilege spec set by %s=%s"),
103 option, value);
104 }
e23eba97
NC
105 else
106 {
a6743a54
AM
107 /* xgettext:c-format */
108 opcodes_error_handler (_("unrecognized disassembler option: %s"), option);
e23eba97
NC
109 }
110}
111
112static void
113parse_riscv_dis_options (const char *opts_in)
114{
115 char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts;
116
117 set_default_riscv_dis_options ();
118
119 for ( ; opt_end != NULL; opt = opt_end + 1)
120 {
121 if ((opt_end = strchr (opt, ',')) != NULL)
122 *opt_end = 0;
123 parse_riscv_dis_option (opt);
124 }
125
126 free (opts);
127}
128
129/* Print one argument from an array. */
130
131static void
132arg_print (struct disassemble_info *info, unsigned long val,
133 const char* const* array, size_t size)
134{
135 const char *s = val >= size || array[val] == NULL ? "unknown" : array[val];
136 (*info->fprintf_func) (info->stream, "%s", s);
137}
138
139static void
140maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset)
141{
142 if (pd->hi_addr[base_reg] != (bfd_vma)-1)
143 {
35fd2b2b 144 pd->print_addr = (base_reg != 0 ? pd->hi_addr[base_reg] : 0) + offset;
e23eba97
NC
145 pd->hi_addr[base_reg] = -1;
146 }
147 else if (base_reg == X_GP && pd->gp != (bfd_vma)-1)
148 pd->print_addr = pd->gp + offset;
149 else if (base_reg == X_TP || base_reg == 0)
150 pd->print_addr = offset;
151}
152
153/* Print insn arguments for 32/64-bit code. */
154
155static void
156print_insn_args (const char *d, insn_t l, bfd_vma pc, disassemble_info *info)
157{
158 struct riscv_private_data *pd = info->private_data;
159 int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
160 int rd = (l >> OP_SH_RD) & OP_MASK_RD;
161 fprintf_ftype print = info->fprintf_func;
162
163 if (*d != '\0')
164 print (info->stream, "\t");
165
166 for (; *d != '\0'; d++)
167 {
168 switch (*d)
169 {
170 case 'C': /* RVC */
171 switch (*++d)
172 {
173 case 's': /* RS1 x8-x15 */
174 case 'w': /* RS1 x8-x15 */
175 print (info->stream, "%s",
176 riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
177 break;
178 case 't': /* RS2 x8-x15 */
179 case 'x': /* RS2 x8-x15 */
180 print (info->stream, "%s",
181 riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
182 break;
183 case 'U': /* RS1, constrained to equal RD */
184 print (info->stream, "%s", riscv_gpr_names[rd]);
185 break;
186 case 'c': /* RS1, constrained to equal sp */
187 print (info->stream, "%s", riscv_gpr_names[X_SP]);
188 break;
189 case 'V': /* RS2 */
190 print (info->stream, "%s",
191 riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
192 break;
193 case 'i':
194 print (info->stream, "%d", (int)EXTRACT_RVC_SIMM3 (l));
195 break;
f91d48de 196 case 'o':
e23eba97
NC
197 case 'j':
198 print (info->stream, "%d", (int)EXTRACT_RVC_IMM (l));
199 break;
200 case 'k':
201 print (info->stream, "%d", (int)EXTRACT_RVC_LW_IMM (l));
202 break;
203 case 'l':
204 print (info->stream, "%d", (int)EXTRACT_RVC_LD_IMM (l));
205 break;
206 case 'm':
207 print (info->stream, "%d", (int)EXTRACT_RVC_LWSP_IMM (l));
208 break;
209 case 'n':
210 print (info->stream, "%d", (int)EXTRACT_RVC_LDSP_IMM (l));
211 break;
212 case 'K':
213 print (info->stream, "%d", (int)EXTRACT_RVC_ADDI4SPN_IMM (l));
214 break;
215 case 'L':
216 print (info->stream, "%d", (int)EXTRACT_RVC_ADDI16SP_IMM (l));
217 break;
218 case 'M':
219 print (info->stream, "%d", (int)EXTRACT_RVC_SWSP_IMM (l));
220 break;
221 case 'N':
222 print (info->stream, "%d", (int)EXTRACT_RVC_SDSP_IMM (l));
223 break;
224 case 'p':
225 info->target = EXTRACT_RVC_B_IMM (l) + pc;
226 (*info->print_address_func) (info->target, info);
227 break;
228 case 'a':
229 info->target = EXTRACT_RVC_J_IMM (l) + pc;
230 (*info->print_address_func) (info->target, info);
231 break;
232 case 'u':
233 print (info->stream, "0x%x",
234 (int)(EXTRACT_RVC_IMM (l) & (RISCV_BIGIMM_REACH-1)));
235 break;
236 case '>':
237 print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x3f);
238 break;
239 case '<':
240 print (info->stream, "0x%x", (int)EXTRACT_RVC_IMM (l) & 0x1f);
241 break;
242 case 'T': /* floating-point RS2 */
243 print (info->stream, "%s",
244 riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
245 break;
246 case 'D': /* floating-point RS2 x8-x15 */
247 print (info->stream, "%s",
248 riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
249 break;
250 }
251 break;
252
253 case ',':
254 case '(':
255 case ')':
256 case '[':
257 case ']':
258 print (info->stream, "%c", *d);
259 break;
260
261 case '0':
262 /* Only print constant 0 if it is the last argument */
263 if (!d[1])
264 print (info->stream, "0");
265 break;
266
267 case 'b':
268 case 's':
35eeb78f
JW
269 if ((l & MASK_JALR) == MATCH_JALR)
270 maybe_print_address (pd, rs1, 0);
e23eba97
NC
271 print (info->stream, "%s", riscv_gpr_names[rs1]);
272 break;
273
274 case 't':
275 print (info->stream, "%s",
276 riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
277 break;
278
279 case 'u':
280 print (info->stream, "0x%x",
281 (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
282 break;
283
284 case 'm':
285 arg_print (info, EXTRACT_OPERAND (RM, l),
286 riscv_rm, ARRAY_SIZE (riscv_rm));
287 break;
288
289 case 'P':
290 arg_print (info, EXTRACT_OPERAND (PRED, l),
291 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
292 break;
293
294 case 'Q':
295 arg_print (info, EXTRACT_OPERAND (SUCC, l),
296 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
297 break;
298
299 case 'o':
300 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
b52d3cfc 301 /* Fall through. */
e23eba97
NC
302 case 'j':
303 if (((l & MASK_ADDI) == MATCH_ADDI && rs1 != 0)
304 || (l & MASK_JALR) == MATCH_JALR)
305 maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l));
306 print (info->stream, "%d", (int)EXTRACT_ITYPE_IMM (l));
307 break;
308
309 case 'q':
310 maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l));
311 print (info->stream, "%d", (int)EXTRACT_STYPE_IMM (l));
312 break;
313
314 case 'a':
315 info->target = EXTRACT_UJTYPE_IMM (l) + pc;
316 (*info->print_address_func) (info->target, info);
317 break;
318
319 case 'p':
320 info->target = EXTRACT_SBTYPE_IMM (l) + pc;
321 (*info->print_address_func) (info->target, info);
322 break;
323
324 case 'd':
325 if ((l & MASK_AUIPC) == MATCH_AUIPC)
326 pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l);
327 else if ((l & MASK_LUI) == MATCH_LUI)
328 pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l);
329 else if ((l & MASK_C_LUI) == MATCH_C_LUI)
330 pd->hi_addr[rd] = EXTRACT_RVC_LUI_IMM (l);
331 print (info->stream, "%s", riscv_gpr_names[rd]);
332 break;
333
334 case 'z':
335 print (info->stream, "%s", riscv_gpr_names[0]);
336 break;
337
338 case '>':
339 print (info->stream, "0x%x", (int)EXTRACT_OPERAND (SHAMT, l));
340 break;
341
342 case '<':
343 print (info->stream, "0x%x", (int)EXTRACT_OPERAND (SHAMTW, l));
344 break;
345
346 case 'S':
347 case 'U':
348 print (info->stream, "%s", riscv_fpr_names[rs1]);
349 break;
350
351 case 'T':
352 print (info->stream, "%s", riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
353 break;
354
355 case 'D':
356 print (info->stream, "%s", riscv_fpr_names[rd]);
357 break;
358
359 case 'R':
360 print (info->stream, "%s", riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
361 break;
362
363 case 'E':
364 {
8f595e9b
NC
365 static const char *riscv_csr_hash[4096]; /* Total 2^12 CSR. */
366 static bfd_boolean init_csr = FALSE;
e23eba97 367 unsigned int csr = EXTRACT_OPERAND (CSR, l);
8f595e9b
NC
368
369 if (!init_csr)
e23eba97 370 {
8f595e9b
NC
371 unsigned int i;
372 for (i = 0; i < 4096; i++)
373 riscv_csr_hash[i] = NULL;
374
375 /* Set to the newest privilege version. */
376 if (default_priv_spec == PRIV_SPEC_CLASS_NONE)
377 default_priv_spec = PRIV_SPEC_CLASS_DRAFT - 1;
378
379#define DECLARE_CSR(name, num, class, define_version, abort_version) \
380 if (default_priv_spec >= define_version \
381 && default_priv_spec < abort_version) \
382 riscv_csr_hash[num] = #name;
383#define DECLARE_CSR_ALIAS(name, num, class, define_version, abort_version) \
384 DECLARE_CSR (name, num, class, define_version, abort_version)
e23eba97
NC
385#include "opcode/riscv-opc.h"
386#undef DECLARE_CSR
387 }
8f595e9b
NC
388
389 if (riscv_csr_hash[csr] != NULL)
390 print (info->stream, "%s", riscv_csr_hash[csr]);
e23eba97
NC
391 else
392 print (info->stream, "0x%x", csr);
393 break;
394 }
395
396 case 'Z':
397 print (info->stream, "%d", rs1);
398 break;
399
400 default:
401 /* xgettext:c-format */
402 print (info->stream, _("# internal error, undefined modifier (%c)"),
403 *d);
404 return;
405 }
406 }
407}
408
409/* Print the RISC-V instruction at address MEMADDR in debugged memory,
410 on using INFO. Returns length of the instruction, in bytes.
411 BIGENDIAN must be 1 if this is big-endian code, 0 if
412 this is little-endian code. */
413
414static int
415riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info)
416{
417 const struct riscv_opcode *op;
418 static bfd_boolean init = 0;
419 static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
420 struct riscv_private_data *pd;
421 int insnlen;
422
423#define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP))
424
425 /* Build a hash table to shorten the search time. */
426 if (! init)
427 {
428 for (op = riscv_opcodes; op->name; op++)
429 if (!riscv_hash[OP_HASH_IDX (op->match)])
430 riscv_hash[OP_HASH_IDX (op->match)] = op;
431
432 init = 1;
433 }
434
435 if (info->private_data == NULL)
436 {
437 int i;
438
439 pd = info->private_data = xcalloc (1, sizeof (struct riscv_private_data));
440 pd->gp = -1;
441 pd->print_addr = -1;
442 for (i = 0; i < (int)ARRAY_SIZE (pd->hi_addr); i++)
443 pd->hi_addr[i] = -1;
444
445 for (i = 0; i < info->symtab_size; i++)
b5292032 446 if (strcmp (bfd_asymbol_name (info->symtab[i]), RISCV_GP_SYMBOL) == 0)
e23eba97
NC
447 pd->gp = bfd_asymbol_value (info->symtab[i]);
448 }
449 else
450 pd = info->private_data;
451
452 insnlen = riscv_insn_length (word);
453
d7560e2d
JW
454 /* RISC-V instructions are always little-endian. */
455 info->endian_code = BFD_ENDIAN_LITTLE;
456
e23eba97
NC
457 info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2;
458 info->bytes_per_line = 8;
d7560e2d
JW
459 /* We don't support constant pools, so this must be code. */
460 info->display_endian = info->endian_code;
e23eba97
NC
461 info->insn_info_valid = 1;
462 info->branch_delay_insns = 0;
463 info->data_size = 0;
464 info->insn_type = dis_nonbranch;
465 info->target = 0;
466 info->target2 = 0;
467
468 op = riscv_hash[OP_HASH_IDX (word)];
469 if (op != NULL)
470 {
1080bf78 471 unsigned xlen = 0;
e23eba97 472
2922d21d
AW
473 /* If XLEN is not known, get its value from the ELF class. */
474 if (info->mach == bfd_mach_riscv64)
475 xlen = 64;
476 else if (info->mach == bfd_mach_riscv32)
477 xlen = 32;
478 else if (info->section != NULL)
e23eba97
NC
479 {
480 Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner);
481 xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32;
482 }
483
484 for (; op->name; op++)
485 {
486 /* Does the opcode match? */
487 if (! (op->match_func) (op, word))
488 continue;
489 /* Is this a pseudo-instruction and may we print it as such? */
490 if (no_aliases && (op->pinfo & INSN_ALIAS))
491 continue;
492 /* Is this instruction restricted to a certain value of XLEN? */
43135d3b 493 if ((op->xlen_requirement != 0) && (op->xlen_requirement != xlen))
e23eba97
NC
494 continue;
495
496 /* It's a match. */
497 (*info->fprintf_func) (info->stream, "%s", op->name);
498 print_insn_args (op->args, word, memaddr, info);
499
500 /* Try to disassemble multi-instruction addressing sequences. */
501 if (pd->print_addr != (bfd_vma)-1)
502 {
503 info->target = pd->print_addr;
504 (*info->fprintf_func) (info->stream, " # ");
505 (*info->print_address_func) (info->target, info);
506 pd->print_addr = -1;
507 }
508
eb41b248
JW
509 /* Finish filling out insn_info fields. */
510 switch (op->pinfo & INSN_TYPE)
511 {
512 case INSN_BRANCH:
513 info->insn_type = dis_branch;
514 break;
515 case INSN_CONDBRANCH:
516 info->insn_type = dis_condbranch;
517 break;
518 case INSN_JSR:
519 info->insn_type = dis_jsr;
520 break;
521 case INSN_DREF:
522 info->insn_type = dis_dref;
523 break;
524 default:
525 break;
526 }
527
528 if (op->pinfo & INSN_DATA_SIZE)
529 {
530 int size = ((op->pinfo & INSN_DATA_SIZE)
531 >> INSN_DATA_SIZE_SHIFT);
532 info->data_size = 1 << (size - 1);
533 }
534
e23eba97
NC
535 return insnlen;
536 }
537 }
538
539 /* We did not find a match, so just print the instruction bits. */
540 info->insn_type = dis_noninsn;
541 (*info->fprintf_func) (info->stream, "0x%llx", (unsigned long long)word);
542 return insnlen;
543}
544
545int
546print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info)
547{
548 bfd_byte packet[2];
549 insn_t insn = 0;
550 bfd_vma n;
551 int status;
552
553 if (info->disassembler_options != NULL)
554 {
555 parse_riscv_dis_options (info->disassembler_options);
556 /* Avoid repeatedly parsing the options. */
557 info->disassembler_options = NULL;
558 }
559 else if (riscv_gpr_names == NULL)
560 set_default_riscv_dis_options ();
561
562 /* Instructions are a sequence of 2-byte packets in little-endian order. */
563 for (n = 0; n < sizeof (insn) && n < riscv_insn_length (insn); n += 2)
564 {
565 status = (*info->read_memory_func) (memaddr + n, packet, 2, info);
566 if (status != 0)
567 {
568 /* Don't fail just because we fell off the end. */
569 if (n > 0)
570 break;
571 (*info->memory_error_func) (status, memaddr, info);
572 return status;
573 }
574
575 insn |= ((insn_t) bfd_getl16 (packet)) << (8 * n);
576 }
577
578 return riscv_disassemble_insn (memaddr, insn, info);
579}
580
884b49e3
AB
581/* Prevent use of the fake labels that are generated as part of the DWARF
582 and for relaxable relocations in the assembler. */
583
584bfd_boolean
585riscv_symbol_is_valid (asymbol * sym,
586 struct disassemble_info * info ATTRIBUTE_UNUSED)
587{
588 const char * name;
589
590 if (sym == NULL)
591 return FALSE;
592
593 name = bfd_asymbol_name (sym);
594
595 return (strcmp (name, RISCV_FAKE_LABEL_NAME) != 0);
596}
597
e23eba97
NC
598void
599print_riscv_disassembler_options (FILE *stream)
600{
601 fprintf (stream, _("\n\
602The following RISC-V-specific disassembler options are supported for use\n\
603with the -M switch (multiple options should be separated by commas):\n"));
604
605 fprintf (stream, _("\n\
8f595e9b
NC
606 numeric Print numeric register names, rather than ABI names.\n"));
607
608 fprintf (stream, _("\n\
609 no-aliases Disassemble only into canonical instructions, rather\n\
610 than into pseudoinstructions.\n"));
e23eba97
NC
611
612 fprintf (stream, _("\n\
8f595e9b
NC
613 priv-spec=PRIV Print the CSR according to the chosen privilege spec\n\
614 (1.9, 1.9.1, 1.10, 1.11).\n"));
e23eba97
NC
615
616 fprintf (stream, _("\n"));
617}
This page took 0.240007 seconds and 4 git commands to generate.