public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v1 0/6] LoongArch linker relaxation support.
@ 2022-12-05  8:04 mengqinggang
  2022-12-05  8:04 ` [PATCH v1 1/6] LoongArch: include: Add support for linker relaxation mengqinggang
                   ` (6 more replies)
  0 siblings, 7 replies; 14+ messages in thread
From: mengqinggang @ 2022-12-05  8:04 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, liuzhensong, chenglulu, xry111, i.swmail, maskray,
	mengqinggang

There are two instrunction sequence can be relaxed in LoongArch. The first one  
is "pcala12i + addi.d" which can be relaxed to pcaddi. Another one is           
"pcalau12i + ld.d" which can be relaxed to "pcalau12i + addi.d". And it can be  
relaxed to pcaddi one more time. Pcaddi instrunction can address a signed 22       
bits 4-byte alinged offset relative to pc. 

Now, only the instrunctions expand from macro (la.local, la.got, etc.) at          
assembly time can be relaxed, because gcc instruction scheduling causes relax   
unable to handle some special cases. Gcc can add -mno-explicit-relocs option       
to generate macro instrunction.

mengqinggang (6):
  LoongArch: include: Add support for linker relaxation.
  LoongArch: bfd: Add support for linker relaxation.
  LoongArch: opcodes: Add support for linker relaxation.
  LoongArch: binutils: Add support for linker relaxation.
  LoongArch: gas: Add support for linker relaxation.
  LoongArch: ld: Add support for linker relaxation.

 bfd/bfd-in2.h                                 |   8 +
 bfd/elfnn-loongarch.c                         | 582 +++++++++++++--
 bfd/elfxx-loongarch.c                         | 676 +++++++++++++-----
 bfd/elfxx-loongarch.h                         |  10 +-
 bfd/libbfd.h                                  |   8 +
 bfd/reloc.c                                   |  22 +
 binutils/readelf.c                            |  84 ++-
 binutils/testsuite/binutils-all/readelf.exp   |  13 +-
 gas/config/tc-loongarch.c                     | 412 +++++++++--
 gas/config/tc-loongarch.h                     |  45 +-
 gas/testsuite/gas/all/align.d                 |   5 +-
 gas/testsuite/gas/all/gas.exp                 |  10 +-
 gas/testsuite/gas/all/relax.d                 |   4 +
 gas/testsuite/gas/elf/dwarf-5-irp.d           |   3 +-
 gas/testsuite/gas/elf/dwarf-5-loc0.d          |   3 +-
 gas/testsuite/gas/elf/dwarf2-11.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-15.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-16.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-17.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-18.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-19.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-5.d              |   3 +-
 gas/testsuite/gas/elf/ehopt0.d                |   3 +
 gas/testsuite/gas/elf/elf.exp                 |   3 +
 gas/testsuite/gas/elf/section11.d             |   4 +-
 gas/testsuite/gas/lns/lns.exp                 |   1 +
 gas/testsuite/gas/loongarch/jmp_op.d          |  65 +-
 gas/testsuite/gas/loongarch/li.d              |   9 +-
 gas/testsuite/gas/loongarch/macro_op.d        |  69 +-
 .../gas/loongarch/macro_op_large_abs.d        | 103 +--
 .../gas/loongarch/macro_op_large_pc.d         | 103 +--
 gas/testsuite/gas/loongarch/relax_align.d     |  25 +
 gas/testsuite/gas/loongarch/relax_align.s     |   5 +
 gas/testsuite/gas/loongarch/uleb128.d         |  35 +
 gas/testsuite/gas/loongarch/uleb128.s         |  20 +
 include/elf/loongarch.h                       |  20 +
 include/opcode/loongarch.h                    |   3 +
 ld/emultempl/loongarchelf.em                  |   3 +
 ld/testsuite/ld-elf/compressed1d.d            |   3 +
 ld/testsuite/ld-elf/pr26936.d                 |   4 +-
 ld/testsuite/ld-loongarch-elf/disas-jirl.d    |   4 +-
 ld/testsuite/ld-loongarch-elf/jmp_op.d        |  65 +-
 ld/testsuite/ld-loongarch-elf/macro_op.d      | 138 ++--
 ld/testsuite/ld-loongarch-elf/relax-align.dd  |   7 +
 ld/testsuite/ld-loongarch-elf/relax-align.s   |   9 +
 ld/testsuite/ld-loongarch-elf/relax.dd        |   5 +
 ld/testsuite/ld-loongarch-elf/relax.exp       |  65 ++
 ld/testsuite/ld-loongarch-elf/relax.s         |  50 ++
 ld/testsuite/ld-loongarch-elf/uleb128.dd      |  10 +
 ld/testsuite/ld-loongarch-elf/uleb128.s       |  21 +
 opcodes/loongarch-opc.c                       |   5 +-
 51 files changed, 2223 insertions(+), 540 deletions(-)
 create mode 100644 gas/testsuite/gas/loongarch/relax_align.d
 create mode 100644 gas/testsuite/gas/loongarch/relax_align.s
 create mode 100644 gas/testsuite/gas/loongarch/uleb128.d
 create mode 100644 gas/testsuite/gas/loongarch/uleb128.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax-align.dd
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax-align.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax.dd
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax.exp
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/uleb128.dd
 create mode 100644 ld/testsuite/ld-loongarch-elf/uleb128.s

-- 
2.36.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v1 1/6] LoongArch: include: Add support for linker relaxation.
  2022-12-05  8:04 [PATCH v1 0/6] LoongArch linker relaxation support mengqinggang
@ 2022-12-05  8:04 ` mengqinggang
  2022-12-05  8:24   ` Xi Ruoyao
  2022-12-05  8:04 ` [PATCH v1 2/6] LoongArch: bfd: " mengqinggang
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: mengqinggang @ 2022-12-05  8:04 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, liuzhensong, chenglulu, xry111, i.swmail, maskray,
	mengqinggang

Add relocs and gas LARCH_opts.relax option.

include/ChangeLog:

	* elf/loongarch.h: Add relocs.
	* opcode/loongarch.h: Add LARCH_opts.relax and macro LARCH_NOP.
---
 include/elf/loongarch.h    | 20 ++++++++++++++++++++
 include/opcode/loongarch.h |  3 +++
 2 files changed, 23 insertions(+)

diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h
index a6341b46791..0ecddd17b37 100644
--- a/include/elf/loongarch.h
+++ b/include/elf/loongarch.h
@@ -229,6 +229,26 @@ RELOC_NUMBER (R_LARCH_32_PCREL, 99)
 /* RELAX.  */
 RELOC_NUMBER (R_LARCH_RELAX, 100)
 
+/* relax delete.  */
+RELOC_NUMBER (R_LARCH_DELETE, 101)
+
+/* relax align.  */
+RELOC_NUMBER (R_LARCH_ALIGN, 102)
+
+/* pcaddi.  */
+RELOC_NUMBER (R_LARCH_PCREL20_S2, 103)
+
+/* cfa.  */
+RELOC_NUMBER (R_LARCH_CFA, 104)
+
+/* DW_CFA_advance_loc.  */
+RELOC_NUMBER (R_LARCH_ADD6, 105)
+RELOC_NUMBER (R_LARCH_SUB6, 106)
+
+/* unsinged leb128.  */
+RELOC_NUMBER (R_LARCH_ADD_ULEB128, 107)
+RELOC_NUMBER (R_LARCH_SUB_ULEB128, 108)
+
 END_RELOC_NUMBERS (R_LARCH_count)
 
 /* Processor specific flags for the ELF header e_flags field.  */
diff --git a/include/opcode/loongarch.h b/include/opcode/loongarch.h
index c3922348a56..71570e9acc2 100644
--- a/include/opcode/loongarch.h
+++ b/include/opcode/loongarch.h
@@ -28,6 +28,8 @@ extern "C"
 {
 #endif
 
+  #define LARCH_NOP 0x03400000
+
   typedef uint32_t insn_t;
 
   struct loongarch_opcode
@@ -228,6 +230,7 @@ dec2 : [1-9][0-9]?
 #define ase_gpcr	isa.use_la_global_with_pcrel
 #define ase_gabs	isa.use_la_global_with_abs
 
+    int relax;
   } LARCH_opts;
 
   extern size_t loongarch_insn_length (insn_t insn);
-- 
2.36.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v1 2/6] LoongArch: bfd: Add support for linker relaxation.
  2022-12-05  8:04 [PATCH v1 0/6] LoongArch linker relaxation support mengqinggang
  2022-12-05  8:04 ` [PATCH v1 1/6] LoongArch: include: Add support for linker relaxation mengqinggang
@ 2022-12-05  8:04 ` mengqinggang
  2022-12-05  8:04 ` [PATCH v1 3/6] LoongArch: opcodes: " mengqinggang
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: mengqinggang @ 2022-12-05  8:04 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, liuzhensong, chenglulu, xry111, i.swmail, maskray,
	mengqinggang

Add relax support and related relocs in bfd.

bfd/ChangeLog:

	* bfd-in2.h: Add relocs related to relax.
	* elfnn-loongarch.c (struct loongarch_elf_link_hash_table): New integer
	  pointer (data_segment_phase) to monitor the data segment phase.
	  (loongarch_elf_check_relocs): Swap B21/B26 reloc sequence.
	  (loongarch_elf_adjust_dynamic_symbol): Fix code format.
	  (loongarch_reloc_rewrite_imm_insn): Fix function call.
	  (perform_relocation): Handle new relocs related to relax.
	  (RELOCATE_CALC_PC32_HI20): Fix code format.
	  (RELOCATE_CALC_PC64_HI32): Likewise.
	  (loongarch_elf_relocate_section): Handle new relocs related to relax.
	  (loongarch_relax_delete_bytes): New function.
	  (loongarch_relax_pcala_addi): Likewise.
	  (loongarch_relax_pcala_ld): Likewise.
	  (bfd_elfNN_loongarch_set_data_segment_info): Likewise.
	  (loongarch_relax_align): Likewise.
	  (loongarch_elf_relax_section): Likewise.
	  (bfd_elfNN_bfd_relax_section): New macro define.
	* elfxx-loongarch.c (reloc_bits): New bfd point parameter.
	  (reloc_bits_b16): Likewise.
	  (reloc_bits_b21): Likewise.
	  (reloc_bits_b26): Likewise.
	  (loongarch_adjust_reloc_bitsfield): Likewise.
	  (reloc_bits_pcrel20_s2): New function.
	  (loongarch_elf_add_sub_reloc): Likewise.
	  (loongarch_elf_add_sub_reloc_uleb128): Likewise.
	  (loongarch_write_unsigned_leb128): New function.
	* elfxx-loongarch.h (loongarch_adjust_reloc_bitsfield): New bfd point
	    parameter.
	  (bfd_elf32_loongarch_set_data_segment_info): New declare.
	  (bfd_elf64_loongarch_set_data_segment_info): Likewise.
	  (loongarch_write_unsigned_leb128): Likewise.
	* libbfd.h: Add relocs related to relax.
	* reloc.c: Add relocs related to relax.
---
 bfd/bfd-in2.h         |   8 +
 bfd/elfnn-loongarch.c | 582 ++++++++++++++++++++++++++++++++----
 bfd/elfxx-loongarch.c | 676 +++++++++++++++++++++++++++++++-----------
 bfd/elfxx-loongarch.h |  10 +-
 bfd/libbfd.h          |   8 +
 bfd/reloc.c           |  22 ++
 6 files changed, 1077 insertions(+), 229 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 0b071dda1e5..39e3868f6cf 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6310,6 +6310,14 @@ assembler and not (currently) written to any object files.  */
   BFD_RELOC_LARCH_TLS_GD_HI20,
   BFD_RELOC_LARCH_32_PCREL,
   BFD_RELOC_LARCH_RELAX,
+  BFD_RELOC_LARCH_DELETE,
+  BFD_RELOC_LARCH_ALIGN,
+  BFD_RELOC_LARCH_PCREL20_S2,
+  BFD_RELOC_LARCH_CFA,
+  BFD_RELOC_LARCH_ADD6,
+  BFD_RELOC_LARCH_SUB6,
+  BFD_RELOC_LARCH_ADD_ULEB128,
+  BFD_RELOC_LARCH_SUB_ULEB128,
   BFD_RELOC_UNUSED };
 
 typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 8d8a6a47317..11a0da8c3c7 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -27,6 +27,7 @@
 #include "objalloc.h"
 #include "elf/loongarch.h"
 #include "elfxx-loongarch.h"
+#include "opcode/loongarch.h"
 
 static bool
 loongarch_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
@@ -93,6 +94,10 @@ struct loongarch_elf_link_hash_table
 
   /* The max alignment of output sections.  */
   bfd_vma max_alignment;
+
+  /* The data segment phase, don't relax the section
+     when it is exp_seg_relro_adjust.  */
+  int *data_segment_phase;
 };
 
 /* Get the LoongArch ELF linker hash table from a link_info structure.  */
@@ -772,8 +777,8 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
 	  break;
 
-	case R_LARCH_B21:
 	case R_LARCH_B16:
+	case R_LARCH_B21:
 	case R_LARCH_B26:
 	  if (h != NULL)
 	    {
@@ -972,8 +977,12 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
 
   /* Make sure we know what is going on here.  */
   BFD_ASSERT (dynobj != NULL
-	      && (h->needs_plt || h->type == STT_GNU_IFUNC || h->is_weakalias
-		  || (h->def_dynamic && h->ref_regular && !h->def_regular)));
+	      && (h->needs_plt
+		  || h->type == STT_GNU_IFUNC
+		  || h->is_weakalias
+		  || (h->def_dynamic
+		      && h->ref_regular
+		      && !h->def_regular)));
 
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later
@@ -1886,7 +1895,7 @@ loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
   int bits = bfd_get_reloc_size (howto) * 8;
   uint32_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
 
-  if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val))
+  if (!loongarch_adjust_reloc_bitsfield (input_bfd, howto, &reloc_val))
     return bfd_reloc_overflow;
 
   insn = (insn & (uint32_t)howto->src_mask)
@@ -2006,42 +2015,73 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
       bfd_put (bits, input_bfd, value, contents + rel->r_offset);
       break;
 
+    /* LoongArch only has add/sub reloc pair, not has set/sub reloc pair.
+       Because set/sub reloc pair not support multi-thread. While add/sub
+       reloc pair process order not affect the final result.
+
+       For add/sub reloc, the original value will be involved in the
+       calculation. In order not to add/sub extra value, we write 0 to symbol
+       address at assembly time.
+
+       add/sub reloc bits determined by the value after symbol subtraction,
+       not symbol value.
+
+       add/sub reloc save part of the symbol value, so we only need to
+       save howto->dst_mask bits.  */
+    case R_LARCH_ADD6:
+    case R_LARCH_SUB6:
+      {
+	bfd_vma word = bfd_get (howto->bitsize, input_bfd,
+				contents + rel->r_offset);
+	word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
+	bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
+	r = bfd_reloc_ok;
+	break;
+      }
+
+    /* Not need to read the original value, just write the new value.  */
     case R_LARCH_ADD8:
     case R_LARCH_ADD16:
     case R_LARCH_ADD24:
     case R_LARCH_ADD32:
     case R_LARCH_ADD64:
-      r = loongarch_check_offset (rel, input_section);
-      if (r != bfd_reloc_ok)
-	break;
-
-      opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
-      bfd_put (bits, input_bfd, opr1 + value, contents + rel->r_offset);
-      break;
-
     case R_LARCH_SUB8:
     case R_LARCH_SUB16:
     case R_LARCH_SUB24:
     case R_LARCH_SUB32:
     case R_LARCH_SUB64:
-      r = loongarch_check_offset (rel, input_section);
-      if (r != bfd_reloc_ok)
+      {
+	/* Because add/sub reloc is processed separately,
+	   so the high bits is invalid.  */
+	bfd_vma word = value & howto->dst_mask;
+	bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
+	r = bfd_reloc_ok;
 	break;
+      }
 
-      opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
-      bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset);
-      break;
+    case R_LARCH_ADD_ULEB128:
+    case R_LARCH_SUB_ULEB128:
+      {
+	unsigned int len = 0;
+	/* Before write uleb128, first read it to get it's length.  */
+	_bfd_read_unsigned_leb128 (input_bfd, contents + rel->r_offset, &len);
+	loongarch_write_unsigned_leb128 (contents + rel->r_offset, len, value);
+	r = bfd_reloc_ok;
+	break;
+      }
 
     /* For eh_frame and debug info.  */
     case R_LARCH_32_PCREL:
-      value -= sec_addr (input_section) + rel->r_offset;
-      value += rel->r_addend;
-      bfd_vma word = bfd_get (howto->bitsize, input_bfd,
-			      contents + rel->r_offset);
-      word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
-      bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
-      r = bfd_reloc_ok;
-      break;
+      {
+	value -= sec_addr (input_section) + rel->r_offset;
+	value += rel->r_addend;
+	bfd_vma word = bfd_get (howto->bitsize, input_bfd,
+				contents + rel->r_offset);
+	word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
+	bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
+	r = bfd_reloc_ok;
+	break;
+      }
 
     /* New reloc type.
        R_LARCH_B16 ~ R_LARCH_TLS_GD_HI20.  */
@@ -2080,6 +2120,7 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
     case R_LARCH_TLS_LD_HI20:
     case R_LARCH_TLS_GD_PC_HI20:
     case R_LARCH_TLS_GD_HI20:
+    case R_LARCH_PCREL20_S2:
       r = loongarch_check_offset (rel, input_section);
       if (r != bfd_reloc_ok)
 	break;
@@ -2246,9 +2287,9 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info,
 
 #define RELOCATE_CALC_PC32_HI20(relocation, pc) 	\
   ({							\
-    bfd_vma lo = (relocation) & ((bfd_vma)0xfff);	\
+    bfd_vma __lo = (relocation) & ((bfd_vma)0xfff);	\
     pc = pc & (~(bfd_vma)0xfff);			\
-    if (lo > 0x7ff)					\
+    if (__lo > 0x7ff)					\
       {							\
 	relocation += 0x1000;				\
       } 						\
@@ -2258,8 +2299,8 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info,
 
 #define RELOCATE_CALC_PC64_HI32(relocation, pc)  	\
   ({							\
-    bfd_vma lo = (relocation) & ((bfd_vma)0xfff);	\
-    if (lo > 0x7ff)					\
+    bfd_vma __lo = (relocation) & ((bfd_vma)0xfff);	\
+    if (__lo > 0x7ff)					\
       { 						\
 	relocation -= 0x100000000;      		\
       }  						\
@@ -2524,29 +2565,49 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  relocation += rel->r_addend;
 	  break;
 
+	case R_LARCH_ADD6:
 	case R_LARCH_ADD8:
 	case R_LARCH_ADD16:
 	case R_LARCH_ADD24:
 	case R_LARCH_ADD32:
 	case R_LARCH_ADD64:
+	  {
+	    bfd_vma old_value = bfd_get (howto->bitsize, input_bfd,
+					 contents + rel->r_offset);
+	    relocation = old_value + relocation + rel->r_addend;
+	    break;
+	  }
+
+	case R_LARCH_SUB6:
 	case R_LARCH_SUB8:
 	case R_LARCH_SUB16:
 	case R_LARCH_SUB24:
 	case R_LARCH_SUB32:
 	case R_LARCH_SUB64:
-	  if (resolved_dynly)
-	    fatal = (loongarch_reloc_is_fatal
-		     (info, input_bfd, input_section, rel, howto,
-		      bfd_reloc_undefined, is_undefweak, name,
-		      "Can't be resolved dynamically.  "
-		      "If this procedure is hand-written assembly,\n"
-		      "there must be something like '.dword sym1 - sym2' "
-		      "to generate these relocs\n"
-		      "and we can't get known link-time address of "
-		      "these symbols."));
-	  else
-	    relocation += rel->r_addend;
-	  break;
+	  {
+	    bfd_vma old_value = bfd_get (howto->bitsize, input_bfd,
+					  contents + rel->r_offset);
+	    relocation = old_value - relocation - rel->r_addend;
+	    break;
+	  }
+
+	case R_LARCH_ADD_ULEB128:
+	case R_LARCH_SUB_ULEB128:
+	  {
+	    /* Get the value and length of the uleb128 data.  */
+	    unsigned int len = 0;
+	    bfd_vma old_value = _bfd_read_unsigned_leb128 (input_bfd,
+				    contents + rel->r_offset, &len);
+
+	    if (R_LARCH_ADD_ULEB128 == ELFNN_R_TYPE (rel->r_info))
+	      relocation = old_value + relocation + rel->r_addend;
+	    else if (R_LARCH_SUB_ULEB128 == ELFNN_R_TYPE (rel->r_info))
+	      relocation = old_value - relocation - rel->r_addend;
+
+	    bfd_vma mask = (1 << (7 * len)) - 1;
+	    relocation &= mask;
+	    break;
+	  }
 
 	case R_LARCH_TLS_DTPREL32:
 	case R_LARCH_TLS_DTPREL64:
@@ -3086,6 +3147,15 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
 	  break;
 
+	case R_LARCH_PCREL20_S2:
+	  unresolved_reloc = false;
+	  if (h && h->plt.offset != MINUS_ONE)
+	    relocation = sec_addr (plt) + h->plt.offset;
+	  else
+	    relocation += rel->r_addend;
+	  relocation -= pc;
+	  break;
+
 	case R_LARCH_PCALA_HI20:
 	  unresolved_reloc = false;
 	  if (h && h->plt.offset != MINUS_ONE)
@@ -3111,15 +3181,15 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  else
 	    relocation += rel->r_addend;
 
-	  relocation &= 0xfff;
-	  /* Signed extend.  */
-	  relocation = (relocation ^ 0x800) - 0x800;
-
 	  /* For 2G jump, generate pcalau12i, jirl.  */
 	  /* If use jirl, turns to R_LARCH_B16.  */
 	  uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset);
 	  if ((insn & 0x4c000000) == 0x4c000000)
 	    {
+	      relocation &= 0xfff;
+	      /* Signed extend.  */
+	      relocation = (relocation ^ 0x800) - 0x800;
+
 	      rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_B16);
 	      howto = loongarch_elf_rtype_to_howto (input_bfd, R_LARCH_B16);
 	    }
@@ -3255,13 +3325,12 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		    + (idx * GOT_ENTRY_SIZE)
 		    - sec_addr (htab->elf.sgot);
 		}
+
 	      relocation = got_off + sec_addr (got);
 	    }
 
-	  if (r_type == R_LARCH_GOT_PC_LO12)
-	    relocation &= (bfd_vma)0xfff;
-	  else if (r_type == R_LARCH_GOT64_PC_LO20
-		   || r_type == R_LARCH_GOT64_PC_HI12)
+	  if (r_type == R_LARCH_GOT64_PC_HI12
+	      || r_type == R_LARCH_GOT64_PC_LO20)
 	    RELOCATE_CALC_PC64_HI32 (relocation, pc);
 
 	  break;
@@ -3419,15 +3488,16 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
 	    relocation += 2 * GOT_ENTRY_SIZE;
 
-	  if (r_type == R_LARCH_TLS_IE_PC_LO12)
-	    relocation &= (bfd_vma)0xfff;
-	  else if (r_type == R_LARCH_TLS_IE64_PC_LO20
-		   || r_type == R_LARCH_TLS_IE64_PC_HI12)
+	  if (r_type == R_LARCH_TLS_IE64_PC_LO20
+	      || r_type == R_LARCH_TLS_IE64_PC_HI12)
 	    RELOCATE_CALC_PC64_HI32 (relocation, pc);
 
 	  break;
 
 	case R_LARCH_RELAX:
+	case R_LARCH_ALIGN:
+	  r = bfd_reloc_continue;
+	  unresolved_reloc = false;
 	  break;
 
 	default:
@@ -3518,6 +3588,409 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   return !fatal;
 }
 
