RISC-V: Add lga assembler macro support.

Message ID 20210810231353.535700-1-jimw@sifive.com
State New
Headers show
Series
  • RISC-V: Add lga assembler macro support.
Related show

Commit Message

Jim Wilson Aug. 10, 2021, 11:13 p.m.
As proposed in riscv-asm-manual pull request #69.  Commit pending
discussion.

Tested with riscv{32,64}-{elf,linux} cross build and check.

Jim

	gas/
	* config/tc-riscv.c (macro): Add M_LGA support.
	* testsuite/gas/riscv/la-variants.d: New.
	* testsuite/gas/riscv/la-variants.s: New.
	include/
	* opcode/riscv.h (M_LGA): New.
	opcodes/
	* riscv-opc.c (riscv_opcodes): Add lga support.
---
 gas/config/tc-riscv.c                 |  8 ++++++--
 gas/testsuite/gas/riscv/la-variants.d | 21 +++++++++++++++++++++
 gas/testsuite/gas/riscv/la-variants.s | 11 +++++++++++
 include/opcode/riscv.h                |  1 +
 opcodes/riscv-opc.c                   |  1 +
 5 files changed, 40 insertions(+), 2 deletions(-)
 create mode 100644 gas/testsuite/gas/riscv/la-variants.d
 create mode 100644 gas/testsuite/gas/riscv/la-variants.s

-- 
2.25.1

Comments

Nelson Chu Aug. 11, 2021, 1:43 a.m. | #1
Seems like lga has the same behavior as la + pic.  A new pseudo
without the .option should be useful and increase code readability.
Looks good to me.

Thanks
Nelson

On Wed, Aug 11, 2021 at 7:14 AM Jim Wilson <jimw@sifive.com> wrote:
>

> As proposed in riscv-asm-manual pull request #69.  Commit pending

> discussion.

>

> Tested with riscv{32,64}-{elf,linux} cross build and check.

>

> Jim

>

>         gas/

>         * config/tc-riscv.c (macro): Add M_LGA support.

>         * testsuite/gas/riscv/la-variants.d: New.

>         * testsuite/gas/riscv/la-variants.s: New.

>         include/

>         * opcode/riscv.h (M_LGA): New.

>         opcodes/

>         * riscv-opc.c (riscv_opcodes): Add lga support.

> ---

>  gas/config/tc-riscv.c                 |  8 ++++++--

>  gas/testsuite/gas/riscv/la-variants.d | 21 +++++++++++++++++++++

>  gas/testsuite/gas/riscv/la-variants.s | 11 +++++++++++

>  include/opcode/riscv.h                |  1 +

>  opcodes/riscv-opc.c                   |  1 +

>  5 files changed, 40 insertions(+), 2 deletions(-)

>  create mode 100644 gas/testsuite/gas/riscv/la-variants.d

>  create mode 100644 gas/testsuite/gas/riscv/la-variants.s

>

> diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c

> index 460667e4349..d5775b60578 100644

> --- a/gas/config/tc-riscv.c

> +++ b/gas/config/tc-riscv.c

