[v4,4/5] oongArch: gas: Add support for tls le relax.

Message ID 20231219064011.90412-5-changjiachen@stu.xupt.edu.cn
State New
Headers
Series LoongArch tls le model linker relaxation support. |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 fail Patch failed to apply

Commit Message

changjiachen Dec. 19, 2023, 6:40 a.m. UTC
  Add tls le relax related relocs support and testsuites in gas.

The main test is three new relocation items,
R_LARCH_TLS_LE_ADD_R, R_LARCH_TLS_LE_HI20_R,
R_LARCH_TLS_LE_LO12_R can be generated properly
and tls le insn format check.

gas/ChangeLog:

	* config/tc-loongarch.c:
	(loongarch_args_parser_can_match_arg_helper): Add support for relax.
	* gas/testsuite/gas/loongarch/reloc.d: Likewise.
	* gas/testsuite/gas/loongarch/reloc.s: Likewise.
	* gas/testsuite/gas/loongarch/loongarch.exp: Likewise.
	* gas/testsuite/gas/loongarch/tls_le_insn_format_check.s: New test.
---
 gas/config/tc-loongarch.c                     | 33 +++++++++++++++++--
 gas/testsuite/gas/loongarch/loongarch.exp     |  9 +++++
 gas/testsuite/gas/loongarch/reloc.d           | 18 ++++++++++
 gas/testsuite/gas/loongarch/reloc.s           | 11 +++++++
 .../gas/loongarch/tls_le_insn_format_check.s  |  5 +++
 5 files changed, 74 insertions(+), 2 deletions(-)
 create mode 100644 gas/testsuite/gas/loongarch/tls_le_insn_format_check.s
  

Patch

diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 59232832cf7..8a8e53ad3ce 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -636,6 +636,28 @@  loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
 	  break;
 	}
       break;
+    /* This is used for TLS, where the fourth operand is %le_add_r,
+       to get a relocation applied to an add instruction, for relaxation to use.
+       Two conditions, ip->match_now and reloc_num, are used to check tls insn
+       to prevent cases like add.d $a0,$a0,$a0,8.  */
+    case 't':
+      ip->match_now =
+	loongarch_parse_expr (arg, ip->reloc_info + ip->reloc_num,
+		reloc_num_we_have, &reloc_num, &imm) == 0;
+
+      if (!ip->match_now)
+	break;
+
+      if (reloc_num &&
+	  ip->reloc_info[ip->reloc_num].type == BFD_RELOC_LARCH_TLS_LE_ADD_R)
+	{
+	  ip->reloc_num += reloc_num;
+	  ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
+	  ip->reloc_info[ip->reloc_num].value = const_0;
+	  ip->reloc_num++;
+	}
+      else ip->match_now = 0;
+      break;
     case 's':
     case 'u':
       ip->match_now =
@@ -680,9 +702,8 @@  loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
 	    as_fatal (
 		      _("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"),
 		      esc_ch1, esc_ch2, bit_field, arg);