+static bool
+loongarch_relax_delete_bytes (bfd *abfd,
+			  asection *sec,
+			  bfd_vma addr,
+			  size_t count,
+			  struct bfd_link_info *link_info)
+{
+  unsigned int i, symcount;
+  bfd_vma toaddr = sec->size;
+  struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (abfd);
+  Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
+  unsigned int sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
+  struct bfd_elf_section_data *data = elf_section_data (sec);
+  bfd_byte *contents = data->this_hdr.contents;
+
+  /* Actually delete the bytes.  */
+  sec->size -= count;
+  memmove (contents + addr, contents + addr + count, toaddr - addr - count);
+
+  /* Adjust the location of all of the relocs.  Note that we need not
+     adjust the addends, since all PC-relative references must be against
+     symbols, which we will adjust below.  */
+  for (i = 0; i < sec->reloc_count; i++)
+    if (data->relocs[i].r_offset > addr && data->relocs[i].r_offset < toaddr)
+      data->relocs[i].r_offset -= count;
+
+  /* Adjust the local symbols defined in this section.  */
+  for (i = 0; i < symtab_hdr->sh_info; i++)
+    {
+      Elf_Internal_Sym *sym = (Elf_Internal_Sym *) symtab_hdr->contents + i;
+      if (sym->st_shndx == sec_shndx)
+	{
+	  /* If the symbol is in the range of memory we just moved, we
+	     have to adjust its value.  */
+	  if (sym->st_value > addr && sym->st_value <= toaddr)
+	    sym->st_value -= count;
+
+	  /* If the symbol *spans* the bytes we just deleted (i.e. its
+	     *end* is in the moved bytes but its *start* isn't), then we
+	     must adjust its size.
+
+	     This test needs to use the original value of st_value, otherwise
+	     we might accidentally decrease size when deleting bytes right
+	     before the symbol.  But since deleted relocs can't span across
+	     symbols, we can't have both a st_value and a st_size decrease,
+	     so it is simpler to just use an else.  */
+	  else if (sym->st_value <= addr
+		   && sym->st_value + sym->st_size > addr
+		   && sym->st_value + sym->st_size <= toaddr)
+	    sym->st_size -= count;
+	}
+    }
+
+  /* Now adjust the global symbols defined in this section.  */
+  symcount = ((symtab_hdr->sh_size / sizeof (ElfNN_External_Sym))
+	      - symtab_hdr->sh_info);
+
+  for (i = 0; i < symcount; i++)
+    {
+      struct elf_link_hash_entry *sym_hash = sym_hashes[i];
+
+      /* The '--wrap SYMBOL' option is causing a pain when the object file,
+	 containing the definition of __wrap_SYMBOL, includes a direct
+	 call to SYMBOL as well. Since both __wrap_SYMBOL and SYMBOL reference
+	 the same symbol (which is __wrap_SYMBOL), but still exist as two
+	 different symbols in 'sym_hashes', we don't want to adjust
+	 the global symbol __wrap_SYMBOL twice.
+
+	 The same problem occurs with symbols that are versioned_hidden, as
+	 foo becomes an alias for foo@BAR, and hence they need the same
+	 treatment.  */
+      if (link_info->wrap_hash != NULL
+	  || sym_hash->versioned != unversioned)
+	{
+	  struct elf_link_hash_entry **cur_sym_hashes;
+
+	  /* Loop only over the symbols which have already been checked.  */
+	  for (cur_sym_hashes = sym_hashes; cur_sym_hashes < &sym_hashes[i];
+	       cur_sym_hashes++)
+	    {
+	      /* If the current symbol is identical to 'sym_hash', that means
+		 the symbol was already adjusted (or at least checked).  */
+	      if (*cur_sym_hashes == sym_hash)
+		break;
+	    }
+	  /* Don't adjust the symbol again.  */
+	  if (cur_sym_hashes < &sym_hashes[i])
+	    continue;
+	}
+
+      if ((sym_hash->root.type == bfd_link_hash_defined
+	   || sym_hash->root.type == bfd_link_hash_defweak)
+	  && sym_hash->root.u.def.section == sec)
+	{
+	  /* As above, adjust the value if needed.  */
+	  if (sym_hash->root.u.def.value > addr
+	      && sym_hash->root.u.def.value <= toaddr)
+	    sym_hash->root.u.def.value -= count;
+
+	  /* As above, adjust the size if needed.  */
+	  else if (sym_hash->root.u.def.value <= addr
+		   && sym_hash->root.u.def.value + sym_hash->size > addr
+		   && sym_hash->root.u.def.value + sym_hash->size <= toaddr)
+	    sym_hash->size -= count;
+	}
+    }
+
+  return true;
+}
+
+/* Relax pcalau12i,addi.d => pcaddi.  */
+static bool
+loongarch_relax_pcala_addi(bfd *abfd, asection *sec,
+		       Elf_Internal_Rela *rel_hi, bfd_vma symval)
+{
+  bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
+  Elf_Internal_Rela *rel_lo = rel_hi + 2;
+  uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
+  uint32_t add = bfd_get (32, abfd, contents + rel_lo->r_offset);
+  uint32_t rd = pca & 0x1f;
+  bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
+  const uint32_t addi_d = 0x02c00000;
+  const uint32_t pcaddi = 0x18000000;
+
+  /* Is pcalau12i + addi.d insns?  */
+  if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_PCALA_LO12)
+      || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX)
+      || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX)
+      || (rel_hi->r_offset + 4 != rel_lo->r_offset)
+      || ((add & addi_d) != addi_d)
+      /* Is pcalau12i $rd + addi.d $rd,$rd?  */
+      || ((add & 0x1f) != rd)
+      || (((add >> 5) & 0x1f) != rd)
+      /* Can be relaxed to pcaddi?  */
+      || (symval & 0x3) /* 4 bytes align.  */
+      || ((bfd_signed_vma)(symval - pc) < (bfd_signed_vma)(int32_t)0xffe00000)
+      || ((bfd_signed_vma)(symval - pc) > (bfd_signed_vma)(int32_t)0x1ffffc))
+    return false;
+
+  pca = pcaddi | rd;
+  bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
+
+  /* Adjust relocations.  */
+  rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
+				 R_LARCH_PCREL20_S2);
+  rel_lo->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
+				 R_LARCH_DELETE);
+
+  return true;
+}
+
+/* Relax pcalau12i,ld.d => pcalau12i,addi.d.  */
+static bool
+loongarch_relax_pcala_ld (bfd *abfd, asection *sec,
+		Elf_Internal_Rela *rel_hi)
+{
+  bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
+  Elf_Internal_Rela *rel_lo = rel_hi + 2;
+  uint32_t pca = bfd_get (32, abfd, contents + rel_hi->r_offset);
+  uint32_t ld = bfd_get (32, abfd, contents + rel_lo->r_offset);
+  uint32_t rd = pca & 0x1f;
+  const uint32_t ld_d = 0x28c00000;
+  uint32_t addi_d = 0x02c00000;
+
+  if ((ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_GOT_PC_LO12)
+      || (ELFNN_R_TYPE ((rel_lo + 1)->r_info) != R_LARCH_RELAX)
+      || (ELFNN_R_TYPE ((rel_hi + 1)->r_info) != R_LARCH_RELAX)
+      || (rel_hi->r_offset + 4 != rel_lo->r_offset)
+      || ((ld & 0x1f) != rd)
+      || (((ld >> 5) & 0x1f) != rd)
+      || ((ld & ld_d) != ld_d))
+    return false;
+
+  addi_d = addi_d | (rd << 5) | rd;
+  bfd_put (32, abfd, addi_d, contents + rel_lo->r_offset);
+
+  rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
+				 R_LARCH_PCALA_HI20);
+  rel_lo->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_lo->r_info),
+				 R_LARCH_PCALA_LO12);
+  return true;
+}
+
+/* Called by after_allocation to set the information of data segment
+   before relaxing.  */
+
+void
+bfd_elfNN_loongarch_set_data_segment_info (struct bfd_link_info *info,
+				     int *data_segment_phase)
+{
+  struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
+  htab->data_segment_phase = data_segment_phase;
+}
+
+/* Implement R_LARCH_ALIGN by deleting excess alignment NOPs.
+   Once we've handled an R_LARCH_ALIGN, we can't relax anything else.  */
+static bool
+loongarch_relax_align (bfd *abfd, asection *sec,
+			asection *sym_sec,
+			struct bfd_link_info *link_info,
+			Elf_Internal_Rela *rel,
+			bfd_vma symval)
+{
+  bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
+  bfd_vma alignment = 1, pos;
+  while (alignment <= rel->r_addend)
+    alignment *= 2;
+
+  symval -= rel->r_addend;
+  bfd_vma aligned_addr = ((symval - 1) & ~(alignment - 1)) + alignment;
+  bfd_vma nop_bytes = aligned_addr - symval;
+
+  /* Once we've handled an R_LARCH_ALIGN, we can't relax anything else.  */
+  sec->sec_flg0 = true;
+
+  /* Make sure there are enough NOPs to actually achieve the alignment.  */
+  if (rel->r_addend < nop_bytes)
+    {
+      _bfd_error_handler
+	(_("%pB(%pA+%#" PRIx64 "): %" PRId64 " bytes required for alignment "
+	   "to %" PRId64 "-byte boundary, but only %" PRId64 " present"),
+	 abfd, sym_sec, (uint64_t) rel->r_offset,
+	 (int64_t) nop_bytes, (int64_t) alignment, (int64_t) rel->r_addend);
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
+
+  /* Delete the reloc.  */
+  rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
+
+  /* If the number of NOPs is already correct, there's nothing to do.  */
+  if (nop_bytes == rel->r_addend)
+    return true;
+
+  /* Write as many LOONGARCH NOPs as we need.  */
+  for (pos = 0; pos < (nop_bytes & -4); pos += 4)
+    bfd_putl32 (LARCH_NOP, contents + rel->r_offset + pos);
+
+  /* Delete the excess NOPs.  */
+  return loongarch_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes,
+				   rel->r_addend - nop_bytes, link_info);
+}
+
+static bool
+loongarch_elf_relax_section (bfd *abfd, asection *sec,
+			       struct bfd_link_info *info,
+			       bool *again)
+{
+  struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
+  Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (abfd);
+  struct bfd_elf_section_data *data = elf_section_data (sec);
+  Elf_Internal_Rela *relocs;
+  *again = false;
+
+  if (bfd_link_relocatable (info)
+      || sec->sec_flg0
+      || (sec->flags & SEC_RELOC) == 0
+      || sec->reloc_count == 0
+      || elf_seg_map (info->output_bfd) == NULL
+      || (info->disable_target_specific_optimizations
+	  && info->relax_pass == 0)
+      /* The exp_seg_relro_adjust is enum phase_enum (0x4),
+	 and defined in ld/ldexp.h.  */
+      || *(htab->data_segment_phase) == 4)
+    return true;
+
+  if (data->relocs)
+    relocs = data->relocs;
+  else if (!(relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
+						 info->keep_memory)))
+    return true;
+
+  if (!data->this_hdr.contents
+      && !bfd_malloc_and_get_section (abfd, sec, &data->this_hdr.contents))
+    return true;
+
+  if (symtab_hdr->sh_info != 0
+      && !symtab_hdr->contents
+      && !(symtab_hdr->contents =
+	   (unsigned char *) bfd_elf_get_elf_syms (abfd, symtab_hdr,
+						   symtab_hdr->sh_info,
+						   0, NULL, NULL, NULL)))
+    return true;
+
+      data->relocs = relocs;
+
+  for (unsigned int i = 0; i < sec->reloc_count; i++)
+    {
+      Elf_Internal_Rela *rel = relocs + i;
+      asection *sym_sec;
+      bfd_vma symval;
+      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
+      bool local_got = false;
+      char symtype;
+      struct elf_link_hash_entry *h = NULL;
+
+      if (r_symndx < symtab_hdr->sh_info)
+	{
+	  Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
+				    + r_symndx;
+	  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
+	    continue;
+
+	  if (sym->st_shndx == SHN_UNDEF)
+	    {
+	      sym_sec = sec;
+	      symval = rel->r_offset;
+	    }
+	  else
+	    {
+	      sym_sec = elf_elfsections (abfd)[sym->st_shndx]->bfd_section;
+	      symval = sym->st_value;
+	    }
+	  symtype = ELF_ST_TYPE (sym->st_info);
+	}
+      else
+	{
+	  r_symndx = ELFNN_R_SYM (rel->r_info) - symtab_hdr->sh_info;
+	  h = elf_sym_hashes (abfd)[r_symndx];
+
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+	  /* Disable the relaxation for ifunc.  */
+	  if (h != NULL && h->type == STT_GNU_IFUNC)
+	    continue;
+
+	  if ((h->root.type == bfd_link_hash_defined
+		    || h->root.type == bfd_link_hash_defweak)
+		   && h->root.u.def.section != NULL
+		   && h->root.u.def.section->output_section != NULL)
+	    {
+	      symval = h->root.u.def.value;
+	      sym_sec = h->root.u.def.section;
+	    }
+	  else
+	    continue;
+
+	  if (h && bfd_link_executable (info)
+	      && SYMBOL_REFERENCES_LOCAL (info, h))
+	    local_got = true;
+	  symtype = h->type;
+	}
+
+      if (sym_sec->sec_info_type == SEC_INFO_TYPE_MERGE
+	   && (sym_sec->flags & SEC_MERGE))
+	{
+	   if (symtype == STT_SECTION)
+	     symval += rel->r_addend;
+
+	   symval = _bfd_merged_section_offset (abfd, &sym_sec,
+				elf_section_data (sym_sec)->sec_info,
+				symval);
+
+	   if (symtype != STT_SECTION)
+	     symval += rel->r_addend;
+	}
+      else
+	symval += rel->r_addend;
+
+      symval += sec_addr (sym_sec);
+
+      switch (ELFNN_R_TYPE (rel->r_info))
+	{
+	case R_LARCH_ALIGN:
+	  if (2 == info->relax_pass)
+	    loongarch_relax_align (abfd, sec, sym_sec, info, rel, symval);
+	  break;
+	case R_LARCH_DELETE:
+	  if (info->relax_pass == 1)
+	    {
+	      loongarch_relax_delete_bytes (abfd, sec, rel->r_offset, 4, info);
+	      rel->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
+	    }
+	  break;
+	case R_LARCH_PCALA_HI20:
+	  if (info->relax_pass == 0)
+	    {
+	      if (i + 4 > sec->reloc_count)
+		break;
+	      loongarch_relax_pcala_addi(abfd, sec, rel, symval);
+	    }
+	  break;
+	case R_LARCH_GOT_PC_HI20:
+	  if (local_got)
+	    {
+	      if (i + 4 > sec->reloc_count)
+		break;
+	      if (loongarch_relax_pcala_ld (abfd, sec, rel))
+		{
+		  loongarch_relax_pcala_addi(abfd, sec, rel, symval);
+		}
+	    }
+	  break;
+	default:
+	  break;
+	}
+    }
+
+  return true;
+}
+
 /* Finish up dynamic symbol handling.  We set the contents of various
    dynamic sections here.  */
 
@@ -4151,5 +4624,6 @@ elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
 #define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
 #define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
 #define elf_backend_hash_symbol elf_loongarch64_hash_symbol
+#define bfd_elfNN_bfd_relax_section loongarch_elf_relax_section
 
 #include "elfNN-target.h"
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index 0b00df556b7..72903863019 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -34,7 +34,7 @@ typedef struct loongarch_reloc_howto_type_struct
   /* The first must be reloc_howto_type!  */
   reloc_howto_type howto;
   bfd_reloc_code_real_type bfd_type;
-  bool (*adjust_reloc_bits)(reloc_howto_type *, bfd_vma *);
+  bool (*adjust_reloc_bits)(bfd *, reloc_howto_type *, bfd_vma *);
   const char *larch_reloc_type_name;
 } loongarch_reloc_howto_type;
 
@@ -52,13 +52,23 @@ typedef struct loongarch_reloc_howto_type_struct
   { EMPTY_HOWTO (C), BFD_RELOC_NONE, NULL, NULL }
 
 static bool
-reloc_bits (reloc_howto_type *howto, bfd_vma *val);
+reloc_bits (bfd *abfd, reloc_howto_type *howto, bfd_vma *val);
 static bool
-reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val);
+reloc_bits_pcrel20_s2 (bfd *abfd, reloc_howto_type *howto, bfd_vma *fix_val);
 static bool
-reloc_bits_b21 (reloc_howto_type *howto, bfd_vma *fix_val);
+reloc_bits_b16 (bfd *abfd, reloc_howto_type *howto, bfd_vma *fix_val);
 static bool
-reloc_bits_b26 (reloc_howto_type *howto, bfd_vma *val);
+reloc_bits_b21 (bfd *abfd, reloc_howto_type *howto, bfd_vma *fix_val);
+static bool
+reloc_bits_b26 (bfd *abfd, reloc_howto_type *howto, bfd_vma *val);
+
+static bfd_reloc_status_type
+loongarch_elf_add_sub_reloc (bfd *, arelent *, asymbol *, void *,
+			      asection *, bfd *, char **);
+
+static bfd_reloc_status_type
+loongarch_elf_add_sub_reloc_uleb128 (bfd *, arelent *, asymbol *, void *,
+				      asection *, bfd *, char **);
 
 /* This does not include any relocation information, but should be
    good enough for GDB or objdump to read the file.  */
@@ -521,175 +531,185 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 reloc_bits,				/* adjust_reloc_bits */
 	 NULL),					/* larch_reloc_type_name */
 
+  /* 8-bit in-place addition, for local label subtraction.  */
   LOONGARCH_HOWTO (R_LARCH_ADD8,		/* type (47).  */
 	 0,					/* rightshift.  */
-	 4,					/* size.  */
+	 1,					/* size.  */
 	 8,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,			/* special_function.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
 	 "R_LARCH_ADD8",			/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 ALL_ONES,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_ADD8,			/* bfd_reloc_code_real_type */
-	 NULL,					/* adjust_reloc_bits */
-	 NULL),					/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0xff,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_ADD8,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
 
+  /* 16-bit in-place addition, for local label subtraction.  */
   LOONGARCH_HOWTO (R_LARCH_ADD16,		/* type (48).  */
 	 0,					/* rightshift.  */
-	 4,					/* size.  */
+	 2,					/* size.  */
 	 16,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,			/* special_function.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
 	 "R_LARCH_ADD16",			/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 ALL_ONES,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_ADD16,			/* bfd_reloc_code_real_type */
-	 NULL,					/* adjust_reloc_bits */
-	 NULL),					/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0xffff,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_ADD16,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
 
+  /* 24-bit in-place addition, for local label subtraction.  */
   LOONGARCH_HOWTO (R_LARCH_ADD24,		/* type (49).  */
 	 0,					/* rightshift.  */
-	 4,					/* size.  */
+	 3,					/* size.  */
 	 24,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,			/* special_function.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
 	 "R_LARCH_ADD24",			/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 ALL_ONES,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_ADD24,			/* bfd_reloc_code_real_type */
-	 NULL,					/* adjust_reloc_bits */
-	 NULL),					/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0xffffff,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_ADD24,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
 
+  /* 32-bit in-place addition, for local label subtraction.  */
   LOONGARCH_HOWTO (R_LARCH_ADD32,		/* type (50).  */
 	 0,					/* rightshift.  */
 	 4,					/* size.  */
 	 32,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,			/* special_function.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
 	 "R_LARCH_ADD32",			/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 ALL_ONES,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_ADD32,			/* bfd_reloc_code_real_type */
-	 NULL,					/* adjust_reloc_bits */
-	 NULL),					/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0xffffffff,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_ADD32,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
 
+  /* 64-bit in-place addition, for local label subtraction.  */
   LOONGARCH_HOWTO (R_LARCH_ADD64,		/* type (51).  */
 	 0,					/* rightshift.  */
 	 8,					/* size.  */
 	 64,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,			/* special_function.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
 	 "R_LARCH_ADD64",			/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 ALL_ONES,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_ADD64,			/* bfd_reloc_code_real_type */
-	 NULL,					/* adjust_reloc_bits */
-	 NULL),					/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 ALL_ONES,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_ADD64,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
 
+  /* 8-bit in-place subtraction, for local label subtraction.  */
   LOONGARCH_HOWTO (R_LARCH_SUB8,		/* type (52).  */
 	 0,					/* rightshift.  */
-	 4,					/* size.  */
+	 1,					/* size.  */
 	 8,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,			/* special_function.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
 	 "R_LARCH_SUB8",			/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 ALL_ONES,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_SUB8,			/* bfd_reloc_code_real_type */
-	 NULL,					/* adjust_reloc_bits */
-	 NULL),					/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0xff,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_SUB8,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
 
+  /* 16-bit in-place subtraction, for local label subtraction.  */
   LOONGARCH_HOWTO (R_LARCH_SUB16,		/* type (53).  */
 	 0,					/* rightshift.  */
-	 4,					/* size.  */
+	 2,					/* size.  */
 	 16,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,			/* special_function.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
 	 "R_LARCH_SUB16",			/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 ALL_ONES,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_SUB16,			/* bfd_reloc_code_real_type */
-	 NULL,					/* adjust_reloc_bits */
-	 NULL),					/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0xffff,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_SUB16,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
 
+  /* 24-bit in-place subtraction, for local label subtraction.  */
   LOONGARCH_HOWTO (R_LARCH_SUB24,		/* type (54).  */
 	 0,					/* rightshift.  */
-	 4,					/* size.  */
+	 3,					/* size.  */
 	 24,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,			/* special_function.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
 	 "R_LARCH_SUB24",			/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 ALL_ONES,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_SUB24,			/* bfd_reloc_code_real_type */
-	 NULL,					/* adjust_reloc_bits */
-	 NULL),					/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0xffffff,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_SUB24,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
 
+  /* 32-bit in-place subtraction, for local label subtraction.  */
   LOONGARCH_HOWTO (R_LARCH_SUB32,		/* type (55).  */
 	 0,					/* rightshift.  */
 	 4,					/* size.  */
 	 32,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,			/* special_function.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
 	 "R_LARCH_SUB32",			/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 ALL_ONES,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_SUB32,			/* bfd_reloc_code_real_type */
-	 NULL,					/* adjust_reloc_bits */
-	 NULL),					/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0xffffffff,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_SUB32,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
 
+  /* 64-bit in-place subtraction, for local label subtraction.  */
   LOONGARCH_HOWTO (R_LARCH_SUB64,		/* type (56).  */
 	 0,					/* rightshift.  */
 	 8,					/* size.  */
 	 64,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,			/* special_function.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
 	 "R_LARCH_SUB64",			/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 ALL_ONES,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_SUB64,			/* bfd_reloc_code_real_type */
-	 NULL,					/* adjust_reloc_bits */
-	 NULL),					/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 ALL_ONES,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_SUB64,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
 
   LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT,	/* type (57).  */
 	 0,					/* rightshift.  */
@@ -742,12 +762,12 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 bfd_elf_generic_reloc,			/* special_function.  */
 	 "R_LARCH_B16",				/* name.  */
 	 false,					/* partial_inplace.  */
-	 0x3fffc00,				/* src_mask */
-	 0x3fffc00,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_B16,			/* bfd_reloc_code_real_type */
-	 reloc_bits_b16,			/* adjust_reloc_bits */
-	 "b16"),				/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0x3fffc00,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_B16,			/* bfd_reloc_code_real_type.  */
+	 reloc_bits_b16,			/* adjust_reloc_bits.  */
+	 "b16"),				/* larch_reloc_type_name.  */
 
   LOONGARCH_HOWTO (R_LARCH_B21,			/* type (65).  */
 	 2,					/* rightshift.  */
@@ -759,12 +779,12 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 bfd_elf_generic_reloc,			/* special_function.  */
 	 "R_LARCH_B21",				/* name.  */
 	 false,					/* partial_inplace.  */
-	 0xfc0003e0,				/* src_mask */
-	 0xfc0003e0,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_B21,			/* bfd_reloc_code_real_type */
-	 reloc_bits_b21,			/* adjust_reloc_bits */
-	 "b21"),				/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0x3fffc1f,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_B21,			/* bfd_reloc_code_real_type.  */
+	 reloc_bits_b21,			/* adjust_reloc_bits.  */
+	 "b21"),				/* larch_reloc_type_name.  */
 
   LOONGARCH_HOWTO (R_LARCH_B26,			/* type (66).  */
 	 2,					/* rightshift.  */
@@ -776,12 +796,12 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 bfd_elf_generic_reloc,			/* special_function.  */
 	 "R_LARCH_B26",				/* name.  */
 	 false,					/* partial_inplace.  */
-	 0,					/* src_mask */
-	 0x03ffffff,				/* dst_mask */
-	 false,					/* pcrel_offset */
-	 BFD_RELOC_LARCH_B26,			/* bfd_reloc_code_real_type */
-	 reloc_bits_b26,			/* adjust_reloc_bits */
-	 "b26"),				/* larch_reloc_type_name */
+	 0,					/* src_mask.  */
+	 0x03ffffff,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_B26,			/* bfd_reloc_code_real_type.  */
+	 reloc_bits_b26,			/* adjust_reloc_bits.  */
+	 "b26"),				/* larch_reloc_type_name.  */
 
   LOONGARCH_HOWTO (R_LARCH_ABS_HI20,		/* type (67).  */
 	 12,					/* rightshift.  */
@@ -1078,7 +1098,7 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 12,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 10,					/* bitpos.  */
-	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 complain_overflow_unsigned,		/* complain_on_overflow.  */
 	 bfd_elf_generic_reloc,			/* special_function.  */
 	 "R_LARCH_TLS_LE_LO12",			/* name.  */
 	 false,					/* partial_inplace.  */
@@ -1146,7 +1166,7 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 12,					/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 10,					/* bitpos.  */
-	 complain_overflow_unsigned,		/* complain_on_overflow.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
 	 bfd_elf_generic_reloc,			/* special_function.  */
 	 "R_LARCH_TLS_IE_PC_LO12",		/* name.  */
 	 false,					/* partial_inplace.  */
@@ -1191,7 +1211,7 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 reloc_bits,				/* adjust_reloc_bits */
 	 "ie64_pc_hi12"),			/* larch_reloc_type_name */
 
