diff --git a/gas/testsuite/gas/riscv/dis-arch-override-1.d b/gas/testsuite/gas/riscv/dis-arch-override-1.d new file mode 100644 index 00000000000..1df81236e2a --- /dev/null +++ b/gas/testsuite/gas/riscv/dis-arch-override-1.d @@ -0,0 +1,13 @@ +#as: -march=rv64imfd_zbb +#source: dis-arch-override.s +#objdump: -d + +.*:[ ]+file format .* + +Disassembly of section .text: + +0+000 : +[ ]+[0-9a-f]+:[ ]+00c5f053[ ]+fadd\.s[ ]+ft0,fa1,fa2 +[ ]+[0-9a-f]+:[ ]+02c5f053[ ]+fadd\.d[ ]+ft0,fa1,fa2 +[ ]+[0-9a-f]+:[ ]+30102573[ ]+csrr[ ]+a0,misa +[ ]+[0-9a-f]+:[ ]+0805c53b[ ]+zext\.h[ ]+a0,a1 diff --git a/gas/testsuite/gas/riscv/dis-arch-override-2.d b/gas/testsuite/gas/riscv/dis-arch-override-2.d new file mode 100644 index 00000000000..bc74149227a --- /dev/null +++ b/gas/testsuite/gas/riscv/dis-arch-override-2.d @@ -0,0 +1,13 @@ +#as: -march=rv64imfd_zbb +#source: dis-arch-override.s +#objdump: -d -M arch=rv32im_zfinx_zbkb + +.*:[ ]+file format .* + +Disassembly of section .text: + +0+000 : +[ ]+[0-9a-f]+:[ ]+00c5f053[ ]+fadd\.s[ ]+zero,a1,a2 +[ ]+[0-9a-f]+:[ ]+02c5f053[ ]+\.insn[ ]+4, 0x02c5f053 +[ ]+[0-9a-f]+:[ ]+30102573[ ]+csrr[ ]+a0,misa +[ ]+[0-9a-f]+:[ ]+0805c53b[ ]+packw[ ]+a0,a1,zero diff --git a/gas/testsuite/gas/riscv/dis-arch-override-3.d b/gas/testsuite/gas/riscv/dis-arch-override-3.d new file mode 100644 index 00000000000..fe6117367b3 --- /dev/null +++ b/gas/testsuite/gas/riscv/dis-arch-override-3.d @@ -0,0 +1,13 @@ +#as: -march=rv64imfd_zbb +#source: dis-arch-override.s +#objdump: -d -m riscv -M arch=rv32im_zfinx_zbkb,numeric + +.*:[ ]+file format .* + +Disassembly of section .text: + +0+000 : +[ ]+[0-9a-f]+:[ ]+00c5f053[ ]+fadd\.s[ ]+x0,x11,x12 +[ ]+[0-9a-f]+:[ ]+02c5f053[ ]+\.insn[ ]+4, 0x02c5f053 +[ ]+[0-9a-f]+:[ ]+30102573[ ]+csrr[ ]+x10,misa +[ ]+[0-9a-f]+:[ ]+0805c53b[ ]+\.insn[ ]+4, 0x0805c53b diff --git a/gas/testsuite/gas/riscv/dis-arch-override.s b/gas/testsuite/gas/riscv/dis-arch-override.s new file mode 100644 index 00000000000..0c2fec44ed3 --- /dev/null +++ b/gas/testsuite/gas/riscv/dis-arch-override.s @@ -0,0 +1,45 @@ +# Assembler configuration: +# -march=rv64imfd_zbb +# Disassembler configurations: +# Test 1: -d +# Test 2: -d -M arch=rv32im_zfinx_zbkb +# Test 3: -d -m riscv -M arch=rv32im_zfinx_zbkb,numeric + +target: + # Assembler : fadd.s (F) + # Disassembler (test 2/3) : fadd.s (Zfinx) + # Test that all three operands point to GPRs. + fadd.s ft0, fa1, fa2 + + # Assembler : fadd.d (D) + # Disassembler (test 2/3) : (invalid) + # On disassembler option on test 2, Zdinx is not present. So, + # it should be disassembled as an invalid instruction. + fadd.d ft0, fa1, fa2 + + # Assembler : csrr (Zicsr) + # Disassembler (test 2/3) : csrr (Zicsr) + # When assembling, Zicsr is implied by F. When disassembling, + # Zicsr is implied by Zfinx. On both cases, csrr should be + # disassembled as csrr. + csrr a0, misa + + # Assembler : zext.h (Zbb) + # Disassembler (test 2) : packw (Zbkb) + # Disassembler (test 3) : (invalid) + # Since zext.h specialized instruction does not exist in Zbkb + # and we disassemble the output with Zbkb, this instruction + # should be disassembled as a packw instruction (on RV64). + # + # We specify arch=rv32im_zfinx_zbkb on disassembling on test + # 2 and 3. But, XLEN part of the ISA string is effective + # only if XLEN-neutral machine is specified by `-m riscv' option + # (because we are disassembling 64-bit RISC-V ELF file, BFD + # architecture is set to `riscv:rv64' unless `-m' option + # is specified). + # + # As a result, test 3 (with `-m riscv' option) disassembles with + # RV32 but test 2 (without it) does with RV64. + # It changes the result of disassembling since packw instruction + # is invalid on RV32. + zext.h a0, a1 diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index fdaffe49115..61342c3068e 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -35,6 +35,9 @@ /* Default architecture string (if not available). */ static const char *const initial_default_arch = "rv64gc"; +/* If set, a custom architecture string is specified. */ +static bool is_custom_arch = false; + /* Current XLEN for the disassembler. */ static unsigned xlen = 0; @@ -197,8 +200,10 @@ update_riscv_dis_xlen (struct disassemble_info *info) This is only effective if XLEN-specific BFD machine architecture is chosen. If XLEN-neutral (like riscv), BFD machine architecture is ignored on XLEN selection. - 2. Non-default RISC-V architecture string set by either an ELF - attribute or a mapping symbol with ISA string. + 2. Non-default RISC-V architecture string set by either: + a. -M arch=... option (GDB: set disassembler-options arch=...), + b. A mapping symbol with ISA string or + c. An ELF attribute 3. ELF class in dummy ELF header. */ if (xlen_by_mach != 0) xlen = xlen_by_mach; @@ -308,6 +313,7 @@ set_default_riscv_dis_options (void) no_aliases = false; is_numeric = false; is_custom_priv_spec = false; + is_custom_arch = false; } /* Parse RISC-V disassembler option (without arguments). */ @@ -369,6 +375,11 @@ parse_riscv_dis_option (const char *option) priv_spec = priv_spec_new; } } + else if (strcmp (option, "arch") == 0) + { + is_custom_arch = true; + update_riscv_dis_arch (&dis_arch_context_override, value); + } else { /* xgettext:c-format */ @@ -1082,6 +1093,9 @@ riscv_get_map_state (int n, *state = newstate; if (newstate == MAP_INSN && update) { + /* Skip if a custom architecture is specified. */ + if (is_custom_arch) + return true; if (arch) { /* Override the architecture. */ @@ -1408,7 +1422,10 @@ riscv_get_disassembler (bfd *abfd) } } - update_riscv_dis_arch (&dis_arch_context_default, default_arch); + if (is_custom_arch) + set_riscv_dis_arch_context (&dis_arch_context_default, default_arch); + else + update_riscv_dis_arch (&dis_arch_context_default, default_arch); return print_insn_riscv; } @@ -1459,6 +1476,7 @@ riscv_symbol_is_valid (asymbol * sym, typedef enum { RISCV_OPTION_ARG_NONE = -1, + RISCV_OPTION_ARG_ARCH, RISCV_OPTION_ARG_PRIV_SPEC, RISCV_OPTION_ARG_COUNT @@ -1476,6 +1494,9 @@ static struct { "numeric", N_("Print numeric register names, rather than ABI names."), RISCV_OPTION_ARG_NONE }, + { "arch=", + N_("Disassemble using specified ISA and extensions."), + RISCV_OPTION_ARG_ARCH }, { "no-aliases", N_("Disassemble only into canonical instructions."), RISCV_OPTION_ARG_NONE }, @@ -1503,6 +1524,9 @@ disassembler_options_riscv (void) args = XNEWVEC (disasm_option_arg_t, num_args + 1); + args[RISCV_OPTION_ARG_ARCH].name = "ARCH"; + args[RISCV_OPTION_ARG_ARCH].values = NULL; + args[RISCV_OPTION_ARG_PRIV_SPEC].name = "SPEC"; priv_spec_count = PRIV_SPEC_CLASS_DRAFT - PRIV_SPEC_CLASS_NONE - 1; args[RISCV_OPTION_ARG_PRIV_SPEC].values