-
 	  if (ip->reloc_info[0].type >= BFD_RELOC_LARCH_B16
-	      && ip->reloc_info[0].type < BFD_RELOC_LARCH_64_PCREL)
+	      && ip->reloc_info[0].type < BFD_RELOC_UNUSED)
 	    {
 	      /* As we compact stack-relocs, it is no need for pop operation.
 		 But break out until here in order to check the imm field.
@@ -690,6 +711,14 @@  loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
 	      ip->reloc_num += reloc_num;
 	      reloc_type = ip->reloc_info[0].type;
 
+	      if (LARCH_opts.relax
+			&& (BFD_RELOC_LARCH_TLS_LE_HI20_R == reloc_type
+			    || BFD_RELOC_LARCH_TLS_LE_LO12_R == reloc_type))
+	      {
+		ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
+		ip->reloc_info[ip->reloc_num].value = const_0;
+		ip->reloc_num++;
+	      }
 	      if (LARCH_opts.relax && ip->macro_id
 		    && (BFD_RELOC_LARCH_PCALA_HI20 == reloc_type
 			|| BFD_RELOC_LARCH_PCALA_LO12 == reloc_type
diff --git a/gas/testsuite/gas/loongarch/loongarch.exp b/gas/testsuite/gas/loongarch/loongarch.exp
index 6d126fd4b0e..c0aa593d8a8 100644
--- a/gas/testsuite/gas/loongarch/loongarch.exp
+++ b/gas/testsuite/gas/loongarch/loongarch.exp
@@ -21,4 +21,13 @@ 
 if [istarget loongarch*-*-*] {
     run_dump_tests [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
     gas_test_old bfd_reloc_8.s "" "bfd_reloc_8"
+    if [file exist "tls_le_insn_format_check.s "] {
+      set format [run_host_cmd "as" "tls_le_insn_format_check.s"]
+      if { [ regexp ".*no match insn.*" $format] } {
+	pass "loongarch tls le insn format pass"
+      } {
+	pass "loongarch tls le insn format fail"
+      }
+    }
+
 }
diff --git a/gas/testsuite/gas/loongarch/reloc.d b/gas/testsuite/gas/loongarch/reloc.d
index c3820c55f98..0458830f30b 100644
--- a/gas/testsuite/gas/loongarch/reloc.d
+++ b/gas/testsuite/gas/loongarch/reloc.d
@@ -165,3 +165,21 @@  Disassembly of section .text:
 [ 	]+134:[ 	]+R_LARCH_TLS_LE64_LO20[ 	]+TLSL1\+0x8
 [ 	]+138:[ 	]+03000085[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a0,[ 	]+0
 [ 	]+138:[ 	]+R_LARCH_TLS_LE64_HI12[ 	]+TLSL1\+0x8
+[ 	]+13c:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
+[ 	]+13c:[ 	]+R_LARCH_TLS_LE_HI20_R[ 	]+TLSL1
+[ 	]+13c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+140:[ 	]+001090a5[ 	]+add.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+\$a0
+[ 	]+140:[ 	]+R_LARCH_TLS_LE_ADD_R[ 	]+TLSL1
+[ 	]+140:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+144:[ 	]+29800085[ 	]+st.w[ 	]+\$a1,[ 	]+\$a0,[ 	]+0
+[ 	]+144:[ 	]+R_LARCH_TLS_LE_LO12_R[ 	]+TLSL1
+[ 	]+144:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+148:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
+[ 	]+148:[ 	]+R_LARCH_TLS_LE_HI20_R[ 	]+TLSL1\+0x8
+[ 	]+148:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+14c:[ 	]+001090a5[ 	]+add.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+\$a0
+[ 	]+14c:[ 	]+R_LARCH_TLS_LE_ADD_R[ 	]+TLSL1\+0x8
+[ 	]+14c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+150:[ 	]+29800085[ 	]+st.w[ 	]+\$a1,[ 	]+\$a0,[ 	]+0
+[ 	]+150:[ 	]+R_LARCH_TLS_LE_LO12_R[ 	]+TLSL1\+0x8
+[ 	]+150:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
diff --git a/gas/testsuite/gas/loongarch/reloc.s b/gas/testsuite/gas/loongarch/reloc.s
index a67fecd9429..0a343c11225 100644
--- a/gas/testsuite/gas/loongarch/reloc.s
+++ b/gas/testsuite/gas/loongarch/reloc.s
@@ -142,3 +142,14 @@  lu12i.w $r4,%le_hi20(TLSL1 + 0x8)
 ori $r5,$r4,%le_lo12(TLSL1 + 0x8)
 lu32i.d $r4,%le64_lo20(TLSL1 + 0x8)
 lu52i.d $r5,$r4,%le64_hi12(TLSL1 + 0x8)
+
+
+/* New TLS Insn.  */
+lu12i.w $r4,%le_hi20_r(TLSL1)
+add.d   $r5,$r5,$r4,%le_add_r(TLSL1)
+st.w $r5,$r4,%le_lo12_r(TLSL1)
+
+/* New TLS Insn with addend.  */
+lu12i.w $r4,%le_hi20_r(TLSL1 + 0x8)
+add.d   $r5,$r5,$r4,%le_add_r(TLSL1 + 0x8)
+st.w $r5,$r4,%le_lo12_r(TLSL1 + 0x8)
diff --git a/gas/testsuite/gas/loongarch/tls_le_insn_format_check.s b/gas/testsuite/gas/loongarch/tls_le_insn_format_check.s
new file mode 100644
index 00000000000..12b8b4769cc
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/tls_le_insn_format_check.s
@@ -0,0 +1,5 @@ 
+/* Assemble the following assembly statements using as. 
+   If a "no match insn" exception is thrown, the test passes; 
+   otherwise, the test fails.  */
+
+add.d $a0,$a0,$a0,8