-  LOONGARCH_HOWTO (R_LARCH_TLS_IE_HI20,	/* type (91).  */
+  LOONGARCH_HOWTO (R_LARCH_TLS_IE_HI20,		/* type (91).  */
 	 12,					/* rightshift.  */
 	 4,					/* size.  */
 	 20,					/* bitsize.  */
@@ -1327,13 +1347,14 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 reloc_bits,				/* adjust_reloc_bits */
 	 "gd_hi20"),				/* larch_reloc_type_name */
 
+  /* 32-bit PC relative.  */
   LOONGARCH_HOWTO (R_LARCH_32_PCREL,		/* type (99).  */
 	 0,					/* rightshift.  */
 	 4,					/* size.  */
 	 32,					/* bitsize.  */
 	 true,					/* pc_relative.  */
 	 0,					/* bitpos.  */
-	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
 	 bfd_elf_generic_reloc,			/* special_function.  */
 	 "R_LARCH_32_PCREL",			/* name.  */
 	 false,					/* partial_inplace.  */
@@ -1344,6 +1365,7 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 NULL,					/* adjust_reloc_bits */
 	 NULL),					/* larch_reloc_type_name */
 
+  /* The paired relocation may be relaxed.  */
   LOONGARCH_HOWTO (R_LARCH_RELAX,		/* type (100).  */
 	 0,					/* rightshift */
 	 1,					/* size */
@@ -1361,6 +1383,158 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 NULL,					/* adjust_reloc_bits */
 	 NULL),					/* larch_reloc_type_name */
 
+  /* Delete relaxed instruction.  */
+  LOONGARCH_HOWTO (R_LARCH_DELETE,		/* type (101).  */
+	 0,					/* rightshift.  */
+	 0,					/* size.  */
+	 0,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_DELETE",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_DELETE,		/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
+
+  /* Indicates an alignment statement.  The addend field encodes how many
+     bytes of NOPs follow the statement.  The desired alignment is the
+     addend rounded up to the next power of two.  */
+  LOONGARCH_HOWTO (R_LARCH_ALIGN,		/* type (102).  */
+	 0,					/* rightshift.  */
+	 0,					/* size.  */
+	 0,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_ALIGN",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_ALIGN,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
+
+  /* pcala_hi20 + pcala_lo12 relaxed to pcrel20_s2.  */
+  LOONGARCH_HOWTO (R_LARCH_PCREL20_S2,		/* type (103).  */
+	 2,					/* rightshift.  */
+	 4,					/* size.  */
+	 20,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 5,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_PCREL20_S2",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0x1ffffe0,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_PCREL20_S2,		/* bfd_reloc_code_real_type.  */
+	 reloc_bits_pcrel20_s2,			/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
+
+  /* Canonical Frame Address.  */
+  LOONGARCH_HOWTO (R_LARCH_CFA,			/* type (104).  */
+	 0,					/* rightshift.  */
+	 0,					/* size.  */
+	 0,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_CFA",				/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_CFA,			/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
+
+  /* 6-bit in-place addition, for local label subtraction
+     to calculate DW_CFA_advance_loc.  */
+  LOONGARCH_HOWTO (R_LARCH_ADD6,		/* type (105).  */
+	 0,					/* rightshift.  */
+	 1,					/* size.  */
+	 8,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
+	 "R_LARCH_ADD6",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0x3f,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_ADD6,			/* bfd_reloc_code_real_type.  */
+	 reloc_bits,				/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
+
+  /* 6-bit in-place subtraction, for local label subtraction
+     to calculate DW_CFA_advance_loc.  */
+  LOONGARCH_HOWTO (R_LARCH_SUB6,		/* type (106).  */
+	 0,					/* rightshift.  */
+	 1,					/* size.  */
+	 8,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc,		/* special_function.  */
+	 "R_LARCH_SUB6",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0x3f,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_SUB6,			/* bfd_reloc_code_real_type.  */
+	 reloc_bits,				/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
+
+  /* The length of unsigned-leb128 is variable, just assume the
+     size is one byte here.
+     uleb128 in-place addition, for local label subtraction.  */
+  LOONGARCH_HOWTO (R_LARCH_ADD_ULEB128,		/* type (107).  */
+	 0,					/* rightshift.  */
+	 1,					/* size.  */
+	 0,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc_uleb128,	/* special_function.  */
+	 "R_LARCH_ADD_ULEB128",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_ADD_ULEB128,		/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
+
+  /* The length of unsigned-leb128 is variable, just assume the
+     size is one byte here.
+     uleb128 in-place subtraction, for local label subtraction.  */
+  LOONGARCH_HOWTO (R_LARCH_SUB_ULEB128,		/* type (108).  */
+	 0,					/* rightshift.  */
+	 1,					/* size.  */
+	 0,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 loongarch_elf_add_sub_reloc_uleb128,	/* special_function.  */
+	 "R_LARCH_SUB_ULEB128",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_SUB_ULEB128,		/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 NULL),					/* larch_reloc_type_name.  */
+
 };
 
 reloc_howto_type *
@@ -1464,13 +1638,54 @@ loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
    BFD_RELOC_LARCH_SOP_POP_32_S_10_16
    BFD_RELOC_LARCH_SOP_POP_32_S_5_20
    BFD_RELOC_LARCH_SOP_POP_32_U.  */
+
+static bool
+reloc_bits (bfd *abfd ATTRIBUTE_UNUSED,
+	    reloc_howto_type *howto,
+	    bfd_vma *fix_val)
+{
+  bfd_signed_vma val = (bfd_signed_vma)(*fix_val);
+  bfd_signed_vma mask = ((bfd_signed_vma)0x1 << howto->bitsize) - 1;
+
+  val = val >> howto->rightshift;
+
+  /* Perform insn bits field.  */
+  val = val & mask;
+  val <<= howto->bitpos;
+
+  *fix_val = (bfd_vma)val;
+
+  return true;
+}
+
 static bool
-reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
+reloc_bits_pcrel20_s2 (bfd *abfd, reloc_howto_type *howto, bfd_vma *fix_val)
 {
-  bfd_signed_vma val = ((bfd_signed_vma)(*fix_val)) >> howto->rightshift;
+  bfd_signed_vma val = (bfd_signed_vma)(*fix_val);
+  bfd_signed_vma mask = ((bfd_signed_vma)0x1 << howto->bitsize) - 1;
+
+  /* Check rightshift.  */
+  if (howto->rightshift
+      && (val & ((((bfd_signed_vma) 1) << howto->rightshift) - 1)))
+    {
+      (*_bfd_error_handler) (_("%pB: relocation %s right shift %d error 0x%lx"),
+			     abfd, howto->name, howto->rightshift, val);
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
+
+  val = val >> howto->rightshift;
+
+  if ((val & ~mask) && ((val & ~mask) != ~mask))
+    {
+      (*_bfd_error_handler) (_("%pB: relocation %s overflow 0x%lx"),
+			     abfd, howto->name, val);
+      bfd_set_error (bfd_error_bad_value);
+      return false;
+    }
 
   /* Perform insn bits field.  */
-  val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
+  val = val & mask;
   val <<= howto->bitpos;
 
   *fix_val = (bfd_vma)val;
@@ -1478,42 +1693,35 @@ reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
   return true;
 }
 
+
 /* Adjust val to perform insn
    R_LARCH_SOP_POP_32_S_10_16_S2
    R_LARCH_B16.  */
 static bool
-reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val)
+reloc_bits_b16 (bfd *abfd, reloc_howto_type *howto, bfd_vma *fix_val)
 {
+  bfd_signed_vma val = *fix_val;
+  bfd_signed_vma mask = ((bfd_signed_vma)0x1 << howto->bitsize) - 1;
+
   if (howto->complain_on_overflow != complain_overflow_signed)
     return false;
 
-  bfd_signed_vma val = *fix_val;
-
   /* Judge whether 4 bytes align.  */
   if (val & ((0x1UL << howto->rightshift) - 1))
     return false;
 
-  int bitsize = howto->bitsize + howto->rightshift;
-  bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
+  val = val >> howto->rightshift;
 
-  /* If val < 0, sign bit is 1.  */
-  if (sig_bit)
-    {
-      /* Signed bits is 1.  */
-      if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
-	  != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
-	return false;
-    }
-  else
+  if ((val & ~mask) && ((val & ~mask) != ~mask))
     {
-      /* Signed bits is 0.  */
-      if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
-	return false;
+      (*_bfd_error_handler) (_("%pB: relocation %s overflow 0x%lx"),
+			     abfd, howto->name, val);
+      bfd_set_error (bfd_error_bad_value);
+      return false;
     }
 
   /* Perform insn bits field.  */
-  val >>= howto->rightshift;
-  val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
+  val = val & mask;
   val <<= howto->bitpos;
 
   *fix_val = val;
@@ -1525,36 +1733,30 @@ reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val)
    R_LARCH_SOP_POP_32_S_0_5_10_16_S2
    R_LARCH_B21.  */
 static bool
-reloc_bits_b21 (reloc_howto_type *howto,
-		bfd_vma *fix_val)
+reloc_bits_b21 (bfd *abfd, reloc_howto_type *howto, bfd_vma *fix_val)
 {
+  bfd_signed_vma val = *fix_val;
+  bfd_signed_vma mask = ((bfd_signed_vma)0x1 << howto->bitsize) - 1;
+
   if (howto->complain_on_overflow != complain_overflow_signed)
     return false;
 
-  bfd_signed_vma val = *fix_val;
-
+  /* Judge whether 4 bytes align.  */
   if (val & ((0x1UL << howto->rightshift) - 1))
     return false;
 
-  int bitsize = howto->bitsize + howto->rightshift;
-  bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
+  val = val >> howto->rightshift;
 
-  /* If val < 0.  */
-  if (sig_bit)
+  if ((val & ~mask) && ((val & ~mask) != ~mask))
     {
-      if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
-	  != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
-	return false;
-    }
-  else
-    {
-      if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
-	return false;
+      (*_bfd_error_handler) (_("%pB: relocation %s overflow 0x%lx"),
+			     abfd, howto->name, val);
+      bfd_set_error (bfd_error_bad_value);
+      return false;
     }
 
   /* Perform insn bits field.  */
-  val >>= howto->rightshift;
-  val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
+  val = val & mask;
 
   /* Perform insn bits field.  15:0<<10, 20:16>>16.  */
   val = ((val & 0xffff) << 10) | ((val >> 16) & 0x1f);
@@ -1568,37 +1770,31 @@ reloc_bits_b21 (reloc_howto_type *howto,
    R_LARCH_SOP_POP_32_S_0_10_10_16_S2
    R_LARCH_B26.  */
 static bool
-reloc_bits_b26 (reloc_howto_type *howto,
-		bfd_vma *fix_val)
+reloc_bits_b26 (bfd *abfd, reloc_howto_type *howto, bfd_vma *fix_val)
 {
-  /* Return false if overflow.  */
+  bfd_signed_vma val = *fix_val;
+  bfd_signed_vma mask = ((bfd_signed_vma)0x1 << howto->bitsize) - 1;
+
   if (howto->complain_on_overflow != complain_overflow_signed)
     return false;
 
-  bfd_signed_vma val = *fix_val;
-
+  /* Judge whether 4 bytes align.  */
   if (val & ((0x1UL << howto->rightshift) - 1))
     return false;
 
-  int bitsize = howto->bitsize + howto->rightshift;
-  bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
+  val = val >> howto->rightshift;
 
-  /* If val < 0.  */
-  if (sig_bit)
+  if ((val & ~mask) && ((val & ~mask) != ~mask))
     {
-      if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
-	  != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
-	return false;
-    }
-  else
-    {
-      if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
-	return false;
+      (*_bfd_error_handler) (_("%pB: relocation %s overflow 0x%lx"),
+			     abfd, howto->name, val);
+      bfd_set_error (bfd_error_bad_value);
+      return false;
     }
 
+
   /* Perform insn bits field.  */
-  val >>= howto->rightshift;
-  val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
+  val = val & mask;
 
   /* Perform insn bits field.  25:16>>16, 15:0<<10.  */
   val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff);
@@ -1609,10 +1805,142 @@ reloc_bits_b26 (reloc_howto_type *howto,
 }
 
 bool
-loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto,
+loongarch_adjust_reloc_bitsfield (bfd *abfd, reloc_howto_type *howto,
 				  bfd_vma *fix_val)
 {
   BFD_ASSERT (((loongarch_reloc_howto_type *)howto)->adjust_reloc_bits);
   return ((loongarch_reloc_howto_type *)
-	  howto)->adjust_reloc_bits(howto, fix_val);
+	  howto)->adjust_reloc_bits (abfd, howto, fix_val);
+}
+
+static bfd_reloc_status_type
+loongarch_elf_add_sub_reloc (bfd *abfd,
+	       arelent *reloc_entry,
+	       asymbol *symbol,
+	       void *data,
+	       asection *input_section,
+	       bfd *output_bfd,
+	       char **error_message ATTRIBUTE_UNUSED)
+{
+  reloc_howto_type *howto = reloc_entry->howto;
+  bfd_vma relocation;
+
+  if (output_bfd != NULL
+      && (symbol->flags & BSF_SECTION_SYM) == 0
+      && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
+    {
+      reloc_entry->address += input_section->output_offset;
+      return bfd_reloc_ok;
+    }
+
+  if (output_bfd != NULL)
+    return bfd_reloc_continue;
+
+  relocation = symbol->value + symbol->section->output_section->vma
+    + symbol->section->output_offset + reloc_entry->addend;
+
+  bfd_size_type octets = reloc_entry->address
+    * bfd_octets_per_byte (abfd, input_section);
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, octets))
+    return bfd_reloc_outofrange;
+
+  bfd_vma old_value = bfd_get (howto->bitsize, abfd,
+			       data + reloc_entry->address);
+
+  switch (howto->type)
+    {
+    case R_LARCH_ADD6:
+    case R_LARCH_ADD8:
+    case R_LARCH_ADD16:
+    case R_LARCH_ADD32:
+    case R_LARCH_ADD64:
+      relocation = old_value + relocation;
+      break;
+
+    case R_LARCH_SUB6:
+    case R_LARCH_SUB8:
+    case R_LARCH_SUB16:
+    case R_LARCH_SUB32:
+    case R_LARCH_SUB64:
+      relocation = old_value - relocation;
+      break;
+    }
+
+  bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address);
+
+  return bfd_reloc_ok;
+}
+
+static bfd_reloc_status_type
+loongarch_elf_add_sub_reloc_uleb128 (bfd *abfd,
+	       arelent *reloc_entry,
+	       asymbol *symbol,
+	       void *data,
+	       asection *input_section,
+	       bfd *output_bfd,
+	       char **error_message ATTRIBUTE_UNUSED)
+{
+  reloc_howto_type *howto = reloc_entry->howto;
+  bfd_vma relocation;
+
+ if (output_bfd != NULL
+     && (symbol->flags & BSF_SECTION_SYM) == 0
+     && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0))
+   {
+     reloc_entry->address += input_section->output_offset;
+     return bfd_reloc_ok;
+   }
+
+  if (output_bfd != NULL)
+    return bfd_reloc_continue;
+
+  relocation = symbol->value + symbol->section->output_section->vma
+    + symbol->section->output_offset + reloc_entry->addend;
+
+  bfd_size_type octets = reloc_entry->address
+    * bfd_octets_per_byte (abfd, input_section);
+  if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd,
+				  input_section, octets))
+    return bfd_reloc_outofrange;
+
+  unsigned int len = 0;
+  bfd_byte *p = data + reloc_entry->address;
+  bfd_vma old_value = _bfd_read_unsigned_leb128 (abfd, p, &len);
+
+  switch (howto->type)
+    {
+    case R_LARCH_ADD_ULEB128:
+      relocation = old_value + relocation;
+      break;
+
+    case R_LARCH_SUB_ULEB128:
+      relocation = old_value - relocation;
+      break;
+    }
+
+  bfd_vma mask = (1 << (7 * len)) - 1;
+  relocation = relocation & mask;
+  loongarch_write_unsigned_leb128 (p, len, relocation);
+  return bfd_reloc_ok;
+}
+
+/* Write VALUE in uleb128 format to P.
+   LEN is the uleb128 value length.
+   Return a pointer to the byte following the last byte that was written.  */
+bfd_byte *
+loongarch_write_unsigned_leb128 (bfd_byte *p, unsigned int len, bfd_vma value)
+{
+  bfd_byte c;
+  do
+    {
+      c = value & 0x7f;
+      if (len > 1)
+	c |= 0x80;
+      *(p++) = c;
+      value >>= 7;
+      len--;
+    }
+  while (len);
+  return p;
 }
diff --git a/bfd/elfxx-loongarch.h b/bfd/elfxx-loongarch.h
index 7b8a72130f1..9b5e560c370 100644
--- a/bfd/elfxx-loongarch.h
+++ b/bfd/elfxx-loongarch.h
@@ -34,7 +34,15 @@ extern bfd_reloc_code_real_type
 loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 				   const char *l_r_name);
 
-bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto, bfd_vma *fix_val);
+bool
+loongarch_adjust_reloc_bitsfield (bfd *, reloc_howto_type *, bfd_vma *);
+void
+bfd_elf32_loongarch_set_data_segment_info (struct bfd_link_info *, int *);
+void
+bfd_elf64_loongarch_set_data_segment_info (struct bfd_link_info *, int *);
+
+bfd_byte *
+loongarch_write_unsigned_leb128 (bfd_byte *p, unsigned int len, bfd_vma value);
 
 /* TRUE if this is a PLT reference to a local IFUNC.  */
 #define PLT_LOCAL_IFUNC_P(INFO, H) \
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 2dec8109bb8..c29e5b54d49 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -3509,6 +3509,14 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_LARCH_TLS_GD_HI20",
   "BFD_RELOC_LARCH_32_PCREL",
   "BFD_RELOC_LARCH_RELAX",
+  "BFD_RELOC_LARCH_DELETE",
+  "BFD_RELOC_LARCH_ALIGN",
+  "BFD_RELOC_LARCH_PCREL20_S2",
+  "BFD_RELOC_LARCH_CFA",
+  "BFD_RELOC_LARCH_ADD6",
+  "BFD_RELOC_LARCH_SUB6",
+  "BFD_RELOC_LARCH_ADD_ULEB128",
+  "BFD_RELOC_LARCH_SUB_ULEB128",
  "@@overflow: BFD_RELOC_UNUSED@@",
 };
 #endif
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 6446acc7a30..7fc82129007 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -8310,6 +8310,28 @@ ENUMX
 ENUMX
   BFD_RELOC_LARCH_RELAX
 
+ENUMX
+  BFD_RELOC_LARCH_DELETE
+
+ENUMX
+  BFD_RELOC_LARCH_ALIGN
+
+ENUMX
+  BFD_RELOC_LARCH_PCREL20_S2
+
+ENUMX
+  BFD_RELOC_LARCH_CFA
+
+ENUMX
+  BFD_RELOC_LARCH_ADD6
+ENUMX
+  BFD_RELOC_LARCH_SUB6
+
+ENUMX
+  BFD_RELOC_LARCH_ADD_ULEB128
+ENUMX
+  BFD_RELOC_LARCH_SUB_ULEB128
+
 ENUMDOC
   LARCH relocations.
 
-- 
2.36.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v1 3/6] LoongArch: opcodes: Add support for linker relaxation.
  2022-12-05  8:04 [PATCH v1 0/6] LoongArch linker relaxation support mengqinggang
  2022-12-05  8:04 ` [PATCH v1 1/6] LoongArch: include: Add support for linker relaxation mengqinggang
  2022-12-05  8:04 ` [PATCH v1 2/6] LoongArch: bfd: " mengqinggang
