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

This is the v4 version of patches to support loongarch linker relax.
This version mainly rebase to the master branch.

The binutils, gcc, glibc and Spec2006 testcases is ok.

Now, only the instrunctions expand from macro (la.local, la.global, 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.

There are two code 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. 

In the future, the TLS LE code sequence and function call in medium
code mode would be relaxed too.

For .align directive, some small problems cannot be perfectly solved (see
http://maskray.me/blog/2021-03-14-the-dark-side-of-riscv-linker-relaxation). 

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

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                     | 427 +++++++++--
 gas/config/tc-loongarch.h                     |  48 +-
 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/dwarf-5-macro-include.d |   2 +-
 gas/testsuite/gas/elf/dwarf-5-macro.d         |   2 +-
 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              |   8 +-
 gas/testsuite/gas/loongarch/macro_op.d        |  68 +-
 gas/testsuite/gas/loongarch/macro_op_32.d     |  24 +-
 .../gas/loongarch/macro_op_large_abs.d        |  32 +-
 .../gas/loongarch/macro_op_large_pc.d         | 134 ++--
 gas/testsuite/gas/loongarch/relax_align.d     |  26 +
 gas/testsuite/gas/loongarch/relax_align.s     |   5 +
 gas/testsuite/gas/loongarch/uleb128.d         |  36 +
 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-32.d |   2 +
 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      |  84 ++-
 ld/testsuite/ld-loongarch-elf/macro_op_32.d   |  24 +-
 ld/testsuite/ld-loongarch-elf/relax-align.dd  |   7 +
 ld/testsuite/ld-loongarch-elf/relax-align.s   |   9 +
 ld/testsuite/ld-loongarch-elf/relax.exp       |  73 ++
 ld/testsuite/ld-loongarch-elf/relax.s         |  16 +
 ld/testsuite/ld-loongarch-elf/uleb128.dd      |  10 +
 ld/testsuite/ld-loongarch-elf/uleb128.s       |  21 +
 opcodes/loongarch-opc.c                       |   5 +-
 55 files changed, 2189 insertions(+), 521 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.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] 16+ messages in thread

* [PATCH v4 1/6] LoongArch: include: Add support for linker relaxation.
  2023-05-22  1:34 [PATCH v4 0/6] LoongArch linker relaxation support mengqinggang
@ 2023-05-22  1:34 ` mengqinggang
  2023-05-22  1:34 ` [PATCH v4 2/6] LoongArch: bfd: " mengqinggang
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: mengqinggang @ 2023-05-22  1:34 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, 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 ba0075d1066..71ab34f2cef 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)
+
+/* unsigned 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 548732e5c70..004bb6561ef 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] 16+ messages in thread

* [PATCH v4 2/6] LoongArch: bfd: Add support for linker relaxation.
  2023-05-22  1:34 [PATCH v4 0/6] LoongArch linker relaxation support mengqinggang
  2023-05-22  1:34 ` [PATCH v4 1/6] LoongArch: include: Add support for linker relaxation mengqinggang
@ 2023-05-22  1:34 ` mengqinggang
  2023-05-22  1:34 ` [PATCH v4 3/6] LoongArch: opcodes: " mengqinggang
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: mengqinggang @ 2023-05-22  1:34 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, 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 7be18db20a8..c0e4b769fcd 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -7332,6 +7332,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 3fb74edb45c..d501991e4cf 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
@@ -1884,7 +1893,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)
@@ -2004,42 +2013,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.  */
@@ -2078,6 +2118,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;
@@ -2244,9 +2285,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;				\
       } 						\
@@ -2256,8 +2297,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;      		\
       }  						\
@@ -2522,29 +2563,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:
@@ -3084,6 +3145,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)
@@ -3109,15 +3179,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);
 	    }
@@ -3253,13 +3323,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;
@@ -3417,15 +3486,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:
@@ -3516,6 +3586,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.  */
 
@@ -4149,5 +4622,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 1253e790512..9cfbef1431f 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 1a6b6df18f8..cb02af4fe73 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 05508c986ad..6f123ecccdc 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -3507,6 +3507,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 aab5d49bdb3..eedd29e6033 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -8127,6 +8127,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] 16+ messages in thread

* [PATCH v4 3/6] LoongArch: opcodes: Add support for linker relaxation.
  2023-05-22  1:34 [PATCH v4 0/6] LoongArch linker relaxation support mengqinggang
  2023-05-22  1:34 ` [PATCH v4 1/6] LoongArch: include: Add support for linker relaxation mengqinggang
  2023-05-22  1:34 ` [PATCH v4 2/6] LoongArch: bfd: " mengqinggang
@ 2023-05-22  1:34 ` mengqinggang
  2023-05-22  5:43   ` Xi Ruoyao
  2023-05-22  1:34 ` [PATCH v4 4/6] LoongArch: binutils: " mengqinggang
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: mengqinggang @ 2023-05-22  1:34 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, xry111, i.swmail, maskray,
	mengqinggang

Set gas default to enable relax.

opcodes/ChangeLog:

	* loongarch-opc.c (struct loongarch_ASEs_option): New member relax
	with the default value 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 39d724a3398..573b691c1fd 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] 16+ messages in thread

* [PATCH v4 4/6] LoongArch: binutils: Add support for linker relaxation.
  2023-05-22  1:34 [PATCH v4 0/6] LoongArch linker relaxation support mengqinggang
                   ` (2 preceding siblings ...)
  2023-05-22  1:34 ` [PATCH v4 3/6] LoongArch: opcodes: " mengqinggang
@ 2023-05-22  1:34 ` mengqinggang
  2023-05-22  5:44   ` Xi Ruoyao
  2023-05-22  1:34 ` [PATCH v4 5/6] LoongArch: gas: " mengqinggang
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: mengqinggang @ 2023-05-22  1:34 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, 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 b872876a8b6..fb2f04901fd 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -14008,6 +14008,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:
       {
@@ -14734,6 +14779,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:
@@ -14750,6 +14797,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:
@@ -14766,6 +14815,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:
@@ -14782,6 +14833,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:
@@ -14798,6 +14851,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:
@@ -14814,6 +14869,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:
@@ -14830,6 +14887,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:
@@ -14846,6 +14905,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:
@@ -14853,6 +14914,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.  */
 
@@ -14861,6 +14937,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:
@@ -15108,7 +15186,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;
@@ -15200,7 +15279,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 2a785c6e3df..383a2ea46b6 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] 16+ messages in thread

