public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC)
@ 2023-12-22 11:42 Lulu Cai
  2023-12-22 11:42 ` [PATCH v5 1/5] LoongArch: Add new relocs and macro for TLSDESC Lulu Cai
                   ` (5 more replies)
  0 siblings, 6 replies; 19+ messages in thread
From: Lulu Cai @ 2023-12-22 11:42 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, mengqinggang, xry111,
	i.swmail, maskray, luweining, wanglei, hejinyang, Lulu Cai

v5 mainly changes the relocation name and adds relocation
for immediate value field of ld.w/d.

1. R_LARCH_TLS_DESC_ADD_PC_LO12 -> R_LARCH_TLS_DESC_PC_LO12.
   R_LARCH_TLS_DESC_LD(113)     -> R_LARCH_TLS_DESC_LD(119)

2. Added 32 abs test case.

3. Added R_LARCH_TLS_DESC_LD relocation to the immediate field of
   the ld.w/d instruction.

   Such as:
   pcalau12i $r4,%desc_pc_hi20(var)
   addi.d $r4,$r4,%desc_pc_lo12(var)
   ld.d $r1,$r4,0                    -> ld.d $r1,$r4,%desc_ld(var)
   jirl $r1,$r1,%desc_call(var)
   addi.d $a0,$a0,$tp

Lulu Cai (4):
  LoongArch: Add new relocs and macro for TLSDESC.
  LoongArch: Add support for TLSDESC in ld.
  LoongArch: Add tls transition support.
  LoongArch: Add testsuit for DESC and tls transition and tls
    relaxation.

mengqinggang (1):
  LoongArch: Add support for TLS LD/GD/DESC relaxation

 bfd/bfd-in2.h                                 |  15 +
 bfd/elfnn-loongarch.c                         | 552 +++++++++++++++++-
 bfd/elfxx-loongarch.c                         | 270 ++++++++-
 bfd/libbfd.h                                  |  15 +
 bfd/reloc.c                                   |  36 ++
 gas/config/tc-loongarch.c                     |  20 +-
 gas/testsuite/gas/loongarch/macro_op.d        | 128 ++--
 gas/testsuite/gas/loongarch/macro_op_32.d     | 120 ++--
 .../gas/loongarch/macro_op_large_abs.d        | 160 ++---
 .../gas/loongarch/macro_op_large_pc.d         | 160 ++---
 gas/testsuite/gas/loongarch/tlsdesc_32.d      |  28 +
 gas/testsuite/gas/loongarch/tlsdesc_32.s      |  12 +
 gas/testsuite/gas/loongarch/tlsdesc_32_abs.d  |  26 +
 gas/testsuite/gas/loongarch/tlsdesc_32_abs.s  |   8 +
 gas/testsuite/gas/loongarch/tlsdesc_64.d      |  28 +
 gas/testsuite/gas/loongarch/tlsdesc_64.s      |  12 +
 .../gas/loongarch/tlsdesc_large_abs.d         |  34 ++
 .../gas/loongarch/tlsdesc_large_abs.s         |  12 +
 .../gas/loongarch/tlsdesc_large_pc.d          |  38 ++
 .../gas/loongarch/tlsdesc_large_pc.s          |  17 +
 include/elf/loongarch.h                       |  26 +-
 include/opcode/loongarch.h                    |   6 +
 ld/testsuite/ld-loongarch-elf/desc-ie.d       |  16 +
 ld/testsuite/ld-loongarch-elf/desc-ie.s       |  18 +
 ld/testsuite/ld-loongarch-elf/desc-le.d       |  15 +
 ld/testsuite/ld-loongarch-elf/desc-le.s       |  14 +
 ld/testsuite/ld-loongarch-elf/desc-norelax.d  |  16 +
 ld/testsuite/ld-loongarch-elf/desc-norelax.s  |   5 +
 ld/testsuite/ld-loongarch-elf/desc-relax.d    |  15 +
 ld/testsuite/ld-loongarch-elf/desc-relax.s    |   5 +
 ld/testsuite/ld-loongarch-elf/ie-le.d         |  13 +
 ld/testsuite/ld-loongarch-elf/ie-le.s         |  11 +
 .../ld-loongarch-elf/ld-loongarch-elf.exp     |   9 +
 ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++------
 ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 ++--
 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d   |  56 ++
 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.s   |  65 +++
 opcodes/loongarch-opc.c                       |  54 ++
 38 files changed, 1980 insertions(+), 566 deletions(-)
 create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32.d
 create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32.s
 create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32_abs.d
 create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32_abs.s
 create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_64.d
 create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_64.s
 create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_abs.d
 create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_abs.s
 create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_pc.d
 create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_pc.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/desc-ie.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/desc-ie.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/desc-le.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/desc-le.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/desc-norelax.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/desc-norelax.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/desc-relax.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/desc-relax.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/ie-le.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/ie-le.s
 create mode 100644 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
 create mode 100644 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.s

-- 
2.43.0


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

* [PATCH v5 1/5] LoongArch: Add new relocs and macro for TLSDESC.
  2023-12-22 11:42 [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC) Lulu Cai
@ 2023-12-22 11:42 ` Lulu Cai
  2023-12-22 11:42 ` [PATCH v5 2/5] LoongArch: Add support for TLSDESC in ld Lulu Cai
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 19+ messages in thread
From: Lulu Cai @ 2023-12-22 11:42 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, mengqinggang, xry111,
	i.swmail, maskray, luweining, wanglei, hejinyang, Lulu Cai

The normal DESC instruction sequence is:
  pcalau12i  $a0,%desc_pc_hi20(var)     #R_LARCH_TLS_DESC_PC_HI20
  addi.d     $a0,$a0,%desc_pc_lo12(var) #R_LARCH_TLS_DESC_PC_LO12
  ld.d       $ra,$a0,%desc_ld(var)	#R_LARCH_TLS_DESC_LD
  jirl       $ra,$ra,%desc_call(var)	#R_LARCH_TLS_DESC_CALL
  add.d	     $a0,$a0,$tp
---
 bfd/bfd-in2.h             |  12 +++
 bfd/elfxx-loongarch.c     | 210 +++++++++++++++++++++++++++++++++++++-
 bfd/libbfd.h              |  12 +++
 bfd/reloc.c               |  29 ++++++
 gas/config/tc-loongarch.c |  14 ++-
 include/elf/loongarch.h   |  22 +++-
 opcodes/loongarch-opc.c   |  54 ++++++++++
 7 files changed, 349 insertions(+), 4 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 53c40ec41d4..85251aa0edd 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -7377,6 +7377,8 @@ enum bfd_reloc_code_real
   BFD_RELOC_LARCH_TLS_DTPREL64,
   BFD_RELOC_LARCH_TLS_TPREL32,
   BFD_RELOC_LARCH_TLS_TPREL64,
+  BFD_RELOC_LARCH_TLS_DESC32,
+  BFD_RELOC_LARCH_TLS_DESC64,
   BFD_RELOC_LARCH_MARK_LA,
   BFD_RELOC_LARCH_MARK_PCREL,
   BFD_RELOC_LARCH_SOP_PUSH_PCREL,
@@ -7461,6 +7463,16 @@ enum bfd_reloc_code_real
   BFD_RELOC_LARCH_SUB_ULEB128,
   BFD_RELOC_LARCH_64_PCREL,
   BFD_RELOC_LARCH_CALL36,
+  BFD_RELOC_LARCH_TLS_DESC_PC_HI20,
+  BFD_RELOC_LARCH_TLS_DESC_PC_LO12,
+  BFD_RELOC_LARCH_TLS_DESC64_PC_LO20,
+  BFD_RELOC_LARCH_TLS_DESC64_PC_HI12,
+  BFD_RELOC_LARCH_TLS_DESC_HI20,
+  BFD_RELOC_LARCH_TLS_DESC_LO12,
+  BFD_RELOC_LARCH_TLS_DESC64_LO20,
+  BFD_RELOC_LARCH_TLS_DESC64_HI12,
+  BFD_RELOC_LARCH_TLS_DESC_LD,
+  BFD_RELOC_LARCH_TLS_DESC_CALL,
   BFD_RELOC_UNUSED
 };
 typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index 679b79f34a4..30a941a851f 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -293,8 +293,40 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 NULL,				  /* adjust_reloc_bits */
 	 NULL),				  /* larch_reloc_type_name */
 
-  LOONGARCH_EMPTY_HOWTO (13),
-  LOONGARCH_EMPTY_HOWTO (14),
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC32,	  /* type (13).  */
+	 0,				  /* rightshift.  */
+	 4,				  /* size.  */
+	 32,				  /* bitsize.  */
+	 false,				  /* pc_relative.  */
+	 0,				  /* bitpos.  */
+	 complain_overflow_dont,	  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,		  /* special_function.  */
+	 "R_LARCH_TLS_DESC32",		  /* name.  */
+	 false,				  /* partial_inplace.  */
+	 0,				  /* src_mask.  */
+	 ALL_ONES,		  	  /* dst_mask.  */
+	 false,				  /* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_DESC32,	  /* bfd_reloc_code_real_type.  */
+	 NULL,				  /* adjust_reloc_bits.  */
+	 NULL),				  /* larch_reloc_type_name.  */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC64,	  /* type (14).  */
+	 0,				  /* rightshift.  */
+	 4,				  /* size.  */
+	 64,				  /* bitsize.  */
+	 false,				  /* pc_relative.  */
+	 0,				  /* bitpos.  */
+	 complain_overflow_dont,	  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,		  /* special_function.  */
+	 "R_LARCH_TLS_DESC64",		  /* name.  */
+	 false,				  /* partial_inplace.  */
+	 0,				  /* src_mask.  */
+	 ALL_ONES,			  /* dst_mask.  */
+	 false,				  /* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_DESC64,	  /* bfd_reloc_code_real_type.  */
+	 NULL,				  /* adjust_reloc_bits.  */
+	 NULL),				  /* larch_reloc_type_name.  */
+
   LOONGARCH_EMPTY_HOWTO (15),
   LOONGARCH_EMPTY_HOWTO (16),
   LOONGARCH_EMPTY_HOWTO (17),
@@ -1569,6 +1601,180 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 BFD_RELOC_LARCH_CALL36,		/* bfd_reloc_code_real_type.  */
 	 reloc_sign_bits,			/* adjust_reloc_bits.  */
 	 "call36"),				/* larch_reloc_type_name.  */
+
+  /* TLS_DESC PCREL.  */
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PC_HI20,	/* type (111).  */
+	 12,					/* rightshift.  */
+	 4,					/* size.  */
+	 20,					/* bitsize.  */
+	 true,					/* pc_relative.  */
+	 5,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_TLS_DESC_PC_HI20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0x1ffffe0,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_DESC_PC_HI20,	/* bfd_reloc_code_real_type.  */
+	 reloc_bits,				/* adjust_reloc_bits.  */
+	 "desc_pc_hi20"),			/* larch_reloc_type_name.  */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PC_LO12,	/* type (112).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 12,					/* bitsize.  */
+	 true,					/* pc_relative.  */
+	 10,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_TLS_DESC_PC_LO12",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0x3ffc00,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_DESC_PC_LO12,	/* bfd_reloc_code_real_type.  */
+	 reloc_bits,				/* adjust_reloc_bits.  */
+	 "desc_pc_lo12"),			/* larch_reloc_type_name.  */
+
+  /* TLS_DESC64 LARGE PCREL.  */
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_PC_LO20, /* type (113).  */
+	32,				       /* rightshift.  */
+	8,				       /* size.  */
+	20,				       /* bitsize.  */
+	true,				       /* pc_relative.  */
+	5,				       /* bitpos.  */
+	complain_overflow_signed,	       /* complain_on_overflow.  */
+	bfd_elf_generic_reloc,		       /* special_function.  */
+	"R_LARCH_TLS_DESC64_PC_LO20",	       /* name.  */
+	false,				       /* partial_inplace.  */
+	0,				       /* src_mask.  */
+	0x1ffffe0,			       /* dst_mask.  */
+	false,				       /* pcrel_offset.  */
+	BFD_RELOC_LARCH_TLS_DESC64_PC_LO20,    /* bfd_reloc_code_real_type.  */
+	reloc_bits,			       /* adjust_reloc_bits.  */
+	"desc64_pc_lo20"),		       /* larch_reloc_type_name.  */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_PC_HI12, /* type (114).  */
+	52,				       /* rightshift.  */
+	8,				       /* size.  */
+	12,				       /* bitsize.  */
+	true,				       /* pc_relative.  */
+	10,				       /* bitpos.  */
+	complain_overflow_signed,	       /* complain_on_overflow.  */
+	bfd_elf_generic_reloc,		       /* special_function.  */
+	"R_LARCH_TLS_DESC64_PC_HI12",	       /* name.  */
+	false,				       /* partial_inplace.  */
+	0,				       /* src_mask.  */
+	0x3ffc00,			       /* dst_mask.  */
+	false,				       /* pcrel_offset.  */
+	BFD_RELOC_LARCH_TLS_DESC64_PC_HI12,    /* bfd_reloc_code_real_type.  */
+	reloc_bits,			       /* adjust_reloc_bits.  */
+	"desc64_pc_hi12"),		       /* larch_reloc_type_name.  */
+
+  /* TLS_DESC ABS.  */
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_HI20,	/* type (115).  */
+	 12,					/* rightshift.  */
+	 4,					/* size.  */
+	 20,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 5,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_TLS_DESC_HI20",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0x1ffffe0,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_DESC_HI20,		/* bfd_reloc_code_real_type.  */
+	 reloc_bits,				/* adjust_reloc_bits.  */
+	 "desc_hi20"),				/* larch_reloc_type_name.  */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_LO12,	/* type (116).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 12,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 10,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_TLS_DESC_LO12",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0x3ffc00,				/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_DESC_LO12,		/* bfd_reloc_code_real_type.  */
+	 reloc_bits,				/* adjust_reloc_bits.  */
+	 "desc_lo12"),				/* larch_reloc_type_name.  */
+
+  /* TLS_DESC64 LARGE ABS.  */
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_LO20,    /* type (117).  */
+	32,				       /* rightshift.  */
+	8,				       /* size.  */
+	20,				       /* bitsize.  */
+	false,				       /* pc_relative.  */
+	5,				       /* bitpos.  */
+	complain_overflow_signed,	       /* complain_on_overflow.  */
+	bfd_elf_generic_reloc,		       /* special_function.  */
+	"R_LARCH_TLS_DESC64_LO20",	       /* name.  */
+	false,				       /* partial_inplace.  */
+	0,				       /* src_mask.  */
+	0x1ffffe0,			       /* dst_mask.  */
+	false,				       /* pcrel_offset.  */
+	BFD_RELOC_LARCH_TLS_DESC64_LO20,       /* bfd_reloc_code_real_type.  */
+	reloc_bits,			       /* adjust_reloc_bits.  */
+	"desc64_lo20"),			       /* larch_reloc_type_name.  */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC64_HI12,    /* type (118).  */
+	52,				       /* rightshift.  */
+	8,				       /* size.  */
+	12,				       /* bitsize.  */
+	false,				       /* pc_relative.  */
+	10,				       /* bitpos.  */
+	complain_overflow_signed,	       /* complain_on_overflow.  */
+	bfd_elf_generic_reloc,		       /* special_function.  */
+	"R_LARCH_TLS_DESC64_HI12",	       /* name.  */
+	false,				       /* partial_inplace.  */
+	0,				       /* src_mask.  */
+	0x3ffc00,			       /* dst_mask.  */
+	false,				       /* pcrel_offset.  */
+	BFD_RELOC_LARCH_TLS_DESC64_HI12,       /* bfd_reloc_code_real_type.  */
+	reloc_bits,			       /* adjust_reloc_bits.  */
+	"desc64_hi12"),			       /* larch_reloc_type_name.  */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_LD,		/* type (119).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 0,					/* bitsize.  */
+	 true,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_signed,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_TLS_DESC_LD",			/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_DESC_LD,		/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 "desc_ld"),				/* larch_reloc_type_name.  */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_CALL,	/* type (120).  */
+	 0,					/* rightshift.  */
+	 4,					/* size.  */
+	 0,					/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,					/* bitpos.  */
+	 complain_overflow_dont,		/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,			/* special_function.  */
+	 "R_LARCH_TLS_DESC_CALL",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0,					/* dst_mask.  */
+	 false,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_DESC_CALL,		/* bfd_reloc_code_real_type.  */
+	 NULL,					/* adjust_reloc_bits.  */
+	 "desc_call"),				/* larch_reloc_type_name.  */
 };
 
 reloc_howto_type *
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 399b1f688bb..71b03da14d9 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -3516,6 +3516,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_LARCH_TLS_DTPREL64",
   "BFD_RELOC_LARCH_TLS_TPREL32",
   "BFD_RELOC_LARCH_TLS_TPREL64",
+  "BFD_RELOC_LARCH_TLS_DESC32",
+  "BFD_RELOC_LARCH_TLS_DESC64",
   "BFD_RELOC_LARCH_MARK_LA",
   "BFD_RELOC_LARCH_MARK_PCREL",
   "BFD_RELOC_LARCH_SOP_PUSH_PCREL",
@@ -3600,6 +3602,16 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_LARCH_SUB_ULEB128",
   "BFD_RELOC_LARCH_64_PCREL",
   "BFD_RELOC_LARCH_CALL36",
+  "BFD_RELOC_LARCH_TLS_DESC_PC_HI20",
+  "BFD_RELOC_LARCH_TLS_DESC_PC_LO12",
+  "BFD_RELOC_LARCH_TLS_DESC64_PC_LO20",
+  "BFD_RELOC_LARCH_TLS_DESC64_PC_HI12",
+  "BFD_RELOC_LARCH_TLS_DESC_HI20",
+  "BFD_RELOC_LARCH_TLS_DESC_LO12",
+  "BFD_RELOC_LARCH_TLS_DESC64_LO20",
+  "BFD_RELOC_LARCH_TLS_DESC64_HI12",
+  "BFD_RELOC_LARCH_TLS_DESC_LD",
+  "BFD_RELOC_LARCH_TLS_DESC_CALL",
  "@@overflow: BFD_RELOC_UNUSED@@",
 };
 #endif
diff --git a/bfd/reloc.c b/bfd/reloc.c
index 4d3ac4c1096..f7fe0c7ffe3 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -8111,6 +8111,10 @@ ENUMX
   BFD_RELOC_LARCH_TLS_TPREL32
 ENUMX
   BFD_RELOC_LARCH_TLS_TPREL64
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC32
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC64
 ENUMX
   BFD_RELOC_LARCH_MARK_LA
 ENUMX
@@ -8295,6 +8299,31 @@ ENUMX
 ENUMX
   BFD_RELOC_LARCH_CALL36
 
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC_PC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC_PC_LO12
+
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC64_PC_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC64_PC_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC_HI20
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC_LO12
+
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC64_LO20
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC64_HI12
+
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC_LD
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC_CALL
+
 ENUMDOC
   LARCH relocations.
 
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 9b912daf407..1658025f918 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -682,7 +682,7 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
 		      esc_ch1, esc_ch2, bit_field, arg);
 
 	  if (ip->reloc_info[0].type >= BFD_RELOC_LARCH_B16
-	      && ip->reloc_info[0].type < BFD_RELOC_UNUSED)
+	      && ip->reloc_info[0].type <= BFD_RELOC_LARCH_TLS_DESC_CALL)
 	    {
 	      /* As we compact stack-relocs, it is no need for pop operation.
 		 But break out until here in order to check the imm field.
@@ -1274,6 +1274,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_LARCH_TLS_LD_HI20:
     case BFD_RELOC_LARCH_TLS_GD_PC_HI20:
     case BFD_RELOC_LARCH_TLS_GD_HI20:
+    case BFD_RELOC_LARCH_TLS_DESC_PC_HI20:
+    case BFD_RELOC_LARCH_TLS_DESC_PC_LO12:
+    case BFD_RELOC_LARCH_TLS_DESC64_PC_LO20:
+    case BFD_RELOC_LARCH_TLS_DESC64_PC_HI12:
+    case BFD_RELOC_LARCH_TLS_DESC_HI20:
+    case BFD_RELOC_LARCH_TLS_DESC_LO12:
+    case BFD_RELOC_LARCH_TLS_DESC64_LO20:
+    case BFD_RELOC_LARCH_TLS_DESC64_HI12:
       /* Add tls lo (got_lo reloc type).  */
       if (fixP->fx_addsy == NULL)
 	as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -1294,6 +1302,10 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 	stack_top = 0;
       break;
 
+    case BFD_RELOC_LARCH_TLS_DESC_LD:
+    case BFD_RELOC_LARCH_TLS_DESC_CALL:
+      break;
+
     case BFD_RELOC_LARCH_SOP_POP_32_S_10_5:
     case BFD_RELOC_LARCH_SOP_POP_32_S_10_12:
     case BFD_RELOC_LARCH_SOP_POP_32_U_10_12:
diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h
index 34719ee8b8c..41e9fe4d234 100644
--- a/include/elf/loongarch.h
+++ b/include/elf/loongarch.h
@@ -38,7 +38,8 @@ RELOC_NUMBER (R_LARCH_TLS_DTPREL64, 9)
 RELOC_NUMBER (R_LARCH_TLS_TPREL32, 10)
 RELOC_NUMBER (R_LARCH_TLS_TPREL64, 11)
 RELOC_NUMBER (R_LARCH_IRELATIVE, 12)
-
+RELOC_NUMBER (R_LARCH_TLS_DESC32, 13)
+RELOC_NUMBER (R_LARCH_TLS_DESC64, 14)
 /* Reserved for future relocs that the dynamic linker must understand.  */
 
 /* Used by the static linker for relocating .text.  */
@@ -253,6 +254,25 @@ RELOC_NUMBER (R_LARCH_64_PCREL, 109)
 
 RELOC_NUMBER (R_LARCH_CALL36, 110)
 
+/* TLS_DESC PCREL.  */
+RELOC_NUMBER (R_LARCH_TLS_DESC_PC_HI20, 111)
+RELOC_NUMBER (R_LARCH_TLS_DESC_PC_LO12, 112)
+
+/* TLS_DESC LARGE PCREL.  */
+RELOC_NUMBER (R_LARCH_TLS_DESC64_PC_LO20, 113)
+RELOC_NUMBER (R_LARCH_TLS_DESC64_PC_HI12, 114)
+
+/* TLS_DESC ABS.  */
+RELOC_NUMBER (R_LARCH_TLS_DESC_HI20, 115)
+RELOC_NUMBER (R_LARCH_TLS_DESC_LO12, 116)
+
+/* TLSDESC LARGE ABS.  */
+RELOC_NUMBER (R_LARCH_TLS_DESC64_LO20, 117)
+RELOC_NUMBER (R_LARCH_TLS_DESC64_HI12, 118)
+
+RELOC_NUMBER (R_LARCH_TLS_DESC_LD, 119)
+RELOC_NUMBER (R_LARCH_TLS_DESC_CALL, 120)
+
 END_RELOC_NUMBERS (R_LARCH_count)
 
 /* Processor specific flags for the ELF header e_flags field.  */
diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c
index b47817f8f4b..3ca521267cf 100644
--- a/opcodes/loongarch-opc.c
+++ b/opcodes/loongarch-opc.c
@@ -303,6 +303,55 @@ const char *const loongarch_x_normal_name[32] =
   "jirl $zero,%1,0;",   \
   0, 0
 
+/* For TLS_DESC32 pcrel.  */
+#define INSN_LA_TLS_DESC32		\
+  "pcalau12i $r4,%%desc_pc_hi20(%2);"	\
+  "addi.w $r4,$r4,%%desc_pc_lo12(%2);"	\
+  "ld.w $r1,$r4,%%desc_ld(%2);"		\
+  "jirl $r1,$r1,%%desc_call(%2);",	\
+  &LARCH_opts.ase_ilp32,		\
+  &LARCH_opts.ase_lp64
+
+/* For TLS_DESC32 abs.  */
+#define INSN_LA_TLS_DESC32_ABS		\
+  "lu12i.w $r4,%%desc_hi20(%2);"	\
+  "ori $r4,$r4,%%desc_lo12(%2);"	\
+  "ld.w $r1,$r4,%%desc_ld(%2);"		\
+  "jirl $r1,$r1,%%desc_call(%2);",	\
+  &LARCH_opts.ase_gabs,			\
+  &LARCH_opts.ase_lp64
+
+/* For TLS_DESC64 pcrel.  */
+#define INSN_LA_TLS_DESC64		\
+  "pcalau12i $r4,%%desc_pc_hi20(%2);"	\
+  "addi.d $r4,$r4,%%desc_pc_lo12(%2);"	\
+  "ld.d $r1,$r4,%%desc_ld(%2);"		\
+  "jirl $r1,$r1,%%desc_call(%2);",	\
+  &LARCH_opts.ase_lp64, 0
+
+/* For TLS_DESC64 large pcrel.  */
+#define INSN_LA_TLS_DESC64_LARGE_PCREL	\
+  "pcalau12i $r4,%%desc_pc_hi20(%3);"	\
+  "addi.d %2,$r0,%%desc_pc_lo12(%3);"	\
+  "lu32i.d %2,%%desc64_pc_lo20(%3);"	\
+  "lu52i.d %2,%2,%%desc64_pc_hi12(%3);"	\
+  "add.d $r4,$r4,%2;"			\
+  "ld.d $r1,$r4,%%desc_ld(%3);"		\
+  "jirl $r1,$r1,%%desc_call(%3);",	\
+  &LARCH_opts.ase_lp64,			\
+  &LARCH_opts.ase_gabs
+
+/* For TLS_DESC64 large abs.  */
+#define INSN_LA_TLS_DESC64_LARGE_ABS	\
+  "lu12i.w $r4,%%desc_hi20(%2);"	\
+  "ori $r4,$r4,%%desc_lo12(%2);"	\
+  "lu32i.d $r4,%%desc64_lo20(%2);"	\
+  "lu52i.d $r4,$r4,%%desc64_hi12(%2);"	\
+  "ld.d $r1,$r4,%%desc_ld(%2);"		\
+  "jirl $r1,$r1,%%desc_call(%2);",	\
+  &LARCH_opts.ase_gabs,			\
+  &LARCH_opts.ase_gpcr
+
 static struct loongarch_opcode loongarch_macro_opcodes[] =
 {
   /* match,    mask,	   name, format, macro, include, exclude, pinfo.  */
@@ -352,6 +401,11 @@ static struct loongarch_opcode loongarch_macro_opcodes[] =
   { 0, 0, "call36",	"la",	  INSN_LA_CALL,			0 },
   { 0, 0, "tail36",	"r,la",	  INSN_LA_TAIL,			0 },
   { 0, 0, "pcaddi",	"r,la",	  "pcaddi %1, %%pcrel_20(%2)",	&LARCH_opts.ase_ilp32, 0, 0 },
+  { 0, 0, "la.tls.desc", "r,l",	  INSN_LA_TLS_DESC32_ABS,	0 },
+  { 0, 0, "la.tls.desc", "r,l",	  INSN_LA_TLS_DESC32,		0 },
+  { 0, 0, "la.tls.desc", "r,l",	  INSN_LA_TLS_DESC64_LARGE_ABS, 0 },
+  { 0, 0, "la.tls.desc", "r,l",	  INSN_LA_TLS_DESC64,		0 },
+  { 0, 0, "la.tls.desc", "r,r,l", INSN_LA_TLS_DESC64_LARGE_PCREL,0 },
   { 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminate the list.  */
 };
 
-- 
2.43.0


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

* [PATCH v5 2/5] LoongArch: Add support for TLSDESC in ld.
  2023-12-22 11:42 [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC) Lulu Cai
  2023-12-22 11:42 ` [PATCH v5 1/5] LoongArch: Add new relocs and macro for TLSDESC Lulu Cai
@ 2023-12-22 11:42 ` Lulu Cai
  2023-12-28 14:54   ` Tatsuyuki Ishi
  2023-12-22 11:42 ` [PATCH v5 3/5] LoongArch: Add tls transition support Lulu Cai
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 19+ messages in thread
From: Lulu Cai @ 2023-12-22 11:42 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, mengqinggang, xry111,
	i.swmail, maskray, luweining, wanglei, hejinyang, Lulu Cai

1.The linker for each DESC generates a R_LARCH_TLS_DESC64 dynamic
  relocation, which relocation is placed at .rela.dyn.
  TLSDESC always allocates two GOT slots and one dynamic relocation
  space to TLSDESC.
2. When using multiple ways to access the same TLS variable, a
   maximum of 5 GOT slots are used. For example, using GD, TLSDESC,
   and IE to access the same TLS variable, GD always uses the first
   two of the five GOT, TLSDESC uses the third and fourth, and IE
   uses the last.
---
 bfd/elfnn-loongarch.c | 168 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 146 insertions(+), 22 deletions(-)

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index faffe27294a..95a39148f73 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -48,6 +48,12 @@ struct loongarch_elf_link_hash_entry
 #define GOT_TLS_GD  2
 #define GOT_TLS_IE  4
 #define GOT_TLS_LE  8
+#define GOT_TLS_GDESC 16
+
+#define GOT_TLS_GD_BOTH_P(tls_type) \
+  ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC))
+#define GOT_TLS_GD_ANY_P(tls_type) \
+  ((tls_type & GOT_TLS_GD) || (tls_type & GOT_TLS_GDESC))
   char tls_type;
 };
 
@@ -563,6 +569,7 @@ loongarch_elf_record_tls_and_got_reference (bfd *abfd,
     case GOT_NORMAL:
     case GOT_TLS_GD:
     case GOT_TLS_IE:
+    case GOT_TLS_GDESC:
       /* Need GOT.  */
       if (htab->elf.sgot == NULL
 	  && !loongarch_elf_create_got_section (htab->elf.dynobj, info))
@@ -750,6 +757,14 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    return false;
 	  break;
 
+	case R_LARCH_TLS_DESC_PC_HI20:
+	case R_LARCH_TLS_DESC_HI20:
+	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
+							   r_symndx,
+							   GOT_TLS_GDESC))
+	    return false;
+	  break;
+
 	case R_LARCH_ABS_HI20:
 	case R_LARCH_SOP_PUSH_ABSOLUTE:
 	  if (h != NULL)
@@ -1130,7 +1145,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 
       s = htab->elf.sgot;
       h->got.offset = s->size;
-      if (tls_type & (GOT_TLS_GD | GOT_TLS_IE))
+      if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
 	{
 	  /* TLS_GD needs two dynamic relocs and two GOT slots.  */
 	  if (tls_type & GOT_TLS_GD)
@@ -1167,7 +1182,15 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
 		  htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
 		}
 	    }
+
+	  /* TLS_DESC needs one dynamic reloc and two GOT slot.  */
+	  if (tls_type & GOT_TLS_GDESC)
+	    {
+	      s->size += GOT_ENTRY_SIZE * 2;
+	      htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
+	    }
 	}
+
       else
 	{
 	  s->size += GOT_ENTRY_SIZE;
@@ -1670,19 +1693,34 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd,
 	  if (0 < *local_got)
 	    {
 	      *local_got = s->size;
+	      if (*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
+		{
+		  /* TLS gd use two got.  */
+		  if (*local_tls_type & GOT_TLS_GD)
+		    {
+		      s->size += 2 * GOT_ENTRY_SIZE;
+		      if (!bfd_link_executable (info))
+			srel->size += sizeof (ElfNN_External_Rela);
+		    }
 
-	      /* TLS gd use two got.  */
-	      if (*local_tls_type & GOT_TLS_GD)
-		s->size += GOT_ENTRY_SIZE * 2;
-	      else
-		/* Normal got, tls ie/ld use one got.  */
-		s->size += GOT_ENTRY_SIZE;
+		  /* TLS_DESC use two got.  */
+		  if (*local_tls_type & GOT_TLS_GDESC)
+		    {
+		      s->size += 2 * GOT_ENTRY_SIZE;
+		      srel->size += sizeof (ElfNN_External_Rela);
+		    }
 
-	      if (bfd_link_executable (info)
-		  && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE)))
-		;/* Do nothing.  */
+		  /* TLS ie and use one got.  */
+		  if (*local_tls_type & GOT_TLS_IE)
+		    {
+		      s->size += GOT_ENTRY_SIZE;
+		      if (!bfd_link_executable (info))
+			srel->size += sizeof (ElfNN_External_Rela);
+		    }
+		}
 	      else
 		{
+		  s->size += GOT_ENTRY_SIZE;
 		  srel->size += sizeof (ElfNN_External_Rela);
 		}
 	    }
@@ -2126,6 +2164,15 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
     case R_LARCH_TLS_GD_HI20:
     case R_LARCH_PCREL20_S2:
     case R_LARCH_CALL36:
+    case R_LARCH_TLS_DESC_PC_HI20:
+    case R_LARCH_TLS_DESC_PC_LO12:
+    case R_LARCH_TLS_DESC64_PC_LO20:
+    case R_LARCH_TLS_DESC64_PC_HI12:
+    case R_LARCH_TLS_DESC_HI20:
+    case R_LARCH_TLS_DESC_LO12:
+    case R_LARCH_TLS_DESC64_LO20:
+    case R_LARCH_TLS_DESC64_HI12:
+
       r = loongarch_check_offset (rel, input_section);
       if (r != bfd_reloc_ok)
 	break;
@@ -2135,6 +2182,11 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
 					    contents, value);
       break;
 
+    case R_LARCH_TLS_DESC_LD:
+    case R_LARCH_TLS_DESC_CALL:
+      r = bfd_reloc_ok;
+      break;
+
     case R_LARCH_RELAX:
       break;
 
@@ -2383,10 +2435,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       struct elf_link_hash_entry *h = NULL;
       const char *name;
       bfd_reloc_status_type r = bfd_reloc_ok;
-      bool is_ie, is_undefweak, unresolved_reloc, defined_local;
+      bool is_ie, is_desc, is_undefweak, unresolved_reloc, defined_local;
       bool resolved_local, resolved_dynly, resolved_to_const;
       char tls_type;
-      bfd_vma relocation, off, ie_off;
+      bfd_vma relocation, off, ie_off, desc_off;
       int i, j;
 
       howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
@@ -2515,6 +2567,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
       BFD_ASSERT (!resolved_local || defined_local);
 
+      is_desc = false;
       is_ie = false;
       switch (r_type)
 	{
@@ -3405,6 +3458,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	case R_LARCH_TLS_LD_HI20:
 	case R_LARCH_TLS_GD_PC_HI20:
 	case R_LARCH_TLS_GD_HI20:
+	case R_LARCH_TLS_DESC_PC_HI20:
+	case R_LARCH_TLS_DESC_HI20:
 	  BFD_ASSERT (rel->r_addend == 0);
 	  unresolved_reloc = false;
 
@@ -3412,6 +3467,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	      || r_type == R_LARCH_TLS_IE_HI20)
 	    is_ie = true;
 
+	  if (r_type == R_LARCH_TLS_DESC_PC_HI20
+	      || r_type == R_LARCH_TLS_DESC_HI20)
+	    is_desc = true;
+
 	  bfd_vma got_off = 0;
 	  if (h != NULL)
 	    {
@@ -3426,9 +3485,19 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
 	  BFD_ASSERT (got_off != MINUS_ONE);
 
-	  ie_off = 0;
 	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
-	  if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
+
+	  /* If a tls variable is accessed in multiple ways, GD uses
+	     the first two slots of GOT, desc follows with two slots,
+	     and IE uses one slot at the end.  */
+	  desc_off = 0;
+	  if (GOT_TLS_GD_BOTH_P (tls_type))
+	    desc_off = 2 * GOT_ENTRY_SIZE;
+
+	  ie_off = 0;
+	  if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type & GOT_TLS_IE))
+	    ie_off = 4 * GOT_ENTRY_SIZE;
+	  else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE))
 	    ie_off = 2 * GOT_ENTRY_SIZE;
 
 	  if ((got_off & 1) == 0)
@@ -3477,6 +3546,21 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
 		    }
 		}
+	      if (tls_type & GOT_TLS_GDESC)
+		{
+		  /* Unless it is a static link, DESC always emits a
+		     dynamic relocation.  */
+		  int indx = h && h->dynindx != -1 ? h->dynindx : 0;
+		  rela.r_offset = sec_addr (got) + got_off + desc_off;
+		  rela.r_addend = 0;
+		  if (indx == 0)
+		    rela.r_addend = relocation - elf_hash_table (info)->tls_sec->vma;
+
+		  rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_DESCNN);
+		  loongarch_elf_append_rela (output_bfd, relgot, &rela);
+		  bfd_put_NN (output_bfd, 0,
+			      got->contents + got_off + desc_off);
+		}
 	      if (tls_type & GOT_TLS_IE)
 		{
 		  rela.r_offset = sec_addr (got) + got_off + ie_off;
@@ -3504,16 +3588,52 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 		    }
 		}
 	    }
-	  relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got)
-			+ (is_ie ? ie_off : 0);
+	  relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got);
+	  if (is_desc)
+	    relocation += desc_off;
+	  else if (is_ie)
+	    relocation += ie_off;
 
 	  if (r_type == R_LARCH_TLS_LD_PC_HI20
 	      || r_type == R_LARCH_TLS_GD_PC_HI20
-	      || r_type == R_LARCH_TLS_IE_PC_HI20)
+	      || r_type == R_LARCH_TLS_IE_PC_HI20
+	      || r_type == R_LARCH_TLS_DESC_PC_HI20)
 	    RELOCATE_CALC_PC32_HI20 (relocation, pc);
 
 	  break;
 
+	case R_LARCH_TLS_DESC_PC_LO12:
+	case R_LARCH_TLS_DESC64_PC_LO20:
+	case R_LARCH_TLS_DESC64_PC_HI12:
+	case R_LARCH_TLS_DESC_LO12:
+	case R_LARCH_TLS_DESC64_LO20:
+	case R_LARCH_TLS_DESC64_HI12:
+	  {
+	    unresolved_reloc = false;
+
+	    if (h)
+	      relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)1));
+	    else
+	      relocation = sec_addr (got)
+			   + (local_got_offsets[r_symndx] & (~(bfd_vma)1));
+
+	    tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
+	    /* Use both TLS_GD and TLS_DESC.  */
+	    if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC))
+	      relocation += 2 * GOT_ENTRY_SIZE;
+	  }
+
+	    if (r_type == R_LARCH_TLS_DESC64_PC_LO20
+		|| r_type == R_LARCH_TLS_DESC64_PC_HI12)
+	      RELOCATE_CALC_PC64_HI32 (relocation, pc);
+
+	    break;
+
+	case R_LARCH_TLS_DESC_LD:
+	case R_LARCH_TLS_DESC_CALL:
+	  unresolved_reloc = false;
+	  break;
+
 	case R_LARCH_TLS_IE_PC_LO12:
 	case R_LARCH_TLS_IE64_PC_LO20:
 	case R_LARCH_TLS_IE64_PC_HI12:
@@ -3523,14 +3643,17 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	  unresolved_reloc = false;
 
 	  if (h)
-	    relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)3));
+	    relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)1));
 	  else
 	    relocation = sec_addr (got)
-	      + (local_got_offsets[r_symndx] & (~(bfd_vma)3));
+	      + (local_got_offsets[r_symndx] & (~(bfd_vma)1));
 
 	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
-	  /* Use both TLS_GD and TLS_IE.  */
-	  if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
+	  /* Use TLS_GD TLS_DESC and TLS_IE.  */
+	  if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type & GOT_TLS_IE))
+	    relocation += 4 * GOT_ENTRY_SIZE;
+	  /* Use GOT_TLS_GD_ANY_P (tls_type) and TLS_IE.  */
+	  else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE))
 	    relocation += 2 * GOT_ENTRY_SIZE;
 
 	  if (r_type == R_LARCH_TLS_IE64_PC_LO20
@@ -4174,7 +4297,8 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
 
   if (h->got.offset != MINUS_ONE
       /* TLS got entry have been handled in elf_relocate_section.  */
-      && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE))
+      && !(loongarch_elf_hash_entry (h)->tls_type
+	   & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
       /* Have allocated got entry but not allocated rela before.  */
       && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
     {
-- 
2.43.0


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

* [PATCH v5 3/5] LoongArch: Add tls transition support.
  2023-12-22 11:42 [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC) Lulu Cai
  2023-12-22 11:42 ` [PATCH v5 1/5] LoongArch: Add new relocs and macro for TLSDESC Lulu Cai
  2023-12-22 11:42 ` [PATCH v5 2/5] LoongArch: Add support for TLSDESC in ld Lulu Cai
@ 2023-12-22 11:42 ` Lulu Cai
  2023-12-28 14:42   ` Tatsuyuki Ishi
  2023-12-22 11:42 ` [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation Lulu Cai
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 19+ messages in thread
From: Lulu Cai @ 2023-12-22 11:42 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, mengqinggang, xry111,
	i.swmail, maskray, luweining, wanglei, hejinyang, Lulu Cai

Transitions between DESC->IE/LE and IE->LE are supported now.
1. For DESC -> LE:
   pcalau12i  $a0,%desc_pc_hi20(var)     =>  lu12i.w $a0,%le_hi20(var)
   addi.d     $a0,$a0,%desc_pc_lo12(var) =>  ori $a0,$a0,%le_lo12(var)
   ld.d       $a1,$a0,%desc_ld(var)      =>  NOP
   jirl       $ra,$a1,%desc_call(var)	 =>  NOP
   add.d      $a0,$a0,$tp
2. For DESC -> IE:
   pcalau12i  $a0,%desc_pc_hi20(var)     =>  pcalau12i $a0,%ie_pc_hi20(var)
   addi.d     $a0,$a0,%desc_pc_lo12(var) =>  ld.d $a0,$a0,%ie_pc_lo12(var)
   ld.d       $a1,$a0,%desc_ld(var)      =>  NOP
   jirl       $ra,$a1,%desc_call(var)	 =>  NOP
   add.d      $a0,$a0,$tp
3. For IE -> LE:
   pcalau12i  $a0,%ie_pc_hi20(var)       =>  lu12i.w $a0,%le_hi20(var)
   ld.d       $a0,$a0,%ie_pc_lo12(var)   =>  ori $a0,$a0,%le_lo12(var)
   add.d      $a0,$a0,$tp
4. When a tls variable is accessed using both DESC and IE, DESC transitions
   to IE and uses the same GOT entry as IE.
---
 bfd/elfnn-loongarch.c      | 216 ++++++++++++++++++++++++++++++++++++-
 include/opcode/loongarch.h |   6 ++
 2 files changed, 221 insertions(+), 1 deletion(-)

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 95a39148f73..1347d13d2e2 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -145,6 +145,16 @@ struct loongarch_elf_link_hash_table
 #define elf_backend_rela_normal 1
 #define elf_backend_default_execstack 0
 
+#define IS_LOONGARCH_TLS_DESC_RELOC(R_TYPE)    \
+  ((R_TYPE) == R_LARCH_TLS_DESC_PC_HI20	\
+   || (R_TYPE) == R_LARCH_TLS_DESC_PC_LO12  \
+   || (R_TYPE) == R_LARCH_TLS_DESC_LD \
+   || (R_TYPE) == R_LARCH_TLS_DESC_CALL)
+
+#define IS_LOONGARCH_TLS_IE_RELOC(R_TYPE) \
+  ((R_TYPE) == R_LARCH_TLS_IE_PC_HI20 \
+   || (R_TYPE) == R_LARCH_TLS_IE_PC_LO12)
+
 /* Generate a PLT header.  */
 
 static bool
@@ -593,6 +603,10 @@ loongarch_elf_record_tls_and_got_reference (bfd *abfd,
 
   char *new_tls_type = &_bfd_loongarch_elf_tls_type (abfd, h, symndx);
   *new_tls_type |= tls_type;
+
+  /* If a symbol is accessed by both IE and DESC, relax DESC to IE.  */
+  if ((*new_tls_type & GOT_TLS_IE) && (*new_tls_type & GOT_TLS_GDESC))
+    *new_tls_type &= ~ (GOT_TLS_GDESC);
   if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
     {
       _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
@@ -605,6 +619,104 @@ loongarch_elf_record_tls_and_got_reference (bfd *abfd,
   return true;
 }
 
+static unsigned int
+loongarch_reloc_got_type (unsigned int r_type)
+{
+  switch (r_type)
+    {
+      case R_LARCH_TLS_DESC_PC_HI20:
+      case R_LARCH_TLS_DESC_PC_LO12:
+      case R_LARCH_TLS_DESC_LD:
+      case R_LARCH_TLS_DESC_CALL:
+	return GOT_TLS_GDESC;
+
+      case R_LARCH_TLS_IE_PC_HI20:
+      case R_LARCH_TLS_IE_PC_LO12:
+	return GOT_TLS_IE;
+
+      default:
+	break;
+    }
+  return GOT_UNKNOWN;
+}
+
+/* Return true if tls type transition can be performed.  */
+static bool
+loongarch_can_relax_tls (struct bfd_link_info *info, unsigned int r_type,
+			 struct elf_link_hash_entry *h, bfd *input_bfd,
+			 unsigned long r_symndx)
+{
+  char symbol_tls_type;
+  unsigned int reloc_got_type;
+
+  if (! (IS_LOONGARCH_TLS_DESC_RELOC (r_type)
+	 || IS_LOONGARCH_TLS_IE_RELOC (r_type)))
+    return false;
+
+  symbol_tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
+  reloc_got_type = loongarch_reloc_got_type (r_type);
+
+  if (symbol_tls_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P (reloc_got_type))
+    return true;
+
+  if (! bfd_link_executable (info))
+      return false;
+
+  if (h && h->root.type == bfd_link_hash_undefweak)
+    return false;
+
+  return true;
+}
+
+/* The type of relocation that can be transitioned.  */
+static unsigned int
+loongarch_tls_transition_without_check (struct bfd_link_info *info,
+					unsigned int r_type,
+					struct elf_link_hash_entry *h)
+{
+  bool local_exec = bfd_link_executable (info)
+		    && SYMBOL_REFERENCES_LOCAL (info, h);
+
+  switch (r_type)
+    {
+      case R_LARCH_TLS_DESC_PC_HI20:
+	return (local_exec
+		? R_LARCH_TLS_LE_HI20
+		: R_LARCH_TLS_IE_PC_HI20);
+
+      case R_LARCH_TLS_DESC_PC_LO12:
+	return (local_exec
+		? R_LARCH_TLS_LE_LO12
+		: R_LARCH_TLS_IE_PC_LO12);
+
+      case R_LARCH_TLS_DESC_LD:
+      case R_LARCH_TLS_DESC_CALL:
+	return R_LARCH_NONE;
+
+      case R_LARCH_TLS_IE_PC_HI20:
+	return local_exec ? R_LARCH_TLS_LE_HI20 : r_type;
+
+      case R_LARCH_TLS_IE_PC_LO12:
+	return local_exec ? R_LARCH_TLS_LE_LO12 : r_type;
+
+      default:
+	break;
+    }
+
+  return r_type;
+}
+
+static unsigned int
+loongarch_tls_transition (struct bfd_link_info *info, unsigned int r_type,
+			  struct elf_link_hash_entry *h, bfd *input_bfd,
+			  unsigned long r_symndx)
+{
+  if (! loongarch_can_relax_tls (info, r_type, h, input_bfd,r_symndx))
+    return r_type;
+
+  return loongarch_tls_transition_without_check (info, r_type, h);
+}
+
 /* Look through the relocs for a section during the first phase, and
    allocate space in the global offset table or procedure linkage
    table.  */
@@ -706,6 +818,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
       int need_dynreloc = 0;
       int only_need_pcrel = 0;
 
+      r_type = loongarch_tls_transition (info, r_type, h, abfd, r_symndx);
       switch (r_type)
 	{
 	case R_LARCH_GOT_PC_HI20:
@@ -2403,6 +2516,96 @@ loongarch_reloc_is_fatal (struct bfd_link_info *info,
       relocation += 0x100000000;			\
   })
 
+/* Transition instruction sequence to relax instruction sequence.  */
+static bool
+loongarch_tls_relax (bfd *abfd, asection *sec, Elf_Internal_Rela *rel,
+		    int r_type, struct elf_link_hash_entry *h,
+		    struct bfd_link_info *info)
+{
+  bool local_exec = bfd_link_executable (info)
+		    && SYMBOL_REFERENCES_LOCAL (info, h);
+  bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
+  unsigned long insn;
+
+  switch (r_type)
+    {
+      case R_LARCH_TLS_DESC_PC_HI20:
+	if (local_exec)
+	    /* DESC -> LE relaxation:
+	       pcalalau12i $a0,%desc_pc_hi20(var) =>
+	       lu12i.w $a0,%le_hi20(var)
+	    */
+	    bfd_put (32, abfd, LARCH_LU12I_W | LARCH_RD_A0,
+		     contents + rel->r_offset);
+
+	/* DESC -> IE relaxation:
+	   pcalalau12i $a0,%desc_pc_hi20(var) =>
+	   pcalalau12i $a0,%ie_pc_hi20(var)
+	*/
+	return true;
+
+      case R_LARCH_TLS_DESC_PC_LO12:
+	if (local_exec)
+	  {
+	    /* DESC -> LE relaxation:
+	       addi.d $a0,$a0,%desc_pc_lo12(var) =>
+	       ori  $a0,$a0,le_lo12(var)
+	    */
+	    insn = LARCH_ORI | LARCH_RD_RJ_A0;
+	    bfd_put (32, abfd, LARCH_ORI | LARCH_RD_RJ_A0,
+		     contents + rel->r_offset);
+	  }
+	else
+	  {
+	    /* DESC -> IE relaxation:
+	       addi.d $a0,$a0,%desc_pc_lo12(var) =>
+	       ld.d $a0,$a0,%%ie_pc_lo12
+	    */
+	    bfd_put (32, abfd, LARCH_LD_D | LARCH_RD_RJ_A0,
+		     contents + rel->r_offset);
+	  }
+	return true;
+
+      case R_LARCH_TLS_DESC_LD:
+      case R_LARCH_TLS_DESC_CALL:
+	/* DESC -> LE/IE relaxation:
+	   ld.d $ra,$a0,%desc_ld(var) => NOP
+	   jirl $ra,$ra,%desc_call(var) => NOP
+	*/
+	bfd_put (32, abfd, LARCH_NOP, contents + rel->r_offset);
+	return true;
+
+      case R_LARCH_TLS_IE_PC_HI20:
+	if (local_exec)
+	  {
+	    /* IE -> LE relaxation:
+	       pcalalau12i $rd,%ie_pc_hi20(var) =>
+	       lu12i.w $rd,%le_hi20(var)
+	    */
+	    insn = bfd_getl32 (contents + rel->r_offset);
+	    bfd_put (32, abfd, LARCH_LU12I_W | (insn & 0x1f),
+		     contents + rel->r_offset);
+	  }
+	return true;
+
+      case R_LARCH_TLS_IE_PC_LO12:
+	if (local_exec)
+	  {
+	    /* IE -> LE relaxation:
+	       ld.d $rd,$rj,%%ie_pc_lo12 =>
+	       ori  $rd,$rj,le_lo12(var)
+	    */
+	    insn = bfd_getl32 (contents + rel->r_offset);
+	    bfd_put (32, abfd, LARCH_ORI | (insn & 0x3ff),
+		     contents + rel->r_offset);
+	  }
+	return true;
+    }
+
+  return false;
+}
+
+
 static int
 loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 				bfd *input_bfd, asection *input_section,
@@ -2426,7 +2629,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
   relend = relocs + input_section->reloc_count;
   for (rel = relocs; rel < relend; rel++)
     {
-      int r_type = ELFNN_R_TYPE (rel->r_info);
+      unsigned int r_type = ELFNN_R_TYPE (rel->r_info);
       unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
       bfd_vma pc = sec_addr (input_section) + rel->r_offset;
       reloc_howto_type *howto = NULL;
@@ -2436,6 +2639,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
       const char *name;
       bfd_reloc_status_type r = bfd_reloc_ok;
       bool is_ie, is_desc, is_undefweak, unresolved_reloc, defined_local;
+      unsigned int relaxed_r_type;
       bool resolved_local, resolved_dynly, resolved_to_const;
       char tls_type;
       bfd_vma relocation, off, ie_off, desc_off;
@@ -2567,6 +2771,16 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 
       BFD_ASSERT (!resolved_local || defined_local);
 
+      relaxed_r_type = loongarch_tls_transition (info, r_type, h, input_bfd, r_symndx);
+      if (relaxed_r_type != r_type)
+      {
+	howto = loongarch_elf_rtype_to_howto (input_bfd, relaxed_r_type);
+	BFD_ASSERT (howto != NULL);
+
+	if (loongarch_tls_relax (input_bfd, input_section, rel, r_type, h, info))
+	  r_type = relaxed_r_type;
+      }
+
       is_desc = false;
       is_ie = false;
       switch (r_type)
diff --git a/include/opcode/loongarch.h b/include/opcode/loongarch.h
index da936f7945a..32ff4d8a0f1 100644
--- a/include/opcode/loongarch.h
+++ b/include/opcode/loongarch.h
@@ -42,6 +42,12 @@ extern "C"
     ((value) < (-(1 << ((bits) - 1) << align)) 	\
       || (value) > ((((1 << ((bits) - 1)) - 1) << align)))
 
+  #define LARCH_LU12I_W 0x14000000
+  #define LARCH_ORI 0x03800000
+  #define LARCH_LD_D 0x28c00000
+  #define LARCH_RD_A0 0x04
+  #define LARCH_RD_RJ_A0 0x084
+
   typedef uint32_t insn_t;
 
   struct loongarch_opcode
-- 
2.43.0


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

* [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation
  2023-12-22 11:42 [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC) Lulu Cai
                   ` (2 preceding siblings ...)
  2023-12-22 11:42 ` [PATCH v5 3/5] LoongArch: Add tls transition support Lulu Cai
@ 2023-12-22 11:42 ` Lulu Cai
  2023-12-28 14:38   ` Tatsuyuki Ishi
  2024-01-27  2:54 ` [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC) Fangrui Song
       [not found] ` <DS7PR12MB5765A6FBD6297BAEDB57FF6CCB782@DS7PR12MB5765.namprd12.prod.outlook.com>
  5 siblings, 1 reply; 19+ messages in thread
From: Lulu Cai @ 2023-12-22 11:42 UTC (permalink / raw)
  To: binutils
  Cc: xuchenghua, chenglulu, liuzhensong, mengqinggang, xry111,
	i.swmail, maskray, luweining, wanglei, hejinyang

From: mengqinggang <mengqinggang@loongson.cn>

The pcalau12i + addi.d of TLS LD/GD/DESC relax to pcaddi.
Relaxation is only performed when the TLS model transition is not possible.
---
 bfd/bfd-in2.h                                 |   3 +
 bfd/elfnn-loongarch.c                         | 174 +++++++-
 bfd/elfxx-loongarch.c                         |  60 +++
 bfd/libbfd.h                                  |   3 +
 bfd/reloc.c                                   |   7 +
 gas/config/tc-loongarch.c                     |   8 +-
 gas/testsuite/gas/loongarch/macro_op.d        | 128 +++---
 gas/testsuite/gas/loongarch/macro_op_32.d     | 120 +++---
 .../gas/loongarch/macro_op_large_abs.d        | 160 +++----
 .../gas/loongarch/macro_op_large_pc.d         | 160 +++----
 include/elf/loongarch.h                       |   4 +
 ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++++---------
 ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 +++---
 13 files changed, 795 insertions(+), 543 deletions(-)

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 85251aa0edd..782845926ea 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -7473,6 +7473,9 @@ enum bfd_reloc_code_real
   BFD_RELOC_LARCH_TLS_DESC64_HI12,
   BFD_RELOC_LARCH_TLS_DESC_LD,
   BFD_RELOC_LARCH_TLS_DESC_CALL,
+  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,
+  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,
+  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,
   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 1347d13d2e2..bd448cda453 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -2285,7 +2285,9 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
     case R_LARCH_TLS_DESC_LO12:
     case R_LARCH_TLS_DESC64_LO20:
     case R_LARCH_TLS_DESC64_HI12:
-
+    case R_LARCH_TLS_LD_PCREL20_S2:
+    case R_LARCH_TLS_GD_PCREL20_S2:
+    case R_LARCH_TLS_DESC_PCREL20_S2:
       r = loongarch_check_offset (rel, input_section);
       if (r != bfd_reloc_ok)
 	break;
@@ -3674,6 +3676,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	case R_LARCH_TLS_GD_HI20:
 	case R_LARCH_TLS_DESC_PC_HI20:
 	case R_LARCH_TLS_DESC_HI20:
+	case R_LARCH_TLS_LD_PCREL20_S2:
+	case R_LARCH_TLS_GD_PCREL20_S2:
+	case R_LARCH_TLS_DESC_PCREL20_S2:
 	  BFD_ASSERT (rel->r_addend == 0);
 	  unresolved_reloc = false;
 
@@ -3682,7 +3687,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	    is_ie = true;
 
 	  if (r_type == R_LARCH_TLS_DESC_PC_HI20
-	      || r_type == R_LARCH_TLS_DESC_HI20)
+	      || r_type == R_LARCH_TLS_DESC_HI20
+	      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
 	    is_desc = true;
 
 	  bfd_vma got_off = 0;
@@ -3813,7 +3819,11 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
 	      || r_type == R_LARCH_TLS_IE_PC_HI20
 	      || r_type == R_LARCH_TLS_DESC_PC_HI20)
 	    RELOCATE_CALC_PC32_HI20 (relocation, pc);
-
+	  else if (r_type == R_LARCH_TLS_LD_PCREL20_S2
+	      || r_type == R_LARCH_TLS_GD_PCREL20_S2
+	      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
+	    relocation -= pc;
+	  /* else {} ABS relocations.  */
 	  break;
 
 	case R_LARCH_TLS_DESC_PC_LO12:
@@ -4244,6 +4254,85 @@ loongarch_relax_align (bfd *abfd, asection *sec,
 					addend - need_nop_bytes, link_info);
 }
 
+/* Relax pcalau12i + addi.d of TLS LD/GD/DESC to pcaddi.  */
+static bool
+loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
+		       Elf_Internal_Rela *rel_hi, bfd_vma symval,
+		       struct bfd_link_info *info, bool *again)
+{
+  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;
+
+  /* This section's output_offset need to subtract the bytes of instructions
+     relaxed by the previous sections, so it needs to be updated beforehand.
+     size_input_section already took care of updating it after relaxation,
+     so we additionally update once here.  */
+  sec->output_offset = sec->output_section->size;
+  bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
+
+  /* If pc and symbol not in the same segment, add/sub segment alignment.
+     FIXME: if there are multiple readonly segments?  */
+  if (!(sym_sec->flags & SEC_READONLY))
+    {
+      if (symval > pc)
+	pc -= info->maxpagesize;
+      else if (symval < pc)
+	pc += info->maxpagesize;
+    }
+
+  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_GOT_PC_LO12
+	&& ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_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)
+      || ((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;
+
+  /* Continue next relax trip.  */
+  *again = true;
+
+  pca = pcaddi | rd;
+  bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
+
+  /* Adjust relocations.  */
+  switch (ELFNN_R_TYPE (rel_hi->r_info))
+    {
+    case R_LARCH_TLS_LD_PC_HI20:
+      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
+				      R_LARCH_TLS_LD_PCREL20_S2);
+      break;
+    case R_LARCH_TLS_GD_PC_HI20:
+      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
+				      R_LARCH_TLS_GD_PCREL20_S2);
+      break;
+    case R_LARCH_TLS_DESC_PC_HI20:
+      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
+				      R_LARCH_TLS_DESC_PCREL20_S2);
+      break;
+    default:
+      break;
+    }
+  rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
+
+  loongarch_relax_delete_bytes (abfd, sec, rel_lo->r_offset, 4, info);
+
+  return true;
+}
+
 static bool
 loongarch_elf_relax_section (bfd *abfd, asection *sec,
 			       struct bfd_link_info *info,
@@ -4288,15 +4377,23 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
 
   for (unsigned int i = 0; i < sec->reloc_count; i++)
     {
-      Elf_Internal_Rela *rel = relocs + i;
-      asection *sym_sec;
+      char symtype;
       bfd_vma symval;
-      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
-      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
+      asection *sym_sec;
       bool local_got = false;
-      char symtype;
+      Elf_Internal_Rela *rel = relocs + i;
       struct elf_link_hash_entry *h = NULL;
+      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
+      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
 
+      /* Four kind of relocations:
+	 Normal: symval is the symbol address.
+	 R_LARCH_ALIGN: symval is the address of the last NOP instruction
+	 added by this relocation, and then adds 4 more.
+	 R_LARCH_CALL36: symval is the symbol address for local symbols,
+	 or the PLT entry address of the symbol. (Todo)
+	 R_LARCHL_TLS_LD/GD/DESC_PC_HI20: symval is the GOT entry address
+	 of the symbol.  */
       if (r_symndx < symtab_hdr->sh_info)
 	{
 	  Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
@@ -4304,7 +4401,24 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
 	  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
 	    continue;
 
-	  if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
+	  if (R_LARCH_TLS_LD_PC_HI20 == r_type
+	      || R_LARCH_TLS_GD_PC_HI20 == r_type
+	      || R_LARCH_TLS_DESC_PC_HI20 == r_type)
+	    {
+	      if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
+		continue;
+	      else
+		{
+		  sym_sec = htab->elf.sgot;
+		  symval = elf_local_got_offsets (abfd)[r_symndx];
+		  char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
+								r_symndx);
+		  if (R_LARCH_TLS_DESC_PC_HI20 == r_type
+			&& GOT_TLS_GD_BOTH_P (tls_type))
+		    symval += 2 * GOT_ENTRY_SIZE;
+		}
+	    }
+	  else if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
 	    {
 	      sym_sec = sec;
 	      symval = rel->r_offset;
@@ -4329,7 +4443,26 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
 	  if (h != NULL && h->type == STT_GNU_IFUNC)
 	    continue;
 
-	  if ((h->root.type == bfd_link_hash_defined
+	  /* The GOT entry of tls symbols must in current execute file or
+	     shared object.  */
+	  if (R_LARCH_TLS_LD_PC_HI20 == r_type
+	      || R_LARCH_TLS_GD_PC_HI20 == r_type
+	      || R_LARCH_TLS_DESC_PC_HI20 == r_type)
+	    {
+	      if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
+		continue;
+	      else
+		{
+		  sym_sec = htab->elf.sgot;
+		  symval = h->got.offset;
+		  char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
+								r_symndx);
+		  if (R_LARCH_TLS_DESC_PC_HI20 == r_type
+			&& GOT_TLS_GD_BOTH_P (tls_type))
+		    symval += 2 * GOT_ENTRY_SIZE;
+		}
+	    }
+	  else 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)
@@ -4358,7 +4491,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
 	   if (symtype != STT_SECTION)
 	     symval += rel->r_addend;
 	}
-      /* For R_LARCH_ALIGN, symval is sec_addr (sym_sec) + rel->r_offset
+      /* For R_LARCH_ALIGN, symval is sec_addr (sec) + rel->r_offset
 	 + (alingmeng - 4).
 	 If r_symndx is 0, alignmeng-4 is r_addend.
 	 If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4.  */
@@ -4399,6 +4532,25 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
 					    info, again);
 	    }
 	  break;
+
+	case R_LARCH_TLS_LD_PC_HI20:
+	  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
+	    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
+					    info, again);
+	  break;
+
+	case R_LARCH_TLS_GD_PC_HI20:
+	  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
+	    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
+					    info, again);
+	  break;
+
+	case R_LARCH_TLS_DESC_PC_HI20:
+	  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
+	    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
+					    info, again);
+	  break;
+
 	default:
 	  break;
 	}
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index 30a941a851f..310e6d62dc0 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -1775,6 +1775,60 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
 	 BFD_RELOC_LARCH_TLS_DESC_CALL,		/* bfd_reloc_code_real_type.  */
 	 NULL,					/* adjust_reloc_bits.  */
 	 "desc_call"),				/* larch_reloc_type_name.  */
+
+  /* For pcaddi, ld_pc_hi20 + ld_pc_lo12 can relax to ld_pcrel20_s2.  */
+  LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCREL20_S2,	/* type (124).  */
+	 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_TLS_LD_PCREL20_S2",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0x1ffffe0,				/* dst_mask.  */
+	 true,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,	/* bfd_reloc_code_real_type.  */
+	 reloc_sign_bits,			/* adjust_reloc_bits.  */
+	 "ld_pcrel_20"),			/* larch_reloc_type_name.  */
+
+  /* For pcaddi, gd_pc_hi20 + gd_pc_lo12 can relax to gd_pcrel20_s2.  */
+  LOONGARCH_HOWTO (R_LARCH_TLS_GD_PCREL20_S2,	/* type (125).  */
+	 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_TLS_GD_PCREL20_S2",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0x1ffffe0,				/* dst_mask.  */
+	 true,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,	/* bfd_reloc_code_real_type.  */
+	 reloc_sign_bits,			/* adjust_reloc_bits.  */
+	 "gd_pcrel_20"),			/* larch_reloc_type_name.  */
+
+  /* For pcaddi, desc_pc_hi20 + desc_pc_lo12 can relax to desc_pcrel20_s2.  */
+  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PCREL20_S2,	/* type (126).  */
+	 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_TLS_DESC_PCREL20_S2",		/* name.  */
+	 false,					/* partial_inplace.  */
+	 0,					/* src_mask.  */
+	 0x1ffffe0,				/* dst_mask.  */
+	 true,					/* pcrel_offset.  */
+	 BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,	/* bfd_reloc_code_real_type.  */
+	 reloc_sign_bits,			/* adjust_reloc_bits.  */
+	 "desc_pcrel_20"),			/* larch_reloc_type_name.  */
 };
 
 reloc_howto_type *
@@ -1783,7 +1837,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
   if(r_type < R_LARCH_count)
     {
       /* For search table fast.  */
+      /*
       BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
+      */
 
       if (loongarch_howto_table[r_type].howto.type == r_type)
 	return (reloc_howto_type *)&loongarch_howto_table[r_type];
@@ -1802,7 +1858,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
 reloc_howto_type *
 loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
 {
+  /*
   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
+  */
 
   for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
     if (loongarch_howto_table[i].howto.name
@@ -1821,7 +1879,9 @@ reloc_howto_type *
 loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
 			     bfd_reloc_code_real_type code)
 {
+  /*
   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
+  */
 
   /* Fast search for new reloc types.  */
   if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 71b03da14d9..8dab44110a6 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -3612,6 +3612,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
   "BFD_RELOC_LARCH_TLS_DESC64_HI12",
   "BFD_RELOC_LARCH_TLS_DESC_LD",
   "BFD_RELOC_LARCH_TLS_DESC_CALL",
+  "BFD_RELOC_LARCH_TLS_LD_PCREL20_S2",
+  "BFD_RELOC_LARCH_TLS_GD_PCREL20_S2",
+  "BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2",
  "@@overflow: BFD_RELOC_UNUSED@@",
 };
 #endif
diff --git a/bfd/reloc.c b/bfd/reloc.c
index f7fe0c7ffe3..6fd0f1fb547 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -8324,6 +8324,13 @@ ENUMX
 ENUMX
   BFD_RELOC_LARCH_TLS_DESC_CALL
 
+ENUMX
+  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2
+ENUMX
+  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2
+ENUMX
+  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2
+
 ENUMDOC
   LARCH relocations.
 
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 1658025f918..def26daf634 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -682,7 +682,7 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
 		      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_TLS_DESC_CALL)
+	      && ip->reloc_info[0].type <= BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2)
 	    {
 	      /* As we compact stack-relocs, it is no need for pop operation.
 		 But break out until here in order to check the imm field.
@@ -694,7 +694,11 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
 		    && (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))
+			|| BFD_RELOC_LARCH_GOT_PC_LO12 == reloc_type
+			|| BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_type
+			|| BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_type
+			|| BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_type
+			|| BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_type))
 		{
 		  ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
 		  ip->reloc_info[ip->reloc_num].value = const_0;
diff --git a/gas/testsuite/gas/loongarch/macro_op.d b/gas/testsuite/gas/loongarch/macro_op.d
index 32860864704..47f8f45c663 100644
--- a/gas/testsuite/gas/loongarch/macro_op.d
+++ b/gas/testsuite/gas/loongarch/macro_op.d
@@ -2,70 +2,72 @@
 #objdump: -dr
 #skip: loongarch32-*-*
 
-.*:[    ]+file format .*
+.*:     file format .*
 
 
 Disassembly of section .text:
 
-00000000.* <.text>:
-[ 	]+0:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
-[ 	]+4:[ 	]+02bffc04[ 	]+li\.w[ 	]+\$a0,[ 	]+-1
-[ 	]+8:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
-[ 	]+c:[ 	]+02bffc04[ 	]+li\.w[ 	]+\$a0,[ 	]+-1
-[ 	]+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_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
-[ 	]+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
-[ 	]+38:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+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
-[ 	]+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:[ 	]+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:[ 	]+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:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+TLS1
-[ 	]+64:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
+0+ <.*>:
+   0:	00150004 	move        	\$a0, \$zero
+   4:	02bffc04 	li.w        	\$a0, -1
+   8:	00150004 	move        	\$a0, \$zero
+   c:	02bffc04 	li.w        	\$a0, -1
+  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_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
+  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
+  38:	1a000004 	pcalau12i   	\$a0, 0
+			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
+			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: R_LARCH_TLS_IE_PC_LO12	TLS1
+  58:	1a000004 	pcalau12i   	\$a0, 0
+			58: R_LARCH_TLS_LD_PC_HI20	TLS1
+			58: R_LARCH_RELAX	\*ABS\*
+  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
+			60: R_LARCH_RELAX	\*ABS\*
+  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 188026a5780..a7349aa8dc0 100644
--- a/gas/testsuite/gas/loongarch/macro_op_32.d
+++ b/gas/testsuite/gas/loongarch/macro_op_32.d
@@ -2,66 +2,68 @@
 #objdump: -dr
 #skip: loongarch64-*-*
 
-.*:[    ]+file format .*
+.*:     file format .*
 
 
 Disassembly of section .text:
 
-00000000.* <.L1>:
-[ 	]+0:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
-[ 	]+4:[ 	]+02bffc04[ 	]+li\.w[ 	]+\$a0,[ 	]+-1
-[ 	]+8:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
-[ 	]+c:[ 	]+02bffc04[ 	]+li\.w[ 	]+\$a0,[ 	]+-1
-[ 	]+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[ 	]+.L1
-[ 	]+20:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+24:[ 	]+02800084[ 	]+addi.w[ 	]+\$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
-[ 	]+2c:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
-[ 	]+2c:[ 	]+R_LARCH_ABS_LO12[ 	]+.L1
-[ 	]+30:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+30:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
-[ 	]+30:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+34:[ 	]+02800084[ 	]+addi.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+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
-[ 	]+44:[ 	]+R_LARCH_TLS_LE_LO12[ 	]+TLS1
-[ 	]+48:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+48:[ 	]+R_LARCH_TLS_IE_PC_HI20[ 	]+TLS1
-[ 	]+4c:[ 	]+28800084[ 	]+ld.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+4c:[ 	]+R_LARCH_TLS_IE_PC_LO12[ 	]+TLS1
-[ 	]+50:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+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\*
+0+ <.L1>:
+   0:	00150004 	move        	\$a0, \$zero
+   4:	02bffc04 	li.w        	\$a0, -1
+   8:	00150004 	move        	\$a0, \$zero
+   c:	02bffc04 	li.w        	\$a0, -1
+  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	.L1
+			20: R_LARCH_RELAX	\*ABS\*
+  24:	02800084 	addi.w      	\$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
+  2c:	03800084 	ori         	\$a0, \$a0, 0x0
+			2c: R_LARCH_ABS_LO12	.L1
+  30:	1a000004 	pcalau12i   	\$a0, 0
+			30: R_LARCH_PCALA_HI20	.L1
+			30: R_LARCH_RELAX	\*ABS\*
+  34:	02800084 	addi.w      	\$a0, \$a0, 0
+			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
+			44: R_LARCH_TLS_LE_LO12	TLS1
+  48:	1a000004 	pcalau12i   	\$a0, 0
+			48: R_LARCH_TLS_IE_PC_HI20	TLS1
+  4c:	28800084 	ld.w        	\$a0, \$a0, 0
+			4c: R_LARCH_TLS_IE_PC_LO12	TLS1
+  50:	1a000004 	pcalau12i   	\$a0, 0
+			50: R_LARCH_TLS_LD_PC_HI20	TLS1
+			50: R_LARCH_RELAX	\*ABS\*
+  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
+			58: R_LARCH_RELAX	\*ABS\*
+  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 0c49f68e2ab..729e878ffb8 100644
--- a/gas/testsuite/gas/loongarch/macro_op_large_abs.d
+++ b/gas/testsuite/gas/loongarch/macro_op_large_abs.d
@@ -1,85 +1,89 @@
-#as: -mla-global-with-abs
+#as:
 #objdump: -dr
 #skip: loongarch32-*-*
 
-.*:[    ]+file format .*
+.*:     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:[ 	]+02c00005[ 	]+li\.d[ 	]+\$a1,[ 	]+0
-[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
-[ 	]+4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+8:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+8:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
-[ 	]+c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.L1
-[ 	]+10:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+14:[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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
+0+ <.L1>:
+   0:	1a000004 	pcalau12i   	\$a0, 0
+			0: R_LARCH_PCALA_HI20	.L1
+			0: R_LARCH_RELAX	\*ABS\*
+   4:	02c00005 	li.d        	\$a1, 0
+			4: R_LARCH_PCALA_LO12	.L1
+			4: R_LARCH_RELAX	\*ABS\*
+   8:	16000005 	lu32i.d     	\$a1, 0
+			8: R_LARCH_PCALA64_LO20	.L1
+   c:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			c: R_LARCH_PCALA64_HI12	.L1
+  10:	00109484 	add.d       	\$a0, \$a0, \$a1
+  14:	1a000004 	pcalau12i   	\$a0, 0
+			14: R_LARCH_GOT_PC_HI20	.L1
+			14: R_LARCH_RELAX	\*ABS\*
+  18:	02c00005 	li.d        	\$a1, 0
+			18: R_LARCH_GOT_PC_LO12	.L1
+			18: R_LARCH_RELAX	\*ABS\*
+  1c:	16000005 	lu32i.d     	\$a1, 0
+			1c: R_LARCH_GOT64_PC_LO20	.L1
+  20:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			20: R_LARCH_GOT64_PC_HI12	.L1
+  24:	380c1484 	ldx.d       	\$a0, \$a0, \$a1
+  28:	1a000004 	pcalau12i   	\$a0, 0
+			28: R_LARCH_PCALA_HI20	.L1
+			28: R_LARCH_RELAX	\*ABS\*
+  2c:	02c00005 	li.d        	\$a1, 0
+			2c: R_LARCH_PCALA_LO12	.L1
+			2c: R_LARCH_RELAX	\*ABS\*
+  30:	16000005 	lu32i.d     	\$a1, 0
+			30: R_LARCH_PCALA64_LO20	.L1
+  34:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			34: R_LARCH_PCALA64_HI12	.L1
+  38:	00109484 	add.d       	\$a0, \$a0, \$a1
+  3c:	1a000004 	pcalau12i   	\$a0, 0
+			3c: R_LARCH_GOT_PC_HI20	.L1
+			3c: R_LARCH_RELAX	\*ABS\*
+  40:	02c00005 	li.d        	\$a1, 0
+			40: R_LARCH_GOT_PC_LO12	.L1
+			40: R_LARCH_RELAX	\*ABS\*
+  44:	16000005 	lu32i.d     	\$a1, 0
+			44: R_LARCH_GOT64_PC_LO20	.L1
+  48:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			48: R_LARCH_GOT64_PC_HI12	.L1
+  4c:	380c1484 	ldx.d       	\$a0, \$a0, \$a1
+  50:	14000004 	lu12i.w     	\$a0, 0
+			50: R_LARCH_TLS_LE_HI20	TLS1
+  54:	03800084 	ori         	\$a0, \$a0, 0x0
+			54: R_LARCH_TLS_LE_LO12	TLS1
+  58:	1a000004 	pcalau12i   	\$a0, 0
+			58: R_LARCH_TLS_IE_PC_HI20	TLS1
+  5c:	02c00005 	li.d        	\$a1, 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
+			6c: R_LARCH_RELAX	\*ABS\*
+  70:	02c00005 	li.d        	\$a1, 0
+			70: R_LARCH_GOT_PC_LO12	TLS1
+			70: R_LARCH_RELAX	\*ABS\*
+  74:	16000005 	lu32i.d     	\$a1, 0
+			74: R_LARCH_GOT64_PC_LO20	TLS1
+  78:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			78: 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
+			80: R_LARCH_RELAX	\*ABS\*
+  84:	02c00005 	li.d        	\$a1, 0
+			84: R_LARCH_GOT_PC_LO12	TLS1
+			84: R_LARCH_RELAX	\*ABS\*
+  88:	16000005 	lu32i.d     	\$a1, 0
+			88: R_LARCH_GOT64_PC_LO20	TLS1
+  8c:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			8c: R_LARCH_GOT64_PC_HI12	TLS1
+  90:	00109484 	add.d       	\$a0, \$a0, \$a1
diff --git a/gas/testsuite/gas/loongarch/macro_op_large_pc.d b/gas/testsuite/gas/loongarch/macro_op_large_pc.d
index 0c49f68e2ab..729e878ffb8 100644
--- a/gas/testsuite/gas/loongarch/macro_op_large_pc.d
+++ b/gas/testsuite/gas/loongarch/macro_op_large_pc.d
@@ -1,85 +1,89 @@
-#as: -mla-global-with-abs
+#as:
 #objdump: -dr
 #skip: loongarch32-*-*
 
-.*:[    ]+file format .*
+.*:     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:[ 	]+02c00005[ 	]+li\.d[ 	]+\$a1,[ 	]+0
-[ 	]+4:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
-[ 	]+4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+8:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+8:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
-[ 	]+c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+c:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.L1
-[ 	]+10:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+14:[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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
+0+ <.L1>:
+   0:	1a000004 	pcalau12i   	\$a0, 0
+			0: R_LARCH_PCALA_HI20	.L1
+			0: R_LARCH_RELAX	\*ABS\*
+   4:	02c00005 	li.d        	\$a1, 0
+			4: R_LARCH_PCALA_LO12	.L1
+			4: R_LARCH_RELAX	\*ABS\*
+   8:	16000005 	lu32i.d     	\$a1, 0
+			8: R_LARCH_PCALA64_LO20	.L1
+   c:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			c: R_LARCH_PCALA64_HI12	.L1
+  10:	00109484 	add.d       	\$a0, \$a0, \$a1
+  14:	1a000004 	pcalau12i   	\$a0, 0
+			14: R_LARCH_GOT_PC_HI20	.L1
+			14: R_LARCH_RELAX	\*ABS\*
+  18:	02c00005 	li.d        	\$a1, 0
+			18: R_LARCH_GOT_PC_LO12	.L1
+			18: R_LARCH_RELAX	\*ABS\*
+  1c:	16000005 	lu32i.d     	\$a1, 0
+			1c: R_LARCH_GOT64_PC_LO20	.L1
+  20:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			20: R_LARCH_GOT64_PC_HI12	.L1
+  24:	380c1484 	ldx.d       	\$a0, \$a0, \$a1
+  28:	1a000004 	pcalau12i   	\$a0, 0
+			28: R_LARCH_PCALA_HI20	.L1
+			28: R_LARCH_RELAX	\*ABS\*
+  2c:	02c00005 	li.d        	\$a1, 0
+			2c: R_LARCH_PCALA_LO12	.L1
+			2c: R_LARCH_RELAX	\*ABS\*
+  30:	16000005 	lu32i.d     	\$a1, 0
+			30: R_LARCH_PCALA64_LO20	.L1
+  34:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			34: R_LARCH_PCALA64_HI12	.L1
+  38:	00109484 	add.d       	\$a0, \$a0, \$a1
+  3c:	1a000004 	pcalau12i   	\$a0, 0
+			3c: R_LARCH_GOT_PC_HI20	.L1
+			3c: R_LARCH_RELAX	\*ABS\*
+  40:	02c00005 	li.d        	\$a1, 0
+			40: R_LARCH_GOT_PC_LO12	.L1
+			40: R_LARCH_RELAX	\*ABS\*
+  44:	16000005 	lu32i.d     	\$a1, 0
+			44: R_LARCH_GOT64_PC_LO20	.L1
+  48:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			48: R_LARCH_GOT64_PC_HI12	.L1
+  4c:	380c1484 	ldx.d       	\$a0, \$a0, \$a1
+  50:	14000004 	lu12i.w     	\$a0, 0
+			50: R_LARCH_TLS_LE_HI20	TLS1
+  54:	03800084 	ori         	\$a0, \$a0, 0x0
+			54: R_LARCH_TLS_LE_LO12	TLS1
+  58:	1a000004 	pcalau12i   	\$a0, 0
+			58: R_LARCH_TLS_IE_PC_HI20	TLS1
+  5c:	02c00005 	li.d        	\$a1, 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
+			6c: R_LARCH_RELAX	\*ABS\*
+  70:	02c00005 	li.d        	\$a1, 0
+			70: R_LARCH_GOT_PC_LO12	TLS1
+			70: R_LARCH_RELAX	\*ABS\*
+  74:	16000005 	lu32i.d     	\$a1, 0
+			74: R_LARCH_GOT64_PC_LO20	TLS1
+  78:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			78: 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
+			80: R_LARCH_RELAX	\*ABS\*
+  84:	02c00005 	li.d        	\$a1, 0
+			84: R_LARCH_GOT_PC_LO12	TLS1
+			84: R_LARCH_RELAX	\*ABS\*
+  88:	16000005 	lu32i.d     	\$a1, 0
+			88: R_LARCH_GOT64_PC_LO20	TLS1
+  8c:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			8c: R_LARCH_GOT64_PC_HI12	TLS1
+  90:	00109484 	add.d       	\$a0, \$a0, \$a1
diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h
index 41e9fe4d234..6cfee164312 100644
--- a/include/elf/loongarch.h
+++ b/include/elf/loongarch.h
@@ -273,6 +273,10 @@ RELOC_NUMBER (R_LARCH_TLS_DESC64_HI12, 118)
 RELOC_NUMBER (R_LARCH_TLS_DESC_LD, 119)
 RELOC_NUMBER (R_LARCH_TLS_DESC_CALL, 120)
 
+RELOC_NUMBER (R_LARCH_TLS_LD_PCREL20_S2, 124)
+RELOC_NUMBER (R_LARCH_TLS_GD_PCREL20_S2, 125)
+RELOC_NUMBER (R_LARCH_TLS_DESC_PCREL20_S2, 126)
+
 END_RELOC_NUMBERS (R_LARCH_count)
 
 /* Processor specific flags for the ELF header e_flags field.  */
diff --git a/ld/testsuite/ld-loongarch-elf/macro_op.d b/ld/testsuite/ld-loongarch-elf/macro_op.d
index edc71bc0dbf..f0d87c03802 100644
--- a/ld/testsuite/ld-loongarch-elf/macro_op.d
+++ b/ld/testsuite/ld-loongarch-elf/macro_op.d
@@ -1,200 +1,205 @@
 #as:
 #objdump: -dr
+#skip: loongarch32-*-*
 
-.*:[    ]+file format .*
+.*:     file format .*
 
 
 Disassembly of section .text:
 
-00000000.* <.L1>:
-[ 	]+0:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
-[ 	]+4:[ 	]+02bffc04[ 	]+li\.w[ 	]+\$a0,[ 	]+-1
-[ 	]+8:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
-[ 	]+c:[ 	]+02bffc04[ 	]+li\.w[ 	]+\$a0,[ 	]+-1
-[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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
-[ 	]+2c:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.L1
-[ 	]+30:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+34:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+34:[ 	]+R_LARCH_GOT_PC_HI20[ 	]+.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[ 	]+li\.d[ 	]+\$a1,[ 	]+0
-[ 	]+40:[ 	]+R_LARCH_GOT_PC_LO12[ 	]+.L1
-[ 	]+40:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+44:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+44:[ 	]+R_LARCH_GOT64_PC_LO20[ 	]+.L1
-[ 	]+48:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+48:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.L1
-[ 	]+4c:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+50:[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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[ 	]+.L1
-[ 	]+6c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+70:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+70:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
-[ 	]+70:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+74:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+74:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
-[ 	]+74:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+78:[ 	]+02c00005[ 	]+li\.d[ 	]+\$a1,[ 	]+0
-[ 	]+78:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
-[ 	]+78:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+7c:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+7c:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
-[ 	]+80:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+80:[ 	]+R_LARCH_PCALA64_HI12[ 	]+.L1
-[ 	]+84:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+88:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+88:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
-[ 	]+88:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+8c:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+8c:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
-[ 	]+8c:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+90:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+90:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
-[ 	]+90:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+94:[ 	]+02c00005[ 	]+li\.d[ 	]+\$a1,[ 	]+0
-[ 	]+94:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
-[ 	]+94:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+98:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+98:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
-[ 	]+9c:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+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[ 	]+.L1
-[ 	]+a8:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
-[ 	]+a8:[ 	]+R_LARCH_ABS_LO12[ 	]+.L1
-[ 	]+ac:[ 	]+16000004[ 	]+lu32i.d[ 	]+\$a0,[ 	]+0
-[ 	]+ac:[ 	]+R_LARCH_ABS64_LO20[ 	]+.L1
-[ 	]+b0:[ 	]+03000084[ 	]+lu52i.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+b0:[ 	]+R_LARCH_ABS64_HI12[ 	]+.L1
-[ 	]+b4:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+b4:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
-[ 	]+b4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+b8:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+b8:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
-[ 	]+b8:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+bc:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+bc:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
-[ 	]+bc:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+c0:[ 	]+02c00084[ 	]+addi.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+c0:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
-[ 	]+c0:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+c4:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+c4:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
-[ 	]+c4:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+c8:[ 	]+02c00005[ 	]+li\.d[ 	]+\$a1,[ 	]+0
-[ 	]+c8:[ 	]+R_LARCH_PCALA_LO12[ 	]+.L1
-[ 	]+c8:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+cc:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+cc:[ 	]+R_LARCH_PCALA64_LO20[ 	]+.L1
-[ 	]+d0:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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
-[ 	]+ec:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+.L1
-[ 	]+f0:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+f4:[ 	]+14000004[ 	]+lu12i.w[ 	]+\$a0,[ 	]+0
-[ 	]+f4:[ 	]+R_LARCH_TLS_LE_HI20[ 	]+TLS1
-[ 	]+f8:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
-[ 	]+f8:[ 	]+R_LARCH_TLS_LE_LO12[ 	]+TLS1
-[ 	]+fc:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+fc:[ 	]+R_LARCH_TLS_IE_PC_HI20[ 	]+TLS1
-[ 	]+100:[ 	]+28c00084[ 	]+ld.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+100:[ 	]+R_LARCH_TLS_IE_PC_LO12[ 	]+TLS1
-[ 	]+104:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+104:[ 	]+R_LARCH_TLS_IE_PC_HI20[ 	]+TLS1
-[ 	]+108:[ 	]+02c00005[ 	]+li\.d[ 	]+\$a1,[ 	]+0
-[ 	]+108:[ 	]+R_LARCH_TLS_IE_PC_LO12[ 	]+TLS1
-[ 	]+10c:[ 	]+16000005[ 	]+lu32i.d[ 	]+\$a1,[ 	]+0
-[ 	]+10c:[ 	]+R_LARCH_TLS_IE64_PC_LO20[ 	]+TLS1
-[ 	]+110:[ 	]+030000a5[ 	]+lu52i.d[ 	]+\$a1,[ 	]+\$a1,[ 	]+0
-[ 	]+110:[ 	]+R_LARCH_TLS_IE64_PC_HI12[ 	]+TLS1
-[ 	]+114:[ 	]+380c1484[ 	]+ldx.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+118:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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
-[ 	]+12c:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+TLS1
-[ 	]+130:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
-[ 	]+134:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+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[ 	]+li\.d[ 	]+\$a1,[ 	]+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
-[ 	]+148:[ 	]+R_LARCH_GOT64_PC_HI12[ 	]+TLS1
-[ 	]+14c:[ 	]+00109484[ 	]+add.d[ 	]+\$a0,[ 	]+\$a0,[ 	]+\$a1
+0+ <.L1>:
+   0:	00150004 	move        	\$a0, \$zero
+   4:	02bffc04 	li.w        	\$a0, -1
+   8:	00150004 	move        	\$a0, \$zero
+   c:	02bffc04 	li.w        	\$a0, -1
+  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 	li.d        	\$a1, 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
+			2c: R_LARCH_GOT64_PC_HI12	.L1
+  30:	380c1484 	ldx.d       	\$a0, \$a0, \$a1
+  34:	1a000004 	pcalau12i   	\$a0, 0
+			34: R_LARCH_GOT_PC_HI20	.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 	li.d        	\$a1, 0
+			40: R_LARCH_GOT_PC_LO12	.L1
+			40: R_LARCH_RELAX	\*ABS\*
+  44:	16000005 	lu32i.d     	\$a1, 0
+			44: R_LARCH_GOT64_PC_LO20	.L1
+  48:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			48: R_LARCH_GOT64_PC_HI12	.L1
+  4c:	380c1484 	ldx.d       	\$a0, \$a0, \$a1
+  50:	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 	li.d        	\$a1, 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	.L1
+			6c: R_LARCH_RELAX	\*ABS\*
+  70:	02c00084 	addi.d      	\$a0, \$a0, 0
+			70: R_LARCH_PCALA_LO12	.L1
+			70: R_LARCH_RELAX	\*ABS\*
+  74:	1a000004 	pcalau12i   	\$a0, 0
+			74: R_LARCH_PCALA_HI20	.L1
+			74: R_LARCH_RELAX	\*ABS\*
+  78:	02c00005 	li.d        	\$a1, 0
+			78: R_LARCH_PCALA_LO12	.L1
+			78: R_LARCH_RELAX	\*ABS\*
+  7c:	16000005 	lu32i.d     	\$a1, 0
+			7c: R_LARCH_PCALA64_LO20	.L1
+  80:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			80: R_LARCH_PCALA64_HI12	.L1
+  84:	00109484 	add.d       	\$a0, \$a0, \$a1
+  88:	1a000004 	pcalau12i   	\$a0, 0
+			88: R_LARCH_PCALA_HI20	.L1
+			88: R_LARCH_RELAX	\*ABS\*
+  8c:	02c00084 	addi.d      	\$a0, \$a0, 0
+			8c: R_LARCH_PCALA_LO12	.L1
+			8c: R_LARCH_RELAX	\*ABS\*
+  90:	1a000004 	pcalau12i   	\$a0, 0
+			90: R_LARCH_PCALA_HI20	.L1
+			90: R_LARCH_RELAX	\*ABS\*
+  94:	02c00005 	li.d        	\$a1, 0
+			94: R_LARCH_PCALA_LO12	.L1
+			94: R_LARCH_RELAX	\*ABS\*
+  98:	16000005 	lu32i.d     	\$a1, 0
+			98: R_LARCH_PCALA64_LO20	.L1
+  9c:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			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	.L1
+  a8:	03800084 	ori         	\$a0, \$a0, 0x0
+			a8: R_LARCH_ABS_LO12	.L1
+  ac:	16000004 	lu32i.d     	\$a0, 0
+			ac: R_LARCH_ABS64_LO20	.L1
+  b0:	03000084 	lu52i.d     	\$a0, \$a0, 0
+			b0: R_LARCH_ABS64_HI12	.L1
+  b4:	1a000004 	pcalau12i   	\$a0, 0
+			b4: R_LARCH_PCALA_HI20	.L1
+			b4: R_LARCH_RELAX	\*ABS\*
+  b8:	02c00084 	addi.d      	\$a0, \$a0, 0
+			b8: R_LARCH_PCALA_LO12	.L1
+			b8: R_LARCH_RELAX	\*ABS\*
+  bc:	1a000004 	pcalau12i   	\$a0, 0
+			bc: R_LARCH_PCALA_HI20	.L1
+			bc: R_LARCH_RELAX	\*ABS\*
+  c0:	02c00084 	addi.d      	\$a0, \$a0, 0
+			c0: R_LARCH_PCALA_LO12	.L1
+			c0: R_LARCH_RELAX	\*ABS\*
+  c4:	1a000004 	pcalau12i   	\$a0, 0
+			c4: R_LARCH_PCALA_HI20	.L1
+			c4: R_LARCH_RELAX	\*ABS\*
+  c8:	02c00005 	li.d        	\$a1, 0
+			c8: R_LARCH_PCALA_LO12	.L1
+			c8: R_LARCH_RELAX	\*ABS\*
+  cc:	16000005 	lu32i.d     	\$a1, 0
+			cc: R_LARCH_PCALA64_LO20	.L1
+  d0:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			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 	li.d        	\$a1, 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
+			ec: R_LARCH_GOT64_PC_HI12	.L1
+  f0:	380c1484 	ldx.d       	\$a0, \$a0, \$a1
+  f4:	14000004 	lu12i.w     	\$a0, 0
+			f4: R_LARCH_TLS_LE_HI20	TLS1
+  f8:	03800084 	ori         	\$a0, \$a0, 0x0
+			f8: R_LARCH_TLS_LE_LO12	TLS1
+  fc:	1a000004 	pcalau12i   	\$a0, 0
+			fc: R_LARCH_TLS_IE_PC_HI20	TLS1
+ 100:	28c00084 	ld.d        	\$a0, \$a0, 0
+			100: R_LARCH_TLS_IE_PC_LO12	TLS1
+ 104:	1a000004 	pcalau12i   	\$a0, 0
+			104: R_LARCH_TLS_IE_PC_HI20	TLS1
+ 108:	02c00005 	li.d        	\$a1, 0
+			108: R_LARCH_TLS_IE_PC_LO12	TLS1
+ 10c:	16000005 	lu32i.d     	\$a1, 0
+			10c: R_LARCH_TLS_IE64_PC_LO20	TLS1
+ 110:	030000a5 	lu52i.d     	\$a1, \$a1, 0
+			110: R_LARCH_TLS_IE64_PC_HI12	TLS1
+ 114:	380c1484 	ldx.d       	\$a0, \$a0, \$a1
+ 118:	1a000004 	pcalau12i   	\$a0, 0
+			118: R_LARCH_TLS_LD_PC_HI20	TLS1
+			118: R_LARCH_RELAX	\*ABS\*
+ 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
+			120: R_LARCH_RELAX	\*ABS\*
+ 124:	02c00005 	li.d        	\$a1, 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
+			12c: R_LARCH_GOT64_PC_HI12	TLS1
+ 130:	00109484 	add.d       	\$a0, \$a0, \$a1
+ 134:	1a000004 	pcalau12i   	\$a0, 0
+			134: R_LARCH_TLS_GD_PC_HI20	TLS1
+			134: R_LARCH_RELAX	\*ABS\*
+ 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
+			13c: R_LARCH_RELAX	\*ABS\*
+ 140:	02c00005 	li.d        	\$a1, 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
+			148: R_LARCH_GOT64_PC_HI12	TLS1
+ 14c:	00109484 	add.d       	\$a0, \$a0, \$a1
diff --git a/ld/testsuite/ld-loongarch-elf/macro_op_32.d b/ld/testsuite/ld-loongarch-elf/macro_op_32.d
index 188026a5780..a7349aa8dc0 100644
--- a/ld/testsuite/ld-loongarch-elf/macro_op_32.d
+++ b/ld/testsuite/ld-loongarch-elf/macro_op_32.d
@@ -2,66 +2,68 @@
 #objdump: -dr
 #skip: loongarch64-*-*
 
-.*:[    ]+file format .*
+.*:     file format .*
 
 
 Disassembly of section .text:
 
-00000000.* <.L1>:
-[ 	]+0:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
-[ 	]+4:[ 	]+02bffc04[ 	]+li\.w[ 	]+\$a0,[ 	]+-1
-[ 	]+8:[ 	]+00150004[ 	]+move[ 	]+\$a0,[ 	]+\$zero
-[ 	]+c:[ 	]+02bffc04[ 	]+li\.w[ 	]+\$a0,[ 	]+-1
-[ 	]+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[ 	]+.L1
-[ 	]+20:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+24:[ 	]+02800084[ 	]+addi.w[ 	]+\$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
-[ 	]+2c:[ 	]+03800084[ 	]+ori[ 	]+\$a0,[ 	]+\$a0,[ 	]+0x0
-[ 	]+2c:[ 	]+R_LARCH_ABS_LO12[ 	]+.L1
-[ 	]+30:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+30:[ 	]+R_LARCH_PCALA_HI20[ 	]+.L1
-[ 	]+30:[ 	]+R_LARCH_RELAX[ 	]+\*ABS\*
-[ 	]+34:[ 	]+02800084[ 	]+addi.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+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
-[ 	]+44:[ 	]+R_LARCH_TLS_LE_LO12[ 	]+TLS1
-[ 	]+48:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+48:[ 	]+R_LARCH_TLS_IE_PC_HI20[ 	]+TLS1
-[ 	]+4c:[ 	]+28800084[ 	]+ld.w[ 	]+\$a0,[ 	]+\$a0,[ 	]+0
-[ 	]+4c:[ 	]+R_LARCH_TLS_IE_PC_LO12[ 	]+TLS1
-[ 	]+50:[ 	]+1a000004[ 	]+pcalau12i[ 	]+\$a0,[ 	]+0
-[ 	]+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\*
+0+ <.L1>:
+   0:	00150004 	move        	\$a0, \$zero
+   4:	02bffc04 	li.w        	\$a0, -1
+   8:	00150004 	move        	\$a0, \$zero
+   c:	02bffc04 	li.w        	\$a0, -1
+  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	.L1
+			20: R_LARCH_RELAX	\*ABS\*
+  24:	02800084 	addi.w      	\$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
+  2c:	03800084 	ori         	\$a0, \$a0, 0x0
+			2c: R_LARCH_ABS_LO12	.L1
+  30:	1a000004 	pcalau12i   	\$a0, 0
+			30: R_LARCH_PCALA_HI20	.L1
+			30: R_LARCH_RELAX	\*ABS\*
+  34:	02800084 	addi.w      	\$a0, \$a0, 0
+			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
+			44: R_LARCH_TLS_LE_LO12	TLS1
+  48:	1a000004 	pcalau12i   	\$a0, 0
+			48: R_LARCH_TLS_IE_PC_HI20	TLS1
+  4c:	28800084 	ld.w        	\$a0, \$a0, 0
+			4c: R_LARCH_TLS_IE_PC_LO12	TLS1
+  50:	1a000004 	pcalau12i   	\$a0, 0
+			50: R_LARCH_TLS_LD_PC_HI20	TLS1
+			50: R_LARCH_RELAX	\*ABS\*
+  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
+			58: R_LARCH_RELAX	\*ABS\*
+  5c:	02800084 	addi.w      	\$a0, \$a0, 0
+			5c: R_LARCH_GOT_PC_LO12	TLS1
+			5c: R_LARCH_RELAX	\*ABS\*
-- 
2.43.0


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

* Re: [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation
  2023-12-22 11:42 ` [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation Lulu Cai
@ 2023-12-28 14:38   ` Tatsuyuki Ishi
  2023-12-29 10:36     ` Lulu Cai
  2023-12-29 10:45     ` Lulu Cai
  0 siblings, 2 replies; 19+ messages in thread
From: Tatsuyuki Ishi @ 2023-12-28 14:38 UTC (permalink / raw)
  To: Lulu Cai
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

[-- Attachment #1: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH v5 3/5] LoongArch: Add tls transition support.
  2023-12-22 11:42 ` [PATCH v5 3/5] LoongArch: Add tls transition support Lulu Cai
@ 2023-12-28 14:42   ` Tatsuyuki Ishi
  2023-12-29 10:31     ` Lulu Cai
  0 siblings, 1 reply; 19+ messages in thread
From: Tatsuyuki Ishi @ 2023-12-28 14:42 UTC (permalink / raw)
  To: Lulu Cai
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

[-- Attachment #1: Type: text/plain, Size: 0 bytes --]



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

* Re: [PATCH v5 2/5] LoongArch: Add support for TLSDESC in ld.
  2023-12-22 11:42 ` [PATCH v5 2/5] LoongArch: Add support for TLSDESC in ld Lulu Cai
@ 2023-12-28 14:54   ` Tatsuyuki Ishi
  2023-12-29 10:24     ` Lulu Cai
  0 siblings, 1 reply; 19+ messages in thread
From: Tatsuyuki Ishi @ 2023-12-28 14:54 UTC (permalink / raw)
  To: Lulu Cai
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

Hi, author of RISC-V TLSDESC patches here. I recently learned that LoongArch is working on a similar TLSDESC extension too. I’ll leave some of my thoughts on the patch set.

> On Dec 22, 2023, at 20:42, Lulu Cai <cailulu@loongson.cn> wrote:
> 
> 1.The linker for each DESC generates a R_LARCH_TLS_DESC64 dynamic
>  relocation, which relocation is placed at .rela.dyn.
>  TLSDESC always allocates two GOT slots and one dynamic relocation
>  space to TLSDESC.
> 2. When using multiple ways to access the same TLS variable, a
>   maximum of 5 GOT slots are used. For example, using GD, TLSDESC,
>   and IE to access the same TLS variable, GD always uses the first
>   two of the five GOT, TLSDESC uses the third and fourth, and IE
>   uses the last.
> ---
> bfd/elfnn-loongarch.c | 168 ++++++++++++++++++++++++++++++++++++------
> 1 file changed, 146 insertions(+), 22 deletions(-)
> 
> diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
> index faffe27294a..95a39148f73 100644
> --- a/bfd/elfnn-loongarch.c
> +++ b/bfd/elfnn-loongarch.c
> @@ -48,6 +48,12 @@ struct loongarch_elf_link_hash_entry
> #define GOT_TLS_GD  2
> #define GOT_TLS_IE  4
> #define GOT_TLS_LE  8
> +#define GOT_TLS_GDESC 16
> +
> +#define GOT_TLS_GD_BOTH_P(tls_type) \
> +  ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC))
> +#define GOT_TLS_GD_ANY_P(tls_type) \
> +  ((tls_type & GOT_TLS_GD) || (tls_type & GOT_TLS_GDESC))
>   char tls_type;
> };
> 
> @@ -563,6 +569,7 @@ loongarch_elf_record_tls_and_got_reference (bfd *abfd,
>     case GOT_NORMAL:
>     case GOT_TLS_GD:
>     case GOT_TLS_IE:
> +    case GOT_TLS_GDESC:
>       /* Need GOT.  */
>       if (htab->elf.sgot == NULL
> 	  && !loongarch_elf_create_got_section (htab->elf.dynobj, info))
> @@ -750,6 +757,14 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
> 	    return false;
> 	  break;
> 
> +	case R_LARCH_TLS_DESC_PC_HI20:
> +	case R_LARCH_TLS_DESC_HI20:
> +	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
> +							   r_symndx,
> +							   GOT_TLS_GDESC))
> +	    return false;
> +	  break;
> +
> 	case R_LARCH_ABS_HI20:
> 	case R_LARCH_SOP_PUSH_ABSOLUTE:
> 	  if (h != NULL)
> @@ -1130,7 +1145,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
> 
>       s = htab->elf.sgot;
>       h->got.offset = s->size;
> -      if (tls_type & (GOT_TLS_GD | GOT_TLS_IE))
> +      if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
> 	{
> 	  /* TLS_GD needs two dynamic relocs and two GOT slots.  */
> 	  if (tls_type & GOT_TLS_GD)
> @@ -1167,7 +1182,15 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
> 		  htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
> 		}
> 	    }
> +
> +	  /* TLS_DESC needs one dynamic reloc and two GOT slot.  */
> +	  if (tls_type & GOT_TLS_GDESC)
> +	    {
> +	      s->size += GOT_ENTRY_SIZE * 2;
> +	      htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
> +	    }
> 	}
> +
>       else
> 	{
> 	  s->size += GOT_ENTRY_SIZE;
> @@ -1670,19 +1693,34 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd,
> 	  if (0 < *local_got)
> 	    {
> 	      *local_got = s->size;
> +	      if (*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
> +		{
> +		  /* TLS gd use two got.  */
> +		  if (*local_tls_type & GOT_TLS_GD)
> +		    {
> +		      s->size += 2 * GOT_ENTRY_SIZE;
> +		      if (!bfd_link_executable (info))
> +			srel->size += sizeof (ElfNN_External_Rela);
> +		    }
> 
> -	      /* TLS gd use two got.  */
> -	      if (*local_tls_type & GOT_TLS_GD)
> -		s->size += GOT_ENTRY_SIZE * 2;
> -	      else
> -		/* Normal got, tls ie/ld use one got.  */
> -		s->size += GOT_ENTRY_SIZE;
> +		  /* TLS_DESC use two got.  */
> +		  if (*local_tls_type & GOT_TLS_GDESC)
> +		    {
> +		      s->size += 2 * GOT_ENTRY_SIZE;
> +		      srel->size += sizeof (ElfNN_External_Rela);
> +		    }
> 
> -	      if (bfd_link_executable (info)
> -		  && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE)))
> -		;/* Do nothing.  */
> +		  /* TLS ie and use one got.  */
> +		  if (*local_tls_type & GOT_TLS_IE)
> +		    {
> +		      s->size += GOT_ENTRY_SIZE;
> +		      if (!bfd_link_executable (info))
> +			srel->size += sizeof (ElfNN_External_Rela);
> +		    }
> +		}
> 	      else
> 		{
> +		  s->size += GOT_ENTRY_SIZE;
> 		  srel->size += sizeof (ElfNN_External_Rela);
> 		}
> 	    }
> @@ -2126,6 +2164,15 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
>     case R_LARCH_TLS_GD_HI20:
>     case R_LARCH_PCREL20_S2:
>     case R_LARCH_CALL36:
> +    case R_LARCH_TLS_DESC_PC_HI20:
> +    case R_LARCH_TLS_DESC_PC_LO12:
> +    case R_LARCH_TLS_DESC64_PC_LO20:
> +    case R_LARCH_TLS_DESC64_PC_HI12:
> +    case R_LARCH_TLS_DESC_HI20:
> +    case R_LARCH_TLS_DESC_LO12:
> +    case R_LARCH_TLS_DESC64_LO20:
> +    case R_LARCH_TLS_DESC64_HI12:
> +
>       r = loongarch_check_offset (rel, input_section);
>       if (r != bfd_reloc_ok)
> 	break;
> @@ -2135,6 +2182,11 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
> 					    contents, value);
>       break;
> 
> +    case R_LARCH_TLS_DESC_LD:
> +    case R_LARCH_TLS_DESC_CALL:
> +      r = bfd_reloc_ok;
> +      break;
> +
>     case R_LARCH_RELAX:
>       break;
> 
> @@ -2383,10 +2435,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>       struct elf_link_hash_entry *h = NULL;
>       const char *name;
>       bfd_reloc_status_type r = bfd_reloc_ok;
> -      bool is_ie, is_undefweak, unresolved_reloc, defined_local;
> +      bool is_ie, is_desc, is_undefweak, unresolved_reloc, defined_local;
>       bool resolved_local, resolved_dynly, resolved_to_const;
>       char tls_type;
> -      bfd_vma relocation, off, ie_off;
> +      bfd_vma relocation, off, ie_off, desc_off;
>       int i, j;
> 
>       howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
> @@ -2515,6 +2567,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
> 
>       BFD_ASSERT (!resolved_local || defined_local);
> 
> +      is_desc = false;
>       is_ie = false;
>       switch (r_type)
> 	{
> @@ -3405,6 +3458,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
> 	case R_LARCH_TLS_LD_HI20:
> 	case R_LARCH_TLS_GD_PC_HI20:
> 	case R_LARCH_TLS_GD_HI20:
> +	case R_LARCH_TLS_DESC_PC_HI20:
> +	case R_LARCH_TLS_DESC_HI20:
> 	  BFD_ASSERT (rel->r_addend == 0);
> 	  unresolved_reloc = false;
> 
> @@ -3412,6 +3467,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
> 	      || r_type == R_LARCH_TLS_IE_HI20)
> 	    is_ie = true;
> 
> +	  if (r_type == R_LARCH_TLS_DESC_PC_HI20
> +	      || r_type == R_LARCH_TLS_DESC_HI20)
> +	    is_desc = true;
> +

I see that the got_off assignment logic is duplicated for R_LARCH_SOP_PUSH_TLS_{GOT, GD}, but that path was not modified in this patch. Is this OK? Ideally, the logic should not be duplicated at all.

> 	  bfd_vma got_off = 0;
> 	  if (h != NULL)
> 	    {
> @@ -3426,9 +3485,19 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
> 
> 	  BFD_ASSERT (got_off != MINUS_ONE);
> 
> -	  ie_off = 0;
> 	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
> -	  if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
> +
> +	  /* If a tls variable is accessed in multiple ways, GD uses
> +	     the first two slots of GOT, desc follows with two slots,
> +	     and IE uses one slot at the end.  */
> +	  desc_off = 0;
> +	  if (GOT_TLS_GD_BOTH_P (tls_type))
> +	    desc_off = 2 * GOT_ENTRY_SIZE;
> +
> +	  ie_off = 0;
> +	  if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type & GOT_TLS_IE))
> +	    ie_off = 4 * GOT_ENTRY_SIZE;
> +	  else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE))

I think the calculation should be done additively, instead of checking for every possible combination. That is,

off = 0;
if (tls gd)
  off += gd size;
desc_off = off;
if (tls ie)
  off += desc size;
ie_off = off;

would be much simpler.

> 	    ie_off = 2 * GOT_ENTRY_SIZE;
> 
> 	  if ((got_off & 1) == 0)
> @@ -3477,6 +3546,21 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
> 		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
> 		    }
> 		}
> +	      if (tls_type & GOT_TLS_GDESC)
> +		{
> +		  /* Unless it is a static link, DESC always emits a
> +		     dynamic relocation.  */
> +		  int indx = h && h->dynindx != -1 ? h->dynindx : 0;
> +		  rela.r_offset = sec_addr (got) + got_off + desc_off;
> +		  rela.r_addend = 0;
> +		  if (indx == 0)
> +		    rela.r_addend = relocation - elf_hash_table (info)->tls_sec->vma;
> +
> +		  rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_DESCNN);
> +		  loongarch_elf_append_rela (output_bfd, relgot, &rela);
> +		  bfd_put_NN (output_bfd, 0,
> +			      got->contents + got_off + desc_off);
> +		}
> 	      if (tls_type & GOT_TLS_IE)
> 		{
> 		  rela.r_offset = sec_addr (got) + got_off + ie_off;
> @@ -3504,16 +3588,52 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
> 		    }
> 		}
> 	    }
> -	  relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got)
> -			+ (is_ie ? ie_off : 0);
> +	  relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got);
> +	  if (is_desc)
> +	    relocation += desc_off;
> +	  else if (is_ie)
> +	    relocation += ie_off;
> 
> 	  if (r_type == R_LARCH_TLS_LD_PC_HI20
> 	      || r_type == R_LARCH_TLS_GD_PC_HI20
> -	      || r_type == R_LARCH_TLS_IE_PC_HI20)
> +	      || r_type == R_LARCH_TLS_IE_PC_HI20
> +	      || r_type == R_LARCH_TLS_DESC_PC_HI20)
> 	    RELOCATE_CALC_PC32_HI20 (relocation, pc);
> 
> 	  break;
> 
> +	case R_LARCH_TLS_DESC_PC_LO12:
> +	case R_LARCH_TLS_DESC64_PC_LO20:
> +	case R_LARCH_TLS_DESC64_PC_HI12:
> +	case R_LARCH_TLS_DESC_LO12:
> +	case R_LARCH_TLS_DESC64_LO20:
> +	case R_LARCH_TLS_DESC64_HI12:
> +	  {
> +	    unresolved_reloc = false;
> +
> +	    if (h)
> +	      relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)1));
> +	    else
> +	      relocation = sec_addr (got)
> +			   + (local_got_offsets[r_symndx] & (~(bfd_vma)1));
> +
> +	    tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
> +	    /* Use both TLS_GD and TLS_DESC.  */
> +	    if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC))
> +	      relocation += 2 * GOT_ENTRY_SIZE;

For simplicity, I think the ie_off and desc_off calculation should be moved out of the switch. Then you can just reuse the desc/ie_off calculated there.

> +	  }
> +
> +	    if (r_type == R_LARCH_TLS_DESC64_PC_LO20
> +		|| r_type == R_LARCH_TLS_DESC64_PC_HI12)
> +	      RELOCATE_CALC_PC64_HI32 (relocation, pc);
> +
> +	    break;
> +
> +	case R_LARCH_TLS_DESC_LD:
> +	case R_LARCH_TLS_DESC_CALL:
> +	  unresolved_reloc = false;
> +	  break;
> +
> 	case R_LARCH_TLS_IE_PC_LO12:
> 	case R_LARCH_TLS_IE64_PC_LO20:
> 	case R_LARCH_TLS_IE64_PC_HI12:
> @@ -3523,14 +3643,17 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
> 	  unresolved_reloc = false;
> 
> 	  if (h)
> -	    relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)3));
> +	    relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)1));
> 	  else
> 	    relocation = sec_addr (got)
> -	      + (local_got_offsets[r_symndx] & (~(bfd_vma)3));
> +	      + (local_got_offsets[r_symndx] & (~(bfd_vma)1));
> 
> 	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
> -	  /* Use both TLS_GD and TLS_IE.  */
> -	  if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
> +	  /* Use TLS_GD TLS_DESC and TLS_IE.  */
> +	  if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type & GOT_TLS_IE))
> +	    relocation += 4 * GOT_ENTRY_SIZE;
> +	  /* Use GOT_TLS_GD_ANY_P (tls_type) and TLS_IE.  */
> +	  else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE))
> 	    relocation += 2 * GOT_ENTRY_SIZE;
> 
> 	  if (r_type == R_LARCH_TLS_IE64_PC_LO20
> @@ -4174,7 +4297,8 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
> 
>   if (h->got.offset != MINUS_ONE
>       /* TLS got entry have been handled in elf_relocate_section.  */
> -      && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE))
> +      && !(loongarch_elf_hash_entry (h)->tls_type
> +	   & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
>       /* Have allocated got entry but not allocated rela before.  */
>       && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
>     {
> -- 
> 2.43.0
> 
> 


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

* Re: [PATCH v5 2/5] LoongArch: Add support for TLSDESC in ld.
  2023-12-28 14:54   ` Tatsuyuki Ishi
@ 2023-12-29 10:24     ` Lulu Cai
  0 siblings, 0 replies; 19+ messages in thread
From: Lulu Cai @ 2023-12-29 10:24 UTC (permalink / raw)
  To: Tatsuyuki Ishi
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

On 2023/12/28 at 10:54 PM, Tatsuyuki Ishi Wrote:
> Hi, author of RISC-V TLSDESC patches here. I recently learned that LoongArch is working on a similar TLSDESC extension too. I’ll leave some of my thoughts on the patch set.
Thank you for your suggestions, I will add a reply after these suggestions.
>
>> On Dec 22, 2023, at 20:42, Lulu Cai <cailulu@loongson.cn> wrote:
>>
>> 1.The linker for each DESC generates a R_LARCH_TLS_DESC64 dynamic
>>   relocation, which relocation is placed at .rela.dyn.
>>   TLSDESC always allocates two GOT slots and one dynamic relocation
>>   space to TLSDESC.
>> 2. When using multiple ways to access the same TLS variable, a
>>    maximum of 5 GOT slots are used. For example, using GD, TLSDESC,
>>    and IE to access the same TLS variable, GD always uses the first
>>    two of the five GOT, TLSDESC uses the third and fourth, and IE
>>    uses the last.
>> ---
>> bfd/elfnn-loongarch.c | 168 ++++++++++++++++++++++++++++++++++++------
>> 1 file changed, 146 insertions(+), 22 deletions(-)
>>
>> diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
>> index faffe27294a..95a39148f73 100644
>> --- a/bfd/elfnn-loongarch.c
>> +++ b/bfd/elfnn-loongarch.c
>> @@ -48,6 +48,12 @@ struct loongarch_elf_link_hash_entry
>> #define GOT_TLS_GD  2
>> #define GOT_TLS_IE  4
>> #define GOT_TLS_LE  8
>> +#define GOT_TLS_GDESC 16
>> +
>> +#define GOT_TLS_GD_BOTH_P(tls_type) \
>> +  ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC))
>> +#define GOT_TLS_GD_ANY_P(tls_type) \
>> +  ((tls_type & GOT_TLS_GD) || (tls_type & GOT_TLS_GDESC))
>>    char tls_type;
>> };
>>
>> @@ -563,6 +569,7 @@ loongarch_elf_record_tls_and_got_reference (bfd *abfd,
>>      case GOT_NORMAL:
>>      case GOT_TLS_GD:
>>      case GOT_TLS_IE:
>> +    case GOT_TLS_GDESC:
>>        /* Need GOT.  */
>>        if (htab->elf.sgot == NULL
>> 	  && !loongarch_elf_create_got_section (htab->elf.dynobj, info))
>> @@ -750,6 +757,14 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>> 	    return false;
>> 	  break;
>>
>> +	case R_LARCH_TLS_DESC_PC_HI20:
>> +	case R_LARCH_TLS_DESC_HI20:
>> +	  if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
>> +							   r_symndx,
>> +							   GOT_TLS_GDESC))
>> +	    return false;
>> +	  break;
>> +
>> 	case R_LARCH_ABS_HI20:
>> 	case R_LARCH_SOP_PUSH_ABSOLUTE:
>> 	  if (h != NULL)
>> @@ -1130,7 +1145,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
>>
>>        s = htab->elf.sgot;
>>        h->got.offset = s->size;
>> -      if (tls_type & (GOT_TLS_GD | GOT_TLS_IE))
>> +      if (tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
>> 	{
>> 	  /* TLS_GD needs two dynamic relocs and two GOT slots.  */
>> 	  if (tls_type & GOT_TLS_GD)
>> @@ -1167,7 +1182,15 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
>> 		  htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
>> 		}
>> 	    }
>> +
>> +	  /* TLS_DESC needs one dynamic reloc and two GOT slot.  */
>> +	  if (tls_type & GOT_TLS_GDESC)
>> +	    {
>> +	      s->size += GOT_ENTRY_SIZE * 2;
>> +	      htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
>> +	    }
>> 	}
>> +
>>        else
>> 	{
>> 	  s->size += GOT_ENTRY_SIZE;
>> @@ -1670,19 +1693,34 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd,
>> 	  if (0 < *local_got)
>> 	    {
>> 	      *local_got = s->size;
>> +	      if (*local_tls_type & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
>> +		{
>> +		  /* TLS gd use two got.  */
>> +		  if (*local_tls_type & GOT_TLS_GD)
>> +		    {
>> +		      s->size += 2 * GOT_ENTRY_SIZE;
>> +		      if (!bfd_link_executable (info))
>> +			srel->size += sizeof (ElfNN_External_Rela);
>> +		    }
>>
>> -	      /* TLS gd use two got.  */
>> -	      if (*local_tls_type & GOT_TLS_GD)
>> -		s->size += GOT_ENTRY_SIZE * 2;
>> -	      else
>> -		/* Normal got, tls ie/ld use one got.  */
>> -		s->size += GOT_ENTRY_SIZE;
>> +		  /* TLS_DESC use two got.  */
>> +		  if (*local_tls_type & GOT_TLS_GDESC)
>> +		    {
>> +		      s->size += 2 * GOT_ENTRY_SIZE;
>> +		      srel->size += sizeof (ElfNN_External_Rela);
>> +		    }
>>
>> -	      if (bfd_link_executable (info)
>> -		  && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE)))
>> -		;/* Do nothing.  */
>> +		  /* TLS ie and use one got.  */
>> +		  if (*local_tls_type & GOT_TLS_IE)
>> +		    {
>> +		      s->size += GOT_ENTRY_SIZE;
>> +		      if (!bfd_link_executable (info))
>> +			srel->size += sizeof (ElfNN_External_Rela);
>> +		    }
>> +		}
>> 	      else
>> 		{
>> +		  s->size += GOT_ENTRY_SIZE;
>> 		  srel->size += sizeof (ElfNN_External_Rela);
>> 		}
>> 	    }
>> @@ -2126,6 +2164,15 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
>>      case R_LARCH_TLS_GD_HI20:
>>      case R_LARCH_PCREL20_S2:
>>      case R_LARCH_CALL36:
>> +    case R_LARCH_TLS_DESC_PC_HI20:
>> +    case R_LARCH_TLS_DESC_PC_LO12:
>> +    case R_LARCH_TLS_DESC64_PC_LO20:
>> +    case R_LARCH_TLS_DESC64_PC_HI12:
>> +    case R_LARCH_TLS_DESC_HI20:
>> +    case R_LARCH_TLS_DESC_LO12:
>> +    case R_LARCH_TLS_DESC64_LO20:
>> +    case R_LARCH_TLS_DESC64_HI12:
>> +
>>        r = loongarch_check_offset (rel, input_section);
>>        if (r != bfd_reloc_ok)
>> 	break;
>> @@ -2135,6 +2182,11 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
>> 					    contents, value);
>>        break;
>>
>> +    case R_LARCH_TLS_DESC_LD:
>> +    case R_LARCH_TLS_DESC_CALL:
>> +      r = bfd_reloc_ok;
>> +      break;
>> +
>>      case R_LARCH_RELAX:
>>        break;
>>
>> @@ -2383,10 +2435,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>        struct elf_link_hash_entry *h = NULL;
>>        const char *name;
>>        bfd_reloc_status_type r = bfd_reloc_ok;
>> -      bool is_ie, is_undefweak, unresolved_reloc, defined_local;
>> +      bool is_ie, is_desc, is_undefweak, unresolved_reloc, defined_local;
>>        bool resolved_local, resolved_dynly, resolved_to_const;
>>        char tls_type;
>> -      bfd_vma relocation, off, ie_off;
>> +      bfd_vma relocation, off, ie_off, desc_off;
>>        int i, j;
>>
>>        howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
>> @@ -2515,6 +2567,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>
>>        BFD_ASSERT (!resolved_local || defined_local);
>>
>> +      is_desc = false;
>>        is_ie = false;
>>        switch (r_type)
>> 	{
>> @@ -3405,6 +3458,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>> 	case R_LARCH_TLS_LD_HI20:
>> 	case R_LARCH_TLS_GD_PC_HI20:
>> 	case R_LARCH_TLS_GD_HI20:
>> +	case R_LARCH_TLS_DESC_PC_HI20:
>> +	case R_LARCH_TLS_DESC_HI20:
>> 	  BFD_ASSERT (rel->r_addend == 0);
>> 	  unresolved_reloc = false;
>>
>> @@ -3412,6 +3467,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>> 	      || r_type == R_LARCH_TLS_IE_HI20)
>> 	    is_ie = true;
>>
>> +	  if (r_type == R_LARCH_TLS_DESC_PC_HI20
>> +	      || r_type == R_LARCH_TLS_DESC_HI20)
>> +	    is_desc = true;
>> +
> I see that the got_off assignment logic is duplicated for R_LARCH_SOP_PUSH_TLS_{GOT, GD}, but that path was not modified in this patch. Is this OK? Ideally, the logic should not be duplicated at all.
R_LARCH_SOP_PUSH_TLS_{GOT, GD} are relocations in the old toolchain that 
are no longer used by the new toolchain. So we are not going to modify this.
>
>> 	  bfd_vma got_off = 0;
>> 	  if (h != NULL)
>> 	    {
>> @@ -3426,9 +3485,19 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>
>> 	  BFD_ASSERT (got_off != MINUS_ONE);
>>
>> -	  ie_off = 0;
>> 	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
>> -	  if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
>> +
>> +	  /* If a tls variable is accessed in multiple ways, GD uses
>> +	     the first two slots of GOT, desc follows with two slots,
>> +	     and IE uses one slot at the end.  */
>> +	  desc_off = 0;
>> +	  if (GOT_TLS_GD_BOTH_P (tls_type))
>> +	    desc_off = 2 * GOT_ENTRY_SIZE;
>> +
>> +	  ie_off = 0;
>> +	  if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type & GOT_TLS_IE))
>> +	    ie_off = 4 * GOT_ENTRY_SIZE;
>> +	  else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE))
> I think the calculation should be done additively, instead of checking for every possible combination. That is,
>
> off = 0;
> if (tls gd)
>    off += gd size;
> desc_off = off;
> if (tls ie)
>    off += desc size;
> ie_off = off;
>
> would be much simpler.
Agreed, I will add these changes in a later version.
>> 	    ie_off = 2 * GOT_ENTRY_SIZE;
>>
>> 	  if ((got_off & 1) == 0)
>> @@ -3477,6 +3546,21 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>> 		      loongarch_elf_append_rela (output_bfd, relgot, &rela);
>> 		    }
>> 		}
>> +	      if (tls_type & GOT_TLS_GDESC)
>> +		{
>> +		  /* Unless it is a static link, DESC always emits a
>> +		     dynamic relocation.  */
>> +		  int indx = h && h->dynindx != -1 ? h->dynindx : 0;
>> +		  rela.r_offset = sec_addr (got) + got_off + desc_off;
>> +		  rela.r_addend = 0;
>> +		  if (indx == 0)
>> +		    rela.r_addend = relocation - elf_hash_table (info)->tls_sec->vma;
>> +
>> +		  rela.r_info = ELFNN_R_INFO (indx, R_LARCH_TLS_DESCNN);
>> +		  loongarch_elf_append_rela (output_bfd, relgot, &rela);
>> +		  bfd_put_NN (output_bfd, 0,
>> +			      got->contents + got_off + desc_off);
>> +		}
>> 	      if (tls_type & GOT_TLS_IE)
>> 		{
>> 		  rela.r_offset = sec_addr (got) + got_off + ie_off;
>> @@ -3504,16 +3588,52 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>> 		    }
>> 		}
>> 	    }
>> -	  relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got)
>> -			+ (is_ie ? ie_off : 0);
>> +	  relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got);
>> +	  if (is_desc)
>> +	    relocation += desc_off;
>> +	  else if (is_ie)
>> +	    relocation += ie_off;
>>
>> 	  if (r_type == R_LARCH_TLS_LD_PC_HI20
>> 	      || r_type == R_LARCH_TLS_GD_PC_HI20
>> -	      || r_type == R_LARCH_TLS_IE_PC_HI20)
>> +	      || r_type == R_LARCH_TLS_IE_PC_HI20
>> +	      || r_type == R_LARCH_TLS_DESC_PC_HI20)
>> 	    RELOCATE_CALC_PC32_HI20 (relocation, pc);
>>
>> 	  break;
>>
>> +	case R_LARCH_TLS_DESC_PC_LO12:
>> +	case R_LARCH_TLS_DESC64_PC_LO20:
>> +	case R_LARCH_TLS_DESC64_PC_HI12:
>> +	case R_LARCH_TLS_DESC_LO12:
>> +	case R_LARCH_TLS_DESC64_LO20:
>> +	case R_LARCH_TLS_DESC64_HI12:
>> +	  {
>> +	    unresolved_reloc = false;
>> +
>> +	    if (h)
>> +	      relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)1));
>> +	    else
>> +	      relocation = sec_addr (got)
>> +			   + (local_got_offsets[r_symndx] & (~(bfd_vma)1));
>> +
>> +	    tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
>> +	    /* Use both TLS_GD and TLS_DESC.  */
>> +	    if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_GDESC))
>> +	      relocation += 2 * GOT_ENTRY_SIZE;
> For simplicity, I think the ie_off and desc_off calculation should be moved out of the switch. Then you can just reuse the desc/ie_off calculated there.
I will modify it in a later version.
>> +	  }
>> +
>> +	    if (r_type == R_LARCH_TLS_DESC64_PC_LO20
>> +		|| r_type == R_LARCH_TLS_DESC64_PC_HI12)
>> +	      RELOCATE_CALC_PC64_HI32 (relocation, pc);
>> +
>> +	    break;
>> +
>> +	case R_LARCH_TLS_DESC_LD:
>> +	case R_LARCH_TLS_DESC_CALL:
>> +	  unresolved_reloc = false;
>> +	  break;
>> +
>> 	case R_LARCH_TLS_IE_PC_LO12:
>> 	case R_LARCH_TLS_IE64_PC_LO20:
>> 	case R_LARCH_TLS_IE64_PC_HI12:
>> @@ -3523,14 +3643,17 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>> 	  unresolved_reloc = false;
>>
>> 	  if (h)
>> -	    relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)3));
>> +	    relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)1));
>> 	  else
>> 	    relocation = sec_addr (got)
>> -	      + (local_got_offsets[r_symndx] & (~(bfd_vma)3));
>> +	      + (local_got_offsets[r_symndx] & (~(bfd_vma)1));
>>
>> 	  tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx);
>> -	  /* Use both TLS_GD and TLS_IE.  */
>> -	  if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE))
>> +	  /* Use TLS_GD TLS_DESC and TLS_IE.  */
>> +	  if (GOT_TLS_GD_BOTH_P (tls_type) && (tls_type & GOT_TLS_IE))
>> +	    relocation += 4 * GOT_ENTRY_SIZE;
>> +	  /* Use GOT_TLS_GD_ANY_P (tls_type) and TLS_IE.  */
>> +	  else if (GOT_TLS_GD_ANY_P (tls_type) && (tls_type & GOT_TLS_IE))
>> 	    relocation += 2 * GOT_ENTRY_SIZE;
>>
>> 	  if (r_type == R_LARCH_TLS_IE64_PC_LO20
>> @@ -4174,7 +4297,8 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
>>
>>    if (h->got.offset != MINUS_ONE
>>        /* TLS got entry have been handled in elf_relocate_section.  */
>> -      && !(loongarch_elf_hash_entry (h)->tls_type & (GOT_TLS_GD | GOT_TLS_IE))
>> +      && !(loongarch_elf_hash_entry (h)->tls_type
>> +	   & (GOT_TLS_GD | GOT_TLS_IE | GOT_TLS_GDESC))
>>        /* Have allocated got entry but not allocated rela before.  */
>>        && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
>>      {
>> -- 
>> 2.43.0
>>
>>


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

* Re: [PATCH v5 3/5] LoongArch: Add tls transition support.
  2023-12-28 14:42   ` Tatsuyuki Ishi
@ 2023-12-29 10:31     ` Lulu Cai
  0 siblings, 0 replies; 19+ messages in thread
From: Lulu Cai @ 2023-12-29 10:31 UTC (permalink / raw)
  To: Tatsuyuki Ishi
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

[-- Attachment #1: Type: text/plain, Size: 11312 bytes --]

On 2023/12/28 at 10:42 PM, Tatsuyuki Ishi Wrote:
>> On Dec 22, 2023, at 20:42, Lulu Cai <cailulu@loongson.cn> wrote:
>>
>> Transitions between DESC->IE/LE and IE->LE are supported now.
>> 1. For DESC -> LE:
>>   pcalau12i  $a0,%desc_pc_hi20(var)     =>  lu12i.w $a0,%le_hi20(var)
>>   addi.d     $a0,$a0,%desc_pc_lo12(var) =>  ori $a0,$a0,%le_lo12(var)
>>   ld.d       $a1,$a0,%desc_ld(var)      =>  NOP
>>   jirl       $ra,$a1,%desc_call(var)=>  NOP
>>   add.d      $a0,$a0,$tp
>> 2. For DESC -> IE:
>>   pcalau12i  $a0,%desc_pc_hi20(var)     =>  pcalau12i 
>> $a0,%ie_pc_hi20(var)
>>   addi.d     $a0,$a0,%desc_pc_lo12(var) =>  ld.d $a0,$a0,%ie_pc_lo12(var)
>>   ld.d       $a1,$a0,%desc_ld(var)      =>  NOP
>>   jirl       $ra,$a1,%desc_call(var)=>  NOP
>>   add.d      $a0,$a0,$tp
>> 3. For IE -> LE:
>>   pcalau12i  $a0,%ie_pc_hi20(var)       =>  lu12i.w $a0,%le_hi20(var)
>>   ld.d       $a0,$a0,%ie_pc_lo12(var)   =>  ori $a0,$a0,%le_lo12(var)
>>   add.d      $a0,$a0,$tp
>> 4. When a tls variable is accessed using both DESC and IE, DESC 
>> transitions
>>   to IE and uses the same GOT entry as IE.
>> ---
>> bfd/elfnn-loongarch.c      | 216 ++++++++++++++++++++++++++++++++++++-
>> include/opcode/loongarch.h |   6 ++
>> 2 files changed, 221 insertions(+), 1 deletion(-)
>>
>> diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
>> index 95a39148f73..1347d13d2e2 100644
>> --- a/bfd/elfnn-loongarch.c
>> +++ b/bfd/elfnn-loongarch.c
>> @@ -145,6 +145,16 @@ struct loongarch_elf_link_hash_table
>> #define elf_backend_rela_normal 1
>> #define elf_backend_default_execstack 0
>>
>> +#define IS_LOONGARCH_TLS_DESC_RELOC(R_TYPE)    \
>> +  ((R_TYPE) == R_LARCH_TLS_DESC_PC_HI20\
>> +   || (R_TYPE) == R_LARCH_TLS_DESC_PC_LO12  \
>> +   || (R_TYPE) == R_LARCH_TLS_DESC_LD \
>> +   || (R_TYPE) == R_LARCH_TLS_DESC_CALL)
>> +
>> +#define IS_LOONGARCH_TLS_IE_RELOC(R_TYPE) \
>> +  ((R_TYPE) == R_LARCH_TLS_IE_PC_HI20 \
>> +   || (R_TYPE) == R_LARCH_TLS_IE_PC_LO12)
>> +
>> /* Generate a PLT header.  */
>>
>> static bool
>> @@ -593,6 +603,10 @@ loongarch_elf_record_tls_and_got_reference (bfd 
>> *abfd,
>>
>>   char *new_tls_type = &_bfd_loongarch_elf_tls_type (abfd, h, symndx);
>>   *new_tls_type |= tls_type;
>> +
>> +  /* If a symbol is accessed by both IE and DESC, relax DESC to IE.  */
>> +  if ((*new_tls_type & GOT_TLS_IE) && (*new_tls_type & GOT_TLS_GDESC))
>> +    *new_tls_type &= ~ (GOT_TLS_GDESC);
>>   if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
>>     {
>>       _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
>> @@ -605,6 +619,104 @@ loongarch_elf_record_tls_and_got_reference (bfd 
>> *abfd,
>>   return true;
>> }
>>
>> +static unsigned int
>> +loongarch_reloc_got_type (unsigned int r_type)
>> +{
>> +  switch (r_type)
>> +    {
>> +      case R_LARCH_TLS_DESC_PC_HI20:
>> +      case R_LARCH_TLS_DESC_PC_LO12:
>> +      case R_LARCH_TLS_DESC_LD:
>> +      case R_LARCH_TLS_DESC_CALL:
>> +return GOT_TLS_GDESC;
>> +
>> +      case R_LARCH_TLS_IE_PC_HI20:
>> +      case R_LARCH_TLS_IE_PC_LO12:
>> +return GOT_TLS_IE;
>> +
>> +      default:
>> +break;
>

> I would expect the function to cover GD and LE too. See remark about 
> relaxation below though.
>

I may add it in a later version.

>> +    }
>> +  return GOT_UNKNOWN;
>> +}
>> +
>> +/* Return true if tls type transition can be performed.  */
>> +static bool
>> +loongarch_can_relax_tls (struct bfd_link_info *info, unsigned int 
>> r_type,
>> +struct elf_link_hash_entry *h, bfd *input_bfd,
>> +unsigned long r_symndx)
>> +{
>> +  char symbol_tls_type;
>> +  unsigned int reloc_got_type;
>> +
>> +  if (! (IS_LOONGARCH_TLS_DESC_RELOC (r_type)
>> +|| IS_LOONGARCH_TLS_IE_RELOC (r_type)))
>> +    return false;
>> +
>> +  symbol_tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, 
>> r_symndx);
>> +  reloc_got_type = loongarch_reloc_got_type (r_type);
>> +
>> +  if (symbol_tls_type == GOT_TLS_IE && GOT_TLS_GD_ANY_P 
>> (reloc_got_type))
>> +    return true;
>

> Per the suggestion above, if you add TLS_GD into the return value of 
> loongarch_reloc_got_type, you might want to double check if GD -> IE 
> relaxation is possible. (This was not the case for RISC-V.)

GD->LE relaxation is not possible on LoongArch because the location of 
bl %plt(__tls_get_addr) cannot be determined.

>
>> +
>> +  if (! bfd_link_executable (info))
>> +      return false;
>> +
>> +  if (h && h->root.type == bfd_link_hash_undefweak)
>> +    return false;
>> +
>> +  return true;
>> +}
>> +
>> +/* The type of relocation that can be transitioned.  */
>> +static unsigned int
>> +loongarch_tls_transition_without_check (struct bfd_link_info *info,
>> +unsigned int r_type,
>> +struct elf_link_hash_entry *h)
>> +{
>> +  bool local_exec = bfd_link_executable (info)
>> +   && SYMBOL_REFERENCES_LOCAL (info, h);
>> +
>> +  switch (r_type)
>> +    {
>> +      case R_LARCH_TLS_DESC_PC_HI20:
>> +return (local_exec
>> +? R_LARCH_TLS_LE_HI20
>> +: R_LARCH_TLS_IE_PC_HI20);
>> +
>> +      case R_LARCH_TLS_DESC_PC_LO12:
>> +return (local_exec
>> +? R_LARCH_TLS_LE_LO12
>> +: R_LARCH_TLS_IE_PC_LO12);
>> +
>> +      case R_LARCH_TLS_DESC_LD:
>> +      case R_LARCH_TLS_DESC_CALL:
>> +return R_LARCH_NONE;
>> +
>> +      case R_LARCH_TLS_IE_PC_HI20:
>> +return local_exec ? R_LARCH_TLS_LE_HI20 : r_type;
>> +
>> +      case R_LARCH_TLS_IE_PC_LO12:
>> +return local_exec ? R_LARCH_TLS_LE_LO12 : r_type;
>> +
>> +      default:
>> +break;
>> +    }
>> +
>> +  return r_type;
>> +}
>> +
>> +static unsigned int
>> +loongarch_tls_transition (struct bfd_link_info *info, unsigned int 
>> r_type,
>> + struct elf_link_hash_entry *h, bfd *input_bfd,
>> + unsigned long r_symndx)
>> +{
>> +  if (! loongarch_can_relax_tls (info, r_type, h, input_bfd,r_symndx))
>> +    return r_type;
>> +
>> +  return loongarch_tls_transition_without_check (info, r_type, h);
>> +}
>> +
>> /* Look through the relocs for a section during the first phase, and
>>    allocate space in the global offset table or procedure linkage
>>    table.  */
>> @@ -706,6 +818,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct 
>> bfd_link_info *info,
>>       int need_dynreloc = 0;
>>       int only_need_pcrel = 0;
>>
>> +      r_type = loongarch_tls_transition (info, r_type, h, abfd, 
>> r_symndx);
>>       switch (r_type)
>> {
>> case R_LARCH_GOT_PC_HI20:
>> @@ -2403,6 +2516,96 @@ loongarch_reloc_is_fatal (struct bfd_link_info 
>> *info,
>>       relocation += 0x100000000;\
>>   })
>>
>> +/* Transition instruction sequence to relax instruction sequence.  */
>> +static bool
>> +loongarch_tls_relax (bfd *abfd, asection *sec, Elf_Internal_Rela *rel,
>> +   int r_type, struct elf_link_hash_entry *h,
>> +   struct bfd_link_info *info)
>> +{
>> +  bool local_exec = bfd_link_executable (info)
>> +   && SYMBOL_REFERENCES_LOCAL (info, h);
>> +  bfd_byte *contents = elf_section_data (sec)->this_hdr.contents;
>> +  unsigned long insn;
>> +
>> +  switch (r_type)
>> +    {
>> +      case R_LARCH_TLS_DESC_PC_HI20:
>> +if (local_exec)
>> +   /* DESC -> LE relaxation:
>> +      pcalalau12i $a0,%desc_pc_hi20(var) =>
>> +      lu12i.w $a0,%le_hi20(var)
>> +   */
>> +   bfd_put (32, abfd, LARCH_LU12I_W | LARCH_RD_A0,
>> +    contents + rel->r_offset);
>> +
>> +/* DESC -> IE relaxation:
>> +  pcalalau12i $a0,%desc_pc_hi20(var) =>
>> +  pcalalau12i $a0,%ie_pc_hi20(var)
>> +*/
>> +return true;
>> +
>> +      case R_LARCH_TLS_DESC_PC_LO12:
>> +if (local_exec)
>> + {
>> +   /* DESC -> LE relaxation:
>> +      addi.d $a0,$a0,%desc_pc_lo12(var) =>
>> +      ori  $a0,$a0,le_lo12(var)
>> +   */
>> +   insn = LARCH_ORI | LARCH_RD_RJ_A0;
>> +   bfd_put (32, abfd, LARCH_ORI | LARCH_RD_RJ_A0,
>> +    contents + rel->r_offset);
>> + }
>> +else
>> + {
>> +   /* DESC -> IE relaxation:
>> +      addi.d $a0,$a0,%desc_pc_lo12(var) =>
>> +      ld.d $a0,$a0,%%ie_pc_lo12
>> +   */
>> +   bfd_put (32, abfd, LARCH_LD_D | LARCH_RD_RJ_A0,
>> +    contents + rel->r_offset);
>> + }
>> +return true;
>> +
>> +      case R_LARCH_TLS_DESC_LD:
>> +      case R_LARCH_TLS_DESC_CALL:
>> +/* DESC -> LE/IE relaxation:
>> +  ld.d $ra,$a0,%desc_ld(var) => NOP
>> +  jirl $ra,$ra,%desc_call(var) => NOP
>> +*/
>> +bfd_put (32, abfd, LARCH_NOP, contents + rel->r_offset);
>> +return true;
>> +
>> +      case R_LARCH_TLS_IE_PC_HI20:
>> +if (local_exec)
>> + {
>> +   /* IE -> LE relaxation:
>> +      pcalalau12i $rd,%ie_pc_hi20(var) =>
>> +      lu12i.w $rd,%le_hi20(var)
>> +   */
>> +   insn = bfd_getl32 (contents + rel->r_offset);
>> +   bfd_put (32, abfd, LARCH_LU12I_W | (insn & 0x1f),
>> +    contents + rel->r_offset);
>> + }
>> +return true;
>> +
>> +      case R_LARCH_TLS_IE_PC_LO12:
>> +if (local_exec)
>> + {
>> +   /* IE -> LE relaxation:
>> +      ld.d $rd,$rj,%%ie_pc_lo12 =>
>> +      ori  $rd,$rj,le_lo12(var)
>> +   */
>> +   insn = bfd_getl32 (contents + rel->r_offset);
>> +   bfd_put (32, abfd, LARCH_ORI | (insn & 0x3ff),
>> +    contents + rel->r_offset);
>> + }
>> +return true;
>> +    }
>> +
>> +  return false;
>> +}
>> +
>> +
>> static int
>> loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info 
>> *info,
>> bfd *input_bfd, asection *input_section,
>> @@ -2426,7 +2629,7 @@ loongarch_elf_relocate_section (bfd 
>> *output_bfd, struct bfd_link_info *info,
>>   relend = relocs + input_section->reloc_count;
>>   for (rel = relocs; rel < relend; rel++)
>>     {
>> -      int r_type = ELFNN_R_TYPE (rel->r_info);
>> +      unsigned int r_type = ELFNN_R_TYPE (rel->r_info);
>>       unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>>       bfd_vma pc = sec_addr (input_section) + rel->r_offset;
>>       reloc_howto_type *howto = NULL;
>> @@ -2436,6 +2639,7 @@ loongarch_elf_relocate_section (bfd 
>> *output_bfd, struct bfd_link_info *info,
>>       const char *name;
>>       bfd_reloc_status_type r = bfd_reloc_ok;
>>       bool is_ie, is_desc, is_undefweak, unresolved_reloc, defined_local;
>> +      unsigned int relaxed_r_type;
>>       bool resolved_local, resolved_dynly, resolved_to_const;
>>       char tls_type;
>>       bfd_vma relocation, off, ie_off, desc_off;
>> @@ -2567,6 +2771,16 @@ loongarch_elf_relocate_section (bfd 
>> *output_bfd, struct bfd_link_info *info,
>>
>>       BFD_ASSERT (!resolved_local || defined_local);
>>
>> +      relaxed_r_type = loongarch_tls_transition (info, r_type, h, 
>> input_bfd, r_symndx);
>> +      if (relaxed_r_type != r_type)
>> +      {
>> +howto = loongarch_elf_rtype_to_howto (input_bfd, relaxed_r_type);
>> +BFD_ASSERT (howto != NULL);
>> +
>> +if (loongarch_tls_relax (input_bfd, input_section, rel, r_type, h, 
>> info))
>> + r_type = relaxed_r_type;
>> +      }
>> +
>>       is_desc = false;
>>       is_ie = false;
>>       switch (r_type)
>> diff --git a/include/opcode/loongarch.h b/include/opcode/loongarch.h
>> index da936f7945a..32ff4d8a0f1 100644
>> --- a/include/opcode/loongarch.h
>> +++ b/include/opcode/loongarch.h
>> @@ -42,6 +42,12 @@ extern "C"
>>     ((value) < (-(1 << ((bits) - 1) << align)) \
>>       || (value) > ((((1 << ((bits) - 1)) - 1) << align)))
>>
>> +  #define LARCH_LU12I_W 0x14000000
>> +  #define LARCH_ORI 0x03800000
>> +  #define LARCH_LD_D 0x28c00000
>> +  #define LARCH_RD_A0 0x04
>> +  #define LARCH_RD_RJ_A0 0x084
>> +
>>   typedef uint32_t insn_t;
>>
>>   struct loongarch_opcode
>> -- 
>> 2.43.0
>>
>>
>


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

* Re: [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation
  2023-12-28 14:38   ` Tatsuyuki Ishi
@ 2023-12-29 10:36     ` Lulu Cai
  2023-12-29 10:45     ` Lulu Cai
  1 sibling, 0 replies; 19+ messages in thread
From: Lulu Cai @ 2023-12-29 10:36 UTC (permalink / raw)
  To: Tatsuyuki Ishi
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

[-- Attachment #1: Type: text/plain, Size: 64683 bytes --]

On 2023/12/28 at 10:38 PM, Tatsuyuki Ishi Wrote:
>> On Dec 22, 2023, at 20:42, Lulu Cai <cailulu@loongson.cn> wrote:
>>
>> From: mengqinggang <mengqinggang@loongson.cn>
>>
>> The pcalau12i + addi.d of TLS LD/GD/DESC relax to pcaddi.
>> Relaxation is only performed when the TLS model transition is not 
>> possible.
>> ---
>> bfd/bfd-in2.h                                 |   3 +
>> bfd/elfnn-loongarch.c                         | 174 +++++++-
>> bfd/elfxx-loongarch.c                         |  60 +++
>> bfd/libbfd.h                                  |   3 +
>> bfd/reloc.c                                   |   7 +
>> gas/config/tc-loongarch.c                     |   8 +-
>> gas/testsuite/gas/loongarch/macro_op.d        | 128 +++---
>> gas/testsuite/gas/loongarch/macro_op_32.d     | 120 +++---
>> .../gas/loongarch/macro_op_large_abs.d        | 160 +++----
>> .../gas/loongarch/macro_op_large_pc.d         | 160 +++----
>> include/elf/loongarch.h                       |   4 +
>> ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++++---------
>> ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 +++---
>> 13 files changed, 795 insertions(+), 543 deletions(-)
>>
>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>> index 85251aa0edd..782845926ea 100644
>> --- a/bfd/bfd-in2.h
>> +++ b/bfd/bfd-in2.h
>> @@ -7473,6 +7473,9 @@ enum bfd_reloc_code_real
>>   BFD_RELOC_LARCH_TLS_DESC64_HI12,
>>   BFD_RELOC_LARCH_TLS_DESC_LD,
>>   BFD_RELOC_LARCH_TLS_DESC_CALL,
>> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,
>> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,
>> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,
>>   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 1347d13d2e2..bd448cda453 100644
>> --- a/bfd/elfnn-loongarch.c
>> +++ b/bfd/elfnn-loongarch.c
>> @@ -2285,7 +2285,9 @@ perform_relocation (const Elf_Internal_Rela 
>> *rel, asection *input_section,
>>     case R_LARCH_TLS_DESC_LO12:
>>     case R_LARCH_TLS_DESC64_LO20:
>>     case R_LARCH_TLS_DESC64_HI12:
>> -
>> +    case R_LARCH_TLS_LD_PCREL20_S2:
>> +    case R_LARCH_TLS_GD_PCREL20_S2:
>> +    case R_LARCH_TLS_DESC_PCREL20_S2:
>>       r = loongarch_check_offset (rel, input_section);
>>       if (r != bfd_reloc_ok)
>> break;
>> @@ -3674,6 +3676,9 @@ loongarch_elf_relocate_section (bfd 
>> *output_bfd, struct bfd_link_info *info,
>> case R_LARCH_TLS_GD_HI20:
>> case R_LARCH_TLS_DESC_PC_HI20:
>> case R_LARCH_TLS_DESC_HI20:
>> +case R_LARCH_TLS_LD_PCREL20_S2:
>> +case R_LARCH_TLS_GD_PCREL20_S2:
>> +case R_LARCH_TLS_DESC_PCREL20_S2:
>>  BFD_ASSERT (rel->r_addend == 0);
>>  unresolved_reloc = false;
>>
>> @@ -3682,7 +3687,8 @@ loongarch_elf_relocate_section (bfd 
>> *output_bfd, struct bfd_link_info *info,
>>    is_ie = true;
>>
>>  if (r_type == R_LARCH_TLS_DESC_PC_HI20
>> -     || r_type == R_LARCH_TLS_DESC_HI20)
>> +     || r_type == R_LARCH_TLS_DESC_HI20
>> +     || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>>    is_desc = true;
>>
>>  bfd_vma got_off = 0;
>> @@ -3813,7 +3819,11 @@ loongarch_elf_relocate_section (bfd 
>> *output_bfd, struct bfd_link_info *info,
>>      || r_type == R_LARCH_TLS_IE_PC_HI20
>>      || r_type == R_LARCH_TLS_DESC_PC_HI20)
>>    RELOCATE_CALC_PC32_HI20 (relocation, pc);
>> -
>> + else if (r_type == R_LARCH_TLS_LD_PCREL20_S2
>> +     || r_type == R_LARCH_TLS_GD_PCREL20_S2
>> +     || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>> +   relocation -= pc;
>> + /* else {} ABS relocations.  */
>>  break;
>>
>> case R_LARCH_TLS_DESC_PC_LO12:
>> @@ -4244,6 +4254,85 @@ loongarch_relax_align (bfd *abfd, asection *sec,
>> addend - need_nop_bytes, link_info);
>> }
>>
>> +/* Relax pcalau12i + addi.d of TLS LD/GD/DESC to pcaddi.  */
>> +static bool
>> +loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection 
>> *sym_sec,
>> +      Elf_Internal_Rela *rel_hi, bfd_vma symval,
>> +      struct bfd_link_info *info, bool *again)
>> +{
>> +  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;
>> +
>> +  /* This section's output_offset need to subtract the bytes of 
>> instructions
>> +     relaxed by the previous sections, so it needs to be updated 
>> beforehand.
>> +     size_input_section already took care of updating it after 
>> relaxation,
>> +     so we additionally update once here.  */
>> +  sec->output_offset = sec->output_section->size;
>> +  bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
>> +
>> +  /* If pc and symbol not in the same segment, add/sub segment 
>> alignment.
>> +     FIXME: if there are multiple readonly segments?  */
>> +  if (!(sym_sec->flags & SEC_READONLY))
>> +    {
>> +      if (symval > pc)
>> +pc -= info->maxpagesize;
>> +      else if (symval < pc)
>> +pc += info->maxpagesize;
>> +    }
>> +
>> +  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_GOT_PC_LO12
>> +&& ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_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)
>> +      || ((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;
>> +
>> +  /* Continue next relax trip.  */
>> +  *again = true;
>> +
>> +  pca = pcaddi | rd;
>> +  bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
>> +
>> +  /* Adjust relocations.  */
>> +  switch (ELFNN_R_TYPE (rel_hi->r_info))
>> +    {
>> +    case R_LARCH_TLS_LD_PC_HI20:
>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>> +     R_LARCH_TLS_LD_PCREL20_S2);
>> +      break;
>> +    case R_LARCH_TLS_GD_PC_HI20:
>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>> +     R_LARCH_TLS_GD_PCREL20_S2);
>> +      break;
>> +    case R_LARCH_TLS_DESC_PC_HI20:
>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>> +     R_LARCH_TLS_DESC_PCREL20_S2);
>> +      break;
>> +    default:
>> +      break;
>> +    }
>> +  rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
>> +
>> +  loongarch_relax_delete_bytes (abfd, sec, rel_lo->r_offset, 4, info);
>> +
>> +  return true;
>> +}
>> +
>> static bool
>> loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>       struct bfd_link_info *info,
>> @@ -4288,15 +4377,23 @@ loongarch_elf_relax_section (bfd *abfd, 
>> asection *sec,
>>
>>   for (unsigned int i = 0; i < sec->reloc_count; i++)
>>     {
>> -      Elf_Internal_Rela *rel = relocs + i;
>> -      asection *sym_sec;
>> +      char symtype;
>>       bfd_vma symval;
>> -      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>> -      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
>> +      asection *sym_sec;
>>       bool local_got = false;
>> -      char symtype;
>> +      Elf_Internal_Rela *rel = relocs + i;
>>       struct elf_link_hash_entry *h = NULL;
>> +      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
>> +      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>>
>> +      /* Four kind of relocations:
>> +Normal: symval is the symbol address.
>> +R_LARCH_ALIGN: symval is the address of the last NOP instruction
>> +added by this relocation, and then adds 4 more.
>> +R_LARCH_CALL36: symval is the symbol address for local symbols,
>> +or the PLT entry address of the symbol. (Todo)
>> +R_LARCHL_TLS_LD/GD/DESC_PC_HI20: symval is the GOT entry address
>> +of the symbol.  */
>>       if (r_symndx < symtab_hdr->sh_info)
>> {
>>  Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
>> @@ -4304,7 +4401,24 @@ loongarch_elf_relax_section (bfd *abfd, 
>> asection *sec,
>>  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
>>    continue;
>>
>> - if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>> + if (R_LARCH_TLS_LD_PC_HI20 == r_type
>> +     || R_LARCH_TLS_GD_PC_HI20 == r_type
>> +     || R_LARCH_TLS_DESC_PC_HI20 == r_type)
>> +   {
>> +     if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
>> +continue;
>> +     else
>> +{
>> + sym_sec = htab->elf.sgot;
>> + symval = elf_local_got_offsets (abfd)[r_symndx];
>> + char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
>> +r_symndx);
>> + if (R_LARCH_TLS_DESC_PC_HI20 == r_type
>> +&& GOT_TLS_GD_BOTH_P (tls_type))
>> +   symval += 2 * GOT_ENTRY_SIZE;
>> +}
>> +   }
>> + else if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>>    {
>>      sym_sec = sec;
>>      symval = rel->r_offset;
>> @@ -4329,7 +4443,26 @@ loongarch_elf_relax_section (bfd *abfd, 
>> asection *sec,
>>  if (h != NULL && h->type == STT_GNU_IFUNC)
>>    continue;
>>
>> - if ((h->root.type == bfd_link_hash_defined
>> + /* The GOT entry of tls symbols must in current execute file or
>> +    shared object.  */
>> + if (R_LARCH_TLS_LD_PC_HI20 == r_type
>> +     || R_LARCH_TLS_GD_PC_HI20 == r_type
>> +     || R_LARCH_TLS_DESC_PC_HI20 == r_type)
>> +   {
>> +     if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
>> +continue;
>> +     else
>> +{
>> + sym_sec = htab->elf.sgot;
>> + symval = h->got.offset;
>> + char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
>> +r_symndx);
>> + if (R_LARCH_TLS_DESC_PC_HI20 == r_type
>> +&& GOT_TLS_GD_BOTH_P (tls_type))
>> +   symval += 2 * GOT_ENTRY_SIZE;
>> +}
>> +   }
>> + else 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)
>> @@ -4358,7 +4491,7 @@ loongarch_elf_relax_section (bfd *abfd, 
>> asection *sec,
>>   if (symtype != STT_SECTION)
>>     symval += rel->r_addend;
>> }
>> -      /* For R_LARCH_ALIGN, symval is sec_addr (sym_sec) + rel->r_offset
>> +      /* For R_LARCH_ALIGN, symval is sec_addr (sec) + rel->r_offset
>> + (alingmeng - 4).
>> If r_symndx is 0, alignmeng-4 is r_addend.
>> If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4.  */
>> @@ -4399,6 +4532,25 @@ loongarch_elf_relax_section (bfd *abfd, 
>> asection *sec,
>>    info, again);
>>    }
>>  break;
>> +
>> +case R_LARCH_TLS_LD_PC_HI20:
>> + if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>> +   loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>> +   info, again);
>> + break;
>> +
>> +case R_LARCH_TLS_GD_PC_HI20:
>> + if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>> +   loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>> +   info, again);
>> + break;
>> +
>> +case R_LARCH_TLS_DESC_PC_HI20:
>> + if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>> +   loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>> +   info, again);
>> + break;
>> +
>> default:
>>  break;
>> }
>> diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
>> index 30a941a851f..310e6d62dc0 100644
>> --- a/bfd/elfxx-loongarch.c
>> +++ b/bfd/elfxx-loongarch.c
>> @@ -1775,6 +1775,60 @@ static loongarch_reloc_howto_type 
>> loongarch_howto_table[] =
>> BFD_RELOC_LARCH_TLS_DESC_CALL,/* bfd_reloc_code_real_type.  */
>> NULL,/* adjust_reloc_bits.  */
>> "desc_call"),/* larch_reloc_type_name.  */
>> +
>> +  /* For pcaddi, ld_pc_hi20 + ld_pc_lo12 can relax to ld_pcrel20_s2.  */
>> +  LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCREL20_S2,/* type (124).  */
>> +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_TLS_LD_PCREL20_S2",/* name.  */
>> +false,/* partial_inplace.  */
>> +0,/* src_mask.  */
>> +0x1ffffe0,/* dst_mask.  */
>> +true,/* pcrel_offset.  */
>> +BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,/* bfd_reloc_code_real_type.  */
>> +reloc_sign_bits,/* adjust_reloc_bits.  */
>> +"ld_pcrel_20"),/* larch_reloc_type_name.  */
>> +
>> +  /* For pcaddi, gd_pc_hi20 + gd_pc_lo12 can relax to gd_pcrel20_s2.  */
>> +  LOONGARCH_HOWTO (R_LARCH_TLS_GD_PCREL20_S2,/* type (125).  */
>> +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_TLS_GD_PCREL20_S2",/* name.  */
>> +false,/* partial_inplace.  */
>> +0,/* src_mask.  */
>> +0x1ffffe0,/* dst_mask.  */
>> +true,/* pcrel_offset.  */
>> +BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,/* bfd_reloc_code_real_type.  */
>> +reloc_sign_bits,/* adjust_reloc_bits.  */
>> +"gd_pcrel_20"),/* larch_reloc_type_name.  */
>> +
>> +  /* For pcaddi, desc_pc_hi20 + desc_pc_lo12 can relax to 
>> desc_pcrel20_s2.  */
>> +  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PCREL20_S2,/* type (126).  */
>> +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_TLS_DESC_PCREL20_S2",/* name.  */
>> +false,/* partial_inplace.  */
>> +0,/* src_mask.  */
>> +0x1ffffe0,/* dst_mask.  */
>> +true,/* pcrel_offset.  */
>> +BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,/* bfd_reloc_code_real_type.  */
>> +reloc_sign_bits,/* adjust_reloc_bits.  */
>> +"desc_pcrel_20"),/* larch_reloc_type_name.  */
>> };
>

> I think relaxation relocs is a concept internal to binutils and they 
> should not be in the same number range as psABI defined relocs. Some 
> linkers (e.g. mold) doesn’t create new relocs when relaxing and 
> rewrites the instruction right away, therefore these relocs would have 
> no purpose in the psABI.
>
> We recently refactored out all the linker-internal relocs to a 
> different range [1]; LoongArch might want to follow suit.
>
> [1]: https://sourceware.org/pipermail/binutils/2023-November/130322.html
>

However, it should be noted that in handwritten assembly code, we can 
directly use these relocations.

>>
>> reloc_howto_type *
>> @@ -1783,7 +1837,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, 
>> unsigned int r_type)
>>   if(r_type < R_LARCH_count)
>>     {
>>       /* For search table fast.  */
>> +      /*
>>       BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>> +      */
>

> Was this supposed to be commented out and committed as-is?


It has been deleted.

>
>>
>>       if (loongarch_howto_table[r_type].howto.type == r_type)
>> return (reloc_howto_type *)&loongarch_howto_table[r_type];
>> @@ -1802,7 +1858,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, 
>> unsigned int r_type)
>> reloc_howto_type *
>> loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char 
>> *r_name)
>> {
>> +  /*
>>   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>> +  */
>>
>>   for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
>>     if (loongarch_howto_table[i].howto.name
>> @@ -1821,7 +1879,9 @@ reloc_howto_type *
>> loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
>>     bfd_reloc_code_real_type code)
>> {
>> +  /*
>>   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>> +  */
>>
>>   /* Fast search for new reloc types.  */
>>   if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
>> diff --git a/bfd/libbfd.h b/bfd/libbfd.h
>> index 71b03da14d9..8dab44110a6 100644
>> --- a/bfd/libbfd.h
>> +++ b/bfd/libbfd.h
>> @@ -3612,6 +3612,9 @@ static const char *const 
>> bfd_reloc_code_real_names[] = { "@@uninitialized@@",
>>   "BFD_RELOC_LARCH_TLS_DESC64_HI12",
>>   "BFD_RELOC_LARCH_TLS_DESC_LD",
>>   "BFD_RELOC_LARCH_TLS_DESC_CALL",
>> +  "BFD_RELOC_LARCH_TLS_LD_PCREL20_S2",
>> +  "BFD_RELOC_LARCH_TLS_GD_PCREL20_S2",
>> +  "BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2",
>>  "@@overflow: BFD_RELOC_UNUSED@@",
>> };
>> #endif
>> diff --git a/bfd/reloc.c b/bfd/reloc.c
>> index f7fe0c7ffe3..6fd0f1fb547 100644
>> --- a/bfd/reloc.c
>> +++ b/bfd/reloc.c
>> @@ -8324,6 +8324,13 @@ ENUMX
>> ENUMX
>>   BFD_RELOC_LARCH_TLS_DESC_CALL
>>
>> +ENUMX
>> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2
>> +ENUMX
>> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2
>> +ENUMX
>> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2
>> +
>> ENUMDOC
>>   LARCH relocations.
>>
>> diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
>> index 1658025f918..def26daf634 100644
>> --- a/gas/config/tc-loongarch.c
>> +++ b/gas/config/tc-loongarch.c
>> @@ -682,7 +682,7 @@ loongarch_args_parser_can_match_arg_helper (char 
>> esc_ch1, char esc_ch2,
>>      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_TLS_DESC_CALL)
>> +     && ip->reloc_info[0].type <= BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2)
>>    {
>>      /* As we compact stack-relocs, it is no need for pop operation.
>> But break out until here in order to check the imm field.
>> @@ -694,7 +694,11 @@ loongarch_args_parser_can_match_arg_helper (char 
>> esc_ch1, char esc_ch2,
>>    && (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))
>> +|| BFD_RELOC_LARCH_GOT_PC_LO12 == reloc_type
>> +|| BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_type
>> +|| BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_type
>> +|| BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_type
>> +|| BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_type))
>> {
>>  ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
>>  ip->reloc_info[ip->reloc_num].value = const_0;
>> diff --git a/gas/testsuite/gas/loongarch/macro_op.d 
>> b/gas/testsuite/gas/loongarch/macro_op.d
>> index 32860864704..47f8f45c663 100644
>> --- a/gas/testsuite/gas/loongarch/macro_op.d
>> +++ b/gas/testsuite/gas/loongarch/macro_op.d
>> @@ -2,70 +2,72 @@
>> #objdump: -dr
>> #skip: loongarch32-*-*
>>
>> -.*:[    ]+file format .*
>> +.*:     file format .*
>>
>>
>> Disassembly of section .text:
>>
>> -00000000.* <.text>:
>> -[ ]+0:[ ]+00150004[ ]+move[ ]+\$a0,[ ]+\$zero
>> -[ ]+4:[ ]+02bffc04[ ]+li\.w[ ]+\$a0,[ ]+-1
>> -[ ]+8:[ ]+00150004[ ]+move[ ]+\$a0,[ ]+\$zero
>> -[ ]+c:[ ]+02bffc04[ ]+li\.w[ ]+\$a0,[ ]+-1
>> -[ ]+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_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
>> -[ ]+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
>> -[ ]+38:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+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
>> -[ ]+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:[ ]+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:[ ]+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:[ ]+R_LARCH_GOT_PC_LO12[ ]+TLS1
>> -[ ]+64:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> +0+ <.*>:
>> +   0:00150004 move \$a0, \$zero
>> +   4:02bffc04 li.w \$a0, -1
>> +   8:00150004 move \$a0, \$zero
>> +   c:02bffc04 li.w \$a0, -1
>> +  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_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
>> +  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
>> +  38:1a000004 pcalau12i \$a0, 0
>> +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
>> +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_HI20TLS1
>> +  4c:03800084 ori \$a0, \$a0, 0x0
>> +4c: R_LARCH_TLS_LE_LO12TLS1
>> +  50:1a000004 pcalau12i \$a0, 0
>> +50: R_LARCH_TLS_IE_PC_HI20TLS1
>> +  54:28c00084 ld.d \$a0, \$a0, 0
>> +54: R_LARCH_TLS_IE_PC_LO12TLS1
>> +  58:1a000004 pcalau12i \$a0, 0
>> +58: R_LARCH_TLS_LD_PC_HI20TLS1
>> +58: R_LARCH_RELAX\*ABS\*
>> +  5c:02c00084 addi.d \$a0, \$a0, 0
>> +5c: R_LARCH_GOT_PC_LO12TLS1
>> +5c: R_LARCH_RELAX\*ABS\*
>> +  60:1a000004 pcalau12i \$a0, 0
>> +60: R_LARCH_TLS_GD_PC_HI20TLS1
>> +60: R_LARCH_RELAX\*ABS\*
>> +  64:02c00084 addi.d \$a0, \$a0, 0
>> +64: R_LARCH_GOT_PC_LO12TLS1
>> +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 188026a5780..a7349aa8dc0 100644
>> --- a/gas/testsuite/gas/loongarch/macro_op_32.d
>> +++ b/gas/testsuite/gas/loongarch/macro_op_32.d
>> @@ -2,66 +2,68 @@
>> #objdump: -dr
>> #skip: loongarch64-*-*
>>
>> -.*:[    ]+file format .*
>> +.*:     file format .*
>>
>>
>> Disassembly of section .text:
>>
>> -00000000.* <.L1>:
>> -[ ]+0:[ ]+00150004[ ]+move[ ]+\$a0,[ ]+\$zero
>> -[ ]+4:[ ]+02bffc04[ ]+li\.w[ ]+\$a0,[ ]+-1
>> -[ ]+8:[ ]+00150004[ ]+move[ ]+\$a0,[ ]+\$zero
>> -[ ]+c:[ ]+02bffc04[ ]+li\.w[ ]+\$a0,[ ]+-1
>> -[ ]+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[ ]+.L1
>> -[ ]+20:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+24:[ ]+02800084[ ]+addi.w[ ]+\$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
>> -[ ]+2c:[ ]+03800084[ ]+ori[ ]+\$a0,[ ]+\$a0,[ ]+0x0
>> -[ ]+2c:[ ]+R_LARCH_ABS_LO12[ ]+.L1
>> -[ ]+30:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+30:[ ]+R_LARCH_PCALA_HI20[ ]+.L1
>> -[ ]+30:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+34:[ ]+02800084[ ]+addi.w[ ]+\$a0,[ ]+\$a0,[ ]+0
>> -[ ]+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
>> -[ ]+44:[ ]+R_LARCH_TLS_LE_LO12[ ]+TLS1
>> -[ ]+48:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+48:[ ]+R_LARCH_TLS_IE_PC_HI20[ ]+TLS1
>> -[ ]+4c:[ ]+28800084[ ]+ld.w[ ]+\$a0,[ ]+\$a0,[ ]+0
>> -[ ]+4c:[ ]+R_LARCH_TLS_IE_PC_LO12[ ]+TLS1
>> -[ ]+50:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+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\*
>> +0+ <.L1>:
>> +   0:00150004 move \$a0, \$zero
>> +   4:02bffc04 li.w \$a0, -1
>> +   8:00150004 move \$a0, \$zero
>> +   c:02bffc04 li.w \$a0, -1
>> +  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.L1
>> +20: R_LARCH_RELAX\*ABS\*
>> +  24:02800084 addi.w \$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
>> +  2c:03800084 ori \$a0, \$a0, 0x0
>> +2c: R_LARCH_ABS_LO12.L1
>> +  30:1a000004 pcalau12i \$a0, 0
>> +30: R_LARCH_PCALA_HI20.L1
>> +30: R_LARCH_RELAX\*ABS\*
>> +  34:02800084 addi.w \$a0, \$a0, 0
>> +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_HI20TLS1
>> +  44:03800084 ori \$a0, \$a0, 0x0
>> +44: R_LARCH_TLS_LE_LO12TLS1
>> +  48:1a000004 pcalau12i \$a0, 0
>> +48: R_LARCH_TLS_IE_PC_HI20TLS1
>> +  4c:28800084 ld.w \$a0, \$a0, 0
>> +4c: R_LARCH_TLS_IE_PC_LO12TLS1
>> +  50:1a000004 pcalau12i \$a0, 0
>> +50: R_LARCH_TLS_LD_PC_HI20TLS1
>> +50: R_LARCH_RELAX\*ABS\*
>> +  54:02800084 addi.w \$a0, \$a0, 0
>> +54: R_LARCH_GOT_PC_LO12TLS1
>> +54: R_LARCH_RELAX\*ABS\*
>> +  58:1a000004 pcalau12i \$a0, 0
>> +58: R_LARCH_TLS_GD_PC_HI20TLS1
>> +58: R_LARCH_RELAX\*ABS\*
>> +  5c:02800084 addi.w \$a0, \$a0, 0
>> +5c: R_LARCH_GOT_PC_LO12TLS1
>> +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 0c49f68e2ab..729e878ffb8 100644
>> --- a/gas/testsuite/gas/loongarch/macro_op_large_abs.d
>> +++ b/gas/testsuite/gas/loongarch/macro_op_large_abs.d
>> @@ -1,85 +1,89 @@
>> -#as: -mla-global-with-abs
>> +#as:
>> #objdump: -dr
>> #skip: loongarch32-*-*
>>
>> -.*:[    ]+file format .*
>> +.*:     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:[ ]+02c00005[ ]+li\.d[ ]+\$a1,[ ]+0
>> -[ ]+4:[ ]+R_LARCH_PCALA_LO12[ ]+.L1
>> -[ ]+4:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+8:[ ]+16000005[ ]+lu32i.d[ ]+\$a1,[ ]+0
>> -[ ]+8:[ ]+R_LARCH_PCALA64_LO20[ ]+.L1
>> -[ ]+c:[ ]+030000a5[ ]+lu52i.d[ ]+\$a1,[ ]+\$a1,[ ]+0
>> -[ ]+c:[ ]+R_LARCH_PCALA64_HI12[ ]+.L1
>> -[ ]+10:[ ]+00109484[ ]+add.d[ ]+\$a0,[ ]+\$a0,[ ]+\$a1
>> -[ ]+14:[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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
>> +0+ <.L1>:
>> +   0:1a000004 pcalau12i \$a0, 0
>> +0: R_LARCH_PCALA_HI20.L1
>> +0: R_LARCH_RELAX\*ABS\*
>> +   4:02c00005 li.d \$a1, 0
>> +4: R_LARCH_PCALA_LO12.L1
>> +4: R_LARCH_RELAX\*ABS\*
>> +   8:16000005 lu32i.d \$a1, 0
>> +8: R_LARCH_PCALA64_LO20.L1
>> +   c:030000a5 lu52i.d \$a1, \$a1, 0
>> +c: R_LARCH_PCALA64_HI12.L1
>> +  10:00109484 add.d \$a0, \$a0, \$a1
>> +  14:1a000004 pcalau12i \$a0, 0
>> +14: R_LARCH_GOT_PC_HI20.L1
>> +14: R_LARCH_RELAX\*ABS\*
>> +  18:02c00005 li.d \$a1, 0
>> +18: R_LARCH_GOT_PC_LO12.L1
>> +18: R_LARCH_RELAX\*ABS\*
>> +  1c:16000005 lu32i.d \$a1, 0
>> +1c: R_LARCH_GOT64_PC_LO20.L1
>> +  20:030000a5 lu52i.d \$a1, \$a1, 0
>> +20: R_LARCH_GOT64_PC_HI12.L1
>> +  24:380c1484 ldx.d \$a0, \$a0, \$a1
>> +  28:1a000004 pcalau12i \$a0, 0
>> +28: R_LARCH_PCALA_HI20.L1
>> +28: R_LARCH_RELAX\*ABS\*
>> +  2c:02c00005 li.d \$a1, 0
>> +2c: R_LARCH_PCALA_LO12.L1
>> +2c: R_LARCH_RELAX\*ABS\*
>> +  30:16000005 lu32i.d \$a1, 0
>> +30: R_LARCH_PCALA64_LO20.L1
>> +  34:030000a5 lu52i.d \$a1, \$a1, 0
>> +34: R_LARCH_PCALA64_HI12.L1
>> +  38:00109484 add.d \$a0, \$a0, \$a1
>> +  3c:1a000004 pcalau12i \$a0, 0
>> +3c: R_LARCH_GOT_PC_HI20.L1
>> +3c: R_LARCH_RELAX\*ABS\*
>> +  40:02c00005 li.d \$a1, 0
>> +40: R_LARCH_GOT_PC_LO12.L1
>> +40: R_LARCH_RELAX\*ABS\*
>> +  44:16000005 lu32i.d \$a1, 0
>> +44: R_LARCH_GOT64_PC_LO20.L1
>> +  48:030000a5 lu52i.d \$a1, \$a1, 0
>> +48: R_LARCH_GOT64_PC_HI12.L1
>> +  4c:380c1484 ldx.d \$a0, \$a0, \$a1
>> +  50:14000004 lu12i.w \$a0, 0
>> +50: R_LARCH_TLS_LE_HI20TLS1
>> +  54:03800084 ori \$a0, \$a0, 0x0
>> +54: R_LARCH_TLS_LE_LO12TLS1
>> +  58:1a000004 pcalau12i \$a0, 0
>> +58: R_LARCH_TLS_IE_PC_HI20TLS1
>> +  5c:02c00005 li.d \$a1, 0
>> +5c: R_LARCH_TLS_IE_PC_LO12TLS1
>> +  60:16000005 lu32i.d \$a1, 0
>> +60: R_LARCH_TLS_IE64_PC_LO20TLS1
>> +  64:030000a5 lu52i.d \$a1, \$a1, 0
>> +64: R_LARCH_TLS_IE64_PC_HI12TLS1
>> +  68:380c1484 ldx.d \$a0, \$a0, \$a1
>> +  6c:1a000004 pcalau12i \$a0, 0
>> +6c: R_LARCH_TLS_LD_PC_HI20TLS1
>> +6c: R_LARCH_RELAX\*ABS\*
>> +  70:02c00005 li.d \$a1, 0
>> +70: R_LARCH_GOT_PC_LO12TLS1
>> +70: R_LARCH_RELAX\*ABS\*
>> +  74:16000005 lu32i.d \$a1, 0
>> +74: R_LARCH_GOT64_PC_LO20TLS1
>> +  78:030000a5 lu52i.d \$a1, \$a1, 0
>> +78: R_LARCH_GOT64_PC_HI12TLS1
>> +  7c:00109484 add.d \$a0, \$a0, \$a1
>> +  80:1a000004 pcalau12i \$a0, 0
>> +80: R_LARCH_TLS_GD_PC_HI20TLS1
>> +80: R_LARCH_RELAX\*ABS\*
>> +  84:02c00005 li.d \$a1, 0
>> +84: R_LARCH_GOT_PC_LO12TLS1
>> +84: R_LARCH_RELAX\*ABS\*
>> +  88:16000005 lu32i.d \$a1, 0
>> +88: R_LARCH_GOT64_PC_LO20TLS1
>> +  8c:030000a5 lu52i.d \$a1, \$a1, 0
>> +8c: R_LARCH_GOT64_PC_HI12TLS1
>> +  90:00109484 add.d \$a0, \$a0, \$a1
>> diff --git a/gas/testsuite/gas/loongarch/macro_op_large_pc.d 
>> b/gas/testsuite/gas/loongarch/macro_op_large_pc.d
>> index 0c49f68e2ab..729e878ffb8 100644
>> --- a/gas/testsuite/gas/loongarch/macro_op_large_pc.d
>> +++ b/gas/testsuite/gas/loongarch/macro_op_large_pc.d
>> @@ -1,85 +1,89 @@
>> -#as: -mla-global-with-abs
>> +#as:
>> #objdump: -dr
>> #skip: loongarch32-*-*
>>
>> -.*:[    ]+file format .*
>> +.*:     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:[ ]+02c00005[ ]+li\.d[ ]+\$a1,[ ]+0
>> -[ ]+4:[ ]+R_LARCH_PCALA_LO12[ ]+.L1
>> -[ ]+4:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+8:[ ]+16000005[ ]+lu32i.d[ ]+\$a1,[ ]+0
>> -[ ]+8:[ ]+R_LARCH_PCALA64_LO20[ ]+.L1
>> -[ ]+c:[ ]+030000a5[ ]+lu52i.d[ ]+\$a1,[ ]+\$a1,[ ]+0
>> -[ ]+c:[ ]+R_LARCH_PCALA64_HI12[ ]+.L1
>> -[ ]+10:[ ]+00109484[ ]+add.d[ ]+\$a0,[ ]+\$a0,[ ]+\$a1
>> -[ ]+14:[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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
>> +0+ <.L1>:
>> +   0:1a000004 pcalau12i \$a0, 0
>> +0: R_LARCH_PCALA_HI20.L1
>> +0: R_LARCH_RELAX\*ABS\*
>> +   4:02c00005 li.d \$a1, 0
>> +4: R_LARCH_PCALA_LO12.L1
>> +4: R_LARCH_RELAX\*ABS\*
>> +   8:16000005 lu32i.d \$a1, 0
>> +8: R_LARCH_PCALA64_LO20.L1
>> +   c:030000a5 lu52i.d \$a1, \$a1, 0
>> +c: R_LARCH_PCALA64_HI12.L1
>> +  10:00109484 add.d \$a0, \$a0, \$a1
>> +  14:1a000004 pcalau12i \$a0, 0
>> +14: R_LARCH_GOT_PC_HI20.L1
>> +14: R_LARCH_RELAX\*ABS\*
>> +  18:02c00005 li.d \$a1, 0
>> +18: R_LARCH_GOT_PC_LO12.L1
>> +18: R_LARCH_RELAX\*ABS\*
>> +  1c:16000005 lu32i.d \$a1, 0
>> +1c: R_LARCH_GOT64_PC_LO20.L1
>> +  20:030000a5 lu52i.d \$a1, \$a1, 0
>> +20: R_LARCH_GOT64_PC_HI12.L1
>> +  24:380c1484 ldx.d \$a0, \$a0, \$a1
>> +  28:1a000004 pcalau12i \$a0, 0
>> +28: R_LARCH_PCALA_HI20.L1
>> +28: R_LARCH_RELAX\*ABS\*
>> +  2c:02c00005 li.d \$a1, 0
>> +2c: R_LARCH_PCALA_LO12.L1
>> +2c: R_LARCH_RELAX\*ABS\*
>> +  30:16000005 lu32i.d \$a1, 0
>> +30: R_LARCH_PCALA64_LO20.L1
>> +  34:030000a5 lu52i.d \$a1, \$a1, 0
>> +34: R_LARCH_PCALA64_HI12.L1
>> +  38:00109484 add.d \$a0, \$a0, \$a1
>> +  3c:1a000004 pcalau12i \$a0, 0
>> +3c: R_LARCH_GOT_PC_HI20.L1
>> +3c: R_LARCH_RELAX\*ABS\*
>> +  40:02c00005 li.d \$a1, 0
>> +40: R_LARCH_GOT_PC_LO12.L1
>> +40: R_LARCH_RELAX\*ABS\*
>> +  44:16000005 lu32i.d \$a1, 0
>> +44: R_LARCH_GOT64_PC_LO20.L1
>> +  48:030000a5 lu52i.d \$a1, \$a1, 0
>> +48: R_LARCH_GOT64_PC_HI12.L1
>> +  4c:380c1484 ldx.d \$a0, \$a0, \$a1
>> +  50:14000004 lu12i.w \$a0, 0
>> +50: R_LARCH_TLS_LE_HI20TLS1
>> +  54:03800084 ori \$a0, \$a0, 0x0
>> +54: R_LARCH_TLS_LE_LO12TLS1
>> +  58:1a000004 pcalau12i \$a0, 0
>> +58: R_LARCH_TLS_IE_PC_HI20TLS1
>> +  5c:02c00005 li.d \$a1, 0
>> +5c: R_LARCH_TLS_IE_PC_LO12TLS1
>> +  60:16000005 lu32i.d \$a1, 0
>> +60: R_LARCH_TLS_IE64_PC_LO20TLS1
>> +  64:030000a5 lu52i.d \$a1, \$a1, 0
>> +64: R_LARCH_TLS_IE64_PC_HI12TLS1
>> +  68:380c1484 ldx.d \$a0, \$a0, \$a1
>> +  6c:1a000004 pcalau12i \$a0, 0
>> +6c: R_LARCH_TLS_LD_PC_HI20TLS1
>> +6c: R_LARCH_RELAX\*ABS\*
>> +  70:02c00005 li.d \$a1, 0
>> +70: R_LARCH_GOT_PC_LO12TLS1
>> +70: R_LARCH_RELAX\*ABS\*
>> +  74:16000005 lu32i.d \$a1, 0
>> +74: R_LARCH_GOT64_PC_LO20TLS1
>> +  78:030000a5 lu52i.d \$a1, \$a1, 0
>> +78: R_LARCH_GOT64_PC_HI12TLS1
>> +  7c:00109484 add.d \$a0, \$a0, \$a1
>> +  80:1a000004 pcalau12i \$a0, 0
>> +80: R_LARCH_TLS_GD_PC_HI20TLS1
>> +80: R_LARCH_RELAX\*ABS\*
>> +  84:02c00005 li.d \$a1, 0
>> +84: R_LARCH_GOT_PC_LO12TLS1
>> +84: R_LARCH_RELAX\*ABS\*
>> +  88:16000005 lu32i.d \$a1, 0
>> +88: R_LARCH_GOT64_PC_LO20TLS1
>> +  8c:030000a5 lu52i.d \$a1, \$a1, 0
>> +8c: R_LARCH_GOT64_PC_HI12TLS1
>> +  90:00109484 add.d \$a0, \$a0, \$a1
>> diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h
>> index 41e9fe4d234..6cfee164312 100644
>> --- a/include/elf/loongarch.h
>> +++ b/include/elf/loongarch.h
>> @@ -273,6 +273,10 @@ RELOC_NUMBER (R_LARCH_TLS_DESC64_HI12, 118)
>> RELOC_NUMBER (R_LARCH_TLS_DESC_LD, 119)
>> RELOC_NUMBER (R_LARCH_TLS_DESC_CALL, 120)
>>
>> +RELOC_NUMBER (R_LARCH_TLS_LD_PCREL20_S2, 124)
>> +RELOC_NUMBER (R_LARCH_TLS_GD_PCREL20_S2, 125)
>> +RELOC_NUMBER (R_LARCH_TLS_DESC_PCREL20_S2, 126)
>> +
>> END_RELOC_NUMBERS (R_LARCH_count)
>>
>> /* Processor specific flags for the ELF header e_flags field.  */
>> diff --git a/ld/testsuite/ld-loongarch-elf/macro_op.d 
>> b/ld/testsuite/ld-loongarch-elf/macro_op.d
>> index edc71bc0dbf..f0d87c03802 100644
>> --- a/ld/testsuite/ld-loongarch-elf/macro_op.d
>> +++ b/ld/testsuite/ld-loongarch-elf/macro_op.d
>> @@ -1,200 +1,205 @@
>> #as:
>> #objdump: -dr
>> +#skip: loongarch32-*-*
>>
>> -.*:[    ]+file format .*
>> +.*:     file format .*
>>
>>
>> Disassembly of section .text:
>>
>> -00000000.* <.L1>:
>> -[ ]+0:[ ]+00150004[ ]+move[ ]+\$a0,[ ]+\$zero
>> -[ ]+4:[ ]+02bffc04[ ]+li\.w[ ]+\$a0,[ ]+-1
>> -[ ]+8:[ ]+00150004[ ]+move[ ]+\$a0,[ ]+\$zero
>> -[ ]+c:[ ]+02bffc04[ ]+li\.w[ ]+\$a0,[ ]+-1
>> -[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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
>> -[ ]+2c:[ ]+R_LARCH_GOT64_PC_HI12[ ]+.L1
>> -[ ]+30:[ ]+380c1484[ ]+ldx.d[ ]+\$a0,[ ]+\$a0,[ ]+\$a1
>> -[ ]+34:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+34:[ ]+R_LARCH_GOT_PC_HI20[ ]+.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[ ]+li\.d[ ]+\$a1,[ ]+0
>> -[ ]+40:[ ]+R_LARCH_GOT_PC_LO12[ ]+.L1
>> -[ ]+40:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+44:[ ]+16000005[ ]+lu32i.d[ ]+\$a1,[ ]+0
>> -[ ]+44:[ ]+R_LARCH_GOT64_PC_LO20[ ]+.L1
>> -[ ]+48:[ ]+030000a5[ ]+lu52i.d[ ]+\$a1,[ ]+\$a1,[ ]+0
>> -[ ]+48:[ ]+R_LARCH_GOT64_PC_HI12[ ]+.L1
>> -[ ]+4c:[ ]+380c1484[ ]+ldx.d[ ]+\$a0,[ ]+\$a0,[ ]+\$a1
>> -[ ]+50:[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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[ ]+.L1
>> -[ ]+6c:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+70:[ ]+02c00084[ ]+addi.d[ ]+\$a0,[ ]+\$a0,[ ]+0
>> -[ ]+70:[ ]+R_LARCH_PCALA_LO12[ ]+.L1
>> -[ ]+70:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+74:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+74:[ ]+R_LARCH_PCALA_HI20[ ]+.L1
>> -[ ]+74:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+78:[ ]+02c00005[ ]+li\.d[ ]+\$a1,[ ]+0
>> -[ ]+78:[ ]+R_LARCH_PCALA_LO12[ ]+.L1
>> -[ ]+78:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+7c:[ ]+16000005[ ]+lu32i.d[ ]+\$a1,[ ]+0
>> -[ ]+7c:[ ]+R_LARCH_PCALA64_LO20[ ]+.L1
>> -[ ]+80:[ ]+030000a5[ ]+lu52i.d[ ]+\$a1,[ ]+\$a1,[ ]+0
>> -[ ]+80:[ ]+R_LARCH_PCALA64_HI12[ ]+.L1
>> -[ ]+84:[ ]+00109484[ ]+add.d[ ]+\$a0,[ ]+\$a0,[ ]+\$a1
>> -[ ]+88:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+88:[ ]+R_LARCH_PCALA_HI20[ ]+.L1
>> -[ ]+88:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+8c:[ ]+02c00084[ ]+addi.d[ ]+\$a0,[ ]+\$a0,[ ]+0
>> -[ ]+8c:[ ]+R_LARCH_PCALA_LO12[ ]+.L1
>> -[ ]+8c:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+90:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+90:[ ]+R_LARCH_PCALA_HI20[ ]+.L1
>> -[ ]+90:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+94:[ ]+02c00005[ ]+li\.d[ ]+\$a1,[ ]+0
>> -[ ]+94:[ ]+R_LARCH_PCALA_LO12[ ]+.L1
>> -[ ]+94:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+98:[ ]+16000005[ ]+lu32i.d[ ]+\$a1,[ ]+0
>> -[ ]+98:[ ]+R_LARCH_PCALA64_LO20[ ]+.L1
>> -[ ]+9c:[ ]+030000a5[ ]+lu52i.d[ ]+\$a1,[ ]+\$a1,[ ]+0
>> -[ ]+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[ ]+.L1
>> -[ ]+a8:[ ]+03800084[ ]+ori[ ]+\$a0,[ ]+\$a0,[ ]+0x0
>> -[ ]+a8:[ ]+R_LARCH_ABS_LO12[ ]+.L1
>> -[ ]+ac:[ ]+16000004[ ]+lu32i.d[ ]+\$a0,[ ]+0
>> -[ ]+ac:[ ]+R_LARCH_ABS64_LO20[ ]+.L1
>> -[ ]+b0:[ ]+03000084[ ]+lu52i.d[ ]+\$a0,[ ]+\$a0,[ ]+0
>> -[ ]+b0:[ ]+R_LARCH_ABS64_HI12[ ]+.L1
>> -[ ]+b4:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+b4:[ ]+R_LARCH_PCALA_HI20[ ]+.L1
>> -[ ]+b4:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+b8:[ ]+02c00084[ ]+addi.d[ ]+\$a0,[ ]+\$a0,[ ]+0
>> -[ ]+b8:[ ]+R_LARCH_PCALA_LO12[ ]+.L1
>> -[ ]+b8:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+bc:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+bc:[ ]+R_LARCH_PCALA_HI20[ ]+.L1
>> -[ ]+bc:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+c0:[ ]+02c00084[ ]+addi.d[ ]+\$a0,[ ]+\$a0,[ ]+0
>> -[ ]+c0:[ ]+R_LARCH_PCALA_LO12[ ]+.L1
>> -[ ]+c0:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+c4:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+c4:[ ]+R_LARCH_PCALA_HI20[ ]+.L1
>> -[ ]+c4:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+c8:[ ]+02c00005[ ]+li\.d[ ]+\$a1,[ ]+0
>> -[ ]+c8:[ ]+R_LARCH_PCALA_LO12[ ]+.L1
>> -[ ]+c8:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+cc:[ ]+16000005[ ]+lu32i.d[ ]+\$a1,[ ]+0
>> -[ ]+cc:[ ]+R_LARCH_PCALA64_LO20[ ]+.L1
>> -[ ]+d0:[ ]+030000a5[ ]+lu52i.d[ ]+\$a1,[ ]+\$a1,[ ]+0
>> -[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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
>> -[ ]+ec:[ ]+R_LARCH_GOT64_PC_HI12[ ]+.L1
>> -[ ]+f0:[ ]+380c1484[ ]+ldx.d[ ]+\$a0,[ ]+\$a0,[ ]+\$a1
>> -[ ]+f4:[ ]+14000004[ ]+lu12i.w[ ]+\$a0,[ ]+0
>> -[ ]+f4:[ ]+R_LARCH_TLS_LE_HI20[ ]+TLS1
>> -[ ]+f8:[ ]+03800084[ ]+ori[ ]+\$a0,[ ]+\$a0,[ ]+0x0
>> -[ ]+f8:[ ]+R_LARCH_TLS_LE_LO12[ ]+TLS1
>> -[ ]+fc:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+fc:[ ]+R_LARCH_TLS_IE_PC_HI20[ ]+TLS1
>> -[ ]+100:[ ]+28c00084[ ]+ld.d[ ]+\$a0,[ ]+\$a0,[ ]+0
>> -[ ]+100:[ ]+R_LARCH_TLS_IE_PC_LO12[ ]+TLS1
>> -[ ]+104:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+104:[ ]+R_LARCH_TLS_IE_PC_HI20[ ]+TLS1
>> -[ ]+108:[ ]+02c00005[ ]+li\.d[ ]+\$a1,[ ]+0
>> -[ ]+108:[ ]+R_LARCH_TLS_IE_PC_LO12[ ]+TLS1
>> -[ ]+10c:[ ]+16000005[ ]+lu32i.d[ ]+\$a1,[ ]+0
>> -[ ]+10c:[ ]+R_LARCH_TLS_IE64_PC_LO20[ ]+TLS1
>> -[ ]+110:[ ]+030000a5[ ]+lu52i.d[ ]+\$a1,[ ]+\$a1,[ ]+0
>> -[ ]+110:[ ]+R_LARCH_TLS_IE64_PC_HI12[ ]+TLS1
>> -[ ]+114:[ ]+380c1484[ ]+ldx.d[ ]+\$a0,[ ]+\$a0,[ ]+\$a1
>> -[ ]+118:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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
>> -[ ]+12c:[ ]+R_LARCH_GOT64_PC_HI12[ ]+TLS1
>> -[ ]+130:[ ]+00109484[ ]+add.d[ ]+\$a0,[ ]+\$a0,[ ]+\$a1
>> -[ ]+134:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+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[ ]+li\.d[ ]+\$a1,[ ]+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
>> -[ ]+148:[ ]+R_LARCH_GOT64_PC_HI12[ ]+TLS1
>> -[ ]+14c:[ ]+00109484[ ]+add.d[ ]+\$a0,[ ]+\$a0,[ ]+\$a1
>> +0+ <.L1>:
>> +   0:00150004 move \$a0, \$zero
>> +   4:02bffc04 li.w \$a0, -1
>> +   8:00150004 move \$a0, \$zero
>> +   c:02bffc04 li.w \$a0, -1
>> +  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 li.d \$a1, 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
>> +2c: R_LARCH_GOT64_PC_HI12.L1
>> +  30:380c1484 ldx.d \$a0, \$a0, \$a1
>> +  34:1a000004 pcalau12i \$a0, 0
>> +34: R_LARCH_GOT_PC_HI20.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 li.d \$a1, 0
>> +40: R_LARCH_GOT_PC_LO12.L1
>> +40: R_LARCH_RELAX\*ABS\*
>> +  44:16000005 lu32i.d \$a1, 0
>> +44: R_LARCH_GOT64_PC_LO20.L1
>> +  48:030000a5 lu52i.d \$a1, \$a1, 0
>> +48: R_LARCH_GOT64_PC_HI12.L1
>> +  4c:380c1484 ldx.d \$a0, \$a0, \$a1
>> +  50: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 li.d \$a1, 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.L1
>> +6c: R_LARCH_RELAX\*ABS\*
>> +  70:02c00084 addi.d \$a0, \$a0, 0
>> +70: R_LARCH_PCALA_LO12.L1
>> +70: R_LARCH_RELAX\*ABS\*
>> +  74:1a000004 pcalau12i \$a0, 0
>> +74: R_LARCH_PCALA_HI20.L1
>> +74: R_LARCH_RELAX\*ABS\*
>> +  78:02c00005 li.d \$a1, 0
>> +78: R_LARCH_PCALA_LO12.L1
>> +78: R_LARCH_RELAX\*ABS\*
>> +  7c:16000005 lu32i.d \$a1, 0
>> +7c: R_LARCH_PCALA64_LO20.L1
>> +  80:030000a5 lu52i.d \$a1, \$a1, 0
>> +80: R_LARCH_PCALA64_HI12.L1
>> +  84:00109484 add.d \$a0, \$a0, \$a1
>> +  88:1a000004 pcalau12i \$a0, 0
>> +88: R_LARCH_PCALA_HI20.L1
>> +88: R_LARCH_RELAX\*ABS\*
>> +  8c:02c00084 addi.d \$a0, \$a0, 0
>> +8c: R_LARCH_PCALA_LO12.L1
>> +8c: R_LARCH_RELAX\*ABS\*
>> +  90:1a000004 pcalau12i \$a0, 0
>> +90: R_LARCH_PCALA_HI20.L1
>> +90: R_LARCH_RELAX\*ABS\*
>> +  94:02c00005 li.d \$a1, 0
>> +94: R_LARCH_PCALA_LO12.L1
>> +94: R_LARCH_RELAX\*ABS\*
>> +  98:16000005 lu32i.d \$a1, 0
>> +98: R_LARCH_PCALA64_LO20.L1
>> +  9c:030000a5 lu52i.d \$a1, \$a1, 0
>> +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.L1
>> +  a8:03800084 ori \$a0, \$a0, 0x0
>> +a8: R_LARCH_ABS_LO12.L1
>> +  ac:16000004 lu32i.d \$a0, 0
>> +ac: R_LARCH_ABS64_LO20.L1
>> +  b0:03000084 lu52i.d \$a0, \$a0, 0
>> +b0: R_LARCH_ABS64_HI12.L1
>> +  b4:1a000004 pcalau12i \$a0, 0
>> +b4: R_LARCH_PCALA_HI20.L1
>> +b4: R_LARCH_RELAX\*ABS\*
>> +  b8:02c00084 addi.d \$a0, \$a0, 0
>> +b8: R_LARCH_PCALA_LO12.L1
>> +b8: R_LARCH_RELAX\*ABS\*
>> +  bc:1a000004 pcalau12i \$a0, 0
>> +bc: R_LARCH_PCALA_HI20.L1
>> +bc: R_LARCH_RELAX\*ABS\*
>> +  c0:02c00084 addi.d \$a0, \$a0, 0
>> +c0: R_LARCH_PCALA_LO12.L1
>> +c0: R_LARCH_RELAX\*ABS\*
>> +  c4:1a000004 pcalau12i \$a0, 0
>> +c4: R_LARCH_PCALA_HI20.L1
>> +c4: R_LARCH_RELAX\*ABS\*
>> +  c8:02c00005 li.d \$a1, 0
>> +c8: R_LARCH_PCALA_LO12.L1
>> +c8: R_LARCH_RELAX\*ABS\*
>> +  cc:16000005 lu32i.d \$a1, 0
>> +cc: R_LARCH_PCALA64_LO20.L1
>> +  d0:030000a5 lu52i.d \$a1, \$a1, 0
>> +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 li.d \$a1, 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
>> +ec: R_LARCH_GOT64_PC_HI12.L1
>> +  f0:380c1484 ldx.d \$a0, \$a0, \$a1
>> +  f4:14000004 lu12i.w \$a0, 0
>> +f4: R_LARCH_TLS_LE_HI20TLS1
>> +  f8:03800084 ori \$a0, \$a0, 0x0
>> +f8: R_LARCH_TLS_LE_LO12TLS1
>> +  fc:1a000004 pcalau12i \$a0, 0
>> +fc: R_LARCH_TLS_IE_PC_HI20TLS1
>> + 100:28c00084 ld.d \$a0, \$a0, 0
>> +100: R_LARCH_TLS_IE_PC_LO12TLS1
>> + 104:1a000004 pcalau12i \$a0, 0
>> +104: R_LARCH_TLS_IE_PC_HI20TLS1
>> + 108:02c00005 li.d \$a1, 0
>> +108: R_LARCH_TLS_IE_PC_LO12TLS1
>> + 10c:16000005 lu32i.d \$a1, 0
>> +10c: R_LARCH_TLS_IE64_PC_LO20TLS1
>> + 110:030000a5 lu52i.d \$a1, \$a1, 0
>> +110: R_LARCH_TLS_IE64_PC_HI12TLS1
>> + 114:380c1484 ldx.d \$a0, \$a0, \$a1
>> + 118:1a000004 pcalau12i \$a0, 0
>> +118: R_LARCH_TLS_LD_PC_HI20TLS1
>> +118: R_LARCH_RELAX\*ABS\*
>> + 11c:02c00084 addi.d \$a0, \$a0, 0
>> +11c: R_LARCH_GOT_PC_LO12TLS1
>> +11c: R_LARCH_RELAX\*ABS\*
>> + 120:1a000004 pcalau12i \$a0, 0
>> +120: R_LARCH_TLS_LD_PC_HI20TLS1
>> +120: R_LARCH_RELAX\*ABS\*
>> + 124:02c00005 li.d \$a1, 0
>> +124: R_LARCH_GOT_PC_LO12TLS1
>> +124: R_LARCH_RELAX\*ABS\*
>> + 128:16000005 lu32i.d \$a1, 0
>> +128: R_LARCH_GOT64_PC_LO20TLS1
>> + 12c:030000a5 lu52i.d \$a1, \$a1, 0
>> +12c: R_LARCH_GOT64_PC_HI12TLS1
>> + 130:00109484 add.d \$a0, \$a0, \$a1
>> + 134:1a000004 pcalau12i \$a0, 0
>> +134: R_LARCH_TLS_GD_PC_HI20TLS1
>> +134: R_LARCH_RELAX\*ABS\*
>> + 138:02c00084 addi.d \$a0, \$a0, 0
>> +138: R_LARCH_GOT_PC_LO12TLS1
>> +138: R_LARCH_RELAX\*ABS\*
>> + 13c:1a000004 pcalau12i \$a0, 0
>> +13c: R_LARCH_TLS_GD_PC_HI20TLS1
>> +13c: R_LARCH_RELAX\*ABS\*
>> + 140:02c00005 li.d \$a1, 0
>> +140: R_LARCH_GOT_PC_LO12TLS1
>> +140: R_LARCH_RELAX\*ABS\*
>> + 144:16000005 lu32i.d \$a1, 0
>> +144: R_LARCH_GOT64_PC_LO20TLS1
>> + 148:030000a5 lu52i.d \$a1, \$a1, 0
>> +148: R_LARCH_GOT64_PC_HI12TLS1
>> + 14c:00109484 add.d \$a0, \$a0, \$a1
>> diff --git a/ld/testsuite/ld-loongarch-elf/macro_op_32.d 
>> b/ld/testsuite/ld-loongarch-elf/macro_op_32.d
>> index 188026a5780..a7349aa8dc0 100644
>> --- a/ld/testsuite/ld-loongarch-elf/macro_op_32.d
>> +++ b/ld/testsuite/ld-loongarch-elf/macro_op_32.d
>> @@ -2,66 +2,68 @@
>> #objdump: -dr
>> #skip: loongarch64-*-*
>>
>> -.*:[    ]+file format .*
>> +.*:     file format .*
>>
>>
>> Disassembly of section .text:
>>
>> -00000000.* <.L1>:
>> -[ ]+0:[ ]+00150004[ ]+move[ ]+\$a0,[ ]+\$zero
>> -[ ]+4:[ ]+02bffc04[ ]+li\.w[ ]+\$a0,[ ]+-1
>> -[ ]+8:[ ]+00150004[ ]+move[ ]+\$a0,[ ]+\$zero
>> -[ ]+c:[ ]+02bffc04[ ]+li\.w[ ]+\$a0,[ ]+-1
>> -[ ]+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[ ]+.L1
>> -[ ]+20:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+24:[ ]+02800084[ ]+addi.w[ ]+\$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
>> -[ ]+2c:[ ]+03800084[ ]+ori[ ]+\$a0,[ ]+\$a0,[ ]+0x0
>> -[ ]+2c:[ ]+R_LARCH_ABS_LO12[ ]+.L1
>> -[ ]+30:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+30:[ ]+R_LARCH_PCALA_HI20[ ]+.L1
>> -[ ]+30:[ ]+R_LARCH_RELAX[ ]+\*ABS\*
>> -[ ]+34:[ ]+02800084[ ]+addi.w[ ]+\$a0,[ ]+\$a0,[ ]+0
>> -[ ]+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
>> -[ ]+44:[ ]+R_LARCH_TLS_LE_LO12[ ]+TLS1
>> -[ ]+48:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+48:[ ]+R_LARCH_TLS_IE_PC_HI20[ ]+TLS1
>> -[ ]+4c:[ ]+28800084[ ]+ld.w[ ]+\$a0,[ ]+\$a0,[ ]+0
>> -[ ]+4c:[ ]+R_LARCH_TLS_IE_PC_LO12[ ]+TLS1
>> -[ ]+50:[ ]+1a000004[ ]+pcalau12i[ ]+\$a0,[ ]+0
>> -[ ]+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\*
>> +0+ <.L1>:
>> +   0:00150004 move \$a0, \$zero
>> +   4:02bffc04 li.w \$a0, -1
>> +   8:00150004 move \$a0, \$zero
>> +   c:02bffc04 li.w \$a0, -1
>> +  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.L1
>> +20: R_LARCH_RELAX\*ABS\*
>> +  24:02800084 addi.w \$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
>> +  2c:03800084 ori \$a0, \$a0, 0x0
>> +2c: R_LARCH_ABS_LO12.L1
>> +  30:1a000004 pcalau12i \$a0, 0
>> +30: R_LARCH_PCALA_HI20.L1
>> +30: R_LARCH_RELAX\*ABS\*
>> +  34:02800084 addi.w \$a0, \$a0, 0
>> +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_HI20TLS1
>> +  44:03800084 ori \$a0, \$a0, 0x0
>> +44: R_LARCH_TLS_LE_LO12TLS1
>> +  48:1a000004 pcalau12i \$a0, 0
>> +48: R_LARCH_TLS_IE_PC_HI20TLS1
>> +  4c:28800084 ld.w \$a0, \$a0, 0
>> +4c: R_LARCH_TLS_IE_PC_LO12TLS1
>> +  50:1a000004 pcalau12i \$a0, 0
>> +50: R_LARCH_TLS_LD_PC_HI20TLS1
>> +50: R_LARCH_RELAX\*ABS\*
>> +  54:02800084 addi.w \$a0, \$a0, 0
>> +54: R_LARCH_GOT_PC_LO12TLS1
>> +54: R_LARCH_RELAX\*ABS\*
>> +  58:1a000004 pcalau12i \$a0, 0
>> +58: R_LARCH_TLS_GD_PC_HI20TLS1
>> +58: R_LARCH_RELAX\*ABS\*
>> +  5c:02800084 addi.w \$a0, \$a0, 0
>> +5c: R_LARCH_GOT_PC_LO12TLS1
>> +5c: R_LARCH_RELAX\*ABS\*
>> -- 
>> 2.43.0
>>
>>
>


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

* Re: [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation
  2023-12-28 14:38   ` Tatsuyuki Ishi
  2023-12-29 10:36     ` Lulu Cai
@ 2023-12-29 10:45     ` Lulu Cai
  2024-01-07 23:00       ` Tatsuyuki Ishi
  1 sibling, 1 reply; 19+ messages in thread
From: Lulu Cai @ 2023-12-29 10:45 UTC (permalink / raw)
  To: Tatsuyuki Ishi
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

[-- Attachment #1: Type: text/plain, Size: 19301 bytes --]

On 2023/12/28 at 10:38 PM, Tatsuyuki Ishi Wrote:
>> On Dec 22, 2023, at 20:42, Lulu Cai <cailulu@loongson.cn> wrote:
>>
>> From: mengqinggang <mengqinggang@loongson.cn>
>>
>> The pcalau12i + addi.d of TLS LD/GD/DESC relax to pcaddi.
>> Relaxation is only performed when the TLS model transition is not 
>> possible.
>> ---
>> bfd/bfd-in2.h                                 |   3 +
>> bfd/elfnn-loongarch.c                         | 174 +++++++-
>> bfd/elfxx-loongarch.c                         |  60 +++
>> bfd/libbfd.h                                  |   3 +
>> bfd/reloc.c                                   |   7 +
>> gas/config/tc-loongarch.c                     |   8 +-
>> gas/testsuite/gas/loongarch/macro_op.d        | 128 +++---
>> gas/testsuite/gas/loongarch/macro_op_32.d     | 120 +++---
>> .../gas/loongarch/macro_op_large_abs.d        | 160 +++----
>> .../gas/loongarch/macro_op_large_pc.d         | 160 +++----
>> include/elf/loongarch.h                       |   4 +
>> ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++++---------
>> ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 +++---
>> 13 files changed, 795 insertions(+), 543 deletions(-)
>>
>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>> index 85251aa0edd..782845926ea 100644
>> --- a/bfd/bfd-in2.h
>> +++ b/bfd/bfd-in2.h
>> @@ -7473,6 +7473,9 @@ enum bfd_reloc_code_real
>>   BFD_RELOC_LARCH_TLS_DESC64_HI12,
>>   BFD_RELOC_LARCH_TLS_DESC_LD,
>>   BFD_RELOC_LARCH_TLS_DESC_CALL,
>> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,
>> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,
>> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,
>>   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 1347d13d2e2..bd448cda453 100644
>> --- a/bfd/elfnn-loongarch.c
>> +++ b/bfd/elfnn-loongarch.c
>> @@ -2285,7 +2285,9 @@ perform_relocation (const Elf_Internal_Rela 
>> *rel, asection *input_section,
>>     case R_LARCH_TLS_DESC_LO12:
>>     case R_LARCH_TLS_DESC64_LO20:
>>     case R_LARCH_TLS_DESC64_HI12:
>> -
>> +    case R_LARCH_TLS_LD_PCREL20_S2:
>> +    case R_LARCH_TLS_GD_PCREL20_S2:
>> +    case R_LARCH_TLS_DESC_PCREL20_S2:
>>       r = loongarch_check_offset (rel, input_section);
>>       if (r != bfd_reloc_ok)
>> break;
>> @@ -3674,6 +3676,9 @@ loongarch_elf_relocate_section (bfd 
>> *output_bfd, struct bfd_link_info *info,
>> case R_LARCH_TLS_GD_HI20:
>> case R_LARCH_TLS_DESC_PC_HI20:
>> case R_LARCH_TLS_DESC_HI20:
>> +case R_LARCH_TLS_LD_PCREL20_S2:
>> +case R_LARCH_TLS_GD_PCREL20_S2:
>> +case R_LARCH_TLS_DESC_PCREL20_S2:
>>  BFD_ASSERT (rel->r_addend == 0);
>>  unresolved_reloc = false;
>>
>> @@ -3682,7 +3687,8 @@ loongarch_elf_relocate_section (bfd 
>> *output_bfd, struct bfd_link_info *info,
>>    is_ie = true;
>>
>>  if (r_type == R_LARCH_TLS_DESC_PC_HI20
>> -     || r_type == R_LARCH_TLS_DESC_HI20)
>> +     || r_type == R_LARCH_TLS_DESC_HI20
>> +     || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>>    is_desc = true;
>>
>>  bfd_vma got_off = 0;
>> @@ -3813,7 +3819,11 @@ loongarch_elf_relocate_section (bfd 
>> *output_bfd, struct bfd_link_info *info,
>>      || r_type == R_LARCH_TLS_IE_PC_HI20
>>      || r_type == R_LARCH_TLS_DESC_PC_HI20)
>>    RELOCATE_CALC_PC32_HI20 (relocation, pc);
>> -
>> + else if (r_type == R_LARCH_TLS_LD_PCREL20_S2
>> +     || r_type == R_LARCH_TLS_GD_PCREL20_S2
>> +     || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>> +   relocation -= pc;
>> + /* else {} ABS relocations.  */
>>  break;
>>
>> case R_LARCH_TLS_DESC_PC_LO12:
>> @@ -4244,6 +4254,85 @@ loongarch_relax_align (bfd *abfd, asection *sec,
>> addend - need_nop_bytes, link_info);
>> }
>>
>> +/* Relax pcalau12i + addi.d of TLS LD/GD/DESC to pcaddi.  */
>> +static bool
>> +loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection 
>> *sym_sec,
>> +      Elf_Internal_Rela *rel_hi, bfd_vma symval,
>> +      struct bfd_link_info *info, bool *again)
>> +{
>> +  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;
>> +
>> +  /* This section's output_offset need to subtract the bytes of 
>> instructions
>> +     relaxed by the previous sections, so it needs to be updated 
>> beforehand.
>> +     size_input_section already took care of updating it after 
>> relaxation,
>> +     so we additionally update once here.  */
>> +  sec->output_offset = sec->output_section->size;
>> +  bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
>> +
>> +  /* If pc and symbol not in the same segment, add/sub segment 
>> alignment.
>> +     FIXME: if there are multiple readonly segments?  */
>> +  if (!(sym_sec->flags & SEC_READONLY))
>> +    {
>> +      if (symval > pc)
>> +pc -= info->maxpagesize;
>> +      else if (symval < pc)
>> +pc += info->maxpagesize;
>> +    }
>> +
>> +  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_GOT_PC_LO12
>> +&& ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_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)
>> +      || ((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;
>> +
>> +  /* Continue next relax trip.  */
>> +  *again = true;
>> +
>> +  pca = pcaddi | rd;
>> +  bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
>> +
>> +  /* Adjust relocations.  */
>> +  switch (ELFNN_R_TYPE (rel_hi->r_info))
>> +    {
>> +    case R_LARCH_TLS_LD_PC_HI20:
>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>> +     R_LARCH_TLS_LD_PCREL20_S2);
>> +      break;
>> +    case R_LARCH_TLS_GD_PC_HI20:
>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>> +     R_LARCH_TLS_GD_PCREL20_S2);
>> +      break;
>> +    case R_LARCH_TLS_DESC_PC_HI20:
>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>> +     R_LARCH_TLS_DESC_PCREL20_S2);
>> +      break;
>> +    default:
>> +      break;
>> +    }
>> +  rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
>> +
>> +  loongarch_relax_delete_bytes (abfd, sec, rel_lo->r_offset, 4, info);
>> +
>> +  return true;
>> +}
>> +
>> static bool
>> loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>       struct bfd_link_info *info,
>> @@ -4288,15 +4377,23 @@ loongarch_elf_relax_section (bfd *abfd, 
>> asection *sec,
>>
>>   for (unsigned int i = 0; i < sec->reloc_count; i++)
>>     {
>> -      Elf_Internal_Rela *rel = relocs + i;
>> -      asection *sym_sec;
>> +      char symtype;
>>       bfd_vma symval;
>> -      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>> -      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
>> +      asection *sym_sec;
>>       bool local_got = false;
>> -      char symtype;
>> +      Elf_Internal_Rela *rel = relocs + i;
>>       struct elf_link_hash_entry *h = NULL;
>> +      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
>> +      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>>
>> +      /* Four kind of relocations:
>> +Normal: symval is the symbol address.
>> +R_LARCH_ALIGN: symval is the address of the last NOP instruction
>> +added by this relocation, and then adds 4 more.
>> +R_LARCH_CALL36: symval is the symbol address for local symbols,
>> +or the PLT entry address of the symbol. (Todo)
>> +R_LARCHL_TLS_LD/GD/DESC_PC_HI20: symval is the GOT entry address
>> +of the symbol.  */
>>       if (r_symndx < symtab_hdr->sh_info)
>> {
>>  Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
>> @@ -4304,7 +4401,24 @@ loongarch_elf_relax_section (bfd *abfd, 
>> asection *sec,
>>  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
>>    continue;
>>
>> - if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>> + if (R_LARCH_TLS_LD_PC_HI20 == r_type
>> +     || R_LARCH_TLS_GD_PC_HI20 == r_type
>> +     || R_LARCH_TLS_DESC_PC_HI20 == r_type)
>> +   {
>> +     if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
>> +continue;
>> +     else
>> +{
>> + sym_sec = htab->elf.sgot;
>> + symval = elf_local_got_offsets (abfd)[r_symndx];
>> + char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
>> +r_symndx);
>> + if (R_LARCH_TLS_DESC_PC_HI20 == r_type
>> +&& GOT_TLS_GD_BOTH_P (tls_type))
>> +   symval += 2 * GOT_ENTRY_SIZE;
>> +}
>> +   }
>> + else if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>>    {
>>      sym_sec = sec;
>>      symval = rel->r_offset;
>> @@ -4329,7 +4443,26 @@ loongarch_elf_relax_section (bfd *abfd, 
>> asection *sec,
>>  if (h != NULL && h->type == STT_GNU_IFUNC)
>>    continue;
>>
>> - if ((h->root.type == bfd_link_hash_defined
>> + /* The GOT entry of tls symbols must in current execute file or
>> +    shared object.  */
>> + if (R_LARCH_TLS_LD_PC_HI20 == r_type
>> +     || R_LARCH_TLS_GD_PC_HI20 == r_type
>> +     || R_LARCH_TLS_DESC_PC_HI20 == r_type)
>> +   {
>> +     if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
>> +continue;
>> +     else
>> +{
>> + sym_sec = htab->elf.sgot;
>> + symval = h->got.offset;
>> + char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
>> +r_symndx);
>> + if (R_LARCH_TLS_DESC_PC_HI20 == r_type
>> +&& GOT_TLS_GD_BOTH_P (tls_type))
>> +   symval += 2 * GOT_ENTRY_SIZE;
>> +}
>> +   }
>> + else 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)
>> @@ -4358,7 +4491,7 @@ loongarch_elf_relax_section (bfd *abfd, 
>> asection *sec,
>>   if (symtype != STT_SECTION)
>>     symval += rel->r_addend;
>> }
>> -      /* For R_LARCH_ALIGN, symval is sec_addr (sym_sec) + rel->r_offset
>> +      /* For R_LARCH_ALIGN, symval is sec_addr (sec) + rel->r_offset
>> + (alingmeng - 4).
>> If r_symndx is 0, alignmeng-4 is r_addend.
>> If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4.  */
>> @@ -4399,6 +4532,25 @@ loongarch_elf_relax_section (bfd *abfd, 
>> asection *sec,
>>    info, again);
>>    }
>>  break;
>> +
>> +case R_LARCH_TLS_LD_PC_HI20:
>> + if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>> +   loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>> +   info, again);
>> + break;
>> +
>> +case R_LARCH_TLS_GD_PC_HI20:
>> + if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>> +   loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>> +   info, again);
>> + break;
>> +
>> +case R_LARCH_TLS_DESC_PC_HI20:
>> + if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>> +   loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>> +   info, again);
>> + break;
>> +
>> default:
>>  break;
>> }
>> diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
>> index 30a941a851f..310e6d62dc0 100644
>> --- a/bfd/elfxx-loongarch.c
>> +++ b/bfd/elfxx-loongarch.c
>> @@ -1775,6 +1775,60 @@ static loongarch_reloc_howto_type 
>> loongarch_howto_table[] =
>> BFD_RELOC_LARCH_TLS_DESC_CALL,/* bfd_reloc_code_real_type.  */
>> NULL,/* adjust_reloc_bits.  */
>> "desc_call"),/* larch_reloc_type_name.  */
>> +
>> +  /* For pcaddi, ld_pc_hi20 + ld_pc_lo12 can relax to ld_pcrel20_s2.  */
>> +  LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCREL20_S2,/* type (124).  */
>> +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_TLS_LD_PCREL20_S2",/* name.  */
>> +false,/* partial_inplace.  */
>> +0,/* src_mask.  */
>> +0x1ffffe0,/* dst_mask.  */
>> +true,/* pcrel_offset.  */
>> +BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,/* bfd_reloc_code_real_type.  */
>> +reloc_sign_bits,/* adjust_reloc_bits.  */
>> +"ld_pcrel_20"),/* larch_reloc_type_name.  */
>> +
>> +  /* For pcaddi, gd_pc_hi20 + gd_pc_lo12 can relax to gd_pcrel20_s2.  */
>> +  LOONGARCH_HOWTO (R_LARCH_TLS_GD_PCREL20_S2,/* type (125).  */
>> +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_TLS_GD_PCREL20_S2",/* name.  */
>> +false,/* partial_inplace.  */
>> +0,/* src_mask.  */
>> +0x1ffffe0,/* dst_mask.  */
>> +true,/* pcrel_offset.  */
>> +BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,/* bfd_reloc_code_real_type.  */
>> +reloc_sign_bits,/* adjust_reloc_bits.  */
>> +"gd_pcrel_20"),/* larch_reloc_type_name.  */
>> +
>> +  /* For pcaddi, desc_pc_hi20 + desc_pc_lo12 can relax to 
>> desc_pcrel20_s2.  */
>> +  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PCREL20_S2,/* type (126).  */
>> +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_TLS_DESC_PCREL20_S2",/* name.  */
>> +false,/* partial_inplace.  */
>> +0,/* src_mask.  */
>> +0x1ffffe0,/* dst_mask.  */
>> +true,/* pcrel_offset.  */
>> +BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,/* bfd_reloc_code_real_type.  */
>> +reloc_sign_bits,/* adjust_reloc_bits.  */
>> +"desc_pcrel_20"),/* larch_reloc_type_name.  */
>> };
>

> I think relaxation relocs is a concept internal to binutils and they 
> should not be in the same number range as psABI defined relocs. Some 
> linkers (e.g. mold) doesn’t create new relocs when relaxing and 
> rewrites the instruction right away, therefore these relocs would have 
> no purpose in the psABI.
>
> We recently refactored out all the linker-internal relocs to a 
> different range [1]; LoongArch might want to follow suit.
>
> [1]: https://sourceware.org/pipermail/binutils/2023-November/130322.html


However, it should be noted that in handwritten assembly, these 
relocations can be directly used.

>
>>
>> reloc_howto_type *
>> @@ -1783,7 +1837,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, 
>> unsigned int r_type)
>>   if(r_type < R_LARCH_count)
>>     {
>>       /* For search table fast.  */
>> +      /*
>>       BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>> +      */
>

> Was this supposed to be commented out and committed as-is?


It has been deleted.

>
>>
>>       if (loongarch_howto_table[r_type].howto.type == r_type)
>> return (reloc_howto_type *)&loongarch_howto_table[r_type];
>> @@ -1802,7 +1858,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, 
>> unsigned int r_type)
>> reloc_howto_type *
>> loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char 
>> *r_name)
>> {
>> +  /*
>>   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>> +  */
>>
>>   for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
>>     if (loongarch_howto_table[i].howto.name
>> @@ -1821,7 +1879,9 @@ reloc_howto_type *
>> loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
>>     bfd_reloc_code_real_type code)
>> {
>> +  /*
>>   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>> +  */
>>
>>   /* Fast search for new reloc types.  */
>>   if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
>> diff --git a/bfd/libbfd.h b/bfd/libbfd.h
>> index 71b03da14d9..8dab44110a6 100644
>> --- a/bfd/libbfd.h
>> +++ b/bfd/libbfd.h
>> @@ -3612,6 +3612,9 @@ static const char *const 
>> bfd_reloc_code_real_names[] = { "@@uninitialized@@",
>>   "BFD_RELOC_LARCH_TLS_DESC64_HI12",
>>   "BFD_RELOC_LARCH_TLS_DESC_LD",
>>   "BFD_RELOC_LARCH_TLS_DESC_CALL",
>> +  "BFD_RELOC_LARCH_TLS_LD_PCREL20_S2",
>> +  "BFD_RELOC_LARCH_TLS_GD_PCREL20_S2",
>> +  "BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2",
>>  "@@overflow: BFD_RELOC_UNUSED@@",
>> };
>> #endif
>> diff --git a/bfd/reloc.c b/bfd/reloc.c
>> index f7fe0c7ffe3..6fd0f1fb547 100644
>> --- a/bfd/reloc.c
>> +++ b/bfd/reloc.c
>> @@ -8324,6 +8324,13 @@ ENUMX
>> ENUMX
>>   BFD_RELOC_LARCH_TLS_DESC_CALL
>>
>> +ENUMX
>> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2
>> +ENUMX
>> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2
>> +ENUMX
>> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2
>> +
>> ENUMDOC
>>   LARCH relocations.
>>
>> diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
>> index 1658025f918..def26daf634 100644
>> --- a/gas/config/tc-loongarch.c
>> +++ b/gas/config/tc-loongarch.c
>> @@ -682,7 +682,7 @@ loongarch_args_parser_can_match_arg_helper (char 
>> esc_ch1, char esc_ch2,
>>      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_TLS_DESC_CALL)
>> +     && ip->reloc_info[0].type <= BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2)
>>    {
>>      /* As we compact stack-relocs, it is no need for pop operation.
>> But break out until here in order to check the imm field.
>> @@ -694,7 +694,11 @@ loongarch_args_parser_can_match_arg_helper (char 
>> esc_ch1, char esc_ch2,
>>    && (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))
>> +|| BFD_RELOC_LARCH_GOT_PC_LO12 == reloc_type
>> +|| BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_type
>> +|| BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_type
>> +|| BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_type
>> +|| BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_type))
>> {
>>  ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
>>  ip->reloc_info[ip->reloc_num].value = const_0;
>> diff --git a/gas/testsuite/gas/loongarch/macro_op.d 
>> b/gas/testsuite/gas/loongarch/macro_op.d
>> index 32860864704..47f8f45c663 100644
>> --- a/gas/testsuite/gas/loongarch/macro_op.d
>> +++ b/gas/testsuite/gas/loongarch/macro_op.d
>> @@ -2,70 +2,72 @@
>> #objdump: -dr
>> #skip: loongarch32-*-*
>>
>>
>>
>> -- 
>> 2.43.0
>>
>>
>


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

* Re: [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation
  2023-12-29 10:45     ` Lulu Cai
@ 2024-01-07 23:00       ` Tatsuyuki Ishi
  2024-01-08  0:22         ` Fangrui Song
       [not found]         ` <DS7PR12MB5765D250CD96B4F6EF6674BACB6B2@DS7PR12MB5765.namprd12.prod.outlook.com>
  0 siblings, 2 replies; 19+ messages in thread
From: Tatsuyuki Ishi @ 2024-01-07 23:00 UTC (permalink / raw)
  To: Lulu Cai
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

[-- Attachment #1: Type: text/plain, Size: 20255 bytes --]

> On Dec 29, 2023, at 19:45, Lulu Cai <cailulu@loongson.cn> wrote:
> 
> On 2023/12/28 at 10:38 PM, Tatsuyuki Ishi Wrote:
>>> On Dec 22, 2023, at 20:42, Lulu Cai <cailulu@loongson.cn> <mailto:cailulu@loongson.cn> wrote:
>>> 
>>> From: mengqinggang <mengqinggang@loongson.cn> <mailto:mengqinggang@loongson.cn>
>>> 
>>> The pcalau12i + addi.d of TLS LD/GD/DESC relax to pcaddi.
>>> Relaxation is only performed when the TLS model transition is not possible.
>>> ---
>>> bfd/bfd-in2.h                                 |   3 +
>>> bfd/elfnn-loongarch.c                         | 174 +++++++-
>>> bfd/elfxx-loongarch.c                         |  60 +++
>>> bfd/libbfd.h                                  |   3 +
>>> bfd/reloc.c                                   |   7 +
>>> gas/config/tc-loongarch.c                     |   8 +-
>>> gas/testsuite/gas/loongarch/macro_op.d        | 128 +++---
>>> gas/testsuite/gas/loongarch/macro_op_32.d     | 120 +++---
>>> .../gas/loongarch/macro_op_large_abs.d        | 160 +++----
>>> .../gas/loongarch/macro_op_large_pc.d         | 160 +++----
>>> include/elf/loongarch.h                       |   4 +
>>> ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++++---------
>>> ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 +++---
>>> 13 files changed, 795 insertions(+), 543 deletions(-)
>>> 
>>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>>> index 85251aa0edd..782845926ea 100644
>>> --- a/bfd/bfd-in2.h
>>> +++ b/bfd/bfd-in2.h
>>> @@ -7473,6 +7473,9 @@ enum bfd_reloc_code_real
>>>   BFD_RELOC_LARCH_TLS_DESC64_HI12,
>>>   BFD_RELOC_LARCH_TLS_DESC_LD,
>>>   BFD_RELOC_LARCH_TLS_DESC_CALL,
>>> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,
>>> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,
>>> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,
>>>   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 1347d13d2e2..bd448cda453 100644
>>> --- a/bfd/elfnn-loongarch.c
>>> +++ b/bfd/elfnn-loongarch.c
>>> @@ -2285,7 +2285,9 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
>>>     case R_LARCH_TLS_DESC_LO12:
>>>     case R_LARCH_TLS_DESC64_LO20:
>>>     case R_LARCH_TLS_DESC64_HI12:
>>> -
>>> +    case R_LARCH_TLS_LD_PCREL20_S2:
>>> +    case R_LARCH_TLS_GD_PCREL20_S2:
>>> +    case R_LARCH_TLS_DESC_PCREL20_S2:
>>>       r = loongarch_check_offset (rel, input_section);
>>>       if (r != bfd_reloc_ok)
>>> 	break;
>>> @@ -3674,6 +3676,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>> 	case R_LARCH_TLS_GD_HI20:
>>> 	case R_LARCH_TLS_DESC_PC_HI20:
>>> 	case R_LARCH_TLS_DESC_HI20:
>>> +	case R_LARCH_TLS_LD_PCREL20_S2:
>>> +	case R_LARCH_TLS_GD_PCREL20_S2:
>>> +	case R_LARCH_TLS_DESC_PCREL20_S2:
>>> 	  BFD_ASSERT (rel->r_addend == 0);
>>> 	  unresolved_reloc = false;
>>> 
>>> @@ -3682,7 +3687,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>> 	    is_ie = true;
>>> 
>>> 	  if (r_type == R_LARCH_TLS_DESC_PC_HI20
>>> -	      || r_type == R_LARCH_TLS_DESC_HI20)
>>> +	      || r_type == R_LARCH_TLS_DESC_HI20
>>> +	      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>>> 	    is_desc = true;
>>> 
>>> 	  bfd_vma got_off = 0;
>>> @@ -3813,7 +3819,11 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>> 	      || r_type == R_LARCH_TLS_IE_PC_HI20
>>> 	      || r_type == R_LARCH_TLS_DESC_PC_HI20)
>>> 	    RELOCATE_CALC_PC32_HI20 (relocation, pc);
>>> -
>>> +	  else if (r_type == R_LARCH_TLS_LD_PCREL20_S2
>>> +	      || r_type == R_LARCH_TLS_GD_PCREL20_S2
>>> +	      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>>> +	    relocation -= pc;
>>> +	  /* else {} ABS relocations.  */
>>> 	  break;
>>> 
>>> 	case R_LARCH_TLS_DESC_PC_LO12:
>>> @@ -4244,6 +4254,85 @@ loongarch_relax_align (bfd *abfd, asection *sec,
>>> 					addend - need_nop_bytes, link_info);
>>> }
>>> 
>>> +/* Relax pcalau12i + addi.d of TLS LD/GD/DESC to pcaddi.  */
>>> +static bool
>>> +loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
>>> +		       Elf_Internal_Rela *rel_hi, bfd_vma symval,
>>> +		       struct bfd_link_info *info, bool *again)
>>> +{
>>> +  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;
>>> +
>>> +  /* This section's output_offset need to subtract the bytes of instructions
>>> +     relaxed by the previous sections, so it needs to be updated beforehand.
>>> +     size_input_section already took care of updating it after relaxation,
>>> +     so we additionally update once here.  */
>>> +  sec->output_offset = sec->output_section->size;
>>> +  bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
>>> +
>>> +  /* If pc and symbol not in the same segment, add/sub segment alignment.
>>> +     FIXME: if there are multiple readonly segments?  */
>>> +  if (!(sym_sec->flags & SEC_READONLY))
>>> +    {
>>> +      if (symval > pc)
>>> +	pc -= info->maxpagesize;
>>> +      else if (symval < pc)
>>> +	pc += info->maxpagesize;
>>> +    }
>>> +
>>> +  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_GOT_PC_LO12
>>> +	&& ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_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)
>>> +      || ((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;
>>> +
>>> +  /* Continue next relax trip.  */
>>> +  *again = true;
>>> +
>>> +  pca = pcaddi | rd;
>>> +  bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
>>> +
>>> +  /* Adjust relocations.  */
>>> +  switch (ELFNN_R_TYPE (rel_hi->r_info))
>>> +    {
>>> +    case R_LARCH_TLS_LD_PC_HI20:
>>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>>> +				      R_LARCH_TLS_LD_PCREL20_S2);
>>> +      break;
>>> +    case R_LARCH_TLS_GD_PC_HI20:
>>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>>> +				      R_LARCH_TLS_GD_PCREL20_S2);
>>> +      break;
>>> +    case R_LARCH_TLS_DESC_PC_HI20:
>>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>>> +				      R_LARCH_TLS_DESC_PCREL20_S2);
>>> +      break;
>>> +    default:
>>> +      break;
>>> +    }
>>> +  rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
>>> +
>>> +  loongarch_relax_delete_bytes (abfd, sec, rel_lo->r_offset, 4, info);
>>> +
>>> +  return true;
>>> +}
>>> +
>>> static bool
>>> loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>> 			       struct bfd_link_info *info,
>>> @@ -4288,15 +4377,23 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>> 
>>>   for (unsigned int i = 0; i < sec->reloc_count; i++)
>>>     {
>>> -      Elf_Internal_Rela *rel = relocs + i;
>>> -      asection *sym_sec;
>>> +      char symtype;
>>>       bfd_vma symval;
>>> -      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>>> -      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
>>> +      asection *sym_sec;
>>>       bool local_got = false;
>>> -      char symtype;
>>> +      Elf_Internal_Rela *rel = relocs + i;
>>>       struct elf_link_hash_entry *h = NULL;
>>> +      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
>>> +      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>>> 
>>> +      /* Four kind of relocations:
>>> +	 Normal: symval is the symbol address.
>>> +	 R_LARCH_ALIGN: symval is the address of the last NOP instruction
>>> +	 added by this relocation, and then adds 4 more.
>>> +	 R_LARCH_CALL36: symval is the symbol address for local symbols,
>>> +	 or the PLT entry address of the symbol. (Todo)
>>> +	 R_LARCHL_TLS_LD/GD/DESC_PC_HI20: symval is the GOT entry address
>>> +	 of the symbol.  */
>>>       if (r_symndx < symtab_hdr->sh_info)
>>> 	{
>>> 	  Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
>>> @@ -4304,7 +4401,24 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>> 	  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
>>> 	    continue;
>>> 
>>> -	  if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>>> +	  if (R_LARCH_TLS_LD_PC_HI20 == r_type
>>> +	      || R_LARCH_TLS_GD_PC_HI20 == r_type
>>> +	      || R_LARCH_TLS_DESC_PC_HI20 == r_type)
>>> +	    {
>>> +	      if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
>>> +		continue;
>>> +	      else
>>> +		{
>>> +		  sym_sec = htab->elf.sgot;
>>> +		  symval = elf_local_got_offsets (abfd)[r_symndx];
>>> +		  char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
>>> +								r_symndx);
>>> +		  if (R_LARCH_TLS_DESC_PC_HI20 == r_type
>>> +			&& GOT_TLS_GD_BOTH_P (tls_type))
>>> +		    symval += 2 * GOT_ENTRY_SIZE;
>>> +		}
>>> +	    }
>>> +	  else if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>>> 	    {
>>> 	      sym_sec = sec;
>>> 	      symval = rel->r_offset;
>>> @@ -4329,7 +4443,26 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>> 	  if (h != NULL && h->type == STT_GNU_IFUNC)
>>> 	    continue;
>>> 
>>> -	  if ((h->root.type == bfd_link_hash_defined
>>> +	  /* The GOT entry of tls symbols must in current execute file or
>>> +	     shared object.  */
>>> +	  if (R_LARCH_TLS_LD_PC_HI20 == r_type
>>> +	      || R_LARCH_TLS_GD_PC_HI20 == r_type
>>> +	      || R_LARCH_TLS_DESC_PC_HI20 == r_type)
>>> +	    {
>>> +	      if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
>>> +		continue;
>>> +	      else
>>> +		{
>>> +		  sym_sec = htab->elf.sgot;
>>> +		  symval = h->got.offset;
>>> +		  char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
>>> +								r_symndx);
>>> +		  if (R_LARCH_TLS_DESC_PC_HI20 == r_type
>>> +			&& GOT_TLS_GD_BOTH_P (tls_type))
>>> +		    symval += 2 * GOT_ENTRY_SIZE;
>>> +		}
>>> +	    }
>>> +	  else 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)
>>> @@ -4358,7 +4491,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>> 	   if (symtype != STT_SECTION)
>>> 	     symval += rel->r_addend;
>>> 	}
>>> -      /* For R_LARCH_ALIGN, symval is sec_addr (sym_sec) + rel->r_offset
>>> +      /* For R_LARCH_ALIGN, symval is sec_addr (sec) + rel->r_offset
>>> 	 + (alingmeng - 4).
>>> 	 If r_symndx is 0, alignmeng-4 is r_addend.
>>> 	 If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4.  */
>>> @@ -4399,6 +4532,25 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>> 					    info, again);
>>> 	    }
>>> 	  break;
>>> +
>>> +	case R_LARCH_TLS_LD_PC_HI20:
>>> +	  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>>> +	    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>>> +					    info, again);
>>> +	  break;
>>> +
>>> +	case R_LARCH_TLS_GD_PC_HI20:
>>> +	  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>>> +	    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>>> +					    info, again);
>>> +	  break;
>>> +
>>> +	case R_LARCH_TLS_DESC_PC_HI20:
>>> +	  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>>> +	    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>>> +					    info, again);
>>> +	  break;
>>> +
>>> 	default:
>>> 	  break;
>>> 	}
>>> diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
>>> index 30a941a851f..310e6d62dc0 100644
>>> --- a/bfd/elfxx-loongarch.c
>>> +++ b/bfd/elfxx-loongarch.c
>>> @@ -1775,6 +1775,60 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
>>> 	 BFD_RELOC_LARCH_TLS_DESC_CALL,		/* bfd_reloc_code_real_type.  */
>>> 	 NULL,					/* adjust_reloc_bits.  */
>>> 	 "desc_call"),				/* larch_reloc_type_name.  */
>>> +
>>> +  /* For pcaddi, ld_pc_hi20 + ld_pc_lo12 can relax to ld_pcrel20_s2.  */
>>> +  LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCREL20_S2,	/* type (124).  */
>>> +	 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_TLS_LD_PCREL20_S2",		/* name.  */
>>> +	 false,					/* partial_inplace.  */
>>> +	 0,					/* src_mask.  */
>>> +	 0x1ffffe0,				/* dst_mask.  */
>>> +	 true,					/* pcrel_offset.  */
>>> +	 BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,	/* bfd_reloc_code_real_type.  */
>>> +	 reloc_sign_bits,			/* adjust_reloc_bits.  */
>>> +	 "ld_pcrel_20"),			/* larch_reloc_type_name.  */
>>> +
>>> +  /* For pcaddi, gd_pc_hi20 + gd_pc_lo12 can relax to gd_pcrel20_s2.  */
>>> +  LOONGARCH_HOWTO (R_LARCH_TLS_GD_PCREL20_S2,	/* type (125).  */
>>> +	 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_TLS_GD_PCREL20_S2",		/* name.  */
>>> +	 false,					/* partial_inplace.  */
>>> +	 0,					/* src_mask.  */
>>> +	 0x1ffffe0,				/* dst_mask.  */
>>> +	 true,					/* pcrel_offset.  */
>>> +	 BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,	/* bfd_reloc_code_real_type.  */
>>> +	 reloc_sign_bits,			/* adjust_reloc_bits.  */
>>> +	 "gd_pcrel_20"),			/* larch_reloc_type_name.  */
>>> +
>>> +  /* For pcaddi, desc_pc_hi20 + desc_pc_lo12 can relax to desc_pcrel20_s2.  */
>>> +  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PCREL20_S2,	/* type (126).  */
>>> +	 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_TLS_DESC_PCREL20_S2",		/* name.  */
>>> +	 false,					/* partial_inplace.  */
>>> +	 0,					/* src_mask.  */
>>> +	 0x1ffffe0,				/* dst_mask.  */
>>> +	 true,					/* pcrel_offset.  */
>>> +	 BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,	/* bfd_reloc_code_real_type.  */
>>> +	 reloc_sign_bits,			/* adjust_reloc_bits.  */
>>> +	 "desc_pcrel_20"),			/* larch_reloc_type_name.  */
>>> };
>> 
> 
>> I think relaxation relocs is a concept internal to binutils and they should not be in the same number range as psABI defined relocs. Some linkers (e.g. mold) doesn’t create new relocs when relaxing and rewrites the instruction right away, therefore these relocs would have no purpose in the psABI.
>> 
>> We recently refactored out all the linker-internal relocs to a different range [1]; LoongArch might want to follow suit.
>> 
>> [1]: https://sourceware.org/pipermail/binutils/2023-November/130322.html
> 
> However, it should be noted that in handwritten assembly, these relocations can be directly used.
> 

Sorry for the delay in reply. I’m not sure if there is any use cases to use relaxation-only relocations in assembly source. It’s one of the reasons we did away with this in RISC-V [1].

[1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/398
>> 
>>> 
>>> reloc_howto_type *
>>> @@ -1783,7 +1837,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
>>>   if(r_type < R_LARCH_count)
>>>     {
>>>       /* For search table fast.  */
>>> +      /*
>>>       BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>>> +      */
>> 
> 
>> Was this supposed to be commented out and committed as-is?
> 
> It has been deleted.
> 
>> 
>>> 
>>>       if (loongarch_howto_table[r_type].howto.type == r_type)
>>> 	return (reloc_howto_type *)&loongarch_howto_table[r_type];
>>> @@ -1802,7 +1858,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
>>> reloc_howto_type *
>>> loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
>>> {
>>> +  /*
>>>   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>>> +  */
>>> 
>>>   for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
>>>     if (loongarch_howto_table[i].howto.name
>>> @@ -1821,7 +1879,9 @@ reloc_howto_type *
>>> loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
>>> 			     bfd_reloc_code_real_type code)
>>> {
>>> +  /*
>>>   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>>> +  */
>>> 
>>>   /* Fast search for new reloc types.  */
>>>   if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
>>> diff --git a/bfd/libbfd.h b/bfd/libbfd.h
>>> index 71b03da14d9..8dab44110a6 100644
>>> --- a/bfd/libbfd.h
>>> +++ b/bfd/libbfd.h
>>> @@ -3612,6 +3612,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
>>>   "BFD_RELOC_LARCH_TLS_DESC64_HI12",
>>>   "BFD_RELOC_LARCH_TLS_DESC_LD",
>>>   "BFD_RELOC_LARCH_TLS_DESC_CALL",
>>> +  "BFD_RELOC_LARCH_TLS_LD_PCREL20_S2",
>>> +  "BFD_RELOC_LARCH_TLS_GD_PCREL20_S2",
>>> +  "BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2",
>>>  "@@overflow: BFD_RELOC_UNUSED@@",
>>> };
>>> #endif
>>> diff --git a/bfd/reloc.c b/bfd/reloc.c
>>> index f7fe0c7ffe3..6fd0f1fb547 100644
>>> --- a/bfd/reloc.c
>>> +++ b/bfd/reloc.c
>>> @@ -8324,6 +8324,13 @@ ENUMX
>>> ENUMX
>>>   BFD_RELOC_LARCH_TLS_DESC_CALL
>>> 
>>> +ENUMX
>>> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2
>>> +ENUMX
>>> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2
>>> +ENUMX
>>> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2
>>> +
>>> ENUMDOC
>>>   LARCH relocations.
>>> 
>>> diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
>>> index 1658025f918..def26daf634 100644
>>> --- a/gas/config/tc-loongarch.c
>>> +++ b/gas/config/tc-loongarch.c
>>> @@ -682,7 +682,7 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
>>> 		      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_TLS_DESC_CALL)
>>> +	      && ip->reloc_info[0].type <= BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2)
>>> 	    {
>>> 	      /* As we compact stack-relocs, it is no need for pop operation.
>>> 		 But break out until here in order to check the imm field.
>>> @@ -694,7 +694,11 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
>>> 		    && (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))
>>> +			|| BFD_RELOC_LARCH_GOT_PC_LO12 == reloc_type
>>> +			|| BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_type
>>> +			|| BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_type
>>> +			|| BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_type
>>> +			|| BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_type))
>>> 		{
>>> 		  ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
>>> 		  ip->reloc_info[ip->reloc_num].value = const_0;
>>> diff --git a/gas/testsuite/gas/loongarch/macro_op.d b/gas/testsuite/gas/loongarch/macro_op.d
>>> index 32860864704..47f8f45c663 100644
>>> --- a/gas/testsuite/gas/loongarch/macro_op.d
>>> +++ b/gas/testsuite/gas/loongarch/macro_op.d
>>> @@ -2,70 +2,72 @@
>>> #objdump: -dr
>>> #skip: loongarch32-*-*
>>> 
>>> 
>>> 
>>> -- 
>>> 2.43.0
>>> 
>>> 
>> 
> 


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

* Re: [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation
  2024-01-07 23:00       ` Tatsuyuki Ishi
@ 2024-01-08  0:22         ` Fangrui Song
       [not found]         ` <DS7PR12MB5765D250CD96B4F6EF6674BACB6B2@DS7PR12MB5765.namprd12.prod.outlook.com>
  1 sibling, 0 replies; 19+ messages in thread
From: Fangrui Song @ 2024-01-08  0:22 UTC (permalink / raw)
  To: Lulu Cai
  Cc: Tatsuyuki Ishi, binutils, xuchenghua, chenglulu, liuzhensong,
	mengqinggang, xry111, i.swmail, maskray, luweining, wanglei,
	hejinyang

On Sun, Jan 7, 2024 at 3:00 PM Tatsuyuki Ishi <ishitatsuyuki@gmail.com> wrote:
>
> On Dec 29, 2023, at 19:45, Lulu Cai <cailulu@loongson.cn> wrote:
>
> On 2023/12/28 at 10:38 PM, Tatsuyuki Ishi Wrote:
>
> On Dec 22, 2023, at 20:42, Lulu Cai <cailulu@loongson.cn> wrote:
>
> From: mengqinggang <mengqinggang@loongson.cn>
>
> The pcalau12i + addi.d of TLS LD/GD/DESC relax to pcaddi.
> Relaxation is only performed when the TLS model transition is not possible.
> ---
> bfd/bfd-in2.h                                 |   3 +
> bfd/elfnn-loongarch.c                         | 174 +++++++-
> bfd/elfxx-loongarch.c                         |  60 +++
> bfd/libbfd.h                                  |   3 +
> bfd/reloc.c                                   |   7 +
> gas/config/tc-loongarch.c                     |   8 +-
> gas/testsuite/gas/loongarch/macro_op.d        | 128 +++---
> gas/testsuite/gas/loongarch/macro_op_32.d     | 120 +++---
> .../gas/loongarch/macro_op_large_abs.d        | 160 +++----
> .../gas/loongarch/macro_op_large_pc.d         | 160 +++----
> include/elf/loongarch.h                       |   4 +
> ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++++---------
> ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 +++---
> 13 files changed, 795 insertions(+), 543 deletions(-)
>
> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
> index 85251aa0edd..782845926ea 100644
> --- a/bfd/bfd-in2.h
> +++ b/bfd/bfd-in2.h
> @@ -7473,6 +7473,9 @@ enum bfd_reloc_code_real
>   BFD_RELOC_LARCH_TLS_DESC64_HI12,
>   BFD_RELOC_LARCH_TLS_DESC_LD,
>   BFD_RELOC_LARCH_TLS_DESC_CALL,
> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,
> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,
> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,
>   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 1347d13d2e2..bd448cda453 100644
> --- a/bfd/elfnn-loongarch.c
> +++ b/bfd/elfnn-loongarch.c
> @@ -2285,7 +2285,9 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
>     case R_LARCH_TLS_DESC_LO12:
>     case R_LARCH_TLS_DESC64_LO20:
>     case R_LARCH_TLS_DESC64_HI12:
> -
> +    case R_LARCH_TLS_LD_PCREL20_S2:
> +    case R_LARCH_TLS_GD_PCREL20_S2:
> +    case R_LARCH_TLS_DESC_PCREL20_S2:
>       r = loongarch_check_offset (rel, input_section);
>       if (r != bfd_reloc_ok)
> break;
> @@ -3674,6 +3676,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
> case R_LARCH_TLS_GD_HI20:
> case R_LARCH_TLS_DESC_PC_HI20:
> case R_LARCH_TLS_DESC_HI20:
> + case R_LARCH_TLS_LD_PCREL20_S2:
> + case R_LARCH_TLS_GD_PCREL20_S2:
> + case R_LARCH_TLS_DESC_PCREL20_S2:
>  BFD_ASSERT (rel->r_addend == 0);
>  unresolved_reloc = false;
>
> @@ -3682,7 +3687,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>    is_ie = true;
>
>  if (r_type == R_LARCH_TLS_DESC_PC_HI20
> -      || r_type == R_LARCH_TLS_DESC_HI20)
> +      || r_type == R_LARCH_TLS_DESC_HI20
> +      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>    is_desc = true;
>
>  bfd_vma got_off = 0;
> @@ -3813,7 +3819,11 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>      || r_type == R_LARCH_TLS_IE_PC_HI20
>      || r_type == R_LARCH_TLS_DESC_PC_HI20)
>    RELOCATE_CALC_PC32_HI20 (relocation, pc);
> -
> +  else if (r_type == R_LARCH_TLS_LD_PCREL20_S2
> +      || r_type == R_LARCH_TLS_GD_PCREL20_S2
> +      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
> +    relocation -= pc;
> +  /* else {} ABS relocations.  */
>  break;
>
> case R_LARCH_TLS_DESC_PC_LO12:
> @@ -4244,6 +4254,85 @@ loongarch_relax_align (bfd *abfd, asection *sec,
> addend - need_nop_bytes, link_info);
> }
>
> +/* Relax pcalau12i + addi.d of TLS LD/GD/DESC to pcaddi.  */
> +static bool
> +loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
> +       Elf_Internal_Rela *rel_hi, bfd_vma symval,
> +       struct bfd_link_info *info, bool *again)
> +{
> +  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;
> +
> +  /* This section's output_offset need to subtract the bytes of instructions
> +     relaxed by the previous sections, so it needs to be updated beforehand.
> +     size_input_section already took care of updating it after relaxation,
> +     so we additionally update once here.  */
> +  sec->output_offset = sec->output_section->size;
> +  bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
> +
> +  /* If pc and symbol not in the same segment, add/sub segment alignment.
> +     FIXME: if there are multiple readonly segments?  */
> +  if (!(sym_sec->flags & SEC_READONLY))
> +    {
> +      if (symval > pc)
> + pc -= info->maxpagesize;
> +      else if (symval < pc)
> + pc += info->maxpagesize;
> +    }
> +
> +  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_GOT_PC_LO12
> + && ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_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)
> +      || ((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;
> +
> +  /* Continue next relax trip.  */
> +  *again = true;
> +
> +  pca = pcaddi | rd;
> +  bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
> +
> +  /* Adjust relocations.  */
> +  switch (ELFNN_R_TYPE (rel_hi->r_info))
> +    {
> +    case R_LARCH_TLS_LD_PC_HI20:
> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
> +      R_LARCH_TLS_LD_PCREL20_S2);
> +      break;
> +    case R_LARCH_TLS_GD_PC_HI20:
> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
> +      R_LARCH_TLS_GD_PCREL20_S2);
> +      break;
> +    case R_LARCH_TLS_DESC_PC_HI20:
> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
> +      R_LARCH_TLS_DESC_PCREL20_S2);
> +      break;
> +    default:
> +      break;
> +    }
> +  rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
> +
> +  loongarch_relax_delete_bytes (abfd, sec, rel_lo->r_offset, 4, info);
> +
> +  return true;
> +}
> +
> static bool
> loongarch_elf_relax_section (bfd *abfd, asection *sec,
>       struct bfd_link_info *info,
> @@ -4288,15 +4377,23 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>
>   for (unsigned int i = 0; i < sec->reloc_count; i++)
>     {
> -      Elf_Internal_Rela *rel = relocs + i;
> -      asection *sym_sec;
> +      char symtype;
>       bfd_vma symval;
> -      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
> -      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
> +      asection *sym_sec;
>       bool local_got = false;
> -      char symtype;
> +      Elf_Internal_Rela *rel = relocs + i;
>       struct elf_link_hash_entry *h = NULL;
> +      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
> +      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>
> +      /* Four kind of relocations:
> + Normal: symval is the symbol address.
> + R_LARCH_ALIGN: symval is the address of the last NOP instruction
> + added by this relocation, and then adds 4 more.
> + R_LARCH_CALL36: symval is the symbol address for local symbols,
> + or the PLT entry address of the symbol. (Todo)
> + R_LARCHL_TLS_LD/GD/DESC_PC_HI20: symval is the GOT entry address
> + of the symbol.  */
>       if (r_symndx < symtab_hdr->sh_info)
> {
>  Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
> @@ -4304,7 +4401,24 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
>    continue;
>
> -  if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
> +  if (R_LARCH_TLS_LD_PC_HI20 == r_type
> +      || R_LARCH_TLS_GD_PC_HI20 == r_type
> +      || R_LARCH_TLS_DESC_PC_HI20 == r_type)
> +    {
> +      if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
> + continue;
> +      else
> + {
> +  sym_sec = htab->elf.sgot;
> +  symval = elf_local_got_offsets (abfd)[r_symndx];
> +  char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
> + r_symndx);
> +  if (R_LARCH_TLS_DESC_PC_HI20 == r_type
> + && GOT_TLS_GD_BOTH_P (tls_type))
> +    symval += 2 * GOT_ENTRY_SIZE;
> + }
> +    }
> +  else if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>    {
>      sym_sec = sec;
>      symval = rel->r_offset;
> @@ -4329,7 +4443,26 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>  if (h != NULL && h->type == STT_GNU_IFUNC)
>    continue;
>
> -  if ((h->root.type == bfd_link_hash_defined
> +  /* The GOT entry of tls symbols must in current execute file or
> +     shared object.  */
> +  if (R_LARCH_TLS_LD_PC_HI20 == r_type
> +      || R_LARCH_TLS_GD_PC_HI20 == r_type
> +      || R_LARCH_TLS_DESC_PC_HI20 == r_type)
> +    {
> +      if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
> + continue;
> +      else
> + {
> +  sym_sec = htab->elf.sgot;
> +  symval = h->got.offset;
> +  char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
> + r_symndx);
> +  if (R_LARCH_TLS_DESC_PC_HI20 == r_type
> + && GOT_TLS_GD_BOTH_P (tls_type))
> +    symval += 2 * GOT_ENTRY_SIZE;
> + }
> +    }
> +  else 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)
> @@ -4358,7 +4491,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>   if (symtype != STT_SECTION)
>     symval += rel->r_addend;
> }
> -      /* For R_LARCH_ALIGN, symval is sec_addr (sym_sec) + rel->r_offset
> +      /* For R_LARCH_ALIGN, symval is sec_addr (sec) + rel->r_offset
> + (alingmeng - 4).
> If r_symndx is 0, alignmeng-4 is r_addend.
> If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4.  */
> @@ -4399,6 +4532,25 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>    info, again);
>    }
>  break;
> +
> + case R_LARCH_TLS_LD_PC_HI20:
> +  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
> +    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
> +    info, again);
> +  break;
> +
> + case R_LARCH_TLS_GD_PC_HI20:
> +  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
> +    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
> +    info, again);
> +  break;
> +
> + case R_LARCH_TLS_DESC_PC_HI20:
> +  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
> +    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
> +    info, again);
> +  break;
> +
> default:
>  break;
> }
> diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
> index 30a941a851f..310e6d62dc0 100644
> --- a/bfd/elfxx-loongarch.c
> +++ b/bfd/elfxx-loongarch.c
> @@ -1775,6 +1775,60 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
> BFD_RELOC_LARCH_TLS_DESC_CALL, /* bfd_reloc_code_real_type.  */
> NULL, /* adjust_reloc_bits.  */
> "desc_call"), /* larch_reloc_type_name.  */
>
> +
> +  /* For pcaddi, ld_pc_hi20 + ld_pc_lo12 can relax to ld_pcrel20_s2.  */
> +  LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCREL20_S2, /* type (124).  */
> + 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_TLS_LD_PCREL20_S2", /* name.  */
> + false, /* partial_inplace.  */
> + 0, /* src_mask.  */
> + 0x1ffffe0, /* dst_mask.  */
> + true, /* pcrel_offset.  */
> + BFD_RELOC_LARCH_TLS_LD_PCREL20_S2, /* bfd_reloc_code_real_type.  */
> + reloc_sign_bits, /* adjust_reloc_bits.  */
> + "ld_pcrel_20"), /* larch_reloc_type_name.  */
> +
> +  /* For pcaddi, gd_pc_hi20 + gd_pc_lo12 can relax to gd_pcrel20_s2.  */
> +  LOONGARCH_HOWTO (R_LARCH_TLS_GD_PCREL20_S2, /* type (125).  */
> + 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_TLS_GD_PCREL20_S2", /* name.  */
> + false, /* partial_inplace.  */
> + 0, /* src_mask.  */
> + 0x1ffffe0, /* dst_mask.  */
> + true, /* pcrel_offset.  */
> + BFD_RELOC_LARCH_TLS_GD_PCREL20_S2, /* bfd_reloc_code_real_type.  */
> + reloc_sign_bits, /* adjust_reloc_bits.  */
> + "gd_pcrel_20"), /* larch_reloc_type_name.  */
> +
> +  /* For pcaddi, desc_pc_hi20 + desc_pc_lo12 can relax to desc_pcrel20_s2.  */
> +  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PCREL20_S2, /* type (126).  */
> + 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_TLS_DESC_PCREL20_S2", /* name.  */
> + false, /* partial_inplace.  */
> + 0, /* src_mask.  */
> + 0x1ffffe0, /* dst_mask.  */
> + true, /* pcrel_offset.  */
> + BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2, /* bfd_reloc_code_real_type.  */
> + reloc_sign_bits, /* adjust_reloc_bits.  */
> + "desc_pcrel_20"), /* larch_reloc_type_name.  */
> };
>
>
>
> I think relaxation relocs is a concept internal to binutils and they should not be in the same number range as psABI defined relocs. Some linkers (e.g. mold) doesn’t create new relocs when relaxing and rewrites the instruction right away, therefore these relocs would have no purpose in the psABI.
>
> We recently refactored out all the linker-internal relocs to a different range [1]; LoongArch might want to follow suit.
>
> [1]: https://sourceware.org/pipermail/binutils/2023-November/130322.html
>
>
> However, it should be noted that in handwritten assembly, these relocations can be directly used.
>
>
> Sorry for the delay in reply. I’m not sure if there is any use cases to use relaxation-only relocations in assembly source. It’s one of the reasons we did away with this in RISC-V [1].
>
> [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/398

Agreed. If a relocation type is only used for internal relaxation
purposes, it should not be defined in the psABI and there should not
be an assembler directive generating it (except .reloc using a
hard-coded integer).

>
> reloc_howto_type *
> @@ -1783,7 +1837,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
>   if(r_type < R_LARCH_count)
>     {
>       /* For search table fast.  */
>
> +      /*
>       BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
> +      */
>
>
>
> Was this supposed to be commented out and committed as-is?
>
>
> It has been deleted.
>
>
>
>       if (loongarch_howto_table[r_type].howto.type == r_type)
> return (reloc_howto_type *)&loongarch_howto_table[r_type];
> @@ -1802,7 +1858,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
> reloc_howto_type *
> loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
> {
> +  /*
>   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
> +  */
>
>   for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
>     if (loongarch_howto_table[i].howto.name
> @@ -1821,7 +1879,9 @@ reloc_howto_type *
> loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
>     bfd_reloc_code_real_type code)
> {
> +  /*
>   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
> +  */
>
>   /* Fast search for new reloc types.  */
>   if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
> diff --git a/bfd/libbfd.h b/bfd/libbfd.h
> index 71b03da14d9..8dab44110a6 100644
> --- a/bfd/libbfd.h
> +++ b/bfd/libbfd.h
> @@ -3612,6 +3612,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
>   "BFD_RELOC_LARCH_TLS_DESC64_HI12",
>   "BFD_RELOC_LARCH_TLS_DESC_LD",
>   "BFD_RELOC_LARCH_TLS_DESC_CALL",
> +  "BFD_RELOC_LARCH_TLS_LD_PCREL20_S2",
> +  "BFD_RELOC_LARCH_TLS_GD_PCREL20_S2",
> +  "BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2",
>  "@@overflow: BFD_RELOC_UNUSED@@",
> };
> #endif
> diff --git a/bfd/reloc.c b/bfd/reloc.c
> index f7fe0c7ffe3..6fd0f1fb547 100644
> --- a/bfd/reloc.c
> +++ b/bfd/reloc.c
> @@ -8324,6 +8324,13 @@ ENUMX
> ENUMX
>   BFD_RELOC_LARCH_TLS_DESC_CALL
>
> +ENUMX
> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2
> +ENUMX
> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2
> +ENUMX
> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2
> +
> ENUMDOC
>   LARCH relocations.
>
> diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
> index 1658025f918..def26daf634 100644
> --- a/gas/config/tc-loongarch.c
> +++ b/gas/config/tc-loongarch.c
> @@ -682,7 +682,7 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
>      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_TLS_DESC_CALL)
> +      && ip->reloc_info[0].type <= BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2)
>    {
>      /* As we compact stack-relocs, it is no need for pop operation.
> But break out until here in order to check the imm field.
> @@ -694,7 +694,11 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
>    && (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))
> + || BFD_RELOC_LARCH_GOT_PC_LO12 == reloc_type
> + || BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_type
> + || BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_type
> + || BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_type
> + || BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_type))
> {
>  ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
>  ip->reloc_info[ip->reloc_num].value = const_0;
> diff --git a/gas/testsuite/gas/loongarch/macro_op.d b/gas/testsuite/gas/loongarch/macro_op.d
> index 32860864704..47f8f45c663 100644
> --- a/gas/testsuite/gas/loongarch/macro_op.d
> +++ b/gas/testsuite/gas/loongarch/macro_op.d
> @@ -2,70 +2,72 @@
> #objdump: -dr
> #skip: loongarch32-*-*
>
>
>
> --
> 2.43.0
>
>
>
>
>

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

* Re: [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation
       [not found]         ` <DS7PR12MB5765D250CD96B4F6EF6674BACB6B2@DS7PR12MB5765.namprd12.prod.outlook.com>
@ 2024-01-08  6:00           ` Lulu Cai
  2024-01-08  7:59             ` Tatsuyuki Ishi
  0 siblings, 1 reply; 19+ messages in thread
From: Lulu Cai @ 2024-01-08  6:00 UTC (permalink / raw)
  To: Fangrui Song, Tatsuyuki Ishi, binutils
  Cc: xuchenghua, chenglulu, liuzhensong, mengqinggang, xry111,
	i.swmail, maskray, luweining, wanglei, hejinyang

On 1/8/24 8:22 AM, Fangrui Song wrote:
> On Sun, Jan 7, 2024 at 3:00 PM Tatsuyuki Ishi <ishitatsuyuki@gmail.com> wrote:
>> On Dec 29, 2023, at 19:45, Lulu Cai <cailulu@loongson.cn> wrote:
>>
>> On 2023/12/28 at 10:38 PM, Tatsuyuki Ishi Wrote:
>>
>> On Dec 22, 2023, at 20:42, Lulu Cai <cailulu@loongson.cn> wrote:
>>
>> From: mengqinggang <mengqinggang@loongson.cn>
>>
>> The pcalau12i + addi.d of TLS LD/GD/DESC relax to pcaddi.
>> Relaxation is only performed when the TLS model transition is not possible.
>> ---
>> bfd/bfd-in2.h                                 |   3 +
>> bfd/elfnn-loongarch.c                         | 174 +++++++-
>> bfd/elfxx-loongarch.c                         |  60 +++
>> bfd/libbfd.h                                  |   3 +
>> bfd/reloc.c                                   |   7 +
>> gas/config/tc-loongarch.c                     |   8 +-
>> gas/testsuite/gas/loongarch/macro_op.d        | 128 +++---
>> gas/testsuite/gas/loongarch/macro_op_32.d     | 120 +++---
>> .../gas/loongarch/macro_op_large_abs.d        | 160 +++----
>> .../gas/loongarch/macro_op_large_pc.d         | 160 +++----
>> include/elf/loongarch.h                       |   4 +
>> ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++++---------
>> ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 +++---
>> 13 files changed, 795 insertions(+), 543 deletions(-)
>>
>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>> index 85251aa0edd..782845926ea 100644
>> --- a/bfd/bfd-in2.h
>> +++ b/bfd/bfd-in2.h
>> @@ -7473,6 +7473,9 @@ enum bfd_reloc_code_real
>>    BFD_RELOC_LARCH_TLS_DESC64_HI12,
>>    BFD_RELOC_LARCH_TLS_DESC_LD,
>>    BFD_RELOC_LARCH_TLS_DESC_CALL,
>> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,
>> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,
>> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,
>>    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 1347d13d2e2..bd448cda453 100644
>> --- a/bfd/elfnn-loongarch.c
>> +++ b/bfd/elfnn-loongarch.c
>> @@ -2285,7 +2285,9 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
>>      case R_LARCH_TLS_DESC_LO12:
>>      case R_LARCH_TLS_DESC64_LO20:
>>      case R_LARCH_TLS_DESC64_HI12:
>> -
>> +    case R_LARCH_TLS_LD_PCREL20_S2:
>> +    case R_LARCH_TLS_GD_PCREL20_S2:
>> +    case R_LARCH_TLS_DESC_PCREL20_S2:
>>        r = loongarch_check_offset (rel, input_section);
>>        if (r != bfd_reloc_ok)
>> break;
>> @@ -3674,6 +3676,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>> case R_LARCH_TLS_GD_HI20:
>> case R_LARCH_TLS_DESC_PC_HI20:
>> case R_LARCH_TLS_DESC_HI20:
>> + case R_LARCH_TLS_LD_PCREL20_S2:
>> + case R_LARCH_TLS_GD_PCREL20_S2:
>> + case R_LARCH_TLS_DESC_PCREL20_S2:
>>   BFD_ASSERT (rel->r_addend == 0);
>>   unresolved_reloc = false;
>>
>> @@ -3682,7 +3687,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>     is_ie = true;
>>
>>   if (r_type == R_LARCH_TLS_DESC_PC_HI20
>> -      || r_type == R_LARCH_TLS_DESC_HI20)
>> +      || r_type == R_LARCH_TLS_DESC_HI20
>> +      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>>     is_desc = true;
>>
>>   bfd_vma got_off = 0;
>> @@ -3813,7 +3819,11 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>       || r_type == R_LARCH_TLS_IE_PC_HI20
>>       || r_type == R_LARCH_TLS_DESC_PC_HI20)
>>     RELOCATE_CALC_PC32_HI20 (relocation, pc);
>> -
>> +  else if (r_type == R_LARCH_TLS_LD_PCREL20_S2
>> +      || r_type == R_LARCH_TLS_GD_PCREL20_S2
>> +      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>> +    relocation -= pc;
>> +  /* else {} ABS relocations.  */
>>   break;
>>
>> case R_LARCH_TLS_DESC_PC_LO12:
>> @@ -4244,6 +4254,85 @@ loongarch_relax_align (bfd *abfd, asection *sec,
>> addend - need_nop_bytes, link_info);
>> }
>>
>> +/* Relax pcalau12i + addi.d of TLS LD/GD/DESC to pcaddi.  */
>> +static bool
>> +loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
>> +       Elf_Internal_Rela *rel_hi, bfd_vma symval,
>> +       struct bfd_link_info *info, bool *again)
>> +{
>> +  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;
>> +
>> +  /* This section's output_offset need to subtract the bytes of instructions
>> +     relaxed by the previous sections, so it needs to be updated beforehand.
>> +     size_input_section already took care of updating it after relaxation,
>> +     so we additionally update once here.  */
>> +  sec->output_offset = sec->output_section->size;
>> +  bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
>> +
>> +  /* If pc and symbol not in the same segment, add/sub segment alignment.
>> +     FIXME: if there are multiple readonly segments?  */
>> +  if (!(sym_sec->flags & SEC_READONLY))
>> +    {
>> +      if (symval > pc)
>> + pc -= info->maxpagesize;
>> +      else if (symval < pc)
>> + pc += info->maxpagesize;
>> +    }
>> +
>> +  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_GOT_PC_LO12
>> + && ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_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)
>> +      || ((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;
>> +
>> +  /* Continue next relax trip.  */
>> +  *again = true;
>> +
>> +  pca = pcaddi | rd;
>> +  bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
>> +
>> +  /* Adjust relocations.  */
>> +  switch (ELFNN_R_TYPE (rel_hi->r_info))
>> +    {
>> +    case R_LARCH_TLS_LD_PC_HI20:
>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>> +      R_LARCH_TLS_LD_PCREL20_S2);
>> +      break;
>> +    case R_LARCH_TLS_GD_PC_HI20:
>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>> +      R_LARCH_TLS_GD_PCREL20_S2);
>> +      break;
>> +    case R_LARCH_TLS_DESC_PC_HI20:
>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>> +      R_LARCH_TLS_DESC_PCREL20_S2);
>> +      break;
>> +    default:
>> +      break;
>> +    }
>> +  rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
>> +
>> +  loongarch_relax_delete_bytes (abfd, sec, rel_lo->r_offset, 4, info);
>> +
>> +  return true;
>> +}
>> +
>> static bool
>> loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>        struct bfd_link_info *info,
>> @@ -4288,15 +4377,23 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>
>>    for (unsigned int i = 0; i < sec->reloc_count; i++)
>>      {
>> -      Elf_Internal_Rela *rel = relocs + i;
>> -      asection *sym_sec;
>> +      char symtype;
>>        bfd_vma symval;
>> -      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>> -      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
>> +      asection *sym_sec;
>>        bool local_got = false;
>> -      char symtype;
>> +      Elf_Internal_Rela *rel = relocs + i;
>>        struct elf_link_hash_entry *h = NULL;
>> +      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
>> +      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>>
>> +      /* Four kind of relocations:
>> + Normal: symval is the symbol address.
>> + R_LARCH_ALIGN: symval is the address of the last NOP instruction
>> + added by this relocation, and then adds 4 more.
>> + R_LARCH_CALL36: symval is the symbol address for local symbols,
>> + or the PLT entry address of the symbol. (Todo)
>> + R_LARCHL_TLS_LD/GD/DESC_PC_HI20: symval is the GOT entry address
>> + of the symbol.  */
>>        if (r_symndx < symtab_hdr->sh_info)
>> {
>>   Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
>> @@ -4304,7 +4401,24 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>   if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
>>     continue;
>>
>> -  if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>> +  if (R_LARCH_TLS_LD_PC_HI20 == r_type
>> +      || R_LARCH_TLS_GD_PC_HI20 == r_type
>> +      || R_LARCH_TLS_DESC_PC_HI20 == r_type)
>> +    {
>> +      if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
>> + continue;
>> +      else
>> + {
>> +  sym_sec = htab->elf.sgot;
>> +  symval = elf_local_got_offsets (abfd)[r_symndx];
>> +  char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
>> + r_symndx);
>> +  if (R_LARCH_TLS_DESC_PC_HI20 == r_type
>> + && GOT_TLS_GD_BOTH_P (tls_type))
>> +    symval += 2 * GOT_ENTRY_SIZE;
>> + }
>> +    }
>> +  else if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>>     {
>>       sym_sec = sec;
>>       symval = rel->r_offset;
>> @@ -4329,7 +4443,26 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>   if (h != NULL && h->type == STT_GNU_IFUNC)
>>     continue;
>>
>> -  if ((h->root.type == bfd_link_hash_defined
>> +  /* The GOT entry of tls symbols must in current execute file or
>> +     shared object.  */
>> +  if (R_LARCH_TLS_LD_PC_HI20 == r_type
>> +      || R_LARCH_TLS_GD_PC_HI20 == r_type
>> +      || R_LARCH_TLS_DESC_PC_HI20 == r_type)
>> +    {
>> +      if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
>> + continue;
>> +      else
>> + {
>> +  sym_sec = htab->elf.sgot;
>> +  symval = h->got.offset;
>> +  char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
>> + r_symndx);
>> +  if (R_LARCH_TLS_DESC_PC_HI20 == r_type
>> + && GOT_TLS_GD_BOTH_P (tls_type))
>> +    symval += 2 * GOT_ENTRY_SIZE;
>> + }
>> +    }
>> +  else 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)
>> @@ -4358,7 +4491,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>    if (symtype != STT_SECTION)
>>      symval += rel->r_addend;
>> }
>> -      /* For R_LARCH_ALIGN, symval is sec_addr (sym_sec) + rel->r_offset
>> +      /* For R_LARCH_ALIGN, symval is sec_addr (sec) + rel->r_offset
>> + (alingmeng - 4).
>> If r_symndx is 0, alignmeng-4 is r_addend.
>> If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4.  */
>> @@ -4399,6 +4532,25 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>     info, again);
>>     }
>>   break;
>> +
>> + case R_LARCH_TLS_LD_PC_HI20:
>> +  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>> +    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>> +    info, again);
>> +  break;
>> +
>> + case R_LARCH_TLS_GD_PC_HI20:
>> +  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>> +    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>> +    info, again);
>> +  break;
>> +
>> + case R_LARCH_TLS_DESC_PC_HI20:
>> +  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>> +    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>> +    info, again);
>> +  break;
>> +
>> default:
>>   break;
>> }
>> diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
>> index 30a941a851f..310e6d62dc0 100644
>> --- a/bfd/elfxx-loongarch.c
>> +++ b/bfd/elfxx-loongarch.c
>> @@ -1775,6 +1775,60 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
>> BFD_RELOC_LARCH_TLS_DESC_CALL, /* bfd_reloc_code_real_type.  */
>> NULL, /* adjust_reloc_bits.  */
>> "desc_call"), /* larch_reloc_type_name.  */
>>
>> +
>> +  /* For pcaddi, ld_pc_hi20 + ld_pc_lo12 can relax to ld_pcrel20_s2.  */
>> +  LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCREL20_S2, /* type (124).  */
>> + 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_TLS_LD_PCREL20_S2", /* name.  */
>> + false, /* partial_inplace.  */
>> + 0, /* src_mask.  */
>> + 0x1ffffe0, /* dst_mask.  */
>> + true, /* pcrel_offset.  */
>> + BFD_RELOC_LARCH_TLS_LD_PCREL20_S2, /* bfd_reloc_code_real_type.  */
>> + reloc_sign_bits, /* adjust_reloc_bits.  */
>> + "ld_pcrel_20"), /* larch_reloc_type_name.  */
>> +
>> +  /* For pcaddi, gd_pc_hi20 + gd_pc_lo12 can relax to gd_pcrel20_s2.  */
>> +  LOONGARCH_HOWTO (R_LARCH_TLS_GD_PCREL20_S2, /* type (125).  */
>> + 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_TLS_GD_PCREL20_S2", /* name.  */
>> + false, /* partial_inplace.  */
>> + 0, /* src_mask.  */
>> + 0x1ffffe0, /* dst_mask.  */
>> + true, /* pcrel_offset.  */
>> + BFD_RELOC_LARCH_TLS_GD_PCREL20_S2, /* bfd_reloc_code_real_type.  */
>> + reloc_sign_bits, /* adjust_reloc_bits.  */
>> + "gd_pcrel_20"), /* larch_reloc_type_name.  */
>> +
>> +  /* For pcaddi, desc_pc_hi20 + desc_pc_lo12 can relax to desc_pcrel20_s2.  */
>> +  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PCREL20_S2, /* type (126).  */
>> + 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_TLS_DESC_PCREL20_S2", /* name.  */
>> + false, /* partial_inplace.  */
>> + 0, /* src_mask.  */
>> + 0x1ffffe0, /* dst_mask.  */
>> + true, /* pcrel_offset.  */
>> + BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2, /* bfd_reloc_code_real_type.  */
>> + reloc_sign_bits, /* adjust_reloc_bits.  */
>> + "desc_pcrel_20"), /* larch_reloc_type_name.  */
>> };
>>
>>
>>
>> I think relaxation relocs is a concept internal to binutils and they should not be in the same number range as psABI defined relocs. Some linkers (e.g. mold) doesn’t create new relocs when relaxing and rewrites the instruction right away, therefore these relocs would have no purpose in the psABI.
>>
>> We recently refactored out all the linker-internal relocs to a different range [1]; LoongArch might want to follow suit.
>>
>> [1]: https://sourceware.org/pipermail/binutils/2023-November/130322.html
>>
>>
>> However, it should be noted that in handwritten assembly, these relocations can be directly used.
>>
>>
>> Sorry for the delay in reply. I’m not sure if there is any use cases to use relaxation-only relocations in assembly source. It’s one of the reasons we did away with this in RISC-V [1].
>>
>> [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/398
> Agreed. If a relocation type is only used for internal relaxation
> purposes, it should not be defined in the psABI and there should not
> be an assembler directive generating it (except .reloc using a
> hard-coded integer).

We have considered such a situation. For those familiar with LoongArch 
assembly, if you want to
use DESC to access "var" in assembly source, you can directly use pcaddi 
$a0,%desc_pcrel_20(var)
instead of pcalau12i $a0,%desc_pc_hi20(var) and addi.d $a0, $a0,% 
desc_pc_lo12(var).
The same situation applies to GD/LD.


>
>> reloc_howto_type *
>> @@ -1783,7 +1837,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
>>    if(r_type < R_LARCH_count)
>>      {
>>        /* For search table fast.  */
>>
>> +      /*
>>        BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>> +      */
>>
>>
>>
>> Was this supposed to be commented out and committed as-is?
>>
>>
>> It has been deleted.
>>
>>
>>
>>        if (loongarch_howto_table[r_type].howto.type == r_type)
>> return (reloc_howto_type *)&loongarch_howto_table[r_type];
>> @@ -1802,7 +1858,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
>> reloc_howto_type *
>> loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
>> {
>> +  /*
>>    BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>> +  */
>>
>>    for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
>>      if (loongarch_howto_table[i].howto.name
>> @@ -1821,7 +1879,9 @@ reloc_howto_type *
>> loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
>>      bfd_reloc_code_real_type code)
>> {
>> +  /*
>>    BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>> +  */
>>
>>    /* Fast search for new reloc types.  */
>>    if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
>> diff --git a/bfd/libbfd.h b/bfd/libbfd.h
>> index 71b03da14d9..8dab44110a6 100644
>> --- a/bfd/libbfd.h
>> +++ b/bfd/libbfd.h
>> @@ -3612,6 +3612,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
>>    "BFD_RELOC_LARCH_TLS_DESC64_HI12",
>>    "BFD_RELOC_LARCH_TLS_DESC_LD",
>>    "BFD_RELOC_LARCH_TLS_DESC_CALL",
>> +  "BFD_RELOC_LARCH_TLS_LD_PCREL20_S2",
>> +  "BFD_RELOC_LARCH_TLS_GD_PCREL20_S2",
>> +  "BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2",
>>   "@@overflow: BFD_RELOC_UNUSED@@",
>> };
>> #endif
>> diff --git a/bfd/reloc.c b/bfd/reloc.c
>> index f7fe0c7ffe3..6fd0f1fb547 100644
>> --- a/bfd/reloc.c
>> +++ b/bfd/reloc.c
>> @@ -8324,6 +8324,13 @@ ENUMX
>> ENUMX
>>    BFD_RELOC_LARCH_TLS_DESC_CALL
>>
>> +ENUMX
>> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2
>> +ENUMX
>> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2
>> +ENUMX
>> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2
>> +
>> ENUMDOC
>>    LARCH relocations.
>>
>> diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
>> index 1658025f918..def26daf634 100644
>> --- a/gas/config/tc-loongarch.c
>> +++ b/gas/config/tc-loongarch.c
>> @@ -682,7 +682,7 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
>>       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_TLS_DESC_CALL)
>> +      && ip->reloc_info[0].type <= BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2)
>>     {
>>       /* As we compact stack-relocs, it is no need for pop operation.
>> But break out until here in order to check the imm field.
>> @@ -694,7 +694,11 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
>>     && (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))
>> + || BFD_RELOC_LARCH_GOT_PC_LO12 == reloc_type
>> + || BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_type
>> + || BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_type
>> + || BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_type
>> + || BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_type))
>> {
>>   ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
>>   ip->reloc_info[ip->reloc_num].value = const_0;
>> diff --git a/gas/testsuite/gas/loongarch/macro_op.d b/gas/testsuite/gas/loongarch/macro_op.d
>> index 32860864704..47f8f45c663 100644
>> --- a/gas/testsuite/gas/loongarch/macro_op.d
>> +++ b/gas/testsuite/gas/loongarch/macro_op.d
>> @@ -2,70 +2,72 @@
>> #objdump: -dr
>> #skip: loongarch32-*-*
>>
>>
>>
>> --
>> 2.43.0
>>
>>
>>
>>
>>


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

* Re: [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation
  2024-01-08  6:00           ` Lulu Cai
@ 2024-01-08  7:59             ` Tatsuyuki Ishi
  0 siblings, 0 replies; 19+ messages in thread
From: Tatsuyuki Ishi @ 2024-01-08  7:59 UTC (permalink / raw)
  To: Lulu Cai
  Cc: Fangrui Song, binutils, xuchenghua, chenglulu, liuzhensong,
	mengqinggang, xry111, i.swmail, Fangrui Song, luweining, wanglei,
	hejinyang

[-- Attachment #1: Type: text/plain, Size: 20834 bytes --]

> On Jan 8, 2024, at 15:00, Lulu Cai <cailulu@loongson.cn> wrote:
> 
> On 1/8/24 8:22 AM, Fangrui Song wrote:
>> On Sun, Jan 7, 2024 at 3:00 PM Tatsuyuki Ishi <ishitatsuyuki@gmail.com <mailto:ishitatsuyuki@gmail.com>> wrote:
>>> On Dec 29, 2023, at 19:45, Lulu Cai <cailulu@loongson.cn> wrote:
>>> 
>>> On 2023/12/28 at 10:38 PM, Tatsuyuki Ishi Wrote:
>>> 
>>> On Dec 22, 2023, at 20:42, Lulu Cai <cailulu@loongson.cn> wrote:
>>> 
>>> From: mengqinggang <mengqinggang@loongson.cn>
>>> 
>>> The pcalau12i + addi.d of TLS LD/GD/DESC relax to pcaddi.
>>> Relaxation is only performed when the TLS model transition is not possible.
>>> ---
>>> bfd/bfd-in2.h                                 |   3 +
>>> bfd/elfnn-loongarch.c                         | 174 +++++++-
>>> bfd/elfxx-loongarch.c                         |  60 +++
>>> bfd/libbfd.h                                  |   3 +
>>> bfd/reloc.c                                   |   7 +
>>> gas/config/tc-loongarch.c                     |   8 +-
>>> gas/testsuite/gas/loongarch/macro_op.d        | 128 +++---
>>> gas/testsuite/gas/loongarch/macro_op_32.d     | 120 +++---
>>> .../gas/loongarch/macro_op_large_abs.d        | 160 +++----
>>> .../gas/loongarch/macro_op_large_pc.d         | 160 +++----
>>> include/elf/loongarch.h                       |   4 +
>>> ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++++---------
>>> ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 +++---
>>> 13 files changed, 795 insertions(+), 543 deletions(-)
>>> 
>>> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
>>> index 85251aa0edd..782845926ea 100644
>>> --- a/bfd/bfd-in2.h
>>> +++ b/bfd/bfd-in2.h
>>> @@ -7473,6 +7473,9 @@ enum bfd_reloc_code_real
>>>   BFD_RELOC_LARCH_TLS_DESC64_HI12,
>>>   BFD_RELOC_LARCH_TLS_DESC_LD,
>>>   BFD_RELOC_LARCH_TLS_DESC_CALL,
>>> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2,
>>> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2,
>>> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2,
>>>   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 1347d13d2e2..bd448cda453 100644
>>> --- a/bfd/elfnn-loongarch.c
>>> +++ b/bfd/elfnn-loongarch.c
>>> @@ -2285,7 +2285,9 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
>>>     case R_LARCH_TLS_DESC_LO12:
>>>     case R_LARCH_TLS_DESC64_LO20:
>>>     case R_LARCH_TLS_DESC64_HI12:
>>> -
>>> +    case R_LARCH_TLS_LD_PCREL20_S2:
>>> +    case R_LARCH_TLS_GD_PCREL20_S2:
>>> +    case R_LARCH_TLS_DESC_PCREL20_S2:
>>>       r = loongarch_check_offset (rel, input_section);
>>>       if (r != bfd_reloc_ok)
>>> break;
>>> @@ -3674,6 +3676,9 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>> case R_LARCH_TLS_GD_HI20:
>>> case R_LARCH_TLS_DESC_PC_HI20:
>>> case R_LARCH_TLS_DESC_HI20:
>>> + case R_LARCH_TLS_LD_PCREL20_S2:
>>> + case R_LARCH_TLS_GD_PCREL20_S2:
>>> + case R_LARCH_TLS_DESC_PCREL20_S2:
>>>  BFD_ASSERT (rel->r_addend == 0);
>>>  unresolved_reloc = false;
>>> 
>>> @@ -3682,7 +3687,8 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>>    is_ie = true;
>>> 
>>>  if (r_type == R_LARCH_TLS_DESC_PC_HI20
>>> -      || r_type == R_LARCH_TLS_DESC_HI20)
>>> +      || r_type == R_LARCH_TLS_DESC_HI20
>>> +      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>>>    is_desc = true;
>>> 
>>>  bfd_vma got_off = 0;
>>> @@ -3813,7 +3819,11 @@ loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
>>>      || r_type == R_LARCH_TLS_IE_PC_HI20
>>>      || r_type == R_LARCH_TLS_DESC_PC_HI20)
>>>    RELOCATE_CALC_PC32_HI20 (relocation, pc);
>>> -
>>> +  else if (r_type == R_LARCH_TLS_LD_PCREL20_S2
>>> +      || r_type == R_LARCH_TLS_GD_PCREL20_S2
>>> +      || r_type == R_LARCH_TLS_DESC_PCREL20_S2)
>>> +    relocation -= pc;
>>> +  /* else {} ABS relocations.  */
>>>  break;
>>> 
>>> case R_LARCH_TLS_DESC_PC_LO12:
>>> @@ -4244,6 +4254,85 @@ loongarch_relax_align (bfd *abfd, asection *sec,
>>> addend - need_nop_bytes, link_info);
>>> }
>>> 
>>> +/* Relax pcalau12i + addi.d of TLS LD/GD/DESC to pcaddi.  */
>>> +static bool
>>> +loongarch_relax_tls_ld_gd_desc (bfd *abfd, asection *sec, asection *sym_sec,
>>> +       Elf_Internal_Rela *rel_hi, bfd_vma symval,
>>> +       struct bfd_link_info *info, bool *again)
>>> +{
>>> +  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;
>>> +
>>> +  /* This section's output_offset need to subtract the bytes of instructions
>>> +     relaxed by the previous sections, so it needs to be updated beforehand.
>>> +     size_input_section already took care of updating it after relaxation,
>>> +     so we additionally update once here.  */
>>> +  sec->output_offset = sec->output_section->size;
>>> +  bfd_vma pc = sec_addr (sec) + rel_hi->r_offset;
>>> +
>>> +  /* If pc and symbol not in the same segment, add/sub segment alignment.
>>> +     FIXME: if there are multiple readonly segments?  */
>>> +  if (!(sym_sec->flags & SEC_READONLY))
>>> +    {
>>> +      if (symval > pc)
>>> + pc -= info->maxpagesize;
>>> +      else if (symval < pc)
>>> + pc += info->maxpagesize;
>>> +    }
>>> +
>>> +  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_GOT_PC_LO12
>>> + && ELFNN_R_TYPE (rel_lo->r_info) != R_LARCH_TLS_DESC_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)
>>> +      || ((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;
>>> +
>>> +  /* Continue next relax trip.  */
>>> +  *again = true;
>>> +
>>> +  pca = pcaddi | rd;
>>> +  bfd_put (32, abfd, pca, contents + rel_hi->r_offset);
>>> +
>>> +  /* Adjust relocations.  */
>>> +  switch (ELFNN_R_TYPE (rel_hi->r_info))
>>> +    {
>>> +    case R_LARCH_TLS_LD_PC_HI20:
>>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>>> +      R_LARCH_TLS_LD_PCREL20_S2);
>>> +      break;
>>> +    case R_LARCH_TLS_GD_PC_HI20:
>>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>>> +      R_LARCH_TLS_GD_PCREL20_S2);
>>> +      break;
>>> +    case R_LARCH_TLS_DESC_PC_HI20:
>>> +      rel_hi->r_info = ELFNN_R_INFO (ELFNN_R_SYM (rel_hi->r_info),
>>> +      R_LARCH_TLS_DESC_PCREL20_S2);
>>> +      break;
>>> +    default:
>>> +      break;
>>> +    }
>>> +  rel_lo->r_info = ELFNN_R_INFO (0, R_LARCH_NONE);
>>> +
>>> +  loongarch_relax_delete_bytes (abfd, sec, rel_lo->r_offset, 4, info);
>>> +
>>> +  return true;
>>> +}
>>> +
>>> static bool
>>> loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>>       struct bfd_link_info *info,
>>> @@ -4288,15 +4377,23 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>> 
>>>   for (unsigned int i = 0; i < sec->reloc_count; i++)
>>>     {
>>> -      Elf_Internal_Rela *rel = relocs + i;
>>> -      asection *sym_sec;
>>> +      char symtype;
>>>       bfd_vma symval;
>>> -      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>>> -      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
>>> +      asection *sym_sec;
>>>       bool local_got = false;
>>> -      char symtype;
>>> +      Elf_Internal_Rela *rel = relocs + i;
>>>       struct elf_link_hash_entry *h = NULL;
>>> +      unsigned long r_type = ELFNN_R_TYPE (rel->r_info);
>>> +      unsigned long r_symndx = ELFNN_R_SYM (rel->r_info);
>>> 
>>> +      /* Four kind of relocations:
>>> + Normal: symval is the symbol address.
>>> + R_LARCH_ALIGN: symval is the address of the last NOP instruction
>>> + added by this relocation, and then adds 4 more.
>>> + R_LARCH_CALL36: symval is the symbol address for local symbols,
>>> + or the PLT entry address of the symbol. (Todo)
>>> + R_LARCHL_TLS_LD/GD/DESC_PC_HI20: symval is the GOT entry address
>>> + of the symbol.  */
>>>       if (r_symndx < symtab_hdr->sh_info)
>>> {
>>>  Elf_Internal_Sym *sym = (Elf_Internal_Sym *)symtab_hdr->contents
>>> @@ -4304,7 +4401,24 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>>  if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
>>>    continue;
>>> 
>>> -  if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>>> +  if (R_LARCH_TLS_LD_PC_HI20 == r_type
>>> +      || R_LARCH_TLS_GD_PC_HI20 == r_type
>>> +      || R_LARCH_TLS_DESC_PC_HI20 == r_type)
>>> +    {
>>> +      if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
>>> + continue;
>>> +      else
>>> + {
>>> +  sym_sec = htab->elf.sgot;
>>> +  symval = elf_local_got_offsets (abfd)[r_symndx];
>>> +  char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
>>> + r_symndx);
>>> +  if (R_LARCH_TLS_DESC_PC_HI20 == r_type
>>> + && GOT_TLS_GD_BOTH_P (tls_type))
>>> +    symval += 2 * GOT_ENTRY_SIZE;
>>> + }
>>> +    }
>>> +  else if (sym->st_shndx == SHN_UNDEF || R_LARCH_ALIGN == r_type)
>>>    {
>>>      sym_sec = sec;
>>>      symval = rel->r_offset;
>>> @@ -4329,7 +4443,26 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>>  if (h != NULL && h->type == STT_GNU_IFUNC)
>>>    continue;
>>> 
>>> -  if ((h->root.type == bfd_link_hash_defined
>>> +  /* The GOT entry of tls symbols must in current execute file or
>>> +     shared object.  */
>>> +  if (R_LARCH_TLS_LD_PC_HI20 == r_type
>>> +      || R_LARCH_TLS_GD_PC_HI20 == r_type
>>> +      || R_LARCH_TLS_DESC_PC_HI20 == r_type)
>>> +    {
>>> +      if (loongarch_can_relax_tls (info, r_type, h, abfd, r_symndx))
>>> + continue;
>>> +      else
>>> + {
>>> +  sym_sec = htab->elf.sgot;
>>> +  symval = h->got.offset;
>>> +  char tls_type = _bfd_loongarch_elf_tls_type (abfd, h,
>>> + r_symndx);
>>> +  if (R_LARCH_TLS_DESC_PC_HI20 == r_type
>>> + && GOT_TLS_GD_BOTH_P (tls_type))
>>> +    symval += 2 * GOT_ENTRY_SIZE;
>>> + }
>>> +    }
>>> +  else 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)
>>> @@ -4358,7 +4491,7 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>>   if (symtype != STT_SECTION)
>>>     symval += rel->r_addend;
>>> }
>>> -      /* For R_LARCH_ALIGN, symval is sec_addr (sym_sec) + rel->r_offset
>>> +      /* For R_LARCH_ALIGN, symval is sec_addr (sec) + rel->r_offset
>>> + (alingmeng - 4).
>>> If r_symndx is 0, alignmeng-4 is r_addend.
>>> If r_symndx > 0, alignment-4 is 2^(r_addend & 0xff)-4.  */
>>> @@ -4399,6 +4532,25 @@ loongarch_elf_relax_section (bfd *abfd, asection *sec,
>>>    info, again);
>>>    }
>>>  break;
>>> +
>>> + case R_LARCH_TLS_LD_PC_HI20:
>>> +  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>>> +    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>>> +    info, again);
>>> +  break;
>>> +
>>> + case R_LARCH_TLS_GD_PC_HI20:
>>> +  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>>> +    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>>> +    info, again);
>>> +  break;
>>> +
>>> + case R_LARCH_TLS_DESC_PC_HI20:
>>> +  if (0 == info->relax_pass && (i + 4) <= sec->reloc_count)
>>> +    loongarch_relax_tls_ld_gd_desc (abfd, sec, sym_sec, rel, symval,
>>> +    info, again);
>>> +  break;
>>> +
>>> default:
>>>  break;
>>> }
>>> diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
>>> index 30a941a851f..310e6d62dc0 100644
>>> --- a/bfd/elfxx-loongarch.c
>>> +++ b/bfd/elfxx-loongarch.c
>>> @@ -1775,6 +1775,60 @@ static loongarch_reloc_howto_type loongarch_howto_table[] =
>>> BFD_RELOC_LARCH_TLS_DESC_CALL, /* bfd_reloc_code_real_type.  */
>>> NULL, /* adjust_reloc_bits.  */
>>> "desc_call"), /* larch_reloc_type_name.  */
>>> 
>>> +
>>> +  /* For pcaddi, ld_pc_hi20 + ld_pc_lo12 can relax to ld_pcrel20_s2.  */
>>> +  LOONGARCH_HOWTO (R_LARCH_TLS_LD_PCREL20_S2, /* type (124).  */
>>> + 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_TLS_LD_PCREL20_S2", /* name.  */
>>> + false, /* partial_inplace.  */
>>> + 0, /* src_mask.  */
>>> + 0x1ffffe0, /* dst_mask.  */
>>> + true, /* pcrel_offset.  */
>>> + BFD_RELOC_LARCH_TLS_LD_PCREL20_S2, /* bfd_reloc_code_real_type.  */
>>> + reloc_sign_bits, /* adjust_reloc_bits.  */
>>> + "ld_pcrel_20"), /* larch_reloc_type_name.  */
>>> +
>>> +  /* For pcaddi, gd_pc_hi20 + gd_pc_lo12 can relax to gd_pcrel20_s2.  */
>>> +  LOONGARCH_HOWTO (R_LARCH_TLS_GD_PCREL20_S2, /* type (125).  */
>>> + 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_TLS_GD_PCREL20_S2", /* name.  */
>>> + false, /* partial_inplace.  */
>>> + 0, /* src_mask.  */
>>> + 0x1ffffe0, /* dst_mask.  */
>>> + true, /* pcrel_offset.  */
>>> + BFD_RELOC_LARCH_TLS_GD_PCREL20_S2, /* bfd_reloc_code_real_type.  */
>>> + reloc_sign_bits, /* adjust_reloc_bits.  */
>>> + "gd_pcrel_20"), /* larch_reloc_type_name.  */
>>> +
>>> +  /* For pcaddi, desc_pc_hi20 + desc_pc_lo12 can relax to desc_pcrel20_s2.  */
>>> +  LOONGARCH_HOWTO (R_LARCH_TLS_DESC_PCREL20_S2, /* type (126).  */
>>> + 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_TLS_DESC_PCREL20_S2", /* name.  */
>>> + false, /* partial_inplace.  */
>>> + 0, /* src_mask.  */
>>> + 0x1ffffe0, /* dst_mask.  */
>>> + true, /* pcrel_offset.  */
>>> + BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2, /* bfd_reloc_code_real_type.  */
>>> + reloc_sign_bits, /* adjust_reloc_bits.  */
>>> + "desc_pcrel_20"), /* larch_reloc_type_name.  */
>>> };
>>> 
>>> 
>>> 
>>> I think relaxation relocs is a concept internal to binutils and they should not be in the same number range as psABI defined relocs. Some linkers (e.g. mold) doesn’t create new relocs when relaxing and rewrites the instruction right away, therefore these relocs would have no purpose in the psABI.
>>> 
>>> We recently refactored out all the linker-internal relocs to a different range [1]; LoongArch might want to follow suit.
>>> 
>>> [1]: https://sourceware.org/pipermail/binutils/2023-November/130322.html
>>> 
>>> 
>>> However, it should be noted that in handwritten assembly, these relocations can be directly used.
>>> 
>>> 
>>> Sorry for the delay in reply. I’m not sure if there is any use cases to use relaxation-only relocations in assembly source. It’s one of the reasons we did away with this in RISC-V [1].
>>> 
>>> [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/398
>> Agreed. If a relocation type is only used for internal relaxation
>> purposes, it should not be defined in the psABI and there should not
>> be an assembler directive generating it (except .reloc using a
>> hard-coded integer).
> 
> We have considered such a situation. For those familiar with LoongArch assembly, if you want to
> use DESC to access "var" in assembly source, you can directly use pcaddi $a0,%desc_pcrel_20(var)
> instead of pcalau12i $a0,%desc_pc_hi20(var) and addi.d $a0, $a0,% desc_pc_lo12(var).
> The same situation applies to GD/LD.

I see it now. LoongArch's “normal code model” restricts the addressing of program code to a 256MiB address space, so being able to write out the pcrel_20 variant makes perfect sense. Thanks for the clarification.

>> 
>>> reloc_howto_type *
>>> @@ -1783,7 +1837,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
>>>   if(r_type < R_LARCH_count)
>>>     {
>>>       /* For search table fast.  */
>>> 
>>> +      /*
>>>       BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>>> +      */
>>> 
>>> 
>>> 
>>> Was this supposed to be commented out and committed as-is?
>>> 
>>> 
>>> It has been deleted.
>>> 
>>> 
>>> 
>>>       if (loongarch_howto_table[r_type].howto.type == r_type)
>>> return (reloc_howto_type *)&loongarch_howto_table[r_type];
>>> @@ -1802,7 +1858,9 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
>>> reloc_howto_type *
>>> loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
>>> {
>>> +  /*
>>>   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>>> +  */
>>> 
>>>   for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
>>>     if (loongarch_howto_table[i].howto.name
>>> @@ -1821,7 +1879,9 @@ reloc_howto_type *
>>> loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
>>>     bfd_reloc_code_real_type code)
>>> {
>>> +  /*
>>>   BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
>>> +  */
>>> 
>>>   /* Fast search for new reloc types.  */
>>>   if (BFD_RELOC_LARCH_B16 <= code && code < BFD_RELOC_LARCH_RELAX)
>>> diff --git a/bfd/libbfd.h b/bfd/libbfd.h
>>> index 71b03da14d9..8dab44110a6 100644
>>> --- a/bfd/libbfd.h
>>> +++ b/bfd/libbfd.h
>>> @@ -3612,6 +3612,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
>>>   "BFD_RELOC_LARCH_TLS_DESC64_HI12",
>>>   "BFD_RELOC_LARCH_TLS_DESC_LD",
>>>   "BFD_RELOC_LARCH_TLS_DESC_CALL",
>>> +  "BFD_RELOC_LARCH_TLS_LD_PCREL20_S2",
>>> +  "BFD_RELOC_LARCH_TLS_GD_PCREL20_S2",
>>> +  "BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2",
>>>  "@@overflow: BFD_RELOC_UNUSED@@",
>>> };
>>> #endif
>>> diff --git a/bfd/reloc.c b/bfd/reloc.c
>>> index f7fe0c7ffe3..6fd0f1fb547 100644
>>> --- a/bfd/reloc.c
>>> +++ b/bfd/reloc.c
>>> @@ -8324,6 +8324,13 @@ ENUMX
>>> ENUMX
>>>   BFD_RELOC_LARCH_TLS_DESC_CALL
>>> 
>>> +ENUMX
>>> +  BFD_RELOC_LARCH_TLS_LD_PCREL20_S2
>>> +ENUMX
>>> +  BFD_RELOC_LARCH_TLS_GD_PCREL20_S2
>>> +ENUMX
>>> +  BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2
>>> +
>>> ENUMDOC
>>>   LARCH relocations.
>>> 
>>> diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
>>> index 1658025f918..def26daf634 100644
>>> --- a/gas/config/tc-loongarch.c
>>> +++ b/gas/config/tc-loongarch.c
>>> @@ -682,7 +682,7 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
>>>      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_TLS_DESC_CALL)
>>> +      && ip->reloc_info[0].type <= BFD_RELOC_LARCH_TLS_DESC_PCREL20_S2)
>>>    {
>>>      /* As we compact stack-relocs, it is no need for pop operation.
>>> But break out until here in order to check the imm field.
>>> @@ -694,7 +694,11 @@ loongarch_args_parser_can_match_arg_helper (char esc_ch1, char esc_ch2,
>>>    && (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))
>>> + || BFD_RELOC_LARCH_GOT_PC_LO12 == reloc_type
>>> + || BFD_RELOC_LARCH_TLS_LD_PC_HI20 == reloc_type
>>> + || BFD_RELOC_LARCH_TLS_GD_PC_HI20 == reloc_type
>>> + || BFD_RELOC_LARCH_TLS_DESC_PC_HI20 == reloc_type
>>> + || BFD_RELOC_LARCH_TLS_DESC_PC_LO12 == reloc_type))
>>> {
>>>  ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_RELAX;
>>>  ip->reloc_info[ip->reloc_num].value = const_0;
>>> diff --git a/gas/testsuite/gas/loongarch/macro_op.d b/gas/testsuite/gas/loongarch/macro_op.d
>>> index 32860864704..47f8f45c663 100644
>>> --- a/gas/testsuite/gas/loongarch/macro_op.d
>>> +++ b/gas/testsuite/gas/loongarch/macro_op.d
>>> @@ -2,70 +2,72 @@
>>> #objdump: -dr
>>> #skip: loongarch32-*-*
>>> 
>>> 
>>> 
>>> --
>>> 2.43.0


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

* Re: [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC)
  2023-12-22 11:42 [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC) Lulu Cai
                   ` (3 preceding siblings ...)
  2023-12-22 11:42 ` [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation Lulu Cai
@ 2024-01-27  2:54 ` Fangrui Song
       [not found] ` <DS7PR12MB5765A6FBD6297BAEDB57FF6CCB782@DS7PR12MB5765.namprd12.prod.outlook.com>
  5 siblings, 0 replies; 19+ messages in thread
From: Fangrui Song @ 2024-01-27  2:54 UTC (permalink / raw)
  To: Lulu Cai
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

On Fri, Dec 22, 2023 at 3:42 AM Lulu Cai <cailulu@loongson.cn> wrote:
>
> v5 mainly changes the relocation name and adds relocation
> for immediate value field of ld.w/d.
>
> 1. R_LARCH_TLS_DESC_ADD_PC_LO12 -> R_LARCH_TLS_DESC_PC_LO12.
>    R_LARCH_TLS_DESC_LD(113)     -> R_LARCH_TLS_DESC_LD(119)
>
> 2. Added 32 abs test case.
>
> 3. Added R_LARCH_TLS_DESC_LD relocation to the immediate field of
>    the ld.w/d instruction.
>
>    Such as:
>    pcalau12i $r4,%desc_pc_hi20(var)
>    addi.d $r4,$r4,%desc_pc_lo12(var)
>    ld.d $r1,$r4,0                    -> ld.d $r1,$r4,%desc_ld(var)
>    jirl $r1,$r1,%desc_call(var)
>    addi.d $a0,$a0,$tp
>
> Lulu Cai (4):
>   LoongArch: Add new relocs and macro for TLSDESC.
>   LoongArch: Add support for TLSDESC in ld.
>   LoongArch: Add tls transition support.
>   LoongArch: Add testsuit for DESC and tls transition and tls
>     relaxation.
>
> mengqinggang (1):
>   LoongArch: Add support for TLS LD/GD/DESC relaxation
>
>  bfd/bfd-in2.h                                 |  15 +
>  bfd/elfnn-loongarch.c                         | 552 +++++++++++++++++-
>  bfd/elfxx-loongarch.c                         | 270 ++++++++-
>  bfd/libbfd.h                                  |  15 +
>  bfd/reloc.c                                   |  36 ++
>  gas/config/tc-loongarch.c                     |  20 +-
>  gas/testsuite/gas/loongarch/macro_op.d        | 128 ++--
>  gas/testsuite/gas/loongarch/macro_op_32.d     | 120 ++--
>  .../gas/loongarch/macro_op_large_abs.d        | 160 ++---
>  .../gas/loongarch/macro_op_large_pc.d         | 160 ++---
>  gas/testsuite/gas/loongarch/tlsdesc_32.d      |  28 +
>  gas/testsuite/gas/loongarch/tlsdesc_32.s      |  12 +
>  gas/testsuite/gas/loongarch/tlsdesc_32_abs.d  |  26 +
>  gas/testsuite/gas/loongarch/tlsdesc_32_abs.s  |   8 +
>  gas/testsuite/gas/loongarch/tlsdesc_64.d      |  28 +
>  gas/testsuite/gas/loongarch/tlsdesc_64.s      |  12 +
>  .../gas/loongarch/tlsdesc_large_abs.d         |  34 ++
>  .../gas/loongarch/tlsdesc_large_abs.s         |  12 +
>  .../gas/loongarch/tlsdesc_large_pc.d          |  38 ++
>  .../gas/loongarch/tlsdesc_large_pc.s          |  17 +
>  include/elf/loongarch.h                       |  26 +-
>  include/opcode/loongarch.h                    |   6 +
>  ld/testsuite/ld-loongarch-elf/desc-ie.d       |  16 +
>  ld/testsuite/ld-loongarch-elf/desc-ie.s       |  18 +
>  ld/testsuite/ld-loongarch-elf/desc-le.d       |  15 +
>  ld/testsuite/ld-loongarch-elf/desc-le.s       |  14 +
>  ld/testsuite/ld-loongarch-elf/desc-norelax.d  |  16 +
>  ld/testsuite/ld-loongarch-elf/desc-norelax.s  |   5 +
>  ld/testsuite/ld-loongarch-elf/desc-relax.d    |  15 +
>  ld/testsuite/ld-loongarch-elf/desc-relax.s    |   5 +
>  ld/testsuite/ld-loongarch-elf/ie-le.d         |  13 +
>  ld/testsuite/ld-loongarch-elf/ie-le.s         |  11 +
>  .../ld-loongarch-elf/ld-loongarch-elf.exp     |   9 +
>  ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++------
>  ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 ++--
>  ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d   |  56 ++
>  ld/testsuite/ld-loongarch-elf/tlsdesc-dso.s   |  65 +++
>  opcodes/loongarch-opc.c                       |  54 ++
>  38 files changed, 1980 insertions(+), 566 deletions(-)
>  create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32.d
>  create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32.s
>  create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32_abs.d
>  create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32_abs.s
>  create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_64.d
>  create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_64.s
>  create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_abs.d
>  create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_abs.s
>  create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_pc.d
>  create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_pc.s
>  create mode 100644 ld/testsuite/ld-loongarch-elf/desc-ie.d
>  create mode 100644 ld/testsuite/ld-loongarch-elf/desc-ie.s
>  create mode 100644 ld/testsuite/ld-loongarch-elf/desc-le.d
>  create mode 100644 ld/testsuite/ld-loongarch-elf/desc-le.s
>  create mode 100644 ld/testsuite/ld-loongarch-elf/desc-norelax.d
>  create mode 100644 ld/testsuite/ld-loongarch-elf/desc-norelax.s
>  create mode 100644 ld/testsuite/ld-loongarch-elf/desc-relax.d
>  create mode 100644 ld/testsuite/ld-loongarch-elf/desc-relax.s
>  create mode 100644 ld/testsuite/ld-loongarch-elf/ie-le.d
>  create mode 100644 ld/testsuite/ld-loongarch-elf/ie-le.s
>  create mode 100644 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
>  create mode 100644 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.s
>
> --
> 2.43.0
>

Technically you could define R_LARCH_TLS_DESC to be shared by 32-bit
and 64-bit arches, like RELATIVE/IRELATIVE/JUMP_SLOT.
That said, I see that the change has been made.

It seems that la.tls.desc expands to 4 instructions with 2
R_LARCH_RELAX relocations?
I think one R_LARCH_RELAX is sufficient to implement relaxation.

RISC-V has a similar problem and I have suggested
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/421

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

* Re: [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC)
       [not found] ` <DS7PR12MB5765A6FBD6297BAEDB57FF6CCB782@DS7PR12MB5765.namprd12.prod.outlook.com>
@ 2024-01-27  7:26   ` Lulu Cai
  2024-01-27 19:18     ` Fangrui Song
  0 siblings, 1 reply; 19+ messages in thread
From: Lulu Cai @ 2024-01-27  7:26 UTC (permalink / raw)
  To: Fangrui Song
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

On 1/27/24 10:54 AM, Fangrui Song wrote:
> On Fri, Dec 22, 2023 at 3:42 AM Lulu Cai <cailulu@loongson.cn> wrote:
>> v5 mainly changes the relocation name and adds relocation
>> for immediate value field of ld.w/d.
>>
>> 1. R_LARCH_TLS_DESC_ADD_PC_LO12 -> R_LARCH_TLS_DESC_PC_LO12.
>>     R_LARCH_TLS_DESC_LD(113)     -> R_LARCH_TLS_DESC_LD(119)
>>
>> 2. Added 32 abs test case.
>>
>> 3. Added R_LARCH_TLS_DESC_LD relocation to the immediate field of
>>     the ld.w/d instruction.
>>
>>     Such as:
>>     pcalau12i $r4,%desc_pc_hi20(var)
>>     addi.d $r4,$r4,%desc_pc_lo12(var)
>>     ld.d $r1,$r4,0                    -> ld.d $r1,$r4,%desc_ld(var)
>>     jirl $r1,$r1,%desc_call(var)
>>     addi.d $a0,$a0,$tp
>>
>> Lulu Cai (4):
>>    LoongArch: Add new relocs and macro for TLSDESC.
>>    LoongArch: Add support for TLSDESC in ld.
>>    LoongArch: Add tls transition support.
>>    LoongArch: Add testsuit for DESC and tls transition and tls
>>      relaxation.
>>
>> mengqinggang (1):
>>    LoongArch: Add support for TLS LD/GD/DESC relaxation
>>
>>   bfd/bfd-in2.h                                 |  15 +
>>   bfd/elfnn-loongarch.c                         | 552 +++++++++++++++++-
>>   bfd/elfxx-loongarch.c                         | 270 ++++++++-
>>   bfd/libbfd.h                                  |  15 +
>>   bfd/reloc.c                                   |  36 ++
>>   gas/config/tc-loongarch.c                     |  20 +-
>>   gas/testsuite/gas/loongarch/macro_op.d        | 128 ++--
>>   gas/testsuite/gas/loongarch/macro_op_32.d     | 120 ++--
>>   .../gas/loongarch/macro_op_large_abs.d        | 160 ++---
>>   .../gas/loongarch/macro_op_large_pc.d         | 160 ++---
>>   gas/testsuite/gas/loongarch/tlsdesc_32.d      |  28 +
>>   gas/testsuite/gas/loongarch/tlsdesc_32.s      |  12 +
>>   gas/testsuite/gas/loongarch/tlsdesc_32_abs.d  |  26 +
>>   gas/testsuite/gas/loongarch/tlsdesc_32_abs.s  |   8 +
>>   gas/testsuite/gas/loongarch/tlsdesc_64.d      |  28 +
>>   gas/testsuite/gas/loongarch/tlsdesc_64.s      |  12 +
>>   .../gas/loongarch/tlsdesc_large_abs.d         |  34 ++
>>   .../gas/loongarch/tlsdesc_large_abs.s         |  12 +
>>   .../gas/loongarch/tlsdesc_large_pc.d          |  38 ++
>>   .../gas/loongarch/tlsdesc_large_pc.s          |  17 +
>>   include/elf/loongarch.h                       |  26 +-
>>   include/opcode/loongarch.h                    |   6 +
>>   ld/testsuite/ld-loongarch-elf/desc-ie.d       |  16 +
>>   ld/testsuite/ld-loongarch-elf/desc-ie.s       |  18 +
>>   ld/testsuite/ld-loongarch-elf/desc-le.d       |  15 +
>>   ld/testsuite/ld-loongarch-elf/desc-le.s       |  14 +
>>   ld/testsuite/ld-loongarch-elf/desc-norelax.d  |  16 +
>>   ld/testsuite/ld-loongarch-elf/desc-norelax.s  |   5 +
>>   ld/testsuite/ld-loongarch-elf/desc-relax.d    |  15 +
>>   ld/testsuite/ld-loongarch-elf/desc-relax.s    |   5 +
>>   ld/testsuite/ld-loongarch-elf/ie-le.d         |  13 +
>>   ld/testsuite/ld-loongarch-elf/ie-le.s         |  11 +
>>   .../ld-loongarch-elf/ld-loongarch-elf.exp     |   9 +
>>   ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++------
>>   ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 ++--
>>   ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d   |  56 ++
>>   ld/testsuite/ld-loongarch-elf/tlsdesc-dso.s   |  65 +++
>>   opcodes/loongarch-opc.c                       |  54 ++
>>   38 files changed, 1980 insertions(+), 566 deletions(-)
>>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32.d
>>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32.s
>>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32_abs.d
>>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32_abs.s
>>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_64.d
>>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_64.s
>>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_abs.d
>>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_abs.s
>>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_pc.d
>>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_pc.s
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-ie.d
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-ie.s
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-le.d
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-le.s
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-norelax.d
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-norelax.s
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-relax.d
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-relax.s
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/ie-le.d
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/ie-le.s
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
>>   create mode 100644 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.s
>>
>> --
>> 2.43.0
>>
> Technically you could define R_LARCH_TLS_DESC to be shared by 32-bit
> and 64-bit arches, like RELATIVE/IRELATIVE/JUMP_SLOT.
> That said, I see that the change has been made.


Yes that's totally fine. The main reason here is because other TLS types of

dynamic relocation have 32-bit and 64-bit, so DESC is distinguished.​​


> It seems that la.tls.desc expands to 4 instructions with 2
> R_LARCH_RELAX relocations?
> I think one R_LARCH_RELAX is sufficient to implement relaxation.
>
> RISC-V has a similar problem and I have suggested
> https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/421


This is done because the current psABI stipulates that the instruction

to be deleted must be followed by an R_LARCH_RELAX relocation.

In the future, we will try to implement la.tls.desc with four instructions

using only one R_LARCH_RELAX implementation.


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

* Re: [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC)
  2024-01-27  7:26   ` Lulu Cai
@ 2024-01-27 19:18     ` Fangrui Song
  0 siblings, 0 replies; 19+ messages in thread
From: Fangrui Song @ 2024-01-27 19:18 UTC (permalink / raw)
  To: Lulu Cai
  Cc: binutils, xuchenghua, chenglulu, liuzhensong, mengqinggang,
	xry111, i.swmail, maskray, luweining, wanglei, hejinyang

On Fri, Jan 26, 2024 at 11:26 PM Lulu Cai <cailulu@loongson.cn> wrote:
>
> On 1/27/24 10:54 AM, Fangrui Song wrote:
> > On Fri, Dec 22, 2023 at 3:42 AM Lulu Cai <cailulu@loongson.cn> wrote:
> >> v5 mainly changes the relocation name and adds relocation
> >> for immediate value field of ld.w/d.
> >>
> >> 1. R_LARCH_TLS_DESC_ADD_PC_LO12 -> R_LARCH_TLS_DESC_PC_LO12.
> >>     R_LARCH_TLS_DESC_LD(113)     -> R_LARCH_TLS_DESC_LD(119)
> >>
> >> 2. Added 32 abs test case.
> >>
> >> 3. Added R_LARCH_TLS_DESC_LD relocation to the immediate field of
> >>     the ld.w/d instruction.
> >>
> >>     Such as:
> >>     pcalau12i $r4,%desc_pc_hi20(var)
> >>     addi.d $r4,$r4,%desc_pc_lo12(var)
> >>     ld.d $r1,$r4,0                    -> ld.d $r1,$r4,%desc_ld(var)
> >>     jirl $r1,$r1,%desc_call(var)
> >>     addi.d $a0,$a0,$tp
> >>
> >> Lulu Cai (4):
> >>    LoongArch: Add new relocs and macro for TLSDESC.
> >>    LoongArch: Add support for TLSDESC in ld.
> >>    LoongArch: Add tls transition support.
> >>    LoongArch: Add testsuit for DESC and tls transition and tls
> >>      relaxation.
> >>
> >> mengqinggang (1):
> >>    LoongArch: Add support for TLS LD/GD/DESC relaxation
> >>
> >>   bfd/bfd-in2.h                                 |  15 +
> >>   bfd/elfnn-loongarch.c                         | 552 +++++++++++++++++-
> >>   bfd/elfxx-loongarch.c                         | 270 ++++++++-
> >>   bfd/libbfd.h                                  |  15 +
> >>   bfd/reloc.c                                   |  36 ++
> >>   gas/config/tc-loongarch.c                     |  20 +-
> >>   gas/testsuite/gas/loongarch/macro_op.d        | 128 ++--
> >>   gas/testsuite/gas/loongarch/macro_op_32.d     | 120 ++--
> >>   .../gas/loongarch/macro_op_large_abs.d        | 160 ++---
> >>   .../gas/loongarch/macro_op_large_pc.d         | 160 ++---
> >>   gas/testsuite/gas/loongarch/tlsdesc_32.d      |  28 +
> >>   gas/testsuite/gas/loongarch/tlsdesc_32.s      |  12 +
> >>   gas/testsuite/gas/loongarch/tlsdesc_32_abs.d  |  26 +
> >>   gas/testsuite/gas/loongarch/tlsdesc_32_abs.s  |   8 +
> >>   gas/testsuite/gas/loongarch/tlsdesc_64.d      |  28 +
> >>   gas/testsuite/gas/loongarch/tlsdesc_64.s      |  12 +
> >>   .../gas/loongarch/tlsdesc_large_abs.d         |  34 ++
> >>   .../gas/loongarch/tlsdesc_large_abs.s         |  12 +
> >>   .../gas/loongarch/tlsdesc_large_pc.d          |  38 ++
> >>   .../gas/loongarch/tlsdesc_large_pc.s          |  17 +
> >>   include/elf/loongarch.h                       |  26 +-
> >>   include/opcode/loongarch.h                    |   6 +
> >>   ld/testsuite/ld-loongarch-elf/desc-ie.d       |  16 +
> >>   ld/testsuite/ld-loongarch-elf/desc-ie.s       |  18 +
> >>   ld/testsuite/ld-loongarch-elf/desc-le.d       |  15 +
> >>   ld/testsuite/ld-loongarch-elf/desc-le.s       |  14 +
> >>   ld/testsuite/ld-loongarch-elf/desc-norelax.d  |  16 +
> >>   ld/testsuite/ld-loongarch-elf/desc-norelax.s  |   5 +
> >>   ld/testsuite/ld-loongarch-elf/desc-relax.d    |  15 +
> >>   ld/testsuite/ld-loongarch-elf/desc-relax.s    |   5 +
> >>   ld/testsuite/ld-loongarch-elf/ie-le.d         |  13 +
> >>   ld/testsuite/ld-loongarch-elf/ie-le.s         |  11 +
> >>   .../ld-loongarch-elf/ld-loongarch-elf.exp     |   9 +
> >>   ld/testsuite/ld-loongarch-elf/macro_op.d      | 391 +++++++------
> >>   ld/testsuite/ld-loongarch-elf/macro_op_32.d   | 120 ++--
> >>   ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d   |  56 ++
> >>   ld/testsuite/ld-loongarch-elf/tlsdesc-dso.s   |  65 +++
> >>   opcodes/loongarch-opc.c                       |  54 ++
> >>   38 files changed, 1980 insertions(+), 566 deletions(-)
> >>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32.d
> >>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32.s
> >>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32_abs.d
> >>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_32_abs.s
> >>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_64.d
> >>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_64.s
> >>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_abs.d
> >>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_abs.s
> >>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_pc.d
> >>   create mode 100644 gas/testsuite/gas/loongarch/tlsdesc_large_pc.s
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-ie.d
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-ie.s
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-le.d
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-le.s
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-norelax.d
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-norelax.s
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-relax.d
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/desc-relax.s
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/ie-le.d
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/ie-le.s
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.d
> >>   create mode 100644 ld/testsuite/ld-loongarch-elf/tlsdesc-dso.s
> >>
> >> --
> >> 2.43.0
> >>
> > Technically you could define R_LARCH_TLS_DESC to be shared by 32-bit
> > and 64-bit arches, like RELATIVE/IRELATIVE/JUMP_SLOT.
> > That said, I see that the change has been made.
>
>
> Yes that's totally fine. The main reason here is because other TLS types of
>
> dynamic relocation have 32-bit and 64-bit, so DESC is distinguished.
>
>
> > It seems that la.tls.desc expands to 4 instructions with 2
> > R_LARCH_RELAX relocations?
> > I think one R_LARCH_RELAX is sufficient to implement relaxation.
> >
> > RISC-V has a similar problem and I have suggested
> > https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/421
>
>
> This is done because the current psABI stipulates that the instruction
>
> to be deleted must be followed by an R_LARCH_RELAX relocation.
>
> In the future, we will try to implement la.tls.desc with four instructions
>
> using only one R_LARCH_RELAX implementation.

Thanks for the answer. I am looking forward to one fewer R_LARCH_RELAX.

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

end of thread, other threads:[~2024-01-27 19:18 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-22 11:42 [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC) Lulu Cai
2023-12-22 11:42 ` [PATCH v5 1/5] LoongArch: Add new relocs and macro for TLSDESC Lulu Cai
2023-12-22 11:42 ` [PATCH v5 2/5] LoongArch: Add support for TLSDESC in ld Lulu Cai
2023-12-28 14:54   ` Tatsuyuki Ishi
2023-12-29 10:24     ` Lulu Cai
2023-12-22 11:42 ` [PATCH v5 3/5] LoongArch: Add tls transition support Lulu Cai
2023-12-28 14:42   ` Tatsuyuki Ishi
2023-12-29 10:31     ` Lulu Cai
2023-12-22 11:42 ` [PATCH v5 4/5] LoongArch: Add support for TLS LD/GD/DESC relaxation Lulu Cai
2023-12-28 14:38   ` Tatsuyuki Ishi
2023-12-29 10:36     ` Lulu Cai
2023-12-29 10:45     ` Lulu Cai
2024-01-07 23:00       ` Tatsuyuki Ishi
2024-01-08  0:22         ` Fangrui Song
     [not found]         ` <DS7PR12MB5765D250CD96B4F6EF6674BACB6B2@DS7PR12MB5765.namprd12.prod.outlook.com>
2024-01-08  6:00           ` Lulu Cai
2024-01-08  7:59             ` Tatsuyuki Ishi
2024-01-27  2:54 ` [PATCH v5 0/5] Add support for TLS Descriptors (TLSDESC) Fangrui Song
     [not found] ` <DS7PR12MB5765A6FBD6297BAEDB57FF6CCB782@DS7PR12MB5765.namprd12.prod.outlook.com>
2024-01-27  7:26   ` Lulu Cai
2024-01-27 19:18     ` Fangrui Song

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).