@ 2022-12-05  8:04 ` mengqinggang
  2022-12-05  9:43   ` Andreas Schwab
  2022-12-05  8:04 ` [PATCH v1 4/6] LoongArch: binutils: " mengqinggang
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 14+ messages in thread
From: mengqinggang @ 2022-12-05  8:04 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, liuzhensong, chenglulu, xry111, i.swmail, maskray,
	mengqinggang

Set gas default to enable relax.

opcodes/ChangeLog:

	* loongarch-opc.c (struct loongarch_ASEs_option): New member relax and
	  the default value is 1.
---
 opcodes/loongarch-opc.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c
index 1b510048c29..49e9df56f67 100644
--- a/opcodes/loongarch-opc.c
+++ b/opcodes/loongarch-opc.c
@@ -22,7 +22,10 @@
 #include "opcode/loongarch.h"
 #include "libiberty.h"
 
-struct loongarch_ASEs_option LARCH_opts;
+struct loongarch_ASEs_option LARCH_opts =
+{
+  relax : 1
+};
 
 size_t
 loongarch_insn_length (insn_t insn ATTRIBUTE_UNUSED)
-- 
2.36.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v1 4/6] LoongArch: binutils: Add support for linker relaxation.
  2022-12-05  8:04 [PATCH v1 0/6] LoongArch linker relaxation support mengqinggang
                   ` (2 preceding siblings ...)
  2022-12-05  8:04 ` [PATCH v1 3/6] LoongArch: opcodes: " mengqinggang
@ 2022-12-05  8:04 ` mengqinggang
  2022-12-05  8:04 ` [PATCH v1 5/6] LoongArch: gas: " mengqinggang
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 14+ messages in thread
From: mengqinggang @ 2022-12-05  8:04 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, liuzhensong, chenglulu, xry111, i.swmail, maskray,
	mengqinggang

Add support for relocs related to relax to readelf.

binutils/ChangeLog:

	* readelf.c (target_specific_reloc_handling): Handle ULEB128 reloc.
	  (is_32bit_inplace_add_reloc): Handle new reloc.
	  (is_32bit_inplace_sub_reloc): Likewise.
	  (is_64bit_inplace_add_reloc): Likewise.
	  (is_64bit_inplace_sub_reloc): Likewise.
	  (is_16bit_inplace_add_reloc): Likewise.
	  (is_16bit_inplace_sub_reloc): Likewise.
	  (is_8bit_inplace_add_reloc): Likewise.
	  (is_8bit_inplace_sub_reloc): Likewise.
	  (is_6bit_inplace_sub_reloc): Likewise.
	  (is_6bit_inplace_add_reloc): New function.
	  (apply_relocations): Handle new reloc.
	* testsuite/binutils-all/readelf.exp: Add -mno-relax option
	  for LoongArch.
---
 binutils/readelf.c                          | 84 ++++++++++++++++++++-
 binutils/testsuite/binutils-all/readelf.exp | 13 +++-
 2 files changed, 91 insertions(+), 6 deletions(-)

diff --git a/binutils/readelf.c b/binutils/readelf.c
index 6b2cbbcbb1b..dbca5552bdc 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -13961,6 +13961,51 @@ target_specific_reloc_handling (Filedata *           filedata,
 
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      {
+	switch (reloc_type)
+	  {
+	    /* For .uleb128 .LFE1-.LFB1, loongarch write 0 to object file
+	       at assembly time.  */
+	    case 107: /* R_LARCH_ADD_ULEB128.  */
+	    case 108: /* R_LARCH_SUB_ULEB128.  */
+	      {
+		uint64_t value;
+		unsigned int reloc_size = 0;
+		int leb_ret = 0;
+
+		value = read_leb128 (start + reloc->r_offset, end, false,
+			      &reloc_size, &leb_ret);
+		if (leb_ret != 0 || reloc_size == 0 || reloc_size > 8)
+		  error (_("LoongArch ULEB128 field at 0x%lx contains invalid "
+			   "ULEB128 value\n"),
+			 (long) reloc->r_offset);
+
+		if (107 == reloc_type)
+		  value += (reloc->r_addend + symtab[sym_index].st_value);
+		else if (108 == reloc_type)
+		  value -= (reloc->r_addend + symtab[sym_index].st_value);
+
+		/* Write uleb128 value to p.  */
+		bfd_byte c;
+		bfd_byte *p = start + reloc->r_offset;
+		do
+		  {
+		    c = value & 0x7f;
+		    if (reloc_size > 1)
+		      c |= 0x80;
+		    *(p++) = c;
+		    value >>= 7;
+		    reloc_size--;
+		  }
+		while (reloc_size);
+
+		return true;
+	      }
+	  }
+	break;
+      }
+
     case EM_MSP430:
     case EM_MSP430_OLD:
       {
@@ -14680,6 +14725,8 @@ is_32bit_inplace_add_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 50; /* R_LARCH_ADD32.  */
     case EM_RISCV:
       return reloc_type == 35; /* R_RISCV_ADD32.  */
     default:
@@ -14696,6 +14743,8 @@ is_32bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 55; /* R_LARCH_SUB32.  */
     case EM_RISCV:
       return reloc_type == 39; /* R_RISCV_SUB32.  */
     default:
@@ -14712,6 +14761,8 @@ is_64bit_inplace_add_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 51; /* R_LARCH_ADD64.  */
     case EM_RISCV:
       return reloc_type == 36; /* R_RISCV_ADD64.  */
     default:
@@ -14728,6 +14779,8 @@ is_64bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 56; /* R_LARCH_SUB64.  */
     case EM_RISCV:
       return reloc_type == 40; /* R_RISCV_SUB64.  */
     default:
@@ -14744,6 +14797,8 @@ is_16bit_inplace_add_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 48; /* R_LARCH_ADD16.  */
     case EM_RISCV:
       return reloc_type == 34; /* R_RISCV_ADD16.  */
     default:
@@ -14760,6 +14815,8 @@ is_16bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 53; /* R_LARCH_SUB16.  */
     case EM_RISCV:
       return reloc_type == 38; /* R_RISCV_SUB16.  */
     default:
@@ -14776,6 +14833,8 @@ is_8bit_inplace_add_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 47; /* R_LARCH_ADD8.  */
     case EM_RISCV:
       return reloc_type == 33; /* R_RISCV_ADD8.  */
     default:
@@ -14792,6 +14851,8 @@ is_8bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
   /* Please keep this table alpha-sorted for ease of visual lookup.  */
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 52; /* R_LARCH_SUB8.  */
     case EM_RISCV:
       return reloc_type == 37; /* R_RISCV_SUB8.  */
     default:
@@ -14799,6 +14860,21 @@ is_8bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
     }
 }
 
+/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
+   a 6-bit inplace add RELA relocation used in DWARF debug sections.  */
+
+static bool
+is_6bit_inplace_add_reloc (Filedata * filedata, unsigned int reloc_type)
+{
+  switch (filedata->file_header.e_machine)
+    {
+    case EM_LOONGARCH:
+      return reloc_type == 105; /* R_LARCH_ADD6.  */
+    default:
+      return false;
+    }
+}
+
 /* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is
    a 6-bit inplace sub RELA relocation used in DWARF debug sections.  */
 
@@ -14807,6 +14883,8 @@ is_6bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type)
 {
   switch (filedata->file_header.e_machine)
     {
+    case EM_LOONGARCH:
+      return reloc_type == 106; /* R_LARCH_SUB6.  */
     case EM_RISCV:
       return reloc_type == 52; /* R_RISCV_SUB6.  */
     default:
@@ -15054,7 +15132,8 @@ apply_relocations (Filedata *filedata,
 	      reloc_inplace = true;
 	    }
 	  else if ((reloc_subtract = is_6bit_inplace_sub_reloc (filedata,
-								reloc_type)))
+								reloc_type))
+		   || is_6bit_inplace_add_reloc (filedata, reloc_type))
 	    {
 	      reloc_size = 1;
 	      reloc_inplace = true;
@@ -15144,7 +15223,8 @@ apply_relocations (Filedata *filedata,
 		        reloc_size);
 	    }
 	  else if (is_6bit_abs_reloc (filedata, reloc_type)
-		   || is_6bit_inplace_sub_reloc (filedata, reloc_type))
+		   || is_6bit_inplace_sub_reloc (filedata, reloc_type)
+		   || is_6bit_inplace_add_reloc (filedata, reloc_type))
 	    {
 	      if (reloc_subtract)
 		addend -= sym->st_value;
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index d7f1524fc5c..07056aec6bb 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -489,18 +489,23 @@ if {![binutils_assemble $srcdir/$subdir/z.s tmpdir/z.o]} then {
     readelf_test {--decompress --hex-dump .debug_loc} $tempfile readelf.z
 }
 
-set hpux ""
+set flags ""
 
 # Skip the next test for the RISCV architectures because they
 # do not support .ULEB128 pseudo-ops with non-constant values.
 if ![istarget "riscv*-*-*"] then {
 
     if [istarget "hppa*64*-*-hpux*"] {
-	set hpux "--defsym HPUX=1"
+	set flags "--defsym HPUX=1"
     }
 
+    # LOONGARCH relax align add nops, so label subtractions will increase
+    if [istarget "loongarch*-*-*"] {
+	set flags "-mno-relax"
+     }
+
     # Assemble the DWARF-5 test file.
-    if {![binutils_assemble_flags $srcdir/$subdir/dw5.S tmpdir/dw5.o $hpux]} then {
+    if {![binutils_assemble_flags $srcdir/$subdir/dw5.S tmpdir/dw5.o $flags]} then {
 	unsupported "readelf -wiaoRlL dw5 (failed to assemble)"
     } else {
 
@@ -612,7 +617,7 @@ if ![is_remote host] {
 }
 
 # Check dwarf-5 support for DW_OP_addrx.
-if {![binutils_assemble_flags $srcdir/$subdir/dw5-op.S tmpdir/dw5-op.o $hpux]} then {
+if {![binutils_assemble_flags $srcdir/$subdir/dw5-op.S tmpdir/dw5-op.o $flags]} then {
     unsupported "readelf -wi dw5-op (failed to assemble)"
 } else {
 
-- 
2.36.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v1 5/6] LoongArch: gas: Add support for linker relaxation.
  2022-12-05  8:04 [PATCH v1 0/6] LoongArch linker relaxation support mengqinggang
                   ` (3 preceding siblings ...)
  2022-12-05  8:04 ` [PATCH v1 4/6] LoongArch: binutils: " mengqinggang
@ 2022-12-05  8:04 ` mengqinggang
  2022-12-05  9:47   ` Andreas Schwab
  2022-12-05  8:04 ` [PATCH v1 6/6] LoongArch: ld: " mengqinggang
  2022-12-05  8:43 ` [PATCH v1 0/6] LoongArch linker relaxation support Xi Ruoyao
  6 siblings, 1 reply; 14+ messages in thread
From: mengqinggang @ 2022-12-05  8:04 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, liuzhensong, chenglulu, xry111, i.swmail, maskray,
	mengqinggang

Add gas -mrelax and -mno-relax option.
Add R_LARCH_RELAX reloc for instrction if it can be relaxed.
ADD R_LARCH_ALIGN reloc for alignpeudo instruction because relax.
Add ADD/SUB reloc pair for debug and exception data to calculate symbol
substraction because relax.

gas/ChangeLog:

	* config/tc-loongarch.c:
	  (struct loongarch_cl_insn): New macro_id member.
	  (enum options): New OPTION_RELAX and OPTION_NO_RELAX.
	  (struct option): New mrelax and mno-relax.
	  (md_parse_option): Likewise.
	  (get_internal_label):
	  (loongarch_args_parser_can_match_arg_helper): Generate relax reloc.
	  (move_insn): Set fx_frag and fx_where if exist.
	  (append_fixp_and_insn): Call frag_wane and frag_new for linker relax
	    relocs.
	  (loongarch_assemble_INSNs): New loongarch_cl_insn pointer parameter.
	  (md_assemble): Fix function call.
	  (fix_reloc_insn): Likewise.
	  (md_apply_fix): Generate ADD/SUB reloc pair for debug and exception
	    data.
	  (loongarch_fix_adjustable): Delete.
	  (md_convert_frag): Generate new fix.
	  (loongarch_pre_output_hook): New function.
	  (loongarch_make_nops): Likewise.
	  (loongarch_frag_align_code): Likewise.
	  (loongarch_insert_uleb128_fixes): Likewise.
	  (loongarch_md_finish): Likewise.
	* config/tc-loongarch.h
	  (md_allow_local_subtract): New macro define.
	  (loongarch_frag_align_code): New declare.
	  (md_do_align): Likewise.
	  (loongarch_fix_adjustable): Delete.
	  (tc_fix_adjustable): New macro define.
	  (TC_FORCE_RELOCATION_SUB_SAME): Likewise.
	  (TC_LINKRELAX_FIXUP): Likewise.
	  (TC_FORCE_RELOCATION_LOCAL): Likewise.
	  (DWARF2_USE_FIXED_ADVANCE_PC): Likewise.
	  (MD_APPLY_SYM_VALUE): Likewise.
	  (tc_symbol_new_hook): New extern.
	  (NOP_OPCODE): Delete.
	  (loongarch_pre_output_hook): New macro define.
	  (md_pre_output_hook): Likewise.
	  (md_finish): Likewise.
	  (loongarch_md_finish): New extern.
	* testsuite/gas/all/align.d: Mark as unsupported on LoongArch.
	* testsuite/gas/all/gas.exp: Xfail loongarch*-*.
	* testsuite/gas/all/relax.d: Likewise.
	* testsuite/gas/elf/dwarf-5-irp.d: Likewise.
	* testsuite/gas/elf/dwarf-5-loc0.d: Likewise.
	* testsuite/gas/elf/dwarf2-11.d: Likewise.
	* testsuite/gas/elf/dwarf2-15.d: Likewise.
	* testsuite/gas/elf/dwarf2-16.d: Likewise.
	* testsuite/gas/elf/dwarf2-17.d: Likewise.
	* testsuite/gas/elf/dwarf2-18.d: Likewise.
	* testsuite/gas/elf/dwarf2-19.d: Likewise.
	* testsuite/gas/elf/dwarf2-5.d: Likewise.
	* testsuite/gas/elf/ehopt0.d: Likewise.
	* testsuite/gas/elf/elf.exp: Likewise.
	* testsuite/gas/elf/section11.d: Likewise.
	* testsuite/gas/lns/lns.exp: Likewise.
	* testsuite/gas/loongarch/jmp_op.d: New generated.
	* testsuite/gas/loongarch/li.d: Likewise.
	* testsuite/gas/loongarch/macro_op.d: Likewise.
	* testsuite/gas/loongarch/macro_op_large_abs.d: Likewise.
	* testsuite/gas/loongarch/macro_op_large_pc.d: Likewise.
	* testsuite/gas/loongarch/relax_align.d: New test.
	* testsuite/gas/loongarch/relax_align.s: New test.
	* testsuite/gas/loongarch/uleb128.d: New test.
	* testsuite/gas/loongarch/uleb128.s: New test.
---
 gas/config/tc-loongarch.c                     | 412 +++++++++++++++---
 gas/config/tc-loongarch.h                     |  45 +-
 gas/testsuite/gas/all/align.d                 |   5 +-
 gas/testsuite/gas/all/gas.exp                 |  10 +-
 gas/testsuite/gas/all/relax.d                 |   4 +
 gas/testsuite/gas/elf/dwarf-5-irp.d           |   3 +-
 gas/testsuite/gas/elf/dwarf-5-loc0.d          |   3 +-
 gas/testsuite/gas/elf/dwarf2-11.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-15.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-16.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-17.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-18.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-19.d             |   3 +-
 gas/testsuite/gas/elf/dwarf2-5.d              |   3 +-
 gas/testsuite/gas/elf/ehopt0.d                |   3 +
 gas/testsuite/gas/elf/elf.exp                 |   3 +
 gas/testsuite/gas/elf/section11.d             |   4 +-
 gas/testsuite/gas/lns/lns.exp                 |   1 +
 gas/testsuite/gas/loongarch/jmp_op.d          |  65 ++-
 gas/testsuite/gas/loongarch/li.d              |   9 +-
 gas/testsuite/gas/loongarch/macro_op.d        |  69 +--
 .../gas/loongarch/macro_op_large_abs.d        | 103 +++--
 .../gas/loongarch/macro_op_large_pc.d         | 103 +++--
 gas/testsuite/gas/loongarch/relax_align.d     |  25 ++
 gas/testsuite/gas/loongarch/relax_align.s     |   5 +
 gas/testsuite/gas/loongarch/uleb128.d         |  35 ++
 gas/testsuite/gas/loongarch/uleb128.s         |  20 +
 27 files changed, 721 insertions(+), 227 deletions(-)
 create mode 100644 gas/testsuite/gas/loongarch/relax_align.d
 create mode 100644 gas/testsuite/gas/loongarch/relax_align.s
 create mode 100644 gas/testsuite/gas/loongarch/uleb128.d
 create mode 100644 gas/testsuite/gas/loongarch/uleb128.s

diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 60149a6d8db..10b79fb7894 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -20,6 +20,7 @@
    see <http://www.gnu.org/licenses/>.  */
 
 #include "as.h"
+#include "subsegs.h"
 #include "dw2gencfi.h"
 #include "loongarch-lex.h"
 #include "elf/loongarch.h"
@@ -30,6 +31,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <assert.h>
+#include "libbfd.h"
 
 /* All information about an instruction during assemble.  */
 struct loongarch_cl_insn
@@ -70,6 +72,7 @@ struct loongarch_cl_insn
   long where;
   /* The relocs associated with the instruction, if any.  */
   fixS *fixp[MAX_RELOC_NUMBER_A_INSN];
+  long macro_id;
 };
 
 #ifndef DEFAULT_ARCH
@@ -116,6 +119,8 @@ enum options
   OPTION_LA_LOCAL_WITH_ABS,
   OPTION_LA_GLOBAL_WITH_PCREL,
   OPTION_LA_GLOBAL_WITH_ABS,
+  OPTION_RELAX,
+  OPTION_NO_RELAX,
 
   OPTION_END_OF_ENUM,
 };
@@ -130,6 +135,9 @@ struct option md_longopts[] =
   { "mla-global-with-pcrel", no_argument, NULL, OPTION_LA_GLOBAL_WITH_PCREL },
   { "mla-global-with-abs", no_argument, NULL, OPTION_LA_GLOBAL_WITH_ABS },
 
+  { "mrelax", no_argument, NULL, OPTION_RELAX },
+  { "mno-relax", no_argument, NULL, OPTION_NO_RELAX },
+
   { NULL, no_argument, NULL, 0 }
 };
 
@@ -195,6 +203,14 @@ md_parse_option (int c, const char *arg)
       LARCH_opts.ase_gabs = 1;
       break;
 
+    case OPTION_RELAX:
+      LARCH_opts.relax = 1;
+      break;
+
+    case OPTION_NO_RELAX:
+      LARCH_opts.relax = 0;
+      break;
+
     case OPTION_IGNORE:
       break;
 
@@ -460,7 +476,6 @@ get_internal_label (expressionS *label_expr, unsigned long label,
 		    int augend /* 0 for previous, 1 for next.  */)
 {
   assert (label < INTERNAL_LABEL_SPECIAL);
-  if (augend == 0 && internal_label_count[label] == 0)
     as_fatal (_("internal error: we have no internal label yet"));
   label_expr->X_op = O_symbol;
   label_expr->X_add_symbol =
@@ -617,13 +632,26 @@ 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_RELAX)
+	      && ip->reloc_info[0].type < BFD_RELOC_LARCH_SUB_ULEB128)
 	    {
 	      /* As we compact stack-relocs, it is no need for pop operation.
 		 But break out until here in order to check the imm field.
 		 May be reloc_num > 1 if implement relax?  */
 	      ip->reloc_num += reloc_num;
+	      reloc_type = ip->reloc_info[0].type;
+
+	      if (LARCH_opts.relax && ip->macro_id
+		    && (BFD_RELOC_LARCH_PCALA_HI20 == reloc_type
+			|| BFD_RELOC_LARCH_PCALA_LO12 == reloc_type
+			|| BFD_RELOC_LARCH_GOT_PC_HI20 == reloc_type
+			|| BFD_RELOC_LARCH_GOT_PC_LO12 == 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++;
+		}
 	      break;
 	    }
 	  reloc_num++;
@@ -835,8 +863,11 @@ move_insn (struct loongarch_cl_insn *insn, fragS *frag, long where)
   insn->where = where;
   for (i = 0; i < insn->reloc_num; i++)
     {
-      insn->fixp[i]->fx_frag = frag;
-      insn->fixp[i]->fx_where = where;
+      if (insn->fixp[i])
+	{
+	  insn->fixp[i]->fx_frag = frag;
+	  insn->fixp[i]->fx_where = where;
+	}
     }
   install_insn (insn);
 }
@@ -875,6 +906,21 @@ append_fixp_and_insn (struct loongarch_cl_insn *ip)
     as_fatal (_("Internal error: not support relax now"));
   else
     append_fixed_insn (ip);
+
+  /* We need to start a new frag after any instruction that can be
+     optimized away or compressed by the linker during relaxation, to prevent
+     the assembler from computing static offsets across such an instruction.
+
+     This is necessary to get correct .eh_frame cfa info. If one cfa's two
+     symbol is not in the same frag, it will generate relocs to calculate
+     symbol subtraction. (gas/dw2gencfi.c:output_cfi_insn:
+     if (symbol_get_frag (to) == symbol_get_frag (from)))  */
+  if (BFD_RELOC_LARCH_PCALA_HI20 == reloc_info[0].type
+      || BFD_RELOC_LARCH_GOT_PC_HI20 == reloc_info[0].type)
+    {
+      frag_wane (frag_now);
+      frag_new (0);
+    }
 }
 
 /* Ask helper for returning a malloced c_str or NULL.  */
@@ -968,7 +1014,7 @@ assember_macro_helper (const char *const args[], void *context_ptr)
  * assuming 'not starting with space and not ending with space' or pass in
  * empty c_str.  */
 static void
-loongarch_assemble_INSNs (char *str)
+loongarch_assemble_INSNs (char *str, struct loongarch_cl_insn *ctx)
 {
   char *rest;
   size_t len_str = strlen(str);
@@ -991,6 +1037,7 @@ loongarch_assemble_INSNs (char *str)
 
       struct loongarch_cl_insn the_one = { 0 };
       the_one.name = str;
+      the_one.macro_id = ctx->macro_id;
 
       for (; *str && *str != ' '; str++)
 	;
@@ -1014,24 +1061,27 @@ loongarch_assemble_INSNs (char *str)
       append_fixp_and_insn (&the_one);
       if (the_one.insn_length == 0 && the_one.insn->macro)
 	{
+	  the_one.macro_id = 1;
+
 	  char *c_str = loongarch_expand_macro (the_one.insn->macro,
 						the_one.arg_strs,
 						assember_macro_helper,
 						&the_one, len_str);
-	  loongarch_assemble_INSNs (c_str);
+	  loongarch_assemble_INSNs (c_str, &the_one);
 	  free (c_str);
 	}
     }
   while (0);
 
   if (*rest != '\0')
-    loongarch_assemble_INSNs (rest);
+    loongarch_assemble_INSNs (rest, ctx);
 }
 
 void
 md_assemble (char *str)
 {
-  loongarch_assemble_INSNs (str);
+  struct loongarch_cl_insn the_one = { 0 };
+  loongarch_assemble_INSNs (str, &the_one);
 }
 
 const char *
@@ -1062,7 +1112,7 @@ static void fix_reloc_insn (fixS *fixP, bfd_vma reloc_val, char *buf)
 
   insn = bfd_getl32 (buf);
 
-  if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val))
+  if (!loongarch_adjust_reloc_bitsfield (NULL, howto, &reloc_val))
     as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
 
   insn = (insn & (insn_t)howto->src_mask)
@@ -1137,6 +1187,23 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
       fix_reloc_insn (fixP, (bfd_vma)stack_top, buf);
       break;
 
+    /* LARCH only has R_LARCH_64/32, not has R_LARCH_24/16/8.
+       For BFD_RELOC_64/32, if fx_addsy and fx_subsy not null, wer need
+       generate BFD_RELOC_LARCH_ADD64/32 and BFD_RELOC_LARCH_SUB64/32 here.
+       Then will parse howto table bfd_reloc_code_real_type to generate
+       R_LARCH_ADD64/32 and R_LARCH_SUB64/32 reloc at tc_gen_reloc function.
+       If only fx_addsy not null, skip here directly, then generate
+       R_LARCH_64/32.
+
+       For BFD_RELOC_24/16/8, if fx_addsy and fx_subsy not null, wer need
+       generate BFD_RELOC_LARCH_ADD24/16/8 and BFD_RELOC_LARCH_SUB24/16/8 here.
+       Then will parse howto table bfd_reloc_code_real_type to generate
+       R_LARCH_ADD24/16/8 and R_LARCH_SUB24/16/8 reloc at tc_gen_reloc
+       function. If only fx_addsy not null, we generate
+       BFD_RELOC_LARCH_ADD24/16/8 only, then generate R_LARCH_24/16/8.
+       To avoid R_LARCH_ADDxx add extra value, we write 0 first
+       (use md_number_to_chars (buf, 0, fixP->fx_size)).
+    */
     case BFD_RELOC_64:
     case BFD_RELOC_32:
       if (fixP->fx_r_type == BFD_RELOC_32
@@ -1151,7 +1218,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 	  break;
 	}
 
-      if (fixP->fx_subsy)
+      if (fixP->fx_addsy && fixP->fx_subsy)
 	{
 	  fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
 	  fixP->fx_next->fx_addsy = fixP->fx_subsy;
@@ -1186,34 +1253,37 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_24:
     case BFD_RELOC_16:
     case BFD_RELOC_8:
-      fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
-      fixP->fx_next->fx_addsy = fixP->fx_subsy;
-      fixP->fx_next->fx_subsy = NULL;
-      fixP->fx_next->fx_offset = 0;
-      fixP->fx_subsy = NULL;
-
-      switch (fixP->fx_r_type)
+      if (fixP->fx_addsy)
 	{
-	case BFD_RELOC_24:
-	  fixP->fx_r_type = BFD_RELOC_LARCH_ADD24;
-	  fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24;
-	  break;
-	case BFD_RELOC_16:
-	  fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
-	  fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
-	  break;
-	case BFD_RELOC_8:
-	  fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
-	  fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
-	  break;
-	default:
-	  break;
-	}
+	  fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
+	  fixP->fx_next->fx_addsy = fixP->fx_subsy;
+	  fixP->fx_next->fx_subsy = NULL;
+	  fixP->fx_next->fx_offset = 0;
+	  fixP->fx_subsy = NULL;
+
+	  switch (fixP->fx_r_type)
+	    {
+	    case BFD_RELOC_24:
+	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD24;
+	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24;
+	      break;
+	    case BFD_RELOC_16:
+	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
+	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
+	      break;
+	    case BFD_RELOC_8:
+	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
+	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
+	      break;
+	    default:
+	      break;
+	    }
 
-      md_number_to_chars (buf, 0, fixP->fx_size);
+	  md_number_to_chars (buf, 0, fixP->fx_size);
 
-      if (fixP->fx_next->fx_addsy == NULL)
-	fixP->fx_next->fx_done = 1;
+	  if (fixP->fx_next->fx_addsy == NULL)
+	    fixP->fx_next->fx_done = 1;
+	}
 
       if (fixP->fx_addsy == NULL)
 	{
@@ -1222,6 +1292,67 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 	}
       break;
 
+    case BFD_RELOC_LARCH_CFA:
+      if (fixP->fx_addsy && fixP->fx_subsy)
+	{
+	  fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP));
+	  fixP->fx_next->fx_addsy = fixP->fx_subsy;
+	  fixP->fx_next->fx_subsy = NULL;
+	  fixP->fx_next->fx_offset = 0;
+	  fixP->fx_subsy = NULL;
+
+	  unsigned int subtype;
+	  offsetT loc;
+	  subtype = bfd_get_8 (NULL, &((fragS *)
+		      (fixP->fx_frag->fr_opcode))->fr_literal[fixP->fx_where]);
+	  loc = fixP->fx_frag->fr_fix - (subtype & 7);
+	  switch (subtype)
+	    {
+	    case DW_CFA_advance_loc1:
+	      fixP->fx_where = loc + 1;
+	      fixP->fx_next->fx_where = loc + 1;
+	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD8;
+	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8;
+	      md_number_to_chars (buf+1, 0, fixP->fx_size);
+	      break;
+
+	    case DW_CFA_advance_loc2:
+	      fixP->fx_size = 2;
+	      fixP->fx_next->fx_size = 2;
+	      fixP->fx_where = loc + 1;
+	      fixP->fx_next->fx_where = loc + 1;
+	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD16;
+	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16;
+	      md_number_to_chars (buf+1, 0, fixP->fx_size);
+	      break;
+
+	    case DW_CFA_advance_loc4:
+	      fixP->fx_size = 4;
+	      fixP->fx_next->fx_size = 4;
+	      fixP->fx_where = loc;
+	      fixP->fx_next->fx_where = loc;
+	      fixP->fx_r_type = BFD_RELOC_LARCH_ADD32;
+	      fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32;
+	      md_number_to_chars (buf+1, 0, fixP->fx_size);
+	      break;
+
+	    default:
+	      if (subtype < 0x80 && (subtype & 0x40))
+		{
+		  /* DW_CFA_advance_loc.  */
+		  fixP->fx_frag = (fragS *) fixP->fx_frag->fr_opcode;
+		  fixP->fx_next->fx_frag = fixP->fx_frag;
+		  fixP->fx_r_type = BFD_RELOC_LARCH_ADD6;
+		  fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB6;
+		  md_number_to_chars (buf, 0x40, fixP->fx_size);
+		  }
+	      else
+		as_fatal (_("internal: bad CFA value #%d"), subtype);
+	      break;
+	    }
+	}
+      break;
+
     case BFD_RELOC_LARCH_B16:
     case BFD_RELOC_LARCH_B21:
     case BFD_RELOC_LARCH_B26:
@@ -1236,11 +1367,28 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 	  int64_t sym_addend = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset;
 	  int64_t pc = fixP->fx_where + fixP->fx_frag->fr_address;
 	  fix_reloc_insn (fixP, sym_addend - pc, buf);
-	  fixP->fx_done = 1;
-	}
 
+	  /* If relax, symbol value may change at link time, so reloc need to
+	     be saved.  */
+	  if (!LARCH_opts.relax)
+	    fixP->fx_done = 1;
+	}
       break;
 
+    /* Because ADD_ULEB128/SUB_ULEB128 always occur in pairs.
+       So just deal with one is ok.
+    case BFD_RELOC_LARCH_ADD_ULEB128:  */
+    case BFD_RELOC_LARCH_SUB_ULEB128:
+      {
+	unsigned int len = 0;
+	_bfd_read_unsigned_leb128 (NULL, (bfd_byte *)buf, &len);
+	bfd_byte *endp = (bfd_byte*) buf + len -1;
+	/* Clean the uleb128 value to 0. Do not reduce the length.  */
+	memset (buf, 0x80, len - 1);
+	*endp = 0;
+	break;
+      }
+
     default:
       break;
     }
@@ -1258,19 +1406,7 @@ int
 md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
 			       asection *segtype ATTRIBUTE_UNUSED)
 {
-  return 0;
-}
-
-int
-loongarch_fix_adjustable (fixS *fix)
-{
-  /* Prevent all adjustments to global symbols.  */
-  if (S_IS_EXTERNAL (fix->fx_addsy)
-      || S_IS_WEAK (fix->fx_addsy)
-      || S_FORCE_RELOC (fix->fx_addsy, true))
-    return 0;
-
-  return 1;
+  return (fragp->fr_var = 4);
 }
 
 /* Translate internal representation of relocation info to BFD target
@@ -1300,9 +1436,25 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 /* Convert a machine dependent frag.  */
 void
 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
-		 fragS *fragp ATTRIBUTE_UNUSED)
+		 fragS *fragp)
 {
-  /* fragp->fr_fix += 8; */
+  expressionS exp;
+  exp.X_op = O_symbol;
+  exp.X_add_symbol = fragp->fr_symbol;
+  exp.X_add_number = fragp->fr_offset;
+  bfd_byte *buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
+
+  fixS *fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
+				4, &exp, false, fragp->fr_subtype);
+  buf += 4;
+
+  fixp->fx_file = fragp->fr_file;
+  fixp->fx_line = fragp->fr_line;
+  fragp->fr_fix += fragp->fr_var;
+
+  gas_assert (fragp->fr_next == NULL
+	      || (fragp->fr_next->fr_address - fragp->fr_address
+		  == fragp->fr_fix));
 }
 
 /* Standard calling conventions leave the CFA at SP on entry.  */
@@ -1312,6 +1464,48 @@ loongarch_cfi_frame_initial_instructions (void)
   cfi_add_CFA_def_cfa_register (3 /* $sp */);
 }
 
+void
+loongarch_pre_output_hook (void)
+{
+  const frchainS *frch;
+  segT s;
+
+  /* Save the current segment info.  */
+  segT seg = now_seg;
+  subsegT subseg = now_subseg;
+
+  for (s = stdoutput->sections; s; s = s->next)
+    for (frch = seg_info (s)->frchainP; frch; frch = frch->frch_next)
+      {
+	fragS *frag;
+
+	for (frag = frch->frch_root; frag; frag = frag->fr_next)
+	  {
+	    if (frag->fr_type == rs_cfa)
+	      {
+		expressionS exp;
+		expressionS *symval;
+
+		symval = symbol_get_value_expression (frag->fr_symbol);
+		exp.X_op = O_subtract;
+		exp.X_add_symbol = symval->X_add_symbol;
+		exp.X_add_number = 0;
+		exp.X_op_symbol = symval->X_op_symbol;
+
+		/* We must set the segment before creating a frag after all
+		   frag chains have been chained together.  */
+		subseg_set (s, frch->frch_subseg);
+
+		fix_new_exp (frag, (int) frag->fr_offset, 1, &exp, 0,
+			     BFD_RELOC_LARCH_CFA);
+	      }
+	  }
+      }
+
+  /* Restore the original segment info.  */
+  subseg_set (seg, subseg);
+}
+
 void
 tc_loongarch_parse_to_dw2regnum (expressionS *exp)
 {
@@ -1325,6 +1519,58 @@ md_show_usage (FILE *stream)
   /* FIXME */
 }
 
+static void
+loongarch_make_nops (char *buf, bfd_vma bytes)
+{
+  bfd_vma i = 0;
+
+  /* Fill with 4-byte NOPs.  */
+  for ( ; i < bytes; i += 4)
+    number_to_chars_littleendian (buf + i, LARCH_NOP, 4);
+}
+
+/* Called from md_do_align.  Used to create an alignment frag in a
+   code section by emitting a worst-case NOP sequence that the linker
+   will later relax to the correct number of NOPs.  We can't compute
+   the correct alignment now because of other linker relaxations.  */
+
+bool
+loongarch_frag_align_code (int n)
+{
+  bfd_vma bytes = (bfd_vma) 1 << n;
+  bfd_vma insn_alignment = 4;
+  bfd_vma worst_case_bytes = bytes - insn_alignment;
+  char *nops;
+  expressionS ex;
+
+  /* If we are moving to a smaller alignment than the instruction size, then no
+     alignment is required.  */
+  if (bytes <= insn_alignment)
+    return true;
+
+  /* When not relaxing, loongarch_handle_align handles code alignment.  */
+  if (!LARCH_opts.relax)
+    return false;
+
+  nops = frag_more (worst_case_bytes);
+
+  ex.X_op = O_constant;
+  ex.X_add_number = worst_case_bytes;
+
+  loongarch_make_nops (nops, worst_case_bytes);
+
+  fix_new_exp (frag_now, nops - frag_now->fr_literal, 0,
+	       &ex, false, BFD_RELOC_LARCH_ALIGN);
+
+  /* We need to start a new frag after the alignment which may be removed by
+     the linker, to prevent the assembler from computing static offsets.
+     This is necessary to get correct EH info.  */
+  frag_wane (frag_now);
+  frag_new (0);
+
+  return true;
+}
+
 /* Fill in an rs_align_code fragment.  We want to fill 'andi $r0,$r0,0'.  */
 void
 loongarch_handle_align (fragS *fragp)
@@ -1360,6 +1606,68 @@ loongarch_handle_align (fragS *fragp)
   fragp->fr_var = size;
 }
 
+/* Scan uleb128 subtraction expressions and insert fixups for them.
+   e.g., .uleb128 .L1 - .L0
+   Because relaxation may change the value of the subtraction, we
+   must resolve them at link-time.  */
+
+static void
+loongarch_insert_uleb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
+		      asection *sec, void *xxx ATTRIBUTE_UNUSED)
+{
+  segment_info_type *seginfo = seg_info (sec);
+  struct frag *fragP;
+
+  subseg_set (sec, 0);
+
+  for (fragP = seginfo->frchainP->frch_root;
+       fragP; fragP = fragP->fr_next)
+    {
+      expressionS *exp, *exp_dup;
+
+      if (fragP->fr_type != rs_leb128  || fragP->fr_symbol == NULL)
+	continue;
+
+      exp = symbol_get_value_expression (fragP->fr_symbol);
+
+      if (exp->X_op != O_subtract)
+	continue;
+
+      /* FIXME: Skip for .sleb128.  */
+      if (fragP->fr_subtype != 0)
+	continue;
+
+      exp_dup = xmemdup (exp, sizeof (*exp), sizeof (*exp));
+      exp_dup->X_op = O_symbol;
+      exp_dup->X_op_symbol = NULL;
+
+      exp_dup->X_add_symbol = exp->X_add_symbol;
+      fix_new_exp (fragP, fragP->fr_fix, 0,
+		   exp_dup, 0, BFD_RELOC_LARCH_ADD_ULEB128);
+
+      /* From binutils/testsuite/binutils-all/dw5.S
+	 section .debug_rnglists
+	 .uleb128 .Letext0-.Ltext0    Range length (*.LLRL2)
+    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
+0000000000000015  0000000200000079 R_LARCH_ADD_ULEB128    0000000000000000 .text + 2
+0000000000000015  000000020000007a R_LARCH_SUB_ULEB128    0000000000000000 .text + 0.  */
+
+      /* Only the ADD_ULEB128 has X_add_number (Addend)?  */
+      exp_dup->X_add_number = 0;
+      exp_dup->X_add_symbol = exp->X_op_symbol;
+      fix_new_exp (fragP, fragP->fr_fix, 0,
+		   exp_dup, 0, BFD_RELOC_LARCH_SUB_ULEB128);
+    }
+}
+
+void
+loongarch_md_finish (void)
+{
+  /* Insert relocations for uleb128 directives, so the values can be recomputed
+     at link time.  */
+  bfd_map_over_sections (stdoutput, loongarch_insert_uleb128_fixes, NULL);
+}
+
 void
 loongarch_elf_final_processing (void)
 {
diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h
index 7d416b0c01b..c6e0b4af2d5 100644
--- a/gas/config/tc-loongarch.h
+++ b/gas/config/tc-loongarch.h
@@ -30,6 +30,8 @@ extern unsigned long loongarch_mach (void);
 #define WORKING_DOT_WORD 1
 #define REPEAT_CONS_EXPRESSIONS
 
+#define md_allow_local_subtract(l,r,s) 0
+
 /* Early than md_begin.  */
 #define md_after_parse_args loongarch_after_parse_args
 extern void loongarch_after_parse_args (void);
@@ -47,16 +49,40 @@ extern int loongarch_relax_frag (asection *, struct frag *, long);
 #define md_undefined_symbol(name) (0)
 #define md_operand(x)
 
+extern bool loongarch_frag_align_code (int);
+#define md_do_align(N, FILL, LEN, MAX, LABEL)				\
+  if ((N) != 0 && !(FILL) && !need_pass_2 && subseg_text_p (now_seg))	\
+    {									\
+      if (loongarch_frag_align_code (N))				\
+	goto LABEL;							\
+    }
+
 /* This is called to see whether a reloc against a defined symbol
-   should be converted into a reloc against a section.  */
-extern int loongarch_fix_adjustable (struct fix *fix);
-#define tc_fix_adjustable(fixp) loongarch_fix_adjustable(fixp)
+   should be converted into a reloc against a section.
+   Let the linker resolve all the relocs due to relaxation.  */
+#define tc_fix_adjustable(fixp) 0
 
 /* Values passed to md_apply_fix don't include symbol values.  */
 #define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) 1
 #define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
 #define DIFF_EXPR_OK 1
 
+#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEC)	\
+  (GENERIC_FORCE_RELOCATION_SUB_SAME (FIX, SEC)	\
+   || ((SEC)->flags & SEC_CODE) != 0		\
+   || ((SEC)->flags & SEC_DEBUGGING) != 0	\
+   || TC_FORCE_RELOCATION (FIX))
+
+#define TC_LINKRELAX_FIXUP(seg) ((seg->flags & SEC_CODE)  \
+				    || (seg->flags & SEC_DEBUGGING))
+
+#define TC_FORCE_RELOCATION_LOCAL(FIX) 1
+
+/* Adjust debug_line after relaxation.  */
+#define DWARF2_USE_FIXED_ADVANCE_PC 1
+
+#define MD_APPLY_SYM_VALUE(FIX) 0
+
 #define TARGET_USE_CFIPOP 1
 #define DWARF2_DEFAULT_RETURN_COLUMN 1 /* $ra.  */
 #define DWARF2_CIE_DATA_ALIGNMENT -4
@@ -65,13 +91,15 @@ extern int loongarch_fix_adjustable (struct fix *fix);
   loongarch_cfi_frame_initial_instructions
 extern void loongarch_cfi_frame_initial_instructions (void);
 
+#define tc_symbol_new_hook(sym) \
+  if (0 == strcmp (sym->bsym->name, FAKE_LABEL_NAME)) \
+    S_SET_OTHER (sym, STV_HIDDEN);
+
 #define tc_parse_to_dw2regnum tc_loongarch_parse_to_dw2regnum
 extern void tc_loongarch_parse_to_dw2regnum (expressionS *);
 
-/* A enumerated values to specific how to deal with align in '.text'.
-   Now we want to fill 'andi $r0,$r0,0x0'.
-   Here is the type 0, will fill andi insn later.  */
-#define NOP_OPCODE (0x00)
+extern void loongarch_pre_output_hook (void);
+#define md_pre_output_hook loongarch_pre_output_hook ()
 
 #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
 
@@ -90,4 +118,7 @@ struct reloc_info
   expressionS value;
 };
 
+#define md_finish loongarch_md_finish
+extern void loongarch_md_finish (void);
+
 #endif
diff --git a/gas/testsuite/gas/all/align.d b/gas/testsuite/gas/all/align.d
index c701f25bfcc..43c1413de04 100644
--- a/gas/testsuite/gas/all/align.d
+++ b/gas/testsuite/gas/all/align.d
@@ -3,8 +3,9 @@
 # The RX port will always replace zeros in any aligned area with NOPs,
 # even if the user requested that they filled with zeros.
 # RISC-V handles alignment via relaxation and therefor won't have object files
-# with the expected alignment.
-#notarget: riscv*-* rx-*
+# LoongArch handles alignment via relaxation and therefor won't have object
+# files with the expected alignment.
+#notarget: loongarch*-* riscv*-* rx-*
 
 # Test the alignment pseudo-op.
 
diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp
index 28570c53ac5..20010d9522c 100644
--- a/gas/testsuite/gas/all/gas.exp
+++ b/gas/testsuite/gas/all/gas.exp
@@ -67,14 +67,14 @@ if {    ![istarget alpha*-*-*vms*]
      && ![istarget ft32-*-*]
      && ![istarget hppa*-*-*]
      && ![istarget microblaze-*-*]
+     && ![istarget loongarch*-*-*]
      && ![istarget mn10300-*-*]
      && ![istarget msp430*-*-*]
      && ![istarget powerpc*-*-aix*]
      && ![istarget riscv*-*-*]
      && ![istarget rl78-*-*]
      && ![istarget rs6000*-*-aix*]
-     && ![istarget rx-*-*]
-     && ![istarget loongarch*-*-*] } then {
+     && ![istarget rx-*-*] } then {
     gas_test_error "diff1.s" "" "difference of two undefined symbols"
 }
 
@@ -165,11 +165,11 @@ switch -glob $target_triplet {
 	# These targets fail redef2 because they disallow redefined
 	# symbols on relocs.
 	setup_xfail "m68hc1*-*-*" "m6811-*-*" "m6812-*-*" "rl78-*-*"
-	setup_xfail "riscv*-*-*" "rx-*-*" "vax*-*-*" "xgate*-*-*" "z8k-*-*"
+	setup_xfail "loongarch*-*-*" "riscv*-*-*" "rx-*-*" "vax*-*-*" "xgate*-*-*" "z8k-*-*"
 	setup_xfail "avr-*-*"
 	run_dump_test redef2
 	setup_xfail "m68hc1*-*-*" "m6811-*-*" "m6812-*-*" "rl78-*-*"
-	setup_xfail "riscv*-*-*" "rx-*-*" "vax*-*-*" "xgate*-*-*" "z8k-*-*"
+	setup_xfail "loongarch*-*-*" "riscv*-*-*" "rx-*-*" "vax*-*-*" "xgate*-*-*" "z8k-*-*"
 	setup_xfail "avr-*-*"
 	# rs6000-aix disallows redefinition via .comm.
 	if [is_xcoff_format] {
@@ -281,7 +281,7 @@ if {    ![istarget *c30*-*-*]
     # The vax fails because VMS can apparently actually handle this
     # case in relocs, so gas doesn't handle it itself.
     # msp430, mn10[23]00 and riscv emit two relocs to handle the difference of two symbols.
-    setup_xfail "am3*-*-*" "mn10200-*-*" "mn10300*-*-*" "msp430*-*-*" "riscv*-*-*" "vax*-*-vms*"
+    setup_xfail "am3*-*-*" "loongarch*-*-*" "mn10200-*-*" "mn10300*-*-*" "msp430*-*-*" "riscv*-*-*" "vax*-*-vms*"
     do_930509a
 }
 
diff --git a/gas/testsuite/gas/all/relax.d b/gas/testsuite/gas/all/relax.d
index f394043b017..00fba6d62cd 100644
--- a/gas/testsuite/gas/all/relax.d
+++ b/gas/testsuite/gas/all/relax.d
@@ -4,6 +4,10 @@
 # because symbol values are not known until after linker relaxation has been
 # performed.
 #notarget : riscv*-*-*
+# LoongArch doesn't resolve .uleb operands that are the difference of two
+# symbols because gas write zero to object file and generate add_uleb128 and
+# sub_uleb128 reloc pair.
+#xfail: loongarch*-*-*
 
 .*: .*
 
diff --git a/gas/testsuite/gas/elf/dwarf-5-irp.d b/gas/testsuite/gas/elf/dwarf-5-irp.d
index 048a6d5a87a..6bcdc6636a6 100644
--- a/gas/testsuite/gas/elf/dwarf-5-irp.d
+++ b/gas/testsuite/gas/elf/dwarf-5-irp.d
@@ -5,7 +5,8 @@
 # The bfin target does not allow .subsection with an equated symbol as operand.
 # The d30v target emits sufficiently different debug info, apparently also covering padding it inserts.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am33*-* bfin-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+# The loongarch targets do not support the subtraction of symbols.
+#xfail: am33*-* bfin-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Raw dump of debug contents .*
 #...
diff --git a/gas/testsuite/gas/elf/dwarf-5-loc0.d b/gas/testsuite/gas/elf/dwarf-5-loc0.d
index 7e8473a486f..e58025bba62 100644
--- a/gas/testsuite/gas/elf/dwarf-5-loc0.d
+++ b/gas/testsuite/gas/elf/dwarf-5-loc0.d
@@ -3,7 +3,8 @@
 #name: DWARF5 .loc 0
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+# The loongarch targets do not support the subtraction of symbols.
+#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Contents of the \.debug_line section:
 
diff --git a/gas/testsuite/gas/elf/dwarf2-11.d b/gas/testsuite/gas/elf/dwarf2-11.d
index 2c30e55c695..44f5cd18ec6 100644
--- a/gas/testsuite/gas/elf/dwarf2-11.d
+++ b/gas/testsuite/gas/elf/dwarf2-11.d
@@ -3,7 +3,8 @@
 #name: DWARF2 11
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+# The loongarch targets do not support the subtraction of symbols.
+#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Contents of the \.debug_line section:
 
diff --git a/gas/testsuite/gas/elf/dwarf2-15.d b/gas/testsuite/gas/elf/dwarf2-15.d
index 939c61598cb..3ec9f2785a7 100644
--- a/gas/testsuite/gas/elf/dwarf2-15.d
+++ b/gas/testsuite/gas/elf/dwarf2-15.d
@@ -3,7 +3,8 @@
 #name: DWARF2 15
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+# The loongarch targets do not support the subtraction of symbols.
+#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 01 *.*
diff --git a/gas/testsuite/gas/elf/dwarf2-16.d b/gas/testsuite/gas/elf/dwarf2-16.d
index 8e35d493619..32b57763137 100644
--- a/gas/testsuite/gas/elf/dwarf2-16.d
+++ b/gas/testsuite/gas/elf/dwarf2-16.d
@@ -4,7 +4,8 @@
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The mep target tries to relay code sections which breaks symbolic view computations.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+# The loongarch targets do not support the subtraction of symbols.
+#xfail: am3*-* cr16-* crx-* ft32*-* mep-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 01 *.*
diff --git a/gas/testsuite/gas/elf/dwarf2-17.d b/gas/testsuite/gas/elf/dwarf2-17.d
index 881477cf95b..4c2f2e3999e 100644
--- a/gas/testsuite/gas/elf/dwarf2-17.d
+++ b/gas/testsuite/gas/elf/dwarf2-17.d
@@ -4,7 +4,8 @@
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The mep target tries to relay code sections which breaks symbolic view computations.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+# The loongarch targets do not support the subtraction of symbols.
+#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 00 *.*
diff --git a/gas/testsuite/gas/elf/dwarf2-18.d b/gas/testsuite/gas/elf/dwarf2-18.d
index fbaebaa9019..18157c634a5 100644
--- a/gas/testsuite/gas/elf/dwarf2-18.d
+++ b/gas/testsuite/gas/elf/dwarf2-18.d
@@ -3,7 +3,8 @@
 #name: DWARF2 18
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+# The loongarch targets do not support the subtraction of symbols.
+#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 0100 *.*
diff --git a/gas/testsuite/gas/elf/dwarf2-19.d b/gas/testsuite/gas/elf/dwarf2-19.d
index 55d0caf4cb1..133294affe7 100644
--- a/gas/testsuite/gas/elf/dwarf2-19.d
+++ b/gas/testsuite/gas/elf/dwarf2-19.d
@@ -4,7 +4,8 @@
 # The am33 cr16 crx ft32 mn10 msp430 nds32 and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # The mep targets turns some view computations into complex relocations.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+# The loongarch targets do not support the subtraction of symbols.
+#xfail: am3*-* cr16-* crx-* ft32*-* mep-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Hex dump of section '\.rodata':
   0x00000000 01000102 *.*
diff --git a/gas/testsuite/gas/elf/dwarf2-5.d b/gas/testsuite/gas/elf/dwarf2-5.d
index ced12e7c0c7..886f1a13389 100644
--- a/gas/testsuite/gas/elf/dwarf2-5.d
+++ b/gas/testsuite/gas/elf/dwarf2-5.d
@@ -4,7 +4,8 @@
 # The am33 cr16 crx ft32 mn10 msp430 nds32 rl78 and rx targets do not evaluate the subtraction of symbols at assembly time.
 # The mep target tries to relay code sections which breaks symbolic view computations.
 # The riscv targets do not support the subtraction of symbols.
-#xfail: am3*-* cr16-* crx-* ft32*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-* rx-*
+# The loongarch targets do not support the subtraction of symbols.
+#xfail: am3*-* cr16-* crx-* ft32*-* loongarch*-* mep-* mn10*-* msp430-* nds32*-* riscv*-* rl78-* rx-*
 
 Hex dump of section '\.rodata':
   0x00000000 01010201 010203 *.*
diff --git a/gas/testsuite/gas/elf/ehopt0.d b/gas/testsuite/gas/elf/ehopt0.d
index a13c4f26e33..64c5fb5ddc4 100644
--- a/gas/testsuite/gas/elf/ehopt0.d
+++ b/gas/testsuite/gas/elf/ehopt0.d
@@ -1,5 +1,8 @@
 #objdump: -s -j .eh_frame
 #name: elf ehopt0 
+# The loongarch target do not evaluate .eh_frame fde cfa advance loc at assembly time.
+# Because loongarch use add/sub reloc evaluate cfa advance loc, so gas should write 0 to cfa advance loc address.
+#xfail: loongarch*-*
 
 .*: +file format .*
 
diff --git a/gas/testsuite/gas/elf/elf.exp b/gas/testsuite/gas/elf/elf.exp
index 07f08a00a28..7873eb39ab1 100644
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -72,6 +72,9 @@ if { [is_elf_format] } then {
     if {[istarget "csky*-*-*"]} {
 	set target_machine -csky
     }
+    if {[istarget "loongarch*-*-*"]} then {
+	set dump_opts {{as -mno-relax}}
+    }
     if {[istarget "m32r*-*-*"]} then {
 	set target_machine -m32r
     }
diff --git a/gas/testsuite/gas/elf/section11.d b/gas/testsuite/gas/elf/section11.d
index 427aea67032..277fa6df7d6 100644
--- a/gas/testsuite/gas/elf/section11.d
+++ b/gas/testsuite/gas/elf/section11.d
@@ -2,8 +2,8 @@
 #readelf: -S --wide
 #name: Disabling section padding
 # The RX port uses non standard section names.
-#xfail: rx-*-*
-# RISC-V handles alignment via linker relaxation, so object files don't have
+#xfail: loongarch*-* rx-*-*
+# LoongArch and RISC-V handles alignment via linker relaxation, so object files don't have
 # the expected alignment.
 #xfail: riscv*-*-*
 
diff --git a/gas/testsuite/gas/lns/lns.exp b/gas/testsuite/gas/lns/lns.exp
index 046b50d5729..1d672102743 100644
--- a/gas/testsuite/gas/lns/lns.exp
+++ b/gas/testsuite/gas/lns/lns.exp
@@ -31,6 +31,7 @@ if { ![istarget s390*-*-*] } {
 	 || [istarget cr16-*-*]
 	 || [istarget crx-*-*]
 	 || [istarget ft32*-*]
+	 || [istarget loongarch*-*-*]
 	 || [istarget mn10*-*-*]
 	 || [istarget msp430-*-*]
 	 || [istarget nds32*-*-*]
diff --git a/gas/testsuite/gas/loongarch/jmp_op.d b/gas/testsuite/gas/loongarch/jmp_op.d
index 218c13f9398..a4535c297c9 100644
--- a/gas/testsuite/gas/loongarch/jmp_op.d
+++ b/gas/testsuite/gas/loongarch/jmp_op.d
@@ -6,26 +6,45 @@
 
 Disassembly of section .text:
 
-00000000.* <.text>:
-[ 	]+0:[ 	]+03400000[ 	]+[ 	]+andi[ 	]+\$zero, \$zero, 0x0
-[ 	]+4:[ 	]+63fffc04[ 	]+[ 	]+blt[ 	]+\$zero, \$a0, -4\(0x3fffc\)[ 	]+# 0x0
-[ 	]+8:[ 	]+67fff880[ 	]+[ 	]+bge[ 	]+\$a0, \$zero, -8\(0x3fff8\)[ 	]+# 0x0
-[ 	]+c:[ 	]+67fff404[ 	]+[ 	]+bge[ 	]+\$zero, \$a0, -12\(0x3fff4\)[ 	]+# 0x0
-[ 	]+10:[ 	]+43fff09f[ 	]+[ 	]+beqz[ 	]+\$a0, -16\(0x7ffff0\)[ 	]+# 0x0
-[ 	]+14:[ 	]+47ffec9f[ 	]+[ 	]+bnez[ 	]+\$a0, -20\(0x7fffec\)[ 	]+# 0x0
-[ 	]+18:[ 	]+4bffe81f[ 	]+[ 	]+bceqz[ 	]+\$fcc0, -24\(0x7fffe8\)[ 	]+# 0x0
-[ 	]+1c:[ 	]+4bffe51f[ 	]+[ 	]+bcnez[ 	]+\$fcc0, -28\(0x7fffe4\)[ 	]+# 0x0
-[ 	]+20:[ 	]+4c000080[ 	]+[ 	]+jirl[ 	]+\$zero, \$a0, 0
-[ 	]+24:[ 	]+53ffdfff[ 	]+[ 	]+b[ 	]+-36\(0xfffffdc\)[ 	]+# 0x0
-[ 	]+28:[ 	]+57ffdbff[ 	]+[ 	]+bl[ 	]+-40\(0xfffffd8\)[ 	]+# 0x0
-[ 	]+2c:[ 	]+5bffd485[ 	]+[ 	]+beq[ 	]+\$a0, \$a1, -44\(0x3ffd4\)[ 	]+# 0x0
-[ 	]+30:[ 	]+5fffd085[ 	]+[ 	]+bne[ 	]+\$a0, \$a1, -48\(0x3ffd0\)[ 	]+# 0x0
-[ 	]+34:[ 	]+63ffcc85[ 	]+[ 	]+blt[ 	]+\$a0, \$a1, -52\(0x3ffcc\)[ 	]+# 0x0
-[ 	]+38:[ 	]+63ffc8a4[ 	]+[ 	]+blt[ 	]+\$a1, \$a0, -56\(0x3ffc8\)[ 	]+# 0x0
-[ 	]+3c:[ 	]+67ffc485[ 	]+[ 	]+bge[ 	]+\$a0, \$a1, -60\(0x3ffc4\)[ 	]+# 0x0
-[ 	]+40:[ 	]+67ffc0a4[ 	]+[ 	]+bge[ 	]+\$a1, \$a0, -64\(0x3ffc0\)[ 	]+# 0x0
-[ 	]+44:[ 	]+6bffbc85[ 	]+[ 	]+bltu[ 	]+\$a0, \$a1, -68\(0x3ffbc\)[ 	]+# 0x0
-[ 	]+48:[ 	]+6bffb8a4[ 	]+[ 	]+bltu[ 	]+\$a1, \$a0, -72\(0x3ffb8\)[ 	]+# 0x0
-[ 	]+4c:[ 	]+6fffb485[ 	]+[ 	]+bgeu[ 	]+\$a0, \$a1, -76\(0x3ffb4\)[ 	]+# 0x0
-[ 	]+50:[ 	]+6fffb0a4[ 	]+[ 	]+bgeu[ 	]+\$a1, \$a0, -80\(0x3ffb0\)[ 	]+# 0x0
-[ 	]+54:[ 	]+4c000020[ 	]+[ 	]+jirl[ 	]+\$zero, \$ra, 0
+00000000.* <.L1>:
+[ 	]+0:[ 	]+03400000[ 	]+andi[ 	]+\$zero,[ 	]+\$zero,[ 	]+0x0
+[ 	]+4:[ 	]+63fffc04[ 	]+blt[ 	]+\$zero,[ 	]+\$a0,[ 	]+-4\(0x3fffc\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+4:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+8:[ 	]+67fff880[ 	]+bge[ 	]+\$a0,[ 	]+\$zero,[ 	]+-8\(0x3fff8\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+8:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+c:[ 	]+67fff404[ 	]+bge[ 	]+\$zero,[ 	]+\$a0,[ 	]+-12\(0x3fff4\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+c:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+10:[ 	]+43fff09f[ 	]+beqz[ 	]+\$a0,[ 	]+-16\(0x7ffff0\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+10:[ 	]+R_LARCH_B21[ 	]+\.L1
+[ 	]+14:[ 	]+47ffec9f[ 	]+bnez[ 	]+\$a0,[ 	]+-20\(0x7fffec\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+14:[ 	]+R_LARCH_B21[ 	]+\.L1
+[ 	]+18:[ 	]+4bffe81f[ 	]+bceqz[ 	]+\$fcc0,[ 	]+-24\(0x7fffe8\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+18:[ 	]+R_LARCH_B21[ 	]+\.L1
+[ 	]+1c:[ 	]+4bffe51f[ 	]+bcnez[ 	]+\$fcc0,[ 	]+-28\(0x7fffe4\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+1c:[ 	]+R_LARCH_B21[ 	]+\.L1
+[ 	]+20:[ 	]+4c000080[ 	]+jirl[ 	]+\$zero,[ 	]+\$a0,[ 	]+0
+[ 	]+24:[ 	]+53ffdfff[ 	]+b[ 	]+-36\(0xfffffdc\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+24:[ 	]+R_LARCH_B26[ 	]+\.L1
+[ 	]+28:[ 	]+57ffdbff[ 	]+bl[ 	]+-40\(0xfffffd8\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+28:[ 	]+R_LARCH_B26[ 	]+\.L1
+[ 	]+2c:[ 	]+5bffd485[ 	]+beq[ 	]+\$a0,[ 	]+\$a1,[ 	]+-44\(0x3ffd4\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+2c:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+30:[ 	]+5fffd085[ 	]+bne[ 	]+\$a0,[ 	]+\$a1,[ 	]+-48\(0x3ffd0\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+30:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+34:[ 	]+63ffcc85[ 	]+blt[ 	]+\$a0,[ 	]+\$a1,[ 	]+-52\(0x3ffcc\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+34:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+38:[ 	]+63ffc8a4[ 	]+blt[ 	]+\$a1,[ 	]+\$a0,[ 	]+-56\(0x3ffc8\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+38:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+3c:[ 	]+67ffc485[ 	]+bge[ 	]+\$a0,[ 	]+\$a1,[ 	]+-60\(0x3ffc4\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+3c:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+40:[ 	]+67ffc0a4[ 	]+bge[ 	]+\$a1,[ 	]+\$a0,[ 	]+-64\(0x3ffc0\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+40:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+44:[ 	]+6bffbc85[ 	]+bltu[ 	]+\$a0,[ 	]+\$a1,[ 	]+-68\(0x3ffbc\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+44:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+48:[ 	]+6bffb8a4[ 	]+bltu[ 	]+\$a1,[ 	]+\$a0,[ 	]+-72\(0x3ffb8\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+48:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+4c:[ 	]+6fffb485[ 	]+bgeu[ 	]+\$a0,[ 	]+\$a1,[ 	]+-76\(0x3ffb4\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+4c:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+50:[ 	]+6fffb0a4[ 	]+bgeu[ 	]+\$a1,[ 	]+\$a0,[ 	]+-80\(0x3ffb0\)[ 	]+#[ 	]+0[ 	]+<\.L1>
+[ 	]+50:[ 	]+R_LARCH_B16[ 	]+\.L1
+[ 	]+54:[ 	]+4c000020[ 	]+jirl[ 	]+\$zero,[ 	]+\$ra,[ 	]+0
diff --git a/gas/testsuite/gas/loongarch/li.d b/gas/testsuite/gas/loongarch/li.d
index 850a3f48e30..324130ccc74 100644
--- a/gas/testsuite/gas/loongarch/li.d
+++ b/gas/testsuite/gas/loongarch/li.d
@@ -1,6 +1,5 @@
 #as:
 #objdump: -dr
-#skip: loongarch32-*-*
 
 .*:[    ]+file format .*
 
@@ -10,9 +9,11 @@ Disassembly of section .text:
 00000000.* <_start>:
 [ 	]+0:[ 	]+03803c06[ 	]+ori[ 	]+\$a2,[ 	]+\$zero,[ 	]+0xf
 [ 	]+4:[ 	]+1a000005[ 	]+pcalau12i[ 	]+\$a1,[ 	]+0
-[ 	]+4:[ 	]+R_LARCH_PCALA_HI20[ 	]+.rodata
-[ 	]+8:[ 	]+02c000a5[ 	]+addi.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+8:[ 	]+R_LARCH_PCALA_LO12[ 	]+.rodata
+[ 	]+4:[ 	]+R_LARCH_PCALA_HI20[ 	]+msg
+[ 	]+4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+8:[ 	]+02c000a5[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+8:[ 	]+R_LARCH_PCALA_LO12[ 	]+msg
+[ 	]+8:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+c:[ 	]+03800404[ 	]+ori[ 	]+\$a0,[ 	]+\$zero,[ 	]+0x1
 [ 	]+10:[ 	]+0381000b[ 	]+ori[ 	]+\$a7,[ 	]+\$zero,[ 	]+0x40
 [ 	]+14:[ 	]+002b0000[ 	]+syscall[ 	]+0x0
diff --git a/gas/testsuite/gas/loongarch/macro_op.d b/gas/testsuite/gas/loongarch/macro_op.d
index d264c4f25c5..450a38e479a 100644
--- a/gas/testsuite/gas/loongarch/macro_op.d
+++ b/gas/testsuite/gas/loongarch/macro_op.d
@@ -1,6 +1,5 @@
 #as:
 #objdump: -dr
-#skip: loongarch32-*-*
 
 .*:[    ]+file format .*
 
@@ -9,51 +8,63 @@ Disassembly of section .text:
 
 00000000.* <.text>:
 [ 	]+0:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
-[ 	]+4:[ 	]+02bffc04[ 	]+addi.w[ 	]+\$a0,[ 	]+\$zero,[ 	]+-1\(0xfff\)
+[ 	]+4:[ 	]+02bffc04[ 	]+addi\.w[ 	]+\$a0,[ 	]+\$zero,[ 	]+-1\(0xfff\)
 [ 	]+8:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
-[ 	]+c:[ 	]+02bffc04[ 	]+addi.w[ 	]+\$a0,[ 	]+\$zero,[ 	]+-1\(0xfff\)
+[ 	]+c:[ 	]+02bffc04[ 	]+addi\.w[ 	]+\$a0,[ 	]+\$zero,[ 	]+-1\(0xfff\)
 [ 	]+10:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+10:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
-[ 	]+14:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+14:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+10:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+\.L1
+[ 	]+10:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+14:[ 	]+28c00084[ 	]+ld\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+14:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+\.L1
+[ 	]+14:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+18:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+18:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
-[ 	]+1c:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+1c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+18:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+\.L1
+[ 	]+18:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+1c:[ 	]+28c00084[ 	]+ld\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+1c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+\.L1
+[ 	]+1c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+20:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+20:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
-[ 	]+24:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+24:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
-[ 	]+28:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
+[ 	]+20:[ 	]+R_LARCH_PCALA_HI20[ 	]+\.L1
+[ 	]+20:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+24:[ 	]+02c00084[ 	]+addi\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+24:[ 	]+R_LARCH_PCALA_LO12[ 	]+\.L1
+[ 	]+24:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+28:[ 	]+14000004[ 	]+lu12i\.w[ 	]+\$a0,[ 	]+0
 [ 	]+28:[ 	]+R_LARCH_MARK_LA[ 	]+\*ABS\*
-[ 	]+28:[ 	]+R_LARCH_ABS_HI20[ 	]+.L1
+[ 	]+28:[ 	]+R_LARCH_ABS_HI20[ 	]+\.L1
 [ 	]+2c:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
-[ 	]+2c:[ 	]+R_LARCH_ABS_LO12[ 	]+.L1
-[ 	]+30:[ 	]+16000004[ 	]+lu32i.d[ 	]+\$a0,[ 	]+0
-[ 	]+30:[ 	]+R_LARCH_ABS64_LO20[ 	]+.L1
-[ 	]+34:[ 	]+03000084[ 	]+lu52i.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+34:[ 	]+R_LARCH_ABS64_HI12[ 	]+.L1
+[ 	]+2c:[ 	]+R_LARCH_ABS_LO12[ 	]+\.L1
+[ 	]+30:[ 	]+16000004[ 	]+lu32i\.d[ 	]+\$a0,[ 	]+0
+[ 	]+30:[ 	]+R_LARCH_ABS64_LO20[ 	]+\.L1
+[ 	]+34:[ 	]+03000084[ 	]+lu52i\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+34:[ 	]+R_LARCH_ABS64_HI12[ 	]+\.L1
 [ 	]+38:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+38:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
-[ 	]+3c:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+3c:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+38:[ 	]+R_LARCH_PCALA_HI20[ 	]+\.L1
+[ 	]+38:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+3c:[ 	]+02c00084[ 	]+addi\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+3c:[ 	]+R_LARCH_PCALA_LO12[ 	]+\.L1
+[ 	]+3c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+40:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+40:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
-[ 	]+44:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+44:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
-[ 	]+48:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
+[ 	]+40:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+\.L1
+[ 	]+40:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+44:[ 	]+28c00084[ 	]+ld\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+44:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+\.L1
+[ 	]+44:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+48:[ 	]+14000004[ 	]+lu12i\.w[ 	]+\$a0,[ 	]+0
 [ 	]+48:[ 	]+R_LARCH_TLS_LE_HI20[ 	]+TLS1
 [ 	]+4c:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
 [ 	]+4c:[ 	]+R_LARCH_TLS_LE_LO12[ 	]+TLS1
 [ 	]+50:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+50:[ 	]+R_LARCH_TLS_IE_PC_HI20[ 	]+TLS1
-[ 	]+54:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+54:[ 	]+28c00084[ 	]+ld\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+54:[ 	]+R_LARCH_TLS_IE_PC_LO12[ 	]+TLS1
 [ 	]+58:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+58:[ 	]+R_LARCH_TLS_LD_PC_HI20[ 	]+TLS1
-[ 	]+5c:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+5c:[ 	]+02c00084[ 	]+addi\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+5c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+5c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+60:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+60:[ 	]+R_LARCH_TLS_GD_PC_HI20[ 	]+TLS1
-[ 	]+64:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+64:[ 	]+02c00084[ 	]+addi\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+64:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+64:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
diff --git a/gas/testsuite/gas/loongarch/macro_op_large_abs.d b/gas/testsuite/gas/loongarch/macro_op_large_abs.d
index c3214a859e6..892d0f88b88 100644
--- a/gas/testsuite/gas/loongarch/macro_op_large_abs.d
+++ b/gas/testsuite/gas/loongarch/macro_op_large_abs.d
@@ -1,77 +1,86 @@
 #as:
 #objdump: -dr
-#skip: loongarch32-*-*
 
 .*:[    ]+file format .*
 
 
 Disassembly of section .text:
 
-00000000.* <.text>:
+00000000.* <.L1>:
 [ 	]+0:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
-[ 	]+4:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
-[ 	]+8:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+8:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.text
-[ 	]+c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.text
-[ 	]+10:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+\.L1
+[ 	]+0:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+4:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+\.L1
+[ 	]+4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+8:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
+[ 	]+8:[ 	]+R_LARCH_PCALA64_LO20[ 	]+\.L1
+[ 	]+c:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+\.L1
+[ 	]+10:[ 	]+00109484[ 	]+add\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+14:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+14:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
-[ 	]+18:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+18:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
-[ 	]+1c:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+1c:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.text
-[ 	]+20:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+20:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.text
-[ 	]+24:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+14:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+\.L1
+[ 	]+14:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+18:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+18:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+\.L1
+[ 	]+18:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+1c:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
+[ 	]+1c:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+\.L1
+[ 	]+20:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+20:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+\.L1
+[ 	]+24:[ 	]+380c1484[ 	]+ldx\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+28:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+28:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
-[ 	]+2c:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+2c:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
-[ 	]+30:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+30:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.text
-[ 	]+34:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+34:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.text
-[ 	]+38:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+28:[ 	]+R_LARCH_PCALA_HI20[ 	]+\.L1
+[ 	]+28:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+2c:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+2c:[ 	]+R_LARCH_PCALA_LO12[ 	]+\.L1
+[ 	]+2c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+30:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
+[ 	]+30:[ 	]+R_LARCH_PCALA64_LO20[ 	]+\.L1
+[ 	]+34:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+34:[ 	]+R_LARCH_PCALA64_HI12[ 	]+\.L1
+[ 	]+38:[ 	]+00109484[ 	]+add\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+3c:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+3c:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
-[ 	]+40:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+40:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
-[ 	]+44:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+44:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.text
-[ 	]+48:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+48:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.text
-[ 	]+4c:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+50:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
+[ 	]+3c:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+\.L1
+[ 	]+3c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+40:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+40:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+\.L1
+[ 	]+40:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+44:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
+[ 	]+44:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+\.L1
+[ 	]+48:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+48:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+\.L1
+[ 	]+4c:[ 	]+380c1484[ 	]+ldx\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+50:[ 	]+14000004[ 	]+lu12i\.w[ 	]+\$a0,[ 	]+0
 [ 	]+50:[ 	]+R_LARCH_TLS_LE_HI20[ 	]+TLS1
 [ 	]+54:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
 [ 	]+54:[ 	]+R_LARCH_TLS_LE_LO12[ 	]+TLS1
 [ 	]+58:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+58:[ 	]+R_LARCH_TLS_IE_PC_HI20[ 	]+TLS1
-[ 	]+5c:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+5c:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+5c:[ 	]+R_LARCH_TLS_IE_PC_LO12[ 	]+TLS1
-[ 	]+60:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+60:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
 [ 	]+60:[ 	]+R_LARCH_TLS_IE64_PC_LO20[ 	]+TLS1
-[ 	]+64:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+64:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
 [ 	]+64:[ 	]+R_LARCH_TLS_IE64_PC_HI12[ 	]+TLS1
-[ 	]+68:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+68:[ 	]+380c1484[ 	]+ldx\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+6c:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+6c:[ 	]+R_LARCH_TLS_LD_PC_HI20[ 	]+TLS1
-[ 	]+70:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+70:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+70:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
-[ 	]+74:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+70:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+74:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
 [ 	]+74:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
-[ 	]+78:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+78:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
 [ 	]+78:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+TLS1
-[ 	]+7c:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+7c:[ 	]+00109484[ 	]+add\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+80:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+80:[ 	]+R_LARCH_TLS_GD_PC_HI20[ 	]+TLS1
-[ 	]+84:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+84:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+84:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
-[ 	]+88:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+84:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+88:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
 [ 	]+88:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
-[ 	]+8c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+8c:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
 [ 	]+8c:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+TLS1
-[ 	]+90:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+90:[ 	]+00109484[ 	]+add\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
diff --git a/gas/testsuite/gas/loongarch/macro_op_large_pc.d b/gas/testsuite/gas/loongarch/macro_op_large_pc.d
index c3214a859e6..892d0f88b88 100644
--- a/gas/testsuite/gas/loongarch/macro_op_large_pc.d
+++ b/gas/testsuite/gas/loongarch/macro_op_large_pc.d
@@ -1,77 +1,86 @@
 #as:
 #objdump: -dr
-#skip: loongarch32-*-*
 
 .*:[    ]+file format .*
 
 
 Disassembly of section .text:
 
-00000000.* <.text>:
+00000000.* <.L1>:
 [ 	]+0:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
-[ 	]+4:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
-[ 	]+8:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+8:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.text
-[ 	]+c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.text
-[ 	]+10:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+\.L1
+[ 	]+0:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+4:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+\.L1
+[ 	]+4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+8:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
+[ 	]+8:[ 	]+R_LARCH_PCALA64_LO20[ 	]+\.L1
+[ 	]+c:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+\.L1
+[ 	]+10:[ 	]+00109484[ 	]+add\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+14:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+14:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
-[ 	]+18:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+18:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
-[ 	]+1c:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+1c:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.text
-[ 	]+20:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+20:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.text
-[ 	]+24:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+14:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+\.L1
+[ 	]+14:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+18:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+18:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+\.L1
+[ 	]+18:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+1c:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
+[ 	]+1c:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+\.L1
+[ 	]+20:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+20:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+\.L1
+[ 	]+24:[ 	]+380c1484[ 	]+ldx\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+28:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+28:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
-[ 	]+2c:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+2c:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
-[ 	]+30:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+30:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.text
-[ 	]+34:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+34:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.text
-[ 	]+38:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+28:[ 	]+R_LARCH_PCALA_HI20[ 	]+\.L1
+[ 	]+28:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+2c:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+2c:[ 	]+R_LARCH_PCALA_LO12[ 	]+\.L1
+[ 	]+2c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+30:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
+[ 	]+30:[ 	]+R_LARCH_PCALA64_LO20[ 	]+\.L1
+[ 	]+34:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+34:[ 	]+R_LARCH_PCALA64_HI12[ 	]+\.L1
+[ 	]+38:[ 	]+00109484[ 	]+add\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+3c:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+3c:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
-[ 	]+40:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+40:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
-[ 	]+44:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+44:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.text
-[ 	]+48:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+48:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.text
-[ 	]+4c:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+50:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
+[ 	]+3c:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+\.L1
+[ 	]+3c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+40:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+40:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+\.L1
+[ 	]+40:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+44:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
+[ 	]+44:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+\.L1
+[ 	]+48:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+48:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+\.L1
+[ 	]+4c:[ 	]+380c1484[ 	]+ldx\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+50:[ 	]+14000004[ 	]+lu12i\.w[ 	]+\$a0,[ 	]+0
 [ 	]+50:[ 	]+R_LARCH_TLS_LE_HI20[ 	]+TLS1
 [ 	]+54:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
 [ 	]+54:[ 	]+R_LARCH_TLS_LE_LO12[ 	]+TLS1
 [ 	]+58:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+58:[ 	]+R_LARCH_TLS_IE_PC_HI20[ 	]+TLS1
-[ 	]+5c:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+5c:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+5c:[ 	]+R_LARCH_TLS_IE_PC_LO12[ 	]+TLS1
-[ 	]+60:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+60:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
 [ 	]+60:[ 	]+R_LARCH_TLS_IE64_PC_LO20[ 	]+TLS1
-[ 	]+64:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+64:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
 [ 	]+64:[ 	]+R_LARCH_TLS_IE64_PC_HI12[ 	]+TLS1
-[ 	]+68:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+68:[ 	]+380c1484[ 	]+ldx\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+6c:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+6c:[ 	]+R_LARCH_TLS_LD_PC_HI20[ 	]+TLS1
-[ 	]+70:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+70:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+70:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
-[ 	]+74:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+70:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+74:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
 [ 	]+74:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
-[ 	]+78:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+78:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
 [ 	]+78:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+TLS1
-[ 	]+7c:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+7c:[ 	]+00109484[ 	]+add\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+80:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+80:[ 	]+R_LARCH_TLS_GD_PC_HI20[ 	]+TLS1
-[ 	]+84:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+84:[ 	]+02c00005[ 	]+addi\.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+84:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
-[ 	]+88:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+84:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+88:[ 	]+16000005[ 	]+lu32i\.d[ 	]+\$a1,[ 	]+0
 [ 	]+88:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
-[ 	]+8c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+8c:[ 	]+030000a5[ 	]+lu52i\.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
 [ 	]+8c:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+TLS1
-[ 	]+90:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+90:[ 	]+00109484[ 	]+add\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
diff --git a/gas/testsuite/gas/loongarch/relax_align.d b/gas/testsuite/gas/loongarch/relax_align.d
new file mode 100644
index 00000000000..b9ea0827da9
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/relax_align.d
@@ -0,0 +1,25 @@
+#as:
+#objdump: -dr
+
+.*:[    ]+file format .*
+
+
+Disassembly of section .text:
+
+00000000.* <L1>:
+[ 	]+0:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
+[ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+L1
+[ 	]+0:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+4:[ 	]+02c00084[ 	]+addi\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+L1
+[ 	]+4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+8:[ 	]+03400000[ 	]+andi[ 	]+\$zero,[ 	]+\$zero,[ 	]+0x0
+[ 	]+8:[ 	]+R_LARCH_ALIGN[ 	]+\*ABS\*\+0xc
+[ 	]+c:[ 	]+03400000[ 	]+andi[ 	]+\$zero,[ 	]+\$zero,[ 	]+0x0
+[ 	]+10:[ 	]+03400000[ 	]+andi[ 	]+\$zero,[ 	]+\$zero,[ 	]+0x0
+[ 	]+14:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
+[ 	]+14:[ 	]+R_LARCH_PCALA_HI20[ 	]+L1
+[ 	]+14:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+18:[ 	]+02c00084[ 	]+addi\.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+18:[ 	]+R_LARCH_PCALA_LO12[ 	]+L1
+[ 	]+18:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
diff --git a/gas/testsuite/gas/loongarch/relax_align.s b/gas/testsuite/gas/loongarch/relax_align.s
new file mode 100644
index 00000000000..3880d783e79
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/relax_align.s
@@ -0,0 +1,5 @@
+  .text
+L1:
+  la.local $a0, L1
+  .align 4
+  la.local $a0, L1
diff --git a/gas/testsuite/gas/loongarch/uleb128.d b/gas/testsuite/gas/loongarch/uleb128.d
new file mode 100644
index 00000000000..790adf53e7f
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/uleb128.d
@@ -0,0 +1,35 @@
+#as:
+#objdump: -Dr
+
+.*:[    ]+file format .*
+
+
+Disassembly of section .data:
+
+00000000.* <L1-0x5>:
+[ 	]+0:[ 	]+80030201[ 	]+0x80030201
+[ 	]+3:[ 	]+R_LARCH_ADD_ULEB128[ 	]+L2
+[ 	]+3:[ 	]+R_LARCH_SUB_ULEB128[ 	]+L1
+[ 	]+\.\.\.
+
+0000000000000005[ 	]+<L1>:
+[ 	]+\.\.\.
+[ 	]+81:[ 	]+ff040000[ 	]+0xff040000
+[ 	]+85:[ 	]+cacop[ 	]+0x1f,[ 	]+\$t3,[ 	]+1\(0x1\)
+
+0000000000000086[ 	]+<L2>:
+[ 	]+86:[ 	]+07060005[ 	]+0x07060005
+[ 	]+8a:[ 	]+0x00008080
+[ 	]+8a:[ 	]+R_LARCH_ADD_ULEB128[ 	]+L4
+[ 	]+8a:[ 	]+R_LARCH_SUB_ULEB128[ 	]+L3
+
+000000000000008d[ 	]+<L3>:
+[ 	]+\.\.\.
+[ 	]+4089:[ 	]+ff080000[ 	]+0xff080000
+[ 	]+408d:[ 	]+0x09ffffff
+
+0000000000004090[ 	]+<L4>:
+[ 	]+4090:[ 	]+09090909[ 	]+0x09090909
+[ 	]+4094:[ 	]+09090909[ 	]+0x09090909
+[ 	]+4098:[ 	]+09090909[ 	]+0x09090909
+[ 	]+409c:[ 	]+09090909[ 	]+0x09090909
diff --git a/gas/testsuite/gas/loongarch/uleb128.s b/gas/testsuite/gas/loongarch/uleb128.s
new file mode 100644
index 00000000000..104a8956bd6
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/uleb128.s
@@ -0,0 +1,20 @@
+ .data
+ .byte 1, 2, 3
+ .uleb128 L2 - L1
+L1:
+ .space 128 - 2
+ .byte 4
+ .p2align 1, 0xff
+L2:
+ .byte 5
+
+ .p2align 2
+ .byte 6, 7
+ .uleb128 L4 - L3
+L3:
+ .space 128*128 - 2
+ .byte 8
+ .p2align 2, 0xff
+L4:
+ .byte 9
+ .p2align 4, 9
-- 
2.36.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v1 6/6] LoongArch: ld: Add support for linker relaxation.
  2022-12-05  8:04 [PATCH v1 0/6] LoongArch linker relaxation support mengqinggang
                   ` (4 preceding siblings ...)
  2022-12-05  8:04 ` [PATCH v1 5/6] LoongArch: gas: " mengqinggang
@ 2022-12-05  8:04 ` mengqinggang
  2022-12-05  8:31   ` Xi Ruoyao
  2022-12-05  8:43 ` [PATCH v1 0/6] LoongArch linker relaxation support Xi Ruoyao
  6 siblings, 1 reply; 14+ messages in thread