> @@ -1596,16 +1596,20 @@ macro (struct riscv_cl_insn *ip, expressionS *imm_expr,

>

>      case M_LA:

>      case M_LLA:

> +    case M_LGA:

>        /* Load the address of a symbol into a register.  */

>        if (!IS_SEXT_32BIT_NUM (imm_expr->X_add_number))

>         as_bad (_("offset too large"));

>

>        if (imm_expr->X_op == O_constant)

>         load_const (rd, imm_expr);

> -      else if (riscv_opts.pic && mask == M_LA) /* Global PIC symbol.  */

> +      /* Global PIC symbol.  */

> +      else if ((riscv_opts.pic && mask == M_LA)

> +              || mask == M_LGA)

>         pcrel_load (rd, rd, imm_expr, LOAD_ADDRESS_INSN,

>                     BFD_RELOC_RISCV_GOT_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);

> -      else /* Local PIC symbol, or any non-PIC symbol.  */

> +      /* Local PIC symbol, or any non-PIC symbol.  */

> +      else

>         pcrel_load (rd, rd, imm_expr, "addi",

>                     BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);

>        break;

> diff --git a/gas/testsuite/gas/riscv/la-variants.d b/gas/testsuite/gas/riscv/la-variants.d

> new file mode 100644

> index 00000000000..8532a540105

> --- /dev/null

> +++ b/gas/testsuite/gas/riscv/la-variants.d

> @@ -0,0 +1,21 @@

> +#as: -march=rv32i -mabi=ilp32

> +#objdump: -d

> +

> +.*:     file format elf32-(little|big)riscv

> +

> +

> +Disassembly of section .text:

> +

> +0+000 <.text>:

> +   0:  00000517                auipc   a0,0x0

> +   4:  00050513                mv      a0,a0

> +   8:  00000597                auipc   a1,0x0

> +   c:  00058593                mv      a1,a1

> +  10:  00000617                auipc   a2,0x0

> +  14:  00062603                lw      a2,0\(a2\) # 10 <.text\+0x10>

> +  18:  00000697                auipc   a3,0x0

> +  1c:  0006a683                lw      a3,0\(a3\) # 18 <.text\+0x18>

> +  20:  00000717                auipc   a4,0x0

> +  24:  00070713                mv      a4,a4

> +  28:  00000797                auipc   a5,0x0

> +  2c:  0007a783                lw      a5,0\(a5\) # 28 <.text\+0x28>

> diff --git a/gas/testsuite/gas/riscv/la-variants.s b/gas/testsuite/gas/riscv/la-variants.s

> new file mode 100644

> index 00000000000..bc3b0feec66

> --- /dev/null

> +++ b/gas/testsuite/gas/riscv/la-variants.s

> @@ -0,0 +1,11 @@

> +# lla is always local, lga is always global, and la depends on pic

> +       .extern a

> +.text

> +       .option nopic

> +       la a0, a

> +       lla a1, a

> +       lga a2, a

> +       .option pic

> +       la a3, a

> +       lla a4, a

> +       lga a5, a

> diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h

> index fdf3df4f5c1..793618e0658 100644

> --- a/include/opcode/riscv.h

> +++ b/include/opcode/riscv.h

> @@ -396,6 +396,7 @@ enum

>  {

>    M_LA,

>    M_LLA,

> +  M_LGA,

>    M_LA_TLS_GD,

>    M_LA_TLS_IE,

>    M_LB,

> diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c

> index f55a01b071c..ccf684f1c66 100644

> --- a/opcodes/riscv-opc.c

> +++ b/opcodes/riscv-opc.c

> @@ -289,6 +289,7 @@ const struct riscv_opcode riscv_opcodes[] =

>  {"add",         0, INSN_CLASS_I, "d,s,j",     MATCH_ADDI, MASK_ADDI, match_opcode, INSN_ALIAS },

>  {"la",          0, INSN_CLASS_I, "d,B",       0, (int) M_LA, match_never, INSN_MACRO },

>  {"lla",         0, INSN_CLASS_I, "d,B",       0, (int) M_LLA, match_never, INSN_MACRO },

> +{"lga",         0, INSN_CLASS_I, "d,B",       0, (int) M_LGA, match_never, INSN_MACRO },

>  {"la.tls.gd",   0, INSN_CLASS_I, "d,A",       0, (int) M_LA_TLS_GD, match_never, INSN_MACRO },

>  {"la.tls.ie",   0, INSN_CLASS_I, "d,A",       0, (int) M_LA_TLS_IE, match_never, INSN_MACRO },

>  {"neg",         0, INSN_CLASS_I, "d,t",       MATCH_SUB, MASK_SUB|MASK_RS1, match_opcode, INSN_ALIAS }, /* sub 0  */

> --

> 2.25.1

>

Patch

diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 460667e4349..d5775b60578 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1596,16 +1596,20 @@  macro (struct riscv_cl_insn *ip, expressionS *imm_expr,
 
     case M_LA:
     case M_LLA:
+    case M_LGA:
       /* Load the address of a symbol into a register.  */
       if (!IS_SEXT_32BIT_NUM (imm_expr->X_add_number))
 	as_bad (_("offset too large"));
 
       if (imm_expr->X_op == O_constant)
 	load_const (rd, imm_expr);
-      else if (riscv_opts.pic && mask == M_LA) /* Global PIC symbol.  */
+      /* Global PIC symbol.  */
+      else if ((riscv_opts.pic && mask == M_LA)
+	       || mask == M_LGA)
 	pcrel_load (rd, rd, imm_expr, LOAD_ADDRESS_INSN,
 		    BFD_RELOC_RISCV_GOT_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
-      else /* Local PIC symbol, or any non-PIC symbol.  */
+      /* Local PIC symbol, or any non-PIC symbol.  */
+      else
 	pcrel_load (rd, rd, imm_expr, "addi",
 		    BFD_RELOC_RISCV_PCREL_HI20, BFD_RELOC_RISCV_PCREL_LO12_I);
       break;
diff --git a/gas/testsuite/gas/riscv/la-variants.d b/gas/testsuite/gas/riscv/la-variants.d
new file mode 100644
index 00000000000..8532a540105
--- /dev/null
+++ b/gas/testsuite/gas/riscv/la-variants.d
@@ -0,0 +1,21 @@ 
+#as: -march=rv32i -mabi=ilp32
+#objdump: -d
+
+.*:     file format elf32-(little|big)riscv
+
+
+Disassembly of section .text:
+
+0+000 <.text>:
+   0:	00000517          	auipc	a0,0x0
+   4:	00050513          	mv	a0,a0
+   8:	00000597          	auipc	a1,0x0
+   c:	00058593          	mv	a1,a1
+  10:	00000617          	auipc	a2,0x0
+  14:	00062603          	lw	a2,0\(a2\) # 10 <.text\+0x10>
+  18:	00000697          	auipc	a3,0x0
+  1c:	0006a683          	lw	a3,0\(a3\) # 18 <.text\+0x18>
+  20:	00000717          	auipc	a4,0x0
+  24:	00070713          	mv	a4,a4
+  28:	00000797          	auipc	a5,0x0
+  2c:	0007a783          	lw	a5,0\(a5\) # 28 <.text\+0x28>
diff --git a/gas/testsuite/gas/riscv/la-variants.s b/gas/testsuite/gas/riscv/la-variants.s
new file mode 100644
index 00000000000..bc3b0feec66
--- /dev/null
+++ b/gas/testsuite/gas/riscv/la-variants.s
@@ -0,0 +1,11 @@ 
+# lla is always local, lga is always global, and la depends on pic
+	.extern a
+.text
+	.option nopic
+	la a0, a
+	lla a1, a
+	lga a2, a
+	.option pic
+	la a3, a
+	lla a4, a
+	lga a5, a
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index fdf3df4f5c1..793618e0658 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -396,6 +396,7 @@  enum
 {
   M_LA,
   M_LLA,
+  M_LGA,
   M_LA_TLS_GD,
   M_LA_TLS_IE,
   M_LB,
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index f55a01b071c..ccf684f1c66 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -289,6 +289,7 @@  const struct riscv_opcode riscv_opcodes[] =
 {"add",         0, INSN_CLASS_I, "d,s,j",     MATCH_ADDI, MASK_ADDI, match_opcode, INSN_ALIAS },
 {"la",          0, INSN_CLASS_I, "d,B",       0, (int) M_LA, match_never, INSN_MACRO },
 {"lla",         0, INSN_CLASS_I, "d,B",       0, (int) M_LLA, match_never, INSN_MACRO },
+{"lga",         0, INSN_CLASS_I, "d,B",       0, (int) M_LGA, match_never, INSN_MACRO },
 {"la.tls.gd",   0, INSN_CLASS_I, "d,A",       0, (int) M_LA_TLS_GD, match_never, INSN_MACRO },
 {"la.tls.ie",   0, INSN_CLASS_I, "d,A",       0, (int) M_LA_TLS_IE, match_never, INSN_MACRO },
 {"neg",         0, INSN_CLASS_I, "d,t",       MATCH_SUB, MASK_SUB|MASK_RS1, match_opcode, INSN_ALIAS }, /* sub 0  */