* [PATCH v4 5/6] LoongArch: gas: Add support for linker relaxation.
  2023-05-22  1:34 [PATCH v4 0/6] LoongArch linker relaxation support mengqinggang
                   ` (3 preceding siblings ...)
  2023-05-22  1:34 ` [PATCH v4 4/6] LoongArch: binutils: " mengqinggang
@ 2023-05-22  1:34 ` mengqinggang
  2023-05-22  1:34 ` [PATCH v4 6/6] LoongArch: ld: " mengqinggang
  2023-05-22  5:40 ` [PATCH v4 0/6] LoongArch linker relaxation support Xi Ruoyao
  6 siblings, 0 replies; 16+ messages in thread
From: mengqinggang @ 2023-05-22  1:34 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, 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 align pseudo 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/dwarf-5-macro-include.d: Likewise.
	* testsuite/gas/elf/dwarf-5-macro.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: Regenerated.
	* testsuite/gas/loongarch/li.d: Likewise.
	* testsuite/gas/loongarch/macro_op.d: Likewise.
	* testsuite/gas/loongarch/macro_op_32.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                     | 427 +++++++++++++++---
 gas/config/tc-loongarch.h                     |  48 +-
 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/dwarf-5-macro-include.d |   2 +-
 gas/testsuite/gas/elf/dwarf-5-macro.d         |   2 +-
 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              |   8 +-
 gas/testsuite/gas/loongarch/macro_op.d        |  68 +--
 gas/testsuite/gas/loongarch/macro_op_32.d     |  24 +-
 .../gas/loongarch/macro_op_large_abs.d        |  32 +-
 .../gas/loongarch/macro_op_large_pc.d         | 134 +++---
 gas/testsuite/gas/loongarch/relax_align.d     |  26 ++
 gas/testsuite/gas/loongarch/relax_align.s     |   5 +
 gas/testsuite/gas/loongarch/uleb128.d         |  36 ++
 gas/testsuite/gas/loongarch/uleb128.s         |  20 +
 30 files changed, 725 insertions(+), 229 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 7d8749c5951..c55d4ee234a 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;
 
-      md_number_to_chars (buf, 0, fixP->fx_size);
+	  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);
 
-      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,34 +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;
-
-  /* Loongarch loads extern symbols by GOT, and if there are embedded
-     asm(".local S"), gcc just output ".local S" to assembly file.
-     For a local symbol with GOT relocations, this adjustments will make
-     GOT relocation's addend not equal to zero. So this adjustments is
-     forbidden for got relocs.  */
-  if(fix->fx_r_type == BFD_RELOC_LARCH_GOT_PC_HI20
-      || fix->fx_r_type == BFD_RELOC_LARCH_GOT_PC_LO12
-      || fix->fx_r_type == BFD_RELOC_LARCH_GOT64_PC_LO20
-      || fix->fx_r_type == BFD_RELOC_LARCH_GOT64_PC_HI12
-      || fix->fx_r_type == BFD_RELOC_LARCH_GOT_HI20
-      || fix->fx_r_type == BFD_RELOC_LARCH_GOT_LO12
-      || fix->fx_r_type == BFD_RELOC_LARCH_GOT64_LO20
-      || fix->fx_r_type == BFD_RELOC_LARCH_GOT64_HI12)
-    return 0;
-
-  return 1;
+  return (fragp->fr_var = 4);
 }
 
 /* Translate internal representation of relocation info to BFD target
@@ -1315,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.  */
@@ -1327,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)
 {
@@ -1340,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)
@@ -1375,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 c75a8192cb0..8517bdebf13 100644
--- a/gas/config/tc-loongarch.h
+++ b/gas/config/tc-loongarch.h
@@ -47,16 +47,45 @@ extern int loongarch_relax_frag (asection *, struct frag *, long);
 #define md_undefined_symbol(name) (0)
 #define md_operand(x)
 
-/* This is called to see whether a reloc against a defined symbol
+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;							\
+    }
+
+/* The following two macros let the linker resolve all the relocs
+   due to relaxation.
+   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)
+#define tc_fix_adjustable(fixp) 0
+/* The difference between same-section symbols may be affected by linker
+   relaxation, so do not resolve such expressions in the assembler.  */
+#define md_allow_local_subtract(l,r,s) 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
+
+/* Values passed to md_apply_fix don't include symbol values.  */
+#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 +94,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 +121,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 53d825310e2..a82a42b10c4 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] {
@@ -279,7 +279,7 @@ if {    ![istarget *c30*-*-*]
      && ![istarget h8300*-*-*]
      && ![istarget hppa*-*-*] } then {
     # msp430, mn10[23]00 and riscv emit two relocs to handle the difference of two symbols.
-    setup_xfail "am3*-*-*" "mn10200-*-*" "mn10300*-*-*" "msp430*-*-*" "riscv*-*-*"
+    setup_xfail "am3*-*-*" "loongarch*-*-*" "mn10200-*-*" "mn10300*-*-*" "msp430*-*-*" "riscv*-*-*"
     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 9439d103b1f..9338271c0eb 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/dwarf-5-macro-include.d b/gas/testsuite/gas/elf/dwarf-5-macro-include.d
index 32ea6386992..c39425aa8c9 100644
--- a/gas/testsuite/gas/elf/dwarf-5-macro-include.d
+++ b/gas/testsuite/gas/elf/dwarf-5-macro-include.d
@@ -4,7 +4,7 @@
 # The am33 cr16 crx ft32 mn10* msp430 nds32* and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # 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*-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am33*-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Raw dump of debug contents .*
 #...
diff --git a/gas/testsuite/gas/elf/dwarf-5-macro.d b/gas/testsuite/gas/elf/dwarf-5-macro.d
index 794e17a575e..b2613bd1c16 100644
--- a/gas/testsuite/gas/elf/dwarf-5-macro.d
+++ b/gas/testsuite/gas/elf/dwarf-5-macro.d
@@ -4,7 +4,7 @@
 # The am33 cr16 crx ft32 mn10* msp430 nds32* and rl78 targets do not evaluate the subtraction of symbols at assembly time.
 # 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*-* cr16-* crx-* d30v-* ft32-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
+#xfail: am33*-* cr16-* crx-* d30v-* ft32-* loongarch*-* mn10*-* msp430-* nds32*-* riscv*-* rl78-*
 
 Raw dump of debug contents .*
 #...
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 e2741353c61..4890dd93420 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 244b0e26145..26dc253a84c 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..2b37784f237 100644
--- a/gas/testsuite/gas/loongarch/li.d
+++ b/gas/testsuite/gas/loongarch/li.d
@@ -10,9 +10,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..3465d11d50d 100644
--- a/gas/testsuite/gas/loongarch/macro_op.d
+++ b/gas/testsuite/gas/loongarch/macro_op.d
@@ -9,51 +9,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_32.d b/gas/testsuite/gas/loongarch/macro_op_32.d
index a78c4579ee9..f5a2b54dd9b 100644
--- a/gas/testsuite/gas/loongarch/macro_op_32.d
+++ b/gas/testsuite/gas/loongarch/macro_op_32.d
@@ -14,29 +14,39 @@ Disassembly of section .text:
 [ 	]+c:[ 	]+02bffc04[ 	]+addi.w[ 	]+\$a0,[ 	]+\$zero,[ 	]+-1\(0xfff\)
 [ 	]+10:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+10:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+10:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+14:[ 	]+28800084[ 	]+ld.w[ 	]+\$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
+[ 	]+18:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+1c:[ 	]+28800084[ 	]+ld.w[ 	]+\$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[ 	]+.text
+[ 	]+20:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+20:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+24:[ 	]+02800084[ 	]+addi.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+24:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+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[ 	]+.text
+[ 	]+28:[ 	]+R_LARCH_ABS_HI20[ 	]+.L1
 [ 	]+2c:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
-[ 	]+2c:[ 	]+R_LARCH_ABS_LO12[ 	]+.text
+[ 	]+2c:[ 	]+R_LARCH_ABS_LO12[ 	]+.L1
 [ 	]+30:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+30:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+30:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+30:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+34:[ 	]+02800084[ 	]+addi.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+34:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+34:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+34:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+38:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+38:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+38:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+3c:[ 	]+28800084[ 	]+ld.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+3c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+3c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+40:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
 [ 	]+40:[ 	]+R_LARCH_TLS_LE_HI20[ 	]+TLS1
 [ 	]+44:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
@@ -49,7 +59,9 @@ Disassembly of section .text:
 [ 	]+50:[ 	]+R_LARCH_TLS_LD_PC_HI20[ 	]+TLS1
 [ 	]+54:[ 	]+02800084[ 	]+addi.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+54:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+54:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+58:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+58:[ 	]+R_LARCH_TLS_GD_PC_HI20[ 	]+TLS1
 [ 	]+5c:[ 	]+02800084[ 	]+addi.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+5c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+5c:[ 	]+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 c0b98dbbea2..f3a3a4845b9 100644
--- a/gas/testsuite/gas/loongarch/macro_op_large_abs.d
+++ b/gas/testsuite/gas/loongarch/macro_op_large_abs.d
@@ -9,36 +9,42 @@ Disassembly of section .text:
 
 00000000.* <.L1>:
 [ 	]+0:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+0:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+4:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+8:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+8:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.text
+[ 	]+8:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
 [ 	]+c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.text
+[ 	]+c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.L1
 [ 	]+10:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+14:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
 [ 	]+14:[ 	]+R_LARCH_MARK_LA[ 	]+\*ABS\*
-[ 	]+14:[ 	]+R_LARCH_ABS_HI20[ 	]+.text
+[ 	]+14:[ 	]+R_LARCH_ABS_HI20[ 	]+.L1
 [ 	]+18:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
-[ 	]+18:[ 	]+R_LARCH_ABS_LO12[ 	]+.text
+[ 	]+18:[ 	]+R_LARCH_ABS_LO12[ 	]+.L1
 [ 	]+1c:[ 	]+16000004[ 	]+lu32i.d[ 	]+\$a0,[ 	]+0
-[ 	]+1c:[ 	]+R_LARCH_ABS64_LO20[ 	]+.text
+[ 	]+1c:[ 	]+R_LARCH_ABS64_LO20[ 	]+.L1
 [ 	]+20:[ 	]+03000084[ 	]+lu52i.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+20:[ 	]+R_LARCH_ABS64_HI12[ 	]+.text
+[ 	]+20:[ 	]+R_LARCH_ABS64_HI12[ 	]+.L1
 [ 	]+24:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+24:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+24:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+24:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+28:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+28:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+28:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+28:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+2c:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+2c:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.text
+[ 	]+2c:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
 [ 	]+30:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+30:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.text
+[ 	]+30:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.L1
 [ 	]+34:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+38:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+38:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+38:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+3c:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+3c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+3c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+40:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
 [ 	]+40:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.L1
 [ 	]+44:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
@@ -61,6 +67,7 @@ Disassembly of section .text:
 [ 	]+68:[ 	]+R_LARCH_TLS_LD_PC_HI20[ 	]+TLS1
 [ 	]+6c:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+6c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+6c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+70:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
 [ 	]+70:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
 [ 	]+74:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
@@ -70,6 +77,7 @@ Disassembly of section .text:
 [ 	]+7c:[ 	]+R_LARCH_TLS_GD_PC_HI20[ 	]+TLS1
 [ 	]+80:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+80:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+80:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+84:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
 [ 	]+84:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
 [ 	]+88:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
diff --git a/gas/testsuite/gas/loongarch/macro_op_large_pc.d b/gas/testsuite/gas/loongarch/macro_op_large_pc.d
index 3b532755b6c..f3a3a4845b9 100644
--- a/gas/testsuite/gas/loongarch/macro_op_large_pc.d
+++ b/gas/testsuite/gas/loongarch/macro_op_large_pc.d
@@ -1,4 +1,4 @@
-#as:
+#as: -mla-global-with-abs
 #objdump: -dr
 #skip: loongarch32-*-*
 
@@ -9,69 +9,77 @@ Disassembly of section .text:
 
 00000000.* <.L1>:
 [ 	]+0:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+0:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+4:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+8:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+8:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.text
+[ 	]+8:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
 [ 	]+c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.text
+[ 	]+c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.L1
 [ 	]+10:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+14:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+14:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
-[ 	]+18:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+18:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
-[ 	]+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
-[ 	]+3c:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+3c:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
-[ 	]+40:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
-[ 	]+40:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
-[ 	]+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:[ 	]+R_LARCH_TLS_IE_PC_LO12[ 	]+TLS1
-[ 	]+60:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+60:[ 	]+R_LARCH_TLS_IE64_PC_LO20[ 	]+TLS1
-[ 	]+64:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+64:[ 	]+R_LARCH_TLS_IE64_PC_HI12[ 	]+TLS1
-[ 	]+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:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
-[ 	]+74:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+74:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
-[ 	]+78:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+78:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+TLS1
-[ 	]+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:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
-[ 	]+88:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+88:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
-[ 	]+8c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+8c:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+TLS1
-[ 	]+90:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+14:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
+[ 	]+14:[ 	]+R_LARCH_MARK_LA[ 	]+\*ABS\*
+[ 	]+14:[ 	]+R_LARCH_ABS_HI20[ 	]+.L1
+[ 	]+18:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
+[ 	]+18:[ 	]+R_LARCH_ABS_LO12[ 	]+.L1
+[ 	]+1c:[ 	]+16000004[ 	]+lu32i.d[ 	]+\$a0,[ 	]+0
+[ 	]+1c:[ 	]+R_LARCH_ABS64_LO20[ 	]+.L1
+[ 	]+20:[ 	]+03000084[ 	]+lu52i.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
+[ 	]+20:[ 	]+R_LARCH_ABS64_HI12[ 	]+.L1
+[ 	]+24:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
+[ 	]+24:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+24:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+28:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+28:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+28:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+2c:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+2c:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
+[ 	]+30:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+30:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.L1
+[ 	]+34:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+38:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
+[ 	]+38:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+38:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+3c:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+3c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+3c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+40:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+40:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.L1
+[ 	]+44:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+44:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.L1
+[ 	]+48:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+4c:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
+[ 	]+4c:[ 	]+R_LARCH_TLS_LE_HI20[ 	]+TLS1
+[ 	]+50:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
+[ 	]+50:[ 	]+R_LARCH_TLS_LE_LO12[ 	]+TLS1
+[ 	]+54:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
+[ 	]+54:[ 	]+R_LARCH_TLS_IE_PC_HI20[ 	]+TLS1
+[ 	]+58:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+58:[ 	]+R_LARCH_TLS_IE_PC_LO12[ 	]+TLS1
+[ 	]+5c:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+5c:[ 	]+R_LARCH_TLS_IE64_PC_LO20[ 	]+TLS1
+[ 	]+60:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+60:[ 	]+R_LARCH_TLS_IE64_PC_HI12[ 	]+TLS1
+[ 	]+64:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+68:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
+[ 	]+68:[ 	]+R_LARCH_TLS_LD_PC_HI20[ 	]+TLS1
+[ 	]+6c:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+6c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+6c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+70:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+70:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
+[ 	]+74:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+74:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+TLS1
+[ 	]+78:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+[ 	]+7c:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
+[ 	]+7c:[ 	]+R_LARCH_TLS_GD_PC_HI20[ 	]+TLS1
+[ 	]+80:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
+[ 	]+80:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+80:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+[ 	]+84:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
+[ 	]+84:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+TLS1
+[ 	]+88:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
+[ 	]+88:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+TLS1
+[ 	]+8c:[ 	]+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..8a44573d406
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/relax_align.d
@@ -0,0 +1,26 @@
+#as:
+#objdump: -dr
+#skip: loongarch32-*-*
+
+.*:[    ]+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..41ed8ff870f
--- /dev/null
+++ b/gas/testsuite/gas/loongarch/uleb128.d
@@ -0,0 +1,36 @@
+#as:
+#objdump: -Dr
+#skip: loongarch32-*-*
+
+.*:[    ]+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] 16+ messages in thread

* [PATCH v4 6/6] LoongArch: ld: Add support for linker relaxation.
  2023-05-22  1:34 [PATCH v4 0/6] LoongArch linker relaxation support mengqinggang
                   ` (4 preceding siblings ...)
  2023-05-22  1:34 ` [PATCH v4 5/6] LoongArch: gas: " mengqinggang
@ 2023-05-22  1:34 ` mengqinggang
  2023-05-22  5:40 ` [PATCH v4 0/6] LoongArch linker relaxation support Xi Ruoyao
  6 siblings, 0 replies; 16+ messages in thread
From: mengqinggang @ 2023-05-22  1:34 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, 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/disas-jirl-32.d: Regenerated.
	* testsuite/ld-loongarch-elf/jmp_op.d: Likewise.
	* testsuite/ld-loongarch-elf/macro_op.d: Likewise.
	* testsuite/ld-loongarch-elf/macro_op_32.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.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-32.d |  2 +
 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      | 84 +++++++++++++------
 ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 24 ++++--
 ld/testsuite/ld-loongarch-elf/relax-align.dd  |  7 ++
 ld/testsuite/ld-loongarch-elf/relax-align.s   |  9 ++
 ld/testsuite/ld-loongarch-elf/relax.exp       | 73 ++++++++++++++++
 ld/testsuite/ld-loongarch-elf/relax.s         | 16 ++++
 ld/testsuite/ld-loongarch-elf/uleb128.dd      | 10 +++
 ld/testsuite/ld-loongarch-elf/uleb128.s       | 21 +++++
 14 files changed, 269 insertions(+), 56 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.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 b790f645c9b..4850feb8767 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-32.d b/ld/testsuite/ld-loongarch-elf/disas-jirl-32.d
index 2f2a41afe75..cab7a5d4c99 100644
--- a/ld/testsuite/ld-loongarch-elf/disas-jirl-32.d
+++ b/ld/testsuite/ld-loongarch-elf/disas-jirl-32.d
@@ -10,6 +10,8 @@ Disassembly of section .text:
 00000000.* <_start>:
 [ 	]+0:[ 	]+1a000014[ 	]+pcalau12i[ 	]+\$t8,[ 	]+0
 [ 	]+0:[ 	]+R_LARCH_PCALA_HI20[ 	]+_start
+[ 	]+0:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+4:[ 	]+02800294[ 	]+addi.w[ 	]+\$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/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 39aa1fb929f..2649f63e566 100644
--- a/ld/testsuite/ld-loongarch-elf/macro_op.d
+++ b/ld/testsuite/ld-loongarch-elf/macro_op.d
@@ -13,16 +13,22 @@ Disassembly of section .text:
 [ 	]+c:[ 	]+02bffc04[ 	]+addi.w[ 	]+\$a0,[ 	]+\$zero,[ 	]+-1\(0xfff\)
 [ 	]+10:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+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
+[ 	]+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_GOT_PC_HI20[ 	]+.L1
+[ 	]+20:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+24:[ 	]+02c00005[ 	]+addi.d[ 	]+\$a1,[ 	]+\$zero,[ 	]+0
 [ 	]+24:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+24:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+28:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
 [ 	]+28:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.L1
 [ 	]+2c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
@@ -30,12 +36,16 @@ Disassembly of section .text:
 [ 	]+30:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+34:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+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[ 	]+.L1
+[ 	]+38:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+3c:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$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
@@ -43,77 +53,99 @@ Disassembly of section .text:
 [ 	]+4c:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
 [ 	]+50:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+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[ 	]+.L1
+[ 	]+54:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+58:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+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[ 	]+.L1
+[ 	]+5c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+60:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
 [ 	]+60:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.L1
 [ 	]+64:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
 [ 	]+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[ 	]+.L1
+[ 	]+d8:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+dc:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+dc:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+dc:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+e0:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+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[ 	]+.L1
+[ 	]+e4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+e8:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
 [ 	]+e8:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.L1
 [ 	]+ec:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
@@ -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/macro_op_32.d b/ld/testsuite/ld-loongarch-elf/macro_op_32.d
index a78c4579ee9..f5a2b54dd9b 100644
--- a/ld/testsuite/ld-loongarch-elf/macro_op_32.d
+++ b/ld/testsuite/ld-loongarch-elf/macro_op_32.d
@@ -14,29 +14,39 @@ Disassembly of section .text:
 [ 	]+c:[ 	]+02bffc04[ 	]+addi.w[ 	]+\$a0,[ 	]+\$zero,[ 	]+-1\(0xfff\)
 [ 	]+10:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+10:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+10:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+14:[ 	]+28800084[ 	]+ld.w[ 	]+\$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
+[ 	]+18:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+1c:[ 	]+28800084[ 	]+ld.w[ 	]+\$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[ 	]+.text
+[ 	]+20:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+20:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+24:[ 	]+02800084[ 	]+addi.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+24:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+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[ 	]+.text
+[ 	]+28:[ 	]+R_LARCH_ABS_HI20[ 	]+.L1
 [ 	]+2c:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
-[ 	]+2c:[ 	]+R_LARCH_ABS_LO12[ 	]+.text
+[ 	]+2c:[ 	]+R_LARCH_ABS_LO12[ 	]+.L1
 [ 	]+30:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+30:[ 	]+R_LARCH_PCALA_HI20[ 	]+.text
+[ 	]+30:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
+[ 	]+30:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+34:[ 	]+02800084[ 	]+addi.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+34:[ 	]+R_LARCH_PCALA_LO12[ 	]+.text
+[ 	]+34:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
+[ 	]+34:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+38:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+38:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.L1
+[ 	]+38:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+3c:[ 	]+28800084[ 	]+ld.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+3c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
+[ 	]+3c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+40:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
 [ 	]+40:[ 	]+R_LARCH_TLS_LE_HI20[ 	]+TLS1
 [ 	]+44:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
@@ -49,7 +59,9 @@ Disassembly of section .text:
 [ 	]+50:[ 	]+R_LARCH_TLS_LD_PC_HI20[ 	]+TLS1
 [ 	]+54:[ 	]+02800084[ 	]+addi.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+54:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+54:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
 [ 	]+58:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
 [ 	]+58:[ 	]+R_LARCH_TLS_GD_PC_HI20[ 	]+TLS1
 [ 	]+5c:[ 	]+02800084[ 	]+addi.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
 [ 	]+5c:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
+[ 	]+5c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
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.exp b/ld/testsuite/ld-loongarch-elf/relax.exp
new file mode 100644
index 00000000000..498ab201a9f
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax.exp
@@ -0,0 +1,73 @@
+# 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 loongarch64-*-*] {
+
+  set testname "loongarch relax build"
+  set pre_builds [list \
+    [list \
+      "$testname" \
+      "" \
+      "" \
+      {relax.s} \
+      {} \
+      "relax" \
+    ] \
+  ]
+
+  run_cc_link_tests $pre_builds
+
+  set objdump_output [run_host_cmd "objdump" "-d tmpdir/relax"]
+  if { [ regexp ".*pcaddi.*pcaddi.*" $objdump_output] } {
+    pass "loongarch relax"
+  } {
+    fail "loongarch 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..2979ffa3714
--- /dev/null
+++ b/ld/testsuite/ld-loongarch-elf/relax.s
@@ -0,0 +1,16 @@
+  .data
+  .global a
+  .type a, @object
+a:
+  .word 123
+
+  .text
+  .global main
+  .type main, @function
+main:
+  la.local $a0, a
+  ld.w $a1, $a0, 0
+  la.global $a0, a
+  ld.w $a0, $a0, 0
+  sub.d $a0, $a0, $a1
+  jr $ra
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] 16+ messages in thread

* Re: [PATCH v4 0/6] LoongArch linker relaxation support.
  2023-05-22  1:34 [PATCH v4 0/6] LoongArch linker relaxation support mengqinggang
                   ` (5 preceding siblings ...)
  2023-05-22  1:34 ` [PATCH v4 6/6] LoongArch: ld: " mengqinggang
@ 2023-05-22  5:40 ` Xi Ruoyao
  2023-05-22  8:14   ` mengqinggang
                     ` (3 more replies)
  6 siblings, 4 replies; 16+ messages in thread