From: mengqinggang @ 2022-12-05  8:04 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, liuzhensong, chenglulu, xry111, i.swmail, maskray,
	mengqinggang

Add ld relax support and testsuits.

ld/ChangeLog:

	* emultempl/loongarchelf.em: Regenerated.
	* testsuite/ld-elf/compressed1d.d: Xfail loongarch*-*.
	* testsuite/ld-elf/pr26936.d: Likewise.
	* testsuite/ld-loongarch-elf/disas-jirl.d: Regenerated.
	* testsuite/ld-loongarch-elf/jmp_op.d: Likewise.
	* testsuite/ld-loongarch-elf/macro_op.d: Likewise.
	* testsuite/ld-loongarch-elf/relax-align.dd: New test.
	* testsuite/ld-loongarch-elf/relax-align.s: New test.
	* testsuite/ld-loongarch-elf/relax.dd: New test.
	* testsuite/ld-loongarch-elf/relax.exp: New test.
	* testsuite/ld-loongarch-elf/relax.s: New test.
	* testsuite/ld-loongarch-elf/uleb128.dd: New test.
	* testsuite/ld-loongarch-elf/uleb128.s: New test.
---
 ld/emultempl/loongarchelf.em                 |   3 +
 ld/testsuite/ld-elf/compressed1d.d           |   3 +
 ld/testsuite/ld-elf/pr26936.d                |   4 +-
 ld/testsuite/ld-loongarch-elf/disas-jirl.d   |   4 +-
 ld/testsuite/ld-loongarch-elf/jmp_op.d       |  65 +++++----
 ld/testsuite/ld-loongarch-elf/macro_op.d     | 138 ++++++++++++-------
 ld/testsuite/ld-loongarch-elf/relax-align.dd |   7 +
 ld/testsuite/ld-loongarch-elf/relax-align.s  |   9 ++
 ld/testsuite/ld-loongarch-elf/relax.dd       |   5 +
 ld/testsuite/ld-loongarch-elf/relax.exp      |  65 +++++++++
 ld/testsuite/ld-loongarch-elf/relax.s        |  50 +++++++
 ld/testsuite/ld-loongarch-elf/uleb128.dd     |  10 ++
 ld/testsuite/ld-loongarch-elf/uleb128.s      |  21 +++
 13 files changed, 307 insertions(+), 77 deletions(-)
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax-align.dd
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax-align.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax.dd
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax.exp
 create mode 100644 ld/testsuite/ld-loongarch-elf/relax.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/uleb128.dd
 create mode 100644 ld/testsuite/ld-loongarch-elf/uleb128.s

