From 154e28ca2ff0367be1fca32216949017631bb978 Mon Sep 17 00:00:00 2001 From: Tsukasa OI Date: Fri, 26 Aug 2022 10:14:31 +0000 Subject: [PATCH] RISC-V: Print top GP-relative addresses on the disassembler This patch makes possible to print the address relative to the global pointer even if the corresponding symbol is the highest address (0xffffffff on RV32, 0xffffffff_ffffffff on RV64). Despite that it is very rare to have GP the highest address, it would be nice because we enabled highest address printing on regular cases. opcodes/ChangeLog: * riscv-dis.c (struct riscv_private_data): Add `has_gp' to enable printing the addresses relative to GP with the highest address. (maybe_print_address): Utilize `has_gp'. (riscv_disassemble_insn): Likewise. gas/ChangeLog: * testsuite/gas/riscv/dis-addr-topaddr-gp.s: New test for GP- relative addressing when GP is the highest address. * testsuite/gas/riscv/dis-addr-topaddr-gp-32.d: Likewise. * testsuite/gas/riscv/dis-addr-topaddr-gp-64.d: Likewise. --- gas/testsuite/gas/riscv/dis-addr-topaddr-gp-32.d | 12 ++++++++++++ gas/testsuite/gas/riscv/dis-addr-topaddr-gp-64.d | 12 ++++++++++++ gas/testsuite/gas/riscv/dis-addr-topaddr-gp.s | 15 +++++++++++++++ opcodes/riscv-dis.c | 11 ++++++++--- 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 gas/testsuite/gas/riscv/dis-addr-topaddr-gp-32.d create mode 100644 gas/testsuite/gas/riscv/dis-addr-topaddr-gp-64.d create mode 100644 gas/testsuite/gas/riscv/dis-addr-topaddr-gp.s diff --git a/gas/testsuite/gas/riscv/dis-addr-topaddr-gp-32.d b/gas/testsuite/gas/riscv/dis-addr-topaddr-gp-32.d new file mode 100644 index 00000000000..875bfe73189 --- /dev/null +++ b/gas/testsuite/gas/riscv/dis-addr-topaddr-gp-32.d @@ -0,0 +1,12 @@ +#as: -march=rv32i +#source: dis-addr-topaddr-gp.s +#objdump: -d + +.*: file format elf32-(little|big)riscv + + +Disassembly of section .text: + +0+000 : +[ ]+[0-9a-f]+:[ ]+0051a283[ ]+lw[ ]+t0,5\(gp\) # 4 +[ ]+[0-9a-f]+:[ ]+ffd1a303[ ]+lw[ ]+t1,-3\(gp\) # fffffffc diff --git a/gas/testsuite/gas/riscv/dis-addr-topaddr-gp-64.d b/gas/testsuite/gas/riscv/dis-addr-topaddr-gp-64.d new file mode 100644 index 00000000000..5ac4b52b18d --- /dev/null +++ b/gas/testsuite/gas/riscv/dis-addr-topaddr-gp-64.d @@ -0,0 +1,12 @@ +#as: -march=rv64i -defsym rv64=1 +#source: dis-addr-topaddr-gp.s +#objdump: -d + +.*: file format elf64-(little|big)riscv + + +Disassembly of section .text: + +0+000 : +[ ]+[0-9a-f]+:[ ]+0051a283[ ]+lw[ ]+t0,5\(gp\) # 4 +[ ]+[0-9a-f]+:[ ]+ffd1a303[ ]+lw[ ]+t1,-3\(gp\) # fffffffffffffffc diff --git a/gas/testsuite/gas/riscv/dis-addr-topaddr-gp.s b/gas/testsuite/gas/riscv/dis-addr-topaddr-gp.s new file mode 100644 index 00000000000..6ba9fc7a39d --- /dev/null +++ b/gas/testsuite/gas/riscv/dis-addr-topaddr-gp.s @@ -0,0 +1,15 @@ +.ifdef rv64 +topbase = 0xffffffff00000000 +.else +topbase = 0 +.endif + +.set __global_pointer$, topbase + 0xffffffff # -1 +.set addr_rel_gp_pos, 0x00000004 # +4 +.set addr_rel_gp_neg, topbase + 0xfffffffc # -4 + +target: + # Use addresses relative to gp + # (gp is the highest address) + lw t0, +5(gp) + lw t1, -3(gp) diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c index 7532c72187d..160cc40f865 100644 --- a/opcodes/riscv-dis.c +++ b/opcodes/riscv-dis.c @@ -53,6 +53,7 @@ struct riscv_private_data bfd_vma print_addr; bfd_vma hi_addr[OP_MASK_RD + 1]; bool to_print_addr; + bool has_gp; }; /* Used for mapping symbols. */ @@ -178,7 +179,7 @@ maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset, pd->print_addr = (base_reg != 0 ? pd->hi_addr[base_reg] : 0) + offset; pd->hi_addr[base_reg] = -1; } - else if (base_reg == X_GP && pd->gp != (bfd_vma)-1) + else if (base_reg == X_GP && pd->has_gp) pd->print_addr = pd->gp + offset; else if (base_reg == X_TP || base_reg == 0) pd->print_addr = offset; @@ -603,15 +604,19 @@ riscv_disassemble_insn (bfd_vma memaddr, insn_t word, disassemble_info *info) int i; pd = info->private_data = xcalloc (1, sizeof (struct riscv_private_data)); - pd->gp = -1; + pd->gp = 0; pd->print_addr = 0; for (i = 0; i < (int)ARRAY_SIZE (pd->hi_addr); i++) pd->hi_addr[i] = -1; pd->to_print_addr = false; + pd->has_gp = false; for (i = 0; i < info->symtab_size; i++) if (strcmp (bfd_asymbol_name (info->symtab[i]), RISCV_GP_SYMBOL) == 0) - pd->gp = bfd_asymbol_value (info->symtab[i]); + { + pd->gp = bfd_asymbol_value (info->symtab[i]); + pd->has_gp = true; + } } else pd = info->private_data;