From: Xi Ruoyao @ 2023-05-22  5:40 UTC (permalink / raw)
  To: mengqinggang, binutils
  Cc: xuchenghua, chenglulu, liuzhensong, i.swmail, maskray

On Mon, 2023-05-22 at 09:34 +0800, mengqinggang wrote:
> This is the v4 version of patches to support loongarch linker relax.
> This version mainly rebase to the master branch.
> 
> The binutils, gcc, glibc and Spec2006 testcases is ok.

Have you tried the kernel and GRUB?  AFAIK they are the most "fragile"
package regarding to this kind of optimization.  The RISC-V port of them
uses -mno-relax.

> Now, only the instrunctions expand from macro (la.local, la.global, 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.

I guess -fsection-anchors (enabled by default with any optimization
level but -O0) can also affect.  Maybe we should change GCC to use -mno-
explicit-relocs and maybe -fno-section-anchors for -Os then.  For -O1/-
O2/-O3 the benefit of scheduling is more important on a modern CPU.

> There are two code 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. 
> 
> In the future, the TLS LE code sequence and function call in medium
> code mode would be relaxed too.
> 
> For .align directive, some small problems cannot be perfectly solved (see
> http://maskray.me/blog/2021-03-14-the-dark-side-of-riscv-linker-relaxation).
>
> 
> The new relocs document at here:
>   https://github.com/loongson/LoongArch-Documentation/pull/77

But the repo is archived so any PR in it should be considered dead.  May
I "hijack" the discussion to ask the rationale about archiving it?  Note
that if you want to mean "it's stable and should not be changed w/o a
major update" you should create a tag and release instead of archiving
it.  Archiving basically mean "the repo is dead or moved elsewhere".


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

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

* Re: [PATCH v4 3/6] LoongArch: opcodes: Add support for linker relaxation.
  2023-05-22  1:34 ` [PATCH v4 3/6] LoongArch: opcodes: " mengqinggang
@ 2023-05-22  5:43   ` Xi Ruoyao
  0 siblings, 0 replies; 16+ messages in thread
From: Xi Ruoyao @ 2023-05-22  5:43 UTC (permalink / raw)
  To: mengqinggang, binutils
  Cc: xuchenghua, chenglulu, liuzhensong, i.swmail, maskray

On Mon, 2023-05-22 at 09:34 +0800, mengqinggang wrote:
> Set gas default to enable relax.
> 
> opcodes/ChangeLog:
> 
>         * loongarch-opc.c (struct loongarch_ASEs_option): New member
> relax
>         with the default value 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 39d724a3398..573b691c1fd 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 =
> +{

If I remember correctly there shouldn't be a newline for this '{'.  i.e.
"LARCH_opts = {".

> +  .relax = 1
> +};
>
>  size_t
>  loongarch_insn_length (insn_t insn ATTRIBUTE_UNUSED)

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

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

* Re: [PATCH v4 4/6] LoongArch: binutils: Add support for linker relaxation.
  2023-05-22  1:34 ` [PATCH v4 4/6] LoongArch: binutils: " mengqinggang
@ 2023-05-22  5:44   ` Xi Ruoyao
  0 siblings, 0 replies; 16+ messages in thread
From: Xi Ruoyao @ 2023-05-22  5:44 UTC (permalink / raw)
  To: mengqinggang, binutils
  Cc: xuchenghua, chenglulu, liuzhensong, i.swmail, maskray

On Mon, 2023-05-22 at 09:34 +0800, mengqinggang wrote:
> +    # LOONGARCH relax align add nops, so label subtractions will increase
         ^--------

LoongArch

If you don't respect your registered trademark other people won't :).

> +    if [istarget "loongarch*-*-*"] {
> +       set flags "-mno-relax"
> +     }

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

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

* Re: [PATCH v4 0/6] LoongArch linker relaxation support.
  2023-05-22  5:40 ` [PATCH v4 0/6] LoongArch linker relaxation support Xi Ruoyao
@ 2023-05-22  8:14   ` mengqinggang
  2023-05-22  8:18   ` Andreas Schwab
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 16+ messages in thread
From: mengqinggang @ 2023-05-22  8:14 UTC (permalink / raw)
  To: Xi Ruoyao, binutils; +Cc: xuchenghua, chenglulu, liuzhensong, i.swmail, maskray

The new ABI document is currently being organized, and there will be a
new repo that only stores ABI document.


在 2023/5/22 下午1:40, Xi Ruoyao 写道:
> On Mon, 2023-05-22 at 09:34 +0800, mengqinggang wrote:
>> This is the v4 version of patches to support loongarch linker relax.
>> This version mainly rebase to the master branch.
>>
>> The binutils, gcc, glibc and Spec2006 testcases is ok.
> Have you tried the kernel and GRUB?  AFAIK they are the most "fragile"
> package regarding to this kind of optimization.  The RISC-V port of them
> uses -mno-relax.
>
>> Now, only the instrunctions expand from macro (la.local, la.global, 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.
> I guess -fsection-anchors (enabled by default with any optimization
> level but -O0) can also affect.  Maybe we should change GCC to use -mno-
> explicit-relocs and maybe -fno-section-anchors for -Os then.  For -O1/-
> O2/-O3 the benefit of scheduling is more important on a modern CPU.
>
>> There are two code 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.
>>
>> In the future, the TLS LE code sequence and function call in medium
>> code mode would be relaxed too.
>>
>> For .align directive, some small problems cannot be perfectly solved (see
>> http://maskray.me/blog/2021-03-14-the-dark-side-of-riscv-linker-relaxation).
>>
>>
>> The new relocs document at here:
>>    https://github.com/loongson/LoongArch-Documentation/pull/77
> But the repo is archived so any PR in it should be considered dead.  May
> I "hijack" the discussion to ask the rationale about archiving it?  Note
> that if you want to mean "it's stable and should not be changed w/o a
> major update" you should create a tag and release instead of archiving
> it.  Archiving basically mean "the repo is dead or moved elsewhere".
>
>


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

* Re: [PATCH v4 0/6] LoongArch linker relaxation support.
  2023-05-22  5:40 ` [PATCH v4 0/6] LoongArch linker relaxation support Xi Ruoyao
  2023-05-22  8:14   ` mengqinggang
@ 2023-05-22  8:18   ` Andreas Schwab
  2023-05-22 10:04   ` mengqinggang
  2023-05-24  9:58   ` mengqinggang
  3 siblings, 0 replies; 16+ messages in thread
From: Andreas Schwab @ 2023-05-22  8:18 UTC (permalink / raw)
  To: Xi Ruoyao via Binutils
  Cc: mengqinggang, Xi Ruoyao, xuchenghua, chenglulu, liuzhensong,
	i.swmail, maskray

On Mai 22 2023, Xi Ruoyao via Binutils wrote:

> Have you tried the kernel and GRUB?  AFAIK they are the most "fragile"
> package regarding to this kind of optimization.  The RISC-V port of them
> uses -mno-relax.

GRUB does not use -mno-relax (it just ignores R_RISCV_RELAX).

-- 
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] 16+ messages in thread

* Re: [PATCH v4 0/6] LoongArch linker relaxation support.
  2023-05-22  5:40 ` [PATCH v4 0/6] LoongArch linker relaxation support Xi Ruoyao
  2023-05-22  8:14   ` mengqinggang
  2023-05-22  8:18   ` Andreas Schwab
@ 2023-05-22 10:04   ` mengqinggang
  2023-05-22 11:04     ` Xi Ruoyao
  2023-05-24  9:58   ` mengqinggang
  3 siblings, 1 reply; 16+ messages in thread
From: mengqinggang @ 2023-05-22 10:04 UTC (permalink / raw)
  To: Xi Ruoyao, binutils; +Cc: xuchenghua, chenglulu, liuzhensong, i.swmail, maskray

For -fsection-anchors, I think it is less affected by relax.  Could you 
please
give some special question about this?


On LoongArch architecture, -mno-explicit-relocs may have a higher 
performance
than -mexplicit-relocs for some large program.


在 2023/5/22 下午1:40, Xi Ruoyao 写道:
> On Mon, 2023-05-22 at 09:34 +0800, mengqinggang wrote:
>> This is the v4 version of patches to support loongarch linker relax.
>> This version mainly rebase to the master branch.
>>
>> The binutils, gcc, glibc and Spec2006 testcases is ok.
> Have you tried the kernel and GRUB?  AFAIK they are the most "fragile"
> package regarding to this kind of optimization.  The RISC-V port of them
> uses -mno-relax.
>
>> Now, only the instrunctions expand from macro (la.local, la.global, 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.
> I guess -fsection-anchors (enabled by default with any optimization
> level but -O0) can also affect.  Maybe we should change GCC to use -mno-
> explicit-relocs and maybe -fno-section-anchors for -Os then.  For -O1/-
> O2/-O3 the benefit of scheduling is more important on a modern CPU.
>
>> There are two code 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.
>>
>> In the future, the TLS LE code sequence and function call in medium
>> code mode would be relaxed too.
>>
>> For .align directive, some small problems cannot be perfectly solved (see
>> http://maskray.me/blog/2021-03-14-the-dark-side-of-riscv-linker-relaxation).
>>
>>
>> The new relocs document at here:
>>    https://github.com/loongson/LoongArch-Documentation/pull/77
> But the repo is archived so any PR in it should be considered dead.  May
> I "hijack" the discussion to ask the rationale about archiving it?  Note
> that if you want to mean "it's stable and should not be changed w/o a
> major update" you should create a tag and release instead of archiving
> it.  Archiving basically mean "the repo is dead or moved elsewhere".
>
>


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

* Re: [PATCH v4 0/6] LoongArch linker relaxation support.
  2023-05-22 10:04   ` mengqinggang
@ 2023-05-22 11:04     ` Xi Ruoyao
  2023-05-23  2:04       ` mengqinggang
  0 siblings, 1 reply; 16+ messages in thread
From: Xi Ruoyao @ 2023-05-22 11:04 UTC (permalink / raw)
  To: mengqinggang, binutils
  Cc: xuchenghua, chenglulu, liuzhensong, i.swmail, maskray

On Mon, 2023-05-22 at 18:04 +0800, mengqinggang wrote:
> For -fsection-anchors, I think it is less affected by relax.  Could
> you 
> please
> give some special question about this?

Alright, it seems I'd misunderstood -fsection-anchors with -mno-
explicit-relocs.  It generates things like:

la.pcrel t0, .ANCHOR0 + 8
la.pcrel t1, .ANCHOR0 + 16

Not

la.pcrel t2, .ANCHOR0
addi.d t0, t2, 8
addi.d t1, t2, 16

which may puzzle the relaxation pass.

> On LoongArch architecture, -mno-explicit-relocs may have a higher 
> performance
> than -mexplicit-relocs for some large program.

I'd consider this situation "bad" as a distro maintainer will need to
decide this on per-package or even per-link-unit basis if (s)he really
wants to squeeze the last drop of the performance...  Is there any
possibility to make both scheduling and relaxation work?


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

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

* Re: [PATCH v4 0/6] LoongArch linker relaxation support.
  2023-05-22 11:04     ` Xi Ruoyao
@ 2023-05-23  2:04       ` mengqinggang
  0 siblings, 0 replies; 16+ messages in thread
From: mengqinggang @ 2023-05-23  2:04 UTC (permalink / raw)
  To: Xi Ruoyao, binutils; +Cc: xuchenghua, chenglulu, liuzhensong, i.swmail, maskray

For -mexplicit-relocs, two addi.d may share one pcalau12i after gcc
scheduling like this:

     pcalau12i $t0, %pc_hi20(a)
     beq $t1, $t2, L1
     addi.d $t0, %pc_lo12(a)
L1:
     addi.d $t0, %pc_lo12(a)

If the first pcalau12i and addi.d be relaxed to pcaddi, the last
addi.d would get error address.


I guess riscv function call relaxation has the same question.
Riscv function call using 'call' instruction in  -mexplicit-relocs and
-mno-explicit-relocs. And R_RISCV_CALL relocation size is 8
bytes, so it can directly process two instructions expand from
'call' instruction.


在 2023/5/22 下午7:04, Xi Ruoyao 写道:
> On Mon, 2023-05-22 at 18:04 +0800, mengqinggang wrote:
>> For -fsection-anchors, I think it is less affected by relax.  Could
>> you
>> please
>> give some special question about this?
> Alright, it seems I'd misunderstood -fsection-anchors with -mno-
> explicit-relocs.  It generates things like:
>
> la.pcrel t0, .ANCHOR0 + 8
> la.pcrel t1, .ANCHOR0 + 16
>
> Not
>
> la.pcrel t2, .ANCHOR0
> addi.d t0, t2, 8
> addi.d t1, t2, 16
>
> which may puzzle the relaxation pass.
>
>> On LoongArch architecture, -mno-explicit-relocs may have a higher
>> performance
>> than -mexplicit-relocs for some large program.
> I'd consider this situation "bad" as a distro maintainer will need to
> decide this on per-package or even per-link-unit basis if (s)he really
> wants to squeeze the last drop of the performance...  Is there any
> possibility to make both scheduling and relaxation work?
>
>


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

* Re: [PATCH v4 0/6] LoongArch linker relaxation support.
  2023-05-22  5:40 ` [PATCH v4 0/6] LoongArch linker relaxation support Xi Ruoyao
                     ` (2 preceding siblings ...)
  2023-05-22 10:04   ` mengqinggang
@ 2023-05-24  9:58   ` mengqinggang
  3 siblings, 0 replies; 16+ messages in thread
From: mengqinggang @ 2023-05-24  9:58 UTC (permalink / raw)
  To: Xi Ruoyao, binutils; +Cc: xuchenghua, chenglulu, liuzhensong, i.swmail, maskray

There are some "unsupported relocation" compile errors for grub,
because grub currently does not support relax/b16/b21/add/sub relocations.


For kernel, I just did a simple test. It can be compiled correctly, and
the OS can boot normally.


在 2023/5/22 下午1:40, Xi Ruoyao 写道:
> On Mon, 2023-05-22 at 09:34 +0800, mengqinggang wrote:
>> This is the v4 version of patches to support loongarch linker relax.
>> This version mainly rebase to the master branch.
>>
>> The binutils, gcc, glibc and Spec2006 testcases is ok.
> Have you tried the kernel and GRUB?  AFAIK they are the most "fragile"
> package regarding to this kind of optimization.  The RISC-V port of them
> uses -mno-relax.
>
>> Now, only the instrunctions expand from macro (la.local, la.global, 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.
> I guess -fsection-anchors (enabled by default with any optimization
> level but -O0) can also affect.  Maybe we should change GCC to use -mno-
> explicit-relocs and maybe -fno-section-anchors for -Os then.  For -O1/-
> O2/-O3 the benefit of scheduling is more important on a modern CPU.
>
>> There are two code 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.
>>
>> In the future, the TLS LE code sequence and function call in medium
>> code mode would be relaxed too.
>>
>> For .align directive, some small problems cannot be perfectly solved (see
>> http://maskray.me/blog/2021-03-14-the-dark-side-of-riscv-linker-relaxation).
>>
>>
>> The new relocs document at here:
>>    https://github.com/loongson/LoongArch-Documentation/pull/77
> But the repo is archived so any PR in it should be considered dead.  May
> I "hijack" the discussion to ask the rationale about archiving it?  Note
> that if you want to mean "it's stable and should not be changed w/o a
> major update" you should create a tag and release instead of archiving
> it.  Archiving basically mean "the repo is dead or moved elsewhere".
>
>


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

end of thread, other threads:[~2023-05-24  9:58 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-22  1:34 [PATCH v4 0/6] LoongArch linker relaxation support mengqinggang
2023-05-22  1:34 ` [PATCH v4 1/6] LoongArch: include: Add support for linker relaxation mengqinggang
2023-05-22  1:34 ` [PATCH v4 2/6] LoongArch: bfd: " mengqinggang
2023-05-22  1:34 ` [PATCH v4 3/6] LoongArch: opcodes: " mengqinggang
2023-05-22  5:43   ` Xi Ruoyao
2023-05-22  1:34 ` [PATCH v4 4/6] LoongArch: binutils: " mengqinggang
2023-05-22  5:44   ` Xi Ruoyao
2023-05-22  1:34 ` [PATCH v4 5/6] LoongArch: gas: " mengqinggang
2023-05-22  1:34 ` [PATCH v4 6/6] LoongArch: ld: " mengqinggang
2023-05-22  5:40 ` [PATCH v4 0/6] LoongArch linker relaxation support Xi Ruoyao
2023-05-22  8:14   ` mengqinggang
2023-05-22  8:18   ` Andreas Schwab
2023-05-22 10:04   ` mengqinggang
2023-05-22 11:04     ` Xi Ruoyao
2023-05-23  2:04       ` mengqinggang
2023-05-24  9: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).