diff --git a/ld/emultempl/loongarchelf.em b/ld/emultempl/loongarchelf.em
index e9e32c5c19c..e0b0bebb003 100644
--- a/ld/emultempl/loongarchelf.em
+++ b/ld/emultempl/loongarchelf.em
@@ -23,6 +23,7 @@ fragment <<EOF
 #include "ldmain.h"
 #include "ldctor.h"
 #include "elf/loongarch.h"
+#include "elfxx-loongarch.h"
 
 static void
 larch_elf_before_allocation (void)
@@ -61,6 +62,8 @@ gld${EMULATION_NAME}_after_allocation (void)
 	}
     }
 
+  enum phase_enum *phase = &(expld.dataseg.phase);
+  bfd_elf${ELFSIZE}_loongarch_set_data_segment_info (&link_info, (int *) phase);
   /* gld${EMULATION_NAME}_map_segments (need_layout); */
   ldelf_map_segments (need_layout);
 }
diff --git a/ld/testsuite/ld-elf/compressed1d.d b/ld/testsuite/ld-elf/compressed1d.d
index 9d891c1933f..b178695e23f 100644
--- a/ld/testsuite/ld-elf/compressed1d.d
+++ b/ld/testsuite/ld-elf/compressed1d.d
@@ -4,10 +4,13 @@
 #readelf: -SW
 #xfail: [uses_genelf]
 #xfail: [riscv_little_endian]
