LoongArch: Add new relocs and macro for TLSDESC.
authorLulu Cai <cailulu@loongson.cn>
Tue, 31 Oct 2023 08:11:29 +0000 (16:11 +0800)
committerliuzhensong <liuzhensong@loongson.cn>
Mon, 25 Dec 2023 03:46:22 +0000 (11:46 +0800)
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
bfd/elfxx-loongarch.c
bfd/libbfd.h
bfd/reloc.c
gas/config/tc-loongarch.c
include/elf/loongarch.h
opcodes/loongarch-opc.c

index 53c40ec..85251aa 100644 (file)
@@ -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;
index 679b79f..30a941a 100644 (file)
@@ -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 *
index 399b1f6..71b03da 100644 (file)
@@ -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
index 4d3ac4c..f7fe0c7 100644 (file)
@@ -8112,6 +8112,10 @@ ENUMX
 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
   BFD_RELOC_LARCH_MARK_PCREL
@@ -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.
 
index 9b912da..1658025 100644 (file)
@@ -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:
index 34719ee..41e9fe4 100644 (file)
@@ -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.  */
index b47817f..a632373 100644 (file)
@@ -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.  */
 };