+#xfail: loongarch*-*-*
 # Not all ELF targets use the elf.em emulation...
 # RISC-V has linker relaxations that delete code, so text label subtractions
 # do not get resolved at assembly time, which results in a compressed section
 # for little endian targets; but it is uncompressed for big endian targets.
+# LoongArch has linker relaxations that delete code, so text label subtractions
+# do not get resolved at assembly time, which results in a compressed section.
 
 #failif
 #...
diff --git a/ld/testsuite/ld-elf/pr26936.d b/ld/testsuite/ld-elf/pr26936.d
index c479f475829..26c80ab90dc 100644
--- a/ld/testsuite/ld-elf/pr26936.d
+++ b/ld/testsuite/ld-elf/pr26936.d
@@ -6,10 +6,10 @@
 #readelf: -wL -W
 #target: [check_shared_lib_support]
 # Assembly source file for the HPPA assembler is renamed and modifed by
-# sed.  mn10300 and riscv put different numbers of local symbols in
+# sed. loongarch and mn10300 and riscv put different numbers of local symbols in
 # linkonce section and comdat sections.  xtensa has more than one member
 # in comdat groups.
-#xfail: am33_2.0-*-* hppa*-*-hpux* mn10300-*-* riscv*-*-* xtensa*-*-*
+#xfail: am33_2.0-*-* hppa*-*-hpux* loongarch*-*-* mn10300-*-* riscv*-*-* xtensa*-*-*
 
 #...
 CU: .*/pr26936c.s:
diff --git a/ld/testsuite/ld-loongarch-elf/disas-jirl.d b/ld/testsuite/ld-loongarch-elf/disas-jirl.d
index 595c30c7361..eeb8dd05092 100644
--- a/ld/testsuite/ld-loongarch-elf/disas-jirl.d
+++ b/ld/testsuite/ld-loongarch-elf/disas-jirl.d
@@ -6,9 +6,11 @@
 
 Disassembly of section .text:
 
-00000000.*:
+00000000.* <_start>:
 [ 	]+0:[ 	]+1a000014[ 	]+pcalau12i[ 	]+\$t8,[ 	]+0
 [ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+_start
+[ 	]+0:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+4:[ 	]+02c00294[ 	]+addi.d[ 	]+\$t8,[ 	]+\$t8,[ 	]+0
 [ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+_start
+[ 	]+4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+8:[ 	]+4c000281[ 	]+jirl[ 	]+\$ra,[ 	]+\$t8,[ 	]+0
diff --git a/ld/testsuite/ld-loongarch-elf/jmp_op.d b/ld/testsuite/ld-loongarch-elf/jmp_op.d
index 218c13f9398..09f89100195 100644
--- a/ld/testsuite/ld-loongarch-elf/jmp_op.d
+++ b/ld/testsuite/ld-loongarch-elf/jmp_op.d
@@ -6,26 +6,45 @@
 
 Disassembly of section .text:
 
-00000000.* <.text>:
-[ 	]+0:[ 	]+03400000[ 	]+[ 	]+andi[ 	]+\$zero, \$zero, 0x0
-[ 	]+4:[ 	]+63fffc04[ 	]+[ 	]+blt[ 	]+\$zero, \$a0, -4\(0x3fffc\)[ 	]+# 0x0
-[ 	]+8:[ 	]+67fff880[ 	]+[ 	]+bge[ 	]+\$a0, \$zero, -8\(0x3fff8\)[ 	]+# 0x0
-[ 	]+c:[ 	]+67fff404[ 	]+[ 	]+bge[ 	]+\$zero, \$a0, -12\(0x3fff4\)[ 	]+# 0x0
-[ 	]+10:[ 	]+43fff09f[ 	]+[ 	]+beqz[ 	]+\$a0, -16\(0x7ffff0\)[ 	]+# 0x0
-[ 	]+14:[ 	]+47ffec9f[ 	]+[ 	]+bnez[ 	]+\$a0, -20\(0x7fffec\)[ 	]+# 0x0
-[ 	]+18:[ 	]+4bffe81f[ 	]+[ 	]+bceqz[ 	]+\$fcc0, -24\(0x7fffe8\)[ 	]+# 0x0
-[ 	]+1c:[ 	]+4bffe51f[ 	]+[ 	]+bcnez[ 	]+\$fcc0, -28\(0x7fffe4\)[ 	]+# 0x0
-[ 	]+20:[ 	]+4c000080[ 	]+[ 	]+jirl[ 	]+\$zero, \$a0, 0
-[ 	]+24:[ 	]+53ffdfff[ 	]+[ 	]+b[ 	]+-36\(0xfffffdc\)[ 	]+# 0x0
-[ 	]+28:[ 	]+57ffdbff[ 	]+[ 	]+bl[ 	]+-40\(0xfffffd8\)[ 	]+# 0x0
-[ 	]+2c:[ 	]+5bffd485[ 	]+[ 	]+beq[ 	]+\$a0, \$a1, -44\(0x3ffd4\)[ 	]+# 0x0
-[ 	]+30:[ 	]+5fffd085[ 	]+[ 	]+bne[ 	]+\$a0, \$a1, -48\(0x3ffd0\)[ 	]+# 0x0
-[ 	]+34:[ 	]+63ffcc85[ 	]+[ 	]+blt[ 	]+\$a0, \$a1, -52\(0x3ffcc\)[ 	]+# 0x0
-[ 	]+38:[ 	]+63ffc8a4[ 	]+[ 	]+blt[ 	]+\$a1, \$a0, -56\(0x3ffc8\)[ 	]+# 0x0
-[ 	]+3c:[ 	]+67ffc485[ 	]+[ 	]+bge[ 	]+\$a0, \$a1, -60\(0x3ffc4\)[ 	]+# 0x0
-[ 	]+40:[ 	]+67ffc0a4[ 	]+[ 	]+bge[ 	]+\$a1, \$a0, -64\(0x3ffc0\)[ 	]+# 0x0
-[ 	]+44:[ 	]+6bffbc85[ 	]+[ 	]+bltu[ 	]+\$a0, \$a1, -68\(0x3ffbc\)[ 	]+# 0x0
-[ 	]+48:[ 	]+6bffb8a4[ 	]+[ 	]+bltu[ 	]+\$a1, \$a0, -72\(0x3ffb8\)[ 	]+# 0x0
-[ 	]+4c:[ 	]+6fffb485[ 	]+[ 	]+bgeu[ 	]+\$a0, \$a1, -76\(0x3ffb4\)[ 	]+# 0x0
-[ 	]+50:[ 	]+6fffb0a4[ 	]+[ 	]+bgeu[ 	]+\$a1, \$a0, -80\(0x3ffb0\)[ 	]+# 0x0
-[ 	]+54:[ 	]+4c000020[ 	]+[ 	]+jirl[ 	]+\$zero, \$ra, 0
+00000000.* <.L1>:
+[ 	]+0:[ 	]+03400000[ 	]+andi[ 	]+\$zero,[ 	]+\$zero,[ 	]+0x0
+[ 	]+4:[ 	]+63fffc04[ 	]+blt[ 	]+\$zero,[ 	]+\$a0,[ 	]+-4\(0x3fffc\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+4:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+8:[ 	]+67fff880[ 	]+bge[ 	]+\$a0,[ 	]+\$zero,[ 	]+-8\(0x3fff8\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+8:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+c:[ 	]+67fff404[ 	]+bge[ 	]+\$zero,[ 	]+\$a0,[ 	]+-12\(0x3fff4\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+c:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+10:[ 	]+43fff09f[ 	]+beqz[ 	]+\$a0,[ 	]+-16\(0x7ffff0\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+10:[ 	]+R_LARCH_B21[ 	]+.L1
+[ 	]+14:[ 	]+47ffec9f[ 	]+bnez[ 	]+\$a0,[ 	]+-20\(0x7fffec\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+14:[ 	]+R_LARCH_B21[ 	]+.L1
+[ 	]+18:[ 	]+4bffe81f[ 	]+bceqz[ 	]+\$fcc0,[ 	]+-24\(0x7fffe8\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+18:[ 	]+R_LARCH_B21[ 	]+.L1
+[ 	]+1c:[ 	]+4bffe51f[ 	]+bcnez[ 	]+\$fcc0,[ 	]+-28\(0x7fffe4\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+1c:[ 	]+R_LARCH_B21[ 	]+.L1
+[ 	]+20:[ 	]+4c000080[ 	]+jirl[ 	]+\$zero,[ 	]+\$a0,[ 	]+0
+[ 	]+24:[ 	]+53ffdfff[ 	]+b[ 	]+-36\(0xfffffdc\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+24:[ 	]+R_LARCH_B26[ 	]+.L1
+[ 	]+28:[ 	]+57ffdbff[ 	]+bl[ 	]+-40\(0xfffffd8\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+28:[ 	]+R_LARCH_B26[ 	]+.L1
+[ 	]+2c:[ 	]+5bffd485[ 	]+beq[ 	]+\$a0,[ 	]+\$a1,[ 	]+-44\(0x3ffd4\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+2c:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+30:[ 	]+5fffd085[ 	]+bne[ 	]+\$a0,[ 	]+\$a1,[ 	]+-48\(0x3ffd0\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+30:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+34:[ 	]+63ffcc85[ 	]+blt[ 	]+\$a0,[ 	]+\$a1,[ 	]+-52\(0x3ffcc\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+34:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+38:[ 	]+63ffc8a4[ 	]+blt[ 	]+\$a1,[ 	]+\$a0,[ 	]+-56\(0x3ffc8\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+38:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+3c:[ 	]+67ffc485[ 	]+bge[ 	]+\$a0,[ 	]+\$a1,[ 	]+-60\(0x3ffc4\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+3c:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+40:[ 	]+67ffc0a4[ 	]+bge[ 	]+\$a1,[ 	]+\$a0,[ 	]+-64\(0x3ffc0\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+40:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+44:[ 	]+6bffbc85[ 	]+bltu[ 	]+\$a0,[ 	]+\$a1,[ 	]+-68\(0x3ffbc\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+44:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+48:[ 	]+6bffb8a4[ 	]+bltu[ 	]+\$a1,[ 	]+\$a0,[ 	]+-72\(0x3ffb8\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+48:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+4c:[ 	]+6fffb485[ 	]+bgeu[ 	]+\$a0,[ 	]+\$a1,[ 	]+-76\(0x3ffb4\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+4c:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+50:[ 	]+6fffb0a4[ 	]+bgeu[ 	]+\$a1,[ 	]+\$a0,[ 	]+-80\(0x3ffb0\)[ 	]+#[ 	]+0[ 	]+<.L1>
+[ 	]+50:[ 	]+R_LARCH_B16[ 	]+.L1
+[ 	]+54:[ 	]+4c000020[ 	]+jirl[ 	]+\$zero,[ 	]+\$ra,[ 	]+0
diff --git a/ld/testsuite/ld-loongarch-elf/macro_op.d b/ld/testsuite/ld-loongarch-elf/macro_op.d
index a1c64fcf00f..2649f63e566 100644
--- a/ld/testsuite/ld-loongarch-elf/macro_op.d
+++ b/ld/testsuite/ld-loongarch-elf/macro_op.d
@@ -6,118 +6,150 @@
 
 Disassembly of section .text:
 
-00000000.* <.text>:
+00000000.* <.L1>:
 [ 	]+0:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
 [ 	]+4:[ 	]+02bffc04[ 	]+addi.w[ 	]+\$a0,[ 	]+\$zero,[ 	]+-1\(0xfff\)
 [ 	]+8:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
 [ 	]+c:[ 	]+02bffc04[ 	]+addi.w[ 	]+\$a0,[ 	]+\$zero,[ 	]+-1\(0xfff\)
 [ 	]+10:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+10:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
+[ 	]+10:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+10:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+14:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+14:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
+[ 	]+14:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+14:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+18:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+18:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
+[ 	]+18:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+18:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+1c:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+1c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
+[ 	]+1c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+1c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+20:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+20:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
+[ 	]+20:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+20:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+24:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+24:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
+[ 	]+24:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+24:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+28:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+28:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.text
+[ 	]+28:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.L1
 [ 	]+2c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+2c:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.text
+[ 	]+2c:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.L1
 [ 	]+30:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+34:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+34:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
+[ 	]+34:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+34:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+38:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+38:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
+[ 	]+38:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+38:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+3c:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+3c:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
+[ 	]+3c:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+3c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+40:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+40:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
+[ 	]+40:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+40:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+44:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+44:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.text
+[ 	]+44:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.L1
 [ 	]+48:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+48:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.text
+[ 	]+48:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.L1
 [ 	]+4c:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+50:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+50:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
+[ 	]+50:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+50:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+54:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+54:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
+[ 	]+54:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+54:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+58:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+58:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
+[ 	]+58:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+58:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+5c:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+5c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
+[ 	]+5c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+5c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+60:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+60:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.text
+[ 	]+60:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.L1
 [ 	]+64:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+64:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.text
+[ 	]+64:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.L1
 [ 	]+68:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+6c:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+6c:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+6c:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+6c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+70:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+70:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+70:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+70:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+74:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+74:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+74:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+74:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+78:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+78:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+78:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+78:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+7c:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+7c:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.text
+[ 	]+7c:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
 [ 	]+80:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+80:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.text
+[ 	]+80:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.L1
 [ 	]+84:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+88:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+88:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+88:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+88:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+8c:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+8c:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+8c:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+8c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+90:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+90:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+90:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+90:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+94:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+94:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+94:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+94:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+98:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+98:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.text
+[ 	]+98:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
 [ 	]+9c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+9c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.text
+[ 	]+9c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.L1
 [ 	]+a0:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+a4:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
 [ 	]+a4:[ 	]+R_LARCH_MARK_LA[ 	]+\*ABS\*
-[ 	]+a4:[ 	]+R_LARCH_ABS_HI20[ 	]+.text
+[ 	]+a4:[ 	]+R_LARCH_ABS_HI20[ 	]+.L1
 [ 	]+a8:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
-[ 	]+a8:[ 	]+R_LARCH_ABS_LO12[ 	]+.text
+[ 	]+a8:[ 	]+R_LARCH_ABS_LO12[ 	]+.L1
 [ 	]+ac:[ 	]+16000004[ 	]+lu32i.d[ 	]+\$a0,[ 	]+0
-[ 	]+ac:[ 	]+R_LARCH_ABS64_LO20[ 	]+.text
+[ 	]+ac:[ 	]+R_LARCH_ABS64_LO20[ 	]+.L1
 [ 	]+b0:[ 	]+03000084[ 	]+lu52i.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+b0:[ 	]+R_LARCH_ABS64_HI12[ 	]+.text
+[ 	]+b0:[ 	]+R_LARCH_ABS64_HI12[ 	]+.L1
 [ 	]+b4:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+b4:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+b4:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+b4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+b8:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+b8:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+b8:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+b8:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+bc:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+bc:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+bc:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+bc:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+c0:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+c0:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+c0:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+c0:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+c4:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+c4:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+c4:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+c4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+c8:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+c8:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+c8:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+c8:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+cc:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+cc:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.text
+[ 	]+cc:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
 [ 	]+d0:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+d0:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.text
+[ 	]+d0:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.L1
 [ 	]+d4:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+d8:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+d8:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
+[ 	]+d8:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+d8:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+dc:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+dc:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
+[ 	]+dc:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+dc:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+e0:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+e0:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.text
+[ 	]+e0:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+e0:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+e4:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+e4:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.text
+[ 	]+e4:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+e4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+e8:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+e8:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.text
+[ 	]+e8:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.L1
 [ 	]+ec:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+ec:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.text
+[ 	]+ec:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.L1
 [ 	]+f0:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+f4:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
 [ 	]+f4:[ 	]+R_LARCH_TLS_LE_HI20[ 	]+TLS1
@@ -140,10 +172,12 @@ Disassembly of section .text:
 [ 	]+118:[ 	]+R_LARCH_TLS_LD_PC_HI20[ 	]+TLS1
 [ 	]+11c:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+11c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+11c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+120:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+120:[ 	]+R_LARCH_TLS_LD_PC_HI20[ 	]+TLS1
 [ 	]+124:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+124:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+124:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+128:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
 [ 	]+128:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
 [ 	]+12c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
@@ -153,10 +187,12 @@ Disassembly of section .text:
 [ 	]+134:[ 	]+R_LARCH_TLS_GD_PC_HI20[ 	]+TLS1
 [ 	]+138:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+138:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+138:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+13c:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+13c:[ 	]+R_LARCH_TLS_GD_PC_HI20[ 	]+TLS1
 [ 	]+140:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+140:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+140:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+144:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
 [ 	]+144:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
 [ 	]+148:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
diff --git a/ld/testsuite/ld-loongarch-elf/relax-align.dd b/ld/testsuite/ld-loongarch-elf/relax-align.dd
new file mode 100644
index 00000000000..3149738ff71
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-align.dd
@@ -0,0 +1,7 @@
+#...
+.*pcaddi.*
+.*pcaddi.*
+.*andi.*
+.*andi.*
+.*0:.*pcaddi.*
+#pass
diff --git a/ld/testsuite/ld-loongarch-elf/relax-align.s b/ld/testsuite/ld-loongarch-elf/relax-align.s
new file mode 100644
index 00000000000..9617c02d8e5
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax-align.s
@@ -0,0 +1,9 @@
+# relax-align.o has 3 andi(nop) insns.
+# relax-align has 2 andi insns, ld relax delete andi insns.
+# the last pcaddi 16 bytes align.
+  .text
+L1:
+  la.local $a0, L1
+  la.local $a0, L1
+  .align 4
+  la.local $a0, L1
diff --git a/ld/testsuite/ld-loongarch-elf/relax.dd b/ld/testsuite/ld-loongarch-elf/relax.dd
new file mode 100644
index 00000000000..28d4c7f72cd
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax.dd
@@ -0,0 +1,5 @@
+#...
+.*pcaddi.*
+#...
+.*pcaddi.*
+#pass
diff --git a/ld/testsuite/ld-loongarch-elf/relax.exp b/ld/testsuite/ld-loongarch-elf/relax.exp
new file mode 100644
index 00000000000..fc20f86fdf2
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax.exp
@@ -0,0 +1,65 @@
+# Expect script for LoongArch ELF linker tests
+#   Copyright (C) 2022 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+if [istarget loongarch*-*-*] {
+    run_ld_link_tests \
+	[list \
+	    [list \
+		"relax" \
+		"-e 0x0 -z relro" "" \
+		"" \
+		{relax.s} \
+		[list \
+		    [list objdump -d relax.dd] \
+		] \
+		"relax" \
+	    ] \
+	]
+
+    run_ld_link_tests \
+	[list \
+	    [list \
+		"relax-align" \
+		"-e 0x0 -z relro" "" \
+		"" \
+		{relax-align.s} \
+		[list \
+		    [list objdump -d relax-align.dd] \
+		] \
+		"relax-align" \
+	    ] \
+	]
+
+    set objdump_flags "-s -j .data"
+    run_ld_link_tests \
+	[list \
+	    [list \
+		"uleb128" \
+		"-e 0x0" "" \
+		"" \
+		{uleb128.s} \
+		[list \
+		    [list objdump $objdump_flags uleb128.dd] \
+		] \
+		"uleb128" \
+	    ] \
+	]
+}
diff --git a/ld/testsuite/ld-loongarch-elf/relax.s b/ld/testsuite/ld-loongarch-elf/relax.s
new file mode 100644
index 00000000000..a99bd4de5af
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax.s
@@ -0,0 +1,50 @@
+# m.c: printf global int a, compile with gcc -fpic.
+# la.local and la.global would be relaxed to pcaddi.
+
+	.file	"m.c"
+	.text
+	.globl	a
+	.data
+	.align	2
+	.type	a, @object
+	.size	a, 4
+a:
+	.word	123
+	.section	.rodata
+	.align	3
+.LC0:
+	.ascii	"%d\012\000"
+	.text
+	.align	2
+	.globl	main
+	.type	main, @function
+main:
+.LFB0 = .
+	.cfi_startproc
+	addi.d	$r3,$r3,-16
+	.cfi_def_cfa_offset 16
+	st.d	$r1,$r3,8
+	stptr.d	$r22,$r3,0
+	.cfi_offset 1, -8
+	.cfi_offset 22, -16
+	addi.d	$r22,$r3,16
+	.cfi_def_cfa 22, 0
+	la.global	$r12,a
+	ldptr.w	$r12,$r12,0
+	or	$r5,$r12,$r0
+	la.local	$r4,.LC0
+	#bl	%plt(printf)
+	or	$r12,$r0,$r0
+	or	$r4,$r12,$r0
+	ld.d	$r1,$r3,8
+	.cfi_restore 1
+	ldptr.d	$r22,$r3,0
+	.cfi_restore 22
+	addi.d	$r3,$r3,16
+	.cfi_def_cfa_register 3
+	jr	$r1
+	.cfi_endproc
+.LFE0:
+	.size	main, .-main
+	.ident	"GCC: (GNU) 13.0.0 20221023 (experimental)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-loongarch-elf/uleb128.dd b/ld/testsuite/ld-loongarch-elf/uleb128.dd
new file mode 100644
index 00000000000..c4ad3070ee1
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/uleb128.dd
@@ -0,0 +1,10 @@
+.*: .*
+
+Contents of section .*
+ [0-9a-f]+ 01020381 01000000 00000000 00000000.*
+#...
+ [0-9a-f]+ 00000004 ffff0500 06078380 01000000.*
+#...
+ [0-9a-f]+ 00000000 00000000 00000008 ffffffff.*
+ [0-9a-f]+ 09090909 09090909 09090909 09090909.*
+#pass
diff --git a/ld/testsuite/ld-loongarch-elf/uleb128.s b/ld/testsuite/ld-loongarch-elf/uleb128.s
new file mode 100644
index 00000000000..7299fb91a25
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/uleb128.s
@@ -0,0 +1,21 @@
+# From gas/all/relax.s, test ld process add_uleb128/sub_uleb128 reloc pair.
+ .data
+ .byte 1, 2, 3
+ .uleb128 L2 - L1
+L1:
+ .space 128 - 2
+ .byte 4
+ .p2align 1, 0xff
+L2:
+ .byte 5
+
+ .p2align 2
+ .byte 6, 7
+ .uleb128 L4 - L3
+L3:
+ .space 128*128 - 2
+ .byte 8
+ .p2align 2, 0xff
+L4:
+ .byte 9
+ .p2align 4, 9
-- 
2.36.0


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 1/6] LoongArch: include: Add support for linker relaxation.
  2022-12-05  8:04 ` [PATCH v1 1/6] LoongArch: include: Add support for linker relaxation mengqinggang
@ 2022-12-05  8:24   ` Xi Ruoyao
  2022-12-06  2:59     ` mengqinggang
  0 siblings, 1 reply; 14+ messages in thread
From: Xi Ruoyao @ 2022-12-05  8:24 UTC (permalink / raw)
  To: mengqinggang, binutils
  Cc: xuchenghua, liuzhensong, chenglulu, i.swmail, maskray

On Mon, 2022-12-05 at 16:04 +0800, mengqinggang wrote:
> Add relocs and gas LARCH_opts.relax option.
> 
> include/ChangeLog:
> 
>         * elf/loongarch.h: Add relocs.
>         * opcode/loongarch.h: Add LARCH_opts.relax and macro
> LARCH_NOP.
> ---
>  include/elf/loongarch.h    | 20 ++++++++++++++++++++
>  include/opcode/loongarch.h |  3 +++
>  2 files changed, 23 insertions(+)
> 
> diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h
> index a6341b46791..0ecddd17b37 100644
> --- a/include/elf/loongarch.h
> +++ b/include/elf/loongarch.h
> @@ -229,6 +229,26 @@ RELOC_NUMBER (R_LARCH_32_PCREL, 99)
>  /* RELAX.  */
>  RELOC_NUMBER (R_LARCH_RELAX, 100)
>  

Please add the description of the following new relocation types into
the psELF ABI doc first.

> +/* relax delete.  */
> +RELOC_NUMBER (R_LARCH_DELETE, 101)
> +
> +/* relax align.  */
> +RELOC_NUMBER (R_LARCH_ALIGN, 102)
> +
> +/* pcaddi.  */
> +RELOC_NUMBER (R_LARCH_PCREL20_S2, 103)
> +
> +/* cfa.  */
> +RELOC_NUMBER (R_LARCH_CFA, 104)
> +
> +/* DW_CFA_advance_loc.  */
> +RELOC_NUMBER (R_LARCH_ADD6, 105)
> +RELOC_NUMBER (R_LARCH_SUB6, 106)
> +
> +/* unsinged leb128.  */

Typo: "unsigned".

I often mistype this too.

> +RELOC_NUMBER (R_LARCH_ADD_ULEB128, 107)
> +RELOC_NUMBER (R_LARCH_SUB_ULEB128, 108)
> +

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 6/6] LoongArch: ld: Add support for linker relaxation.
  2022-12-05  8:04 ` [PATCH v1 6/6] LoongArch: ld: " mengqinggang
@ 2022-12-05  8:31   ` Xi Ruoyao
  0 siblings, 0 replies; 14+ messages in thread
From: Xi Ruoyao @ 2022-12-05  8:31 UTC (permalink / raw)
  To: mengqinggang, binutils
  Cc: xuchenghua, liuzhensong, chenglulu, i.swmail, maskray

On Mon, 2022-12-05 at 16:04 +0800, mengqinggang wrote:
> diff --git a/ld/testsuite/ld-loongarch-elf/relax.s b/ld/testsuite/ld-
> loongarch-elf/relax.s
> new file mode 100644
> index 00000000000..a99bd4de5af
> --- /dev/null
> +++ b/ld/testsuite/ld-loongarch-elf/relax.s
> @@ -0,0 +1,50 @@
> +# m.c: printf global int a, compile with gcc -fpic.
> +# la.local and la.global would be relaxed to pcaddi.

Remove things not needed for testing, such as the .cfi and .ident
directives.  Maybe it can be simplified to something like

.data
.global a
.type a, @object
a:
  .word 123

.text
.global main
.type main, @function
main:
  la.global $a0, a
  ld.w $a0, $a0, 0
  xori $a0, $a0, 123
  jr $ra

> +
> +       .file   "m.c"
> +       .text
> +       .globl  a
> +       .data
> +       .align  2
> +       .type   a, @object
> +       .size   a, 4
> +a:
> +       .word   123
> +       .section        .rodata
> +       .align  3
> +.LC0:
> +       .ascii  "%d\012\000"
> +       .text
> +       .align  2
> +       .globl  main
> +       .type   main, @function
> +main:
> +.LFB0 = .
> +       .cfi_startproc
> +       addi.d  $r3,$r3,-16
> +       .cfi_def_cfa_offset 16
> +       st.d    $r1,$r3,8
> +       stptr.d $r22,$r3,0
> +       .cfi_offset 1, -8
> +       .cfi_offset 22, -16
> +       addi.d  $r22,$r3,16
> +       .cfi_def_cfa 22, 0
> +       la.global       $r12,a
> +       ldptr.w $r12,$r12,0
> +       or      $r5,$r12,$r0
> +       la.local        $r4,.LC0
> +       #bl     %plt(printf)
> +       or      $r12,$r0,$r0
> +       or      $r4,$r12,$r0
> +       ld.d    $r1,$r3,8
> +       .cfi_restore 1
> +       ldptr.d $r22,$r3,0
> +       .cfi_restore 22
> +       addi.d  $r3,$r3,16
> +       .cfi_def_cfa_register 3
> +       jr      $r1
> +       .cfi_endproc
> +.LFE0:
> +       .size   main, .-main
> +       .ident  "GCC: (GNU) 13.0.0 20221023 (experimental)"
> +       .section        .note.GNU-stack,"",@progbits

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 0/6] LoongArch linker relaxation support.
  2022-12-05  8:04 [PATCH v1 0/6] LoongArch linker relaxation support mengqinggang
                   ` (5 preceding siblings ...)
  2022-12-05  8:04 ` [PATCH v1 6/6] LoongArch: ld: " mengqinggang
@ 2022-12-05  8:43 ` Xi Ruoyao
  2022-12-06  1:58   ` mengqinggang
  6 siblings, 1 reply; 14+ messages in thread
From: Xi Ruoyao @ 2022-12-05  8:43 UTC (permalink / raw)
  To: mengqinggang, binutils
  Cc: xuchenghua, liuzhensong, chenglulu, i.swmail, maskray

On Mon, 2022-12-05 at 16:04 +0800, mengqinggang wrote:
> Now, only the instrunctions expand from macro (la.local, la.got, etc.) at          
> assembly time can be relaxed, because gcc instruction scheduling causes relax   
> unable to handle some special cases. Gcc can add -mno-explicit-relocs option       
> to generate macro instrunction.

Frankly, I don't like this.  Can the compiler explicitly emit some
relocations to mark a instruction chain suitable for relaxation?  Some
random thought:

.reloc R_LARCH_RELOC_X 1
pcalau12i $a0, %got_pc_hi20(sym_a)
.reloc R_LARCH_RELOC_X 2
pcalau12i $a1, %got_pc_hi20(sym_b)
.reloc R_LARCH_RELOC_X 1
ld.d $a0, $a0, %got_pc_lo12(sym_a)
.reloc R_LARCH_RELOC_X 2
ld.d $a1, $a1, %got_pc_lo12(sym_b)
.reloc R_LARCH_RELOC_X 1
ld.d $a0, $a0, 0
.reloc R_LARCH_RELOC_X 2
ld.d $a1, $a1, 0

Here "R_LARCH_RELOC_X" is an imaginary relocation type.  We may be able
to use the different values of the 32-bit addend to distinguish two load
sequences interleaved after scheduling (I don't think there will be more
than 2147483647 load sequences in an object file).

This is just some random thoughts, I don't understand the linking
process very well anyway.

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 3/6] LoongArch: opcodes: Add support for linker relaxation.
  2022-12-05  8:04 ` [PATCH v1 3/6] LoongArch: opcodes: " mengqinggang
@ 2022-12-05  9:43   ` Andreas Schwab
  0 siblings, 0 replies; 14+ messages in thread
From: Andreas Schwab @ 2022-12-05  9:43 UTC (permalink / raw)
  To: mengqinggang
  Cc: binutils, xuchenghua, liuzhensong, chenglulu, xry111, i.swmail, maskray

On Dez 05 2022, mengqinggang wrote:

> diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c
> index 1b510048c29..49e9df56f67 100644
> --- a/opcodes/loongarch-opc.c
> +++ b/opcodes/loongarch-opc.c
> @@ -22,7 +22,10 @@
>  #include "opcode/loongarch.h"
>  #include "libiberty.h"
>  
> -struct loongarch_ASEs_option LARCH_opts;
> +struct loongarch_ASEs_option LARCH_opts =
> +{
> +  relax : 1
> +};

This uses the obsolete GCC extension.  Please use the C99 designated
initializer syntax.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 5/6] LoongArch: gas: Add support for linker relaxation.
  2022-12-05  8:04 ` [PATCH v1 5/6] LoongArch: gas: " mengqinggang
@ 2022-12-05  9:47   ` Andreas Schwab
  0 siblings, 0 replies; 14+ messages in thread
From: Andreas Schwab @ 2022-12-05  9:47 UTC (permalink / raw)
  To: mengqinggang
  Cc: binutils, xuchenghua, liuzhensong, chenglulu, xry111, i.swmail, maskray

On Dez 05 2022, mengqinggang wrote:

> @@ -1258,19 +1406,7 @@ int
>  md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
>  			       asection *segtype ATTRIBUTE_UNUSED)
>  {
> -  return 0;
> -}
> -
> -int
> -loongarch_fix_adjustable (fixS *fix)
> -{
> -  /* Prevent all adjustments to global symbols.  */
> -  if (S_IS_EXTERNAL (fix->fx_addsy)
> -      || S_IS_WEAK (fix->fx_addsy)
> -      || S_FORCE_RELOC (fix->fx_addsy, true))
> -    return 0;
> -
> -  return 1;
> +  return (fragp->fr_var = 4);

Please don't use an assignment inside an expression.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 0/6] LoongArch linker relaxation support.
  2022-12-05  8:43 ` [PATCH v1 0/6] LoongArch linker relaxation support Xi Ruoyao
@ 2022-12-06  1:58   ` mengqinggang
  0 siblings, 0 replies; 14+ messages in thread
From: mengqinggang @ 2022-12-06  1:58 UTC (permalink / raw)
  To: Xi Ruoyao, binutils; +Cc: xuchenghua, liuzhensong, chenglulu, i.swmail, maskray

We tried this method. We use R_LARCH_RELAX addend to distinguish two load
sequences. But there is a problem that has not been solved.
If there are two load sequences after a branch instruction like this:

   branch ------------
     | |
   pcalau12i pcalau12i
   ld.d ld.d

After scheduling, two pcalau12i may be reduced to one and put before
branch instruction like this:

pcalau12i
   branch -----------
     | |
    ld.d ld.d

For this case, if one branch make a relax, another branch will get a 
mistake.

But we will try to solve this question in relax v2 version.


在 2022/12/5 下午4:43, Xi Ruoyao 写道:
> On Mon, 2022-12-05 at 16:04 +0800, mengqinggang wrote:
>> Now, only the instrunctions expand from macro (la.local, la.got, etc.) at
>> assembly time can be relaxed, because gcc instruction scheduling causes relax
>> unable to handle some special cases. Gcc can add -mno-explicit-relocs option
>> to generate macro instrunction.
> Frankly, I don't like this.  Can the compiler explicitly emit some
> relocations to mark a instruction chain suitable for relaxation?  Some
> random thought:
>
> .reloc R_LARCH_RELOC_X 1
> pcalau12i $a0, %got_pc_hi20(sym_a)
> .reloc R_LARCH_RELOC_X 2
> pcalau12i $a1, %got_pc_hi20(sym_b)
> .reloc R_LARCH_RELOC_X 1
> ld.d $a0, $a0, %got_pc_lo12(sym_a)
> .reloc R_LARCH_RELOC_X 2
> ld.d $a1, $a1, %got_pc_lo12(sym_b)
> .reloc R_LARCH_RELOC_X 1
> ld.d $a0, $a0, 0
> .reloc R_LARCH_RELOC_X 2
> ld.d $a1, $a1, 0
>
> Here "R_LARCH_RELOC_X" is an imaginary relocation type.  We may be able
> to use the different values of the 32-bit addend to distinguish two load
> sequences interleaved after scheduling (I don't think there will be more
> than 2147483647 load sequences in an object file).
>
> This is just some random thoughts, I don't understand the linking
> process very well anyway.
>


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v1 1/6] LoongArch: include: Add support for linker relaxation.
  2022-12-05  8:24   ` Xi Ruoyao
@ 2022-12-06  2:59     ` mengqinggang
  0 siblings, 0 replies; 14+ messages in thread
From: mengqinggang @ 2022-12-06  2:59 UTC (permalink / raw)
  To: Xi Ruoyao, binutils; +Cc: xuchenghua, liuzhensong, chenglulu, i.swmail, maskray

The new relocs document at here:
     https://github.com/loongson/LoongArch-Documentation/pull/77

在 2022/12/5 下午4:24, Xi Ruoyao 写道:
> On Mon, 2022-12-05 at 16:04 +0800, mengqinggang wrote:
>> Add relocs and gas LARCH_opts.relax option.
>>
>> include/ChangeLog:
>>
>>          * elf/loongarch.h: Add relocs.
>>          * opcode/loongarch.h: Add LARCH_opts.relax and macro
>> LARCH_NOP.
>> ---
>>   include/elf/loongarch.h    | 20 ++++++++++++++++++++
>>   include/opcode/loongarch.h |  3 +++
>>   2 files changed, 23 insertions(+)
>>
>> diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h
>> index a6341b46791..0ecddd17b37 100644
>> --- a/include/elf/loongarch.h
>> +++ b/include/elf/loongarch.h
>> @@ -229,6 +229,26 @@ RELOC_NUMBER (R_LARCH_32_PCREL, 99)
>>   /* RELAX.  */
>>   RELOC_NUMBER (R_LARCH_RELAX, 100)
>>   
> Please add the description of the following new relocation types into
> the psELF ABI doc first.
>
>> +/* relax delete.  */
>> +RELOC_NUMBER (R_LARCH_DELETE, 101)
>> +
>> +/* relax align.  */
>> +RELOC_NUMBER (R_LARCH_ALIGN, 102)
>> +
>> +/* pcaddi.  */
>> +RELOC_NUMBER (R_LARCH_PCREL20_S2, 103)
>> +
>> +/* cfa.  */
>> +RELOC_NUMBER (R_LARCH_CFA, 104)
>> +
>> +/* DW_CFA_advance_loc.  */
>> +RELOC_NUMBER (R_LARCH_ADD6, 105)
>> +RELOC_NUMBER (R_LARCH_SUB6, 106)
>> +
>> +/* unsinged leb128.  */
> Typo: "unsigned".
>
> I often mistype this too.
>
>> +RELOC_NUMBER (R_LARCH_ADD_ULEB128, 107)
>> +RELOC_NUMBER (R_LARCH_SUB_ULEB128, 108)
>> +


^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2022-12-06  2:59 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-05  8:04 [PATCH v1 0/6] LoongArch linker relaxation support mengqinggang
2022-12-05  8:04 ` [PATCH v1 1/6] LoongArch: include: Add support for linker relaxation mengqinggang
2022-12-05  8:24   ` Xi Ruoyao
2022-12-06  2:59     ` mengqinggang
2022-12-05  8:04 ` [PATCH v1 2/6] LoongArch: bfd: " mengqinggang
2022-12-05  8:04 ` [PATCH v1 3/6] LoongArch: opcodes: " mengqinggang
2022-12-05  9:43   ` Andreas Schwab
2022-12-05  8:04 ` [PATCH v1 4/6] LoongArch: binutils: " mengqinggang
2022-12-05  8:04 ` [PATCH v1 5/6] LoongArch: gas: " mengqinggang
2022-12-05  9:47   ` Andreas Schwab
2022-12-05  8:04 ` [PATCH v1 6/6] LoongArch: ld: " mengqinggang
2022-12-05  8:31   ` Xi Ruoyao
2022-12-05  8:43 ` [PATCH v1 0/6] LoongArch linker relaxation support Xi Ruoyao
2022-12-06  1:58   ` mengqinggang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).