[binutils-gdb] LoongArch: Use functions instead of magic numbers.

liu & zhensong liuzhensong@sourceware.org
Sun Mar 20 01:47:50 GMT 2022


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=748594bc07f39fda35aba5f46d6e058b42c9c49d

commit 748594bc07f39fda35aba5f46d6e058b42c9c49d
Author: liuzhensong <liuzhensong@loongson.cn>
Date:   Mon Feb 21 14:13:43 2022 +0800

    LoongArch: Use functions instead of magic numbers.
    
      Replace the magic numbers in gas(tc-loongarch.c) and
      bfd(elfnn-loongarch.c) with the functions defined in
      the howto table(elfxx-loongarch.c).
    
      gas/
        * config/tc-loongarch.c: use functions.
    
      bfd/
        * elfnn-loongarch.c: use functions.
        * elfxx-loongarch.c: define functions.
        * elfxx-loongarch.h

Diff:
---
 bfd/elfnn-loongarch.c     |  121 ++---
 bfd/elfxx-loongarch.c     | 1084 +++++++++++++++++++++++++++------------------
 bfd/elfxx-loongarch.h     |    2 +
 gas/config/tc-loongarch.c |  132 ++----
 4 files changed, 719 insertions(+), 620 deletions(-)

diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c
index 00ebe5daeb2..e7861894c07 100644
--- a/bfd/elfnn-loongarch.c
+++ b/bfd/elfnn-loongarch.c
@@ -1446,7 +1446,6 @@ loongarch_check_offset (const Elf_Internal_Rela *rel,
   return bfd_reloc_ok;
 }
 
-
 #define LARCH_RELOC_PERFORM_3OP(op1, op2, op3)	      \
   ({						      \
     bfd_reloc_status_type ret = loongarch_pop (&op2); \
@@ -1459,50 +1458,21 @@ loongarch_check_offset (const Elf_Internal_Rela *rel,
     ret;					      \
    })
 
-#define LARCH_RELOC_UINT32_BIT_MASK(bitsize) \
-  (~((0x1U << (bitsize)) - 1))
-
 static bfd_reloc_status_type
 loongarch_reloc_rewrite_imm_insn (const Elf_Internal_Rela *rel,
 				  const asection *input_section ATTRIBUTE_UNUSED,
 				  reloc_howto_type *howto, bfd *input_bfd,
-				  bfd_byte *contents, int64_t op,
-				  bool is_signed)
+				  bfd_byte *contents, bfd_vma reloc_val)
 {
-  /* Check op low bits if rightshift != 0, before rightshift  */
-  if (howto->rightshift
-      && (((0x1U << howto->rightshift) - 1) & op))
-    return bfd_reloc_overflow;
-
-  uint32_t imm = (uint32_t)(int32_t)(op >> howto->rightshift);
-
-  if (is_signed)
-    {
-      if (op >= 0)
-	{
-	  if (LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize - 1) & imm)
-	    return bfd_reloc_overflow;
-	}
-      else
-	{
-	  if ((LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize - 1) & imm)
-	      != LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize - 1))
-	    return bfd_reloc_overflow;
-	}
-    }
-  else
-    {
-      if (LARCH_RELOC_UINT32_BIT_MASK (howto->bitsize) & imm)
-	return bfd_reloc_overflow;
-    }
-
   int bits = bfd_get_reloc_size (howto) * 8;
   uint32_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
 
-  imm = imm & ((0x1U << howto->bitsize) - 1);
-  imm <<= howto->bitpos;
-  insn = ((insn & howto->src_mask)
-	  | ((insn & (~(uint32_t) howto->dst_mask)) | imm));
+  if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val))
+    return bfd_reloc_overflow;
+
+  insn = (insn & (uint32_t)howto->src_mask)
+    | ((insn & (~(uint32_t)howto->dst_mask)) | reloc_val);
+
   bfd_put (bits, input_bfd, insn, contents + rel->r_offset);
 
   return bfd_reloc_ok;
@@ -1594,19 +1564,8 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
     case R_LARCH_SOP_POP_32_S_10_16:
     case R_LARCH_SOP_POP_32_S_10_16_S2:
     case R_LARCH_SOP_POP_32_S_5_20:
-      r = loongarch_pop (&opr1);
-      if (r != bfd_reloc_ok)
-	break;
-      r = loongarch_check_offset (rel, input_section);
-      if (r != bfd_reloc_ok)
-	break;
-
-      r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
-					    howto, input_bfd,
-					    contents, opr1, true);
-      break;
-
     case R_LARCH_SOP_POP_32_U_10_12:
+    case R_LARCH_SOP_POP_32_U:
       r = loongarch_pop (&opr1);
       if (r != bfd_reloc_ok)
 	break;
@@ -1616,39 +1575,38 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
 
       r = loongarch_reloc_rewrite_imm_insn (rel, input_section,
 					    howto, input_bfd,
-					    contents, opr1, false);
+					    contents, (bfd_vma)opr1);
       break;
 
     case R_LARCH_SOP_POP_32_S_0_5_10_16_S2:
-      {
-	r = loongarch_pop (&opr1);
-	if (r != bfd_reloc_ok)
-	  break;
-
-	if ((opr1 & 0x3) != 0)
-	  {
-	    r = bfd_reloc_overflow;
+	{
+	  r = loongarch_pop (&opr1);
+	  if (r != bfd_reloc_ok)
 	    break;
-	  }
 
-	uint32_t imm = opr1 >> howto->rightshift;
-	if ((imm & (~0xfffffU)) && ((imm & (~0xfffffU)) != (~0xfffffU)))
-	  {
-	    r = bfd_reloc_overflow;
+	  if ((opr1 & 0x3) != 0)
+	    {
+	      r = bfd_reloc_overflow;
+	      break;
+	    }
+
+	  uint32_t imm = opr1 >> howto->rightshift;
+	  if ((imm & (~0xfffffU)) && ((imm & (~0xfffffU)) != (~0xfffffU)))
+	    {
+	      r = bfd_reloc_overflow;
+	      break;
+	    }
+	  r = loongarch_check_offset (rel, input_section);
+	  if (r != bfd_reloc_ok)
 	    break;
-	  }
 
-	r = loongarch_check_offset (rel, input_section);
-	if (r != bfd_reloc_ok)
+	  insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
+	  insn1 = (insn1 & howto->src_mask)
+	    | ((imm & 0xffffU) << 10)
+	    | ((imm & 0x1f0000U) >> 16);
+	  bfd_put (bits, input_bfd, insn1, contents + rel->r_offset);
 	  break;
-
-	insn1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
-	insn1 = ((insn1 & howto->src_mask)
-		 | ((imm & 0xffffU) << 10)
-		 | ((imm & 0x1f0000U) >> 16));
-	bfd_put (bits, input_bfd, insn1, contents + rel->r_offset);
-	break;
-      }
+	}
 
     case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
       {
@@ -1681,21 +1639,6 @@ perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
 	break;
       }
 
-    case R_LARCH_SOP_POP_32_U:
-      r = loongarch_pop (&opr1);
-      if (r != bfd_reloc_ok)
-	break;
-      if ((uint64_t)opr1 & ~(uint64_t) 0xffffffff)
-	r = bfd_reloc_overflow;
-      if (r != bfd_reloc_ok)
-	break;
-      r = loongarch_check_offset (rel, input_section);
-      if (r != bfd_reloc_ok)
-	break;
-
-      bfd_put (bits, input_bfd, opr1, contents + rel->r_offset);
-      break;
-
     case R_LARCH_TLS_DTPREL32:
     case R_LARCH_32:
     case R_LARCH_TLS_DTPREL64:
diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c
index ab78792b630..6f7c82297c5 100644
--- a/bfd/elfxx-loongarch.c
+++ b/bfd/elfxx-loongarch.c
@@ -29,210 +29,259 @@
 
 #define ALL_ONES (~ (bfd_vma) 0)
 
+typedef struct loongarch_reloc_howto_type_struct
+{
+  /* The first must be reloc_howto_type!  */
+  reloc_howto_type howto;
+  bfd_reloc_code_real_type bfd_type;
+  bool (*adjust_reloc_bits)(reloc_howto_type *, bfd_vma *);
+}loongarch_reloc_howto_type;
+
+#define LOONGARCH_DEFAULT_HOWTO(r_name)					    \
+  { HOWTO (R_LARCH_##r_name, 0, 2, 32, false, 0, complain_overflow_signed,  \
+	bfd_elf_generic_reloc, "R_LARCH_" #r_name, false, 0, ALL_ONES,	    \
+	false), BFD_RELOC_LARCH_##r_name, NULL }
+
+#define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func,  \
+	    name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc)	  \
+  { HOWTO(type, right, size, bits, pcrel, left, ovf, func, name,	  \
+	  inplace, src_mask, dst_mask, pcrel_off), btype, afunc }
+
+#define LOONGARCH_EMPTY_HOWTO(C) \
+  { EMPTY_HOWTO(C), BFD_RELOC_NONE, NULL }
+
+bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *val);
+bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
+					     bfd_vma *fix_val);
+bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
+					  bfd_vma *val);
+
+
 /* This does not include any relocation information, but should be
    good enough for GDB or objdump to read the file.  */
-
-static reloc_howto_type howto_table[] =
+static loongarch_reloc_howto_type loongarch_howto_table[] =
 {
-#define LOONGARCH_HOWTO(r_name)						 \
-  HOWTO (R_LARCH_##r_name, 0, 2, 32, false, 0, complain_overflow_signed, \
-	 bfd_elf_generic_reloc, "R_LARCH_" #r_name, false, 0, 0xffffffff, false)
-
   /* No relocation.  */
-  HOWTO (R_LARCH_NONE,			/* type (0).  */
-	 0,				/* rightshift */
-	 3,				/* size */
-	 0,				/* bitsize */
-	 false,				/* pc_relative */
-	 0,				/* bitpos */
-	 complain_overflow_dont,	/* complain_on_overflow */
-	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_LARCH_NONE",		/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 0,				/* dst_mask */
-	 false),			/* pcrel_offset */
+    LOONGARCH_HOWTO (R_LARCH_NONE,	  /* type (0).  */
+	 0,				  /* rightshift */
+	 3,				  /* size */
+	 0,				  /* bitsize */
+	 false,				  /* pc_relative */
+	 0,				  /* bitpos */
+	 complain_overflow_dont,	  /* complain_on_overflow */
+	 bfd_elf_generic_reloc,		  /* special_function */
+	 "R_LARCH_NONE",		  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 0,				  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_NONE,		  /* bfd_reloc_code_real_type */
+	 NULL),				  /* adjust_reloc_bits */
 
   /* 32 bit relocation.  */
-  HOWTO (R_LARCH_32,			/* type (1).  */
-	 0,				/* rightshift */
-	 2,				/* size */
-	 32,				/* bitsize */
-	 false,				/* pc_relative */
-	 0,				/* bitpos */
-	 complain_overflow_dont,	/* complain_on_overflow */
-	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_LARCH_32",			/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 0xffffffff,			/* dst_mask */
-	 false),			/* pcrel_offset */
+  LOONGARCH_HOWTO (R_LARCH_32,		  /* type (1).  */
+	 0,				  /* rightshift */
+	 2,				  /* size */
+	 32,				  /* bitsize */
+	 false,				  /* pc_relative */
+	 0,				  /* bitpos */
+	 complain_overflow_dont,	  /* complain_on_overflow */
+	 bfd_elf_generic_reloc,		  /* special_function */
+	 "R_LARCH_32",			  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 ALL_ONES,			  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_32,			  /* bfd_reloc_code_real_type */
+	 NULL),				  /* adjust_reloc_bits */
 
   /* 64 bit relocation.  */
-  HOWTO (R_LARCH_64,			/* type (2).  */
-	 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_64",			/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 ALL_ONES,			/* dst_mask */
-	 false),			/* pcrel_offset */
-
-  HOWTO (R_LARCH_RELATIVE,		/* type (3).  */
-	 0,				/* rightshift */
-	 2,				/* size */
-	 32,				/* bitsize */
-	 false,				/* pc_relative */
-	 0,				/* bitpos */
-	 complain_overflow_dont,	/* complain_on_overflow */
-	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_LARCH_RELATIVE",		/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 0xffffffff,			/* dst_mask */
-	 false),			/* pcrel_offset */
-
-  HOWTO (R_LARCH_COPY,			/* type (4).  */
-	 0,				/* rightshift */
-	 0,				/* this one is variable size */
-	 0,				/* bitsize */
-	 false,				/* pc_relative */
-	 0,				/* bitpos */
-	 complain_overflow_bitfield,	/* complain_on_overflow */
-	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_LARCH_COPY",		/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 0,				/* dst_mask */
-	 false),			/* pcrel_offset */
-
-  HOWTO (R_LARCH_JUMP_SLOT,		/* type (5).  */
-	 0,				/* rightshift */
-	 4,				/* size */
-	 64,				/* bitsize */
-	 false,				/* pc_relative */
-	 0,				/* bitpos */
-	 complain_overflow_bitfield,	/* complain_on_overflow */
-	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_LARCH_JUMP_SLOT",		/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 0,				/* dst_mask */
-	 false),			/* pcrel_offset */
+  LOONGARCH_HOWTO (R_LARCH_64,		  /* type (2).  */
+	 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_64",			  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 ALL_ONES,			  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_64,			  /* bfd_reloc_code_real_type */
+	 NULL),				  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_RELATIVE,	  /* type (3).  */
+	 0,				  /* rightshift */
+	 2,				  /* size */
+	 32,				  /* bitsize */
+	 false,				  /* pc_relative */
+	 0,				  /* bitpos */
+	 complain_overflow_dont,	  /* complain_on_overflow */
+	 bfd_elf_generic_reloc,		  /* special_function */
+	 "R_LARCH_RELATIVE",		  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 ALL_ONES,			  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_NONE,		  /* undefined?  */
+	 NULL),				  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_COPY,	  /* type (4).  */
+	 0,				  /* rightshift */
+	 0,				  /* this one is variable size */
+	 0,				  /* bitsize */
+	 false,				  /* pc_relative */
+	 0,				  /* bitpos */
+	 complain_overflow_bitfield,	  /* complain_on_overflow */
+	 bfd_elf_generic_reloc,		  /* special_function */
+	 "R_LARCH_COPY",		  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 0,				  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_NONE,			  /* undefined?  */
+	 NULL),				  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_JUMP_SLOT,	  /* type (5).  */
+	 0,				  /* rightshift */
+	 4,				  /* size */
+	 64,				  /* bitsize */
+	 false,				  /* pc_relative */
+	 0,				  /* bitpos */
+	 complain_overflow_bitfield,	  /* complain_on_overflow */
+	 bfd_elf_generic_reloc,		  /* special_function */
+	 "R_LARCH_JUMP_SLOT",		  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 0,				  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_NONE,			  /* undefined?  */
+	 NULL),				  /* adjust_reloc_bits */
 
   /* Dynamic TLS relocations.  */
-  HOWTO (R_LARCH_TLS_DTPMOD32,		/* type (6).  */
-	 0,				/* rightshift */
-	 2,				/* size */
-	 32,				/* bitsize */
-	 false,				/* pc_relative */
-	 0,				/* bitpos */
-	 complain_overflow_dont,	/* complain_on_overflow */
-	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_LARCH_TLS_DTPMOD32",	/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 0xffffffff,			/* dst_mask */
-	 false),			/* pcrel_offset */
-
-  HOWTO (R_LARCH_TLS_DTPMOD64,		/* type (7).  */
-	 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_DTPMOD64",	/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 ALL_ONES,			/* dst_mask */
-	 false),			/* pcrel_offset */
-
-  HOWTO (R_LARCH_TLS_DTPREL32,		/* type (8). */
-	 0,				/* rightshift */
-	 2,				/* size */
-	 32,				/* bitsize */
-	 false,				/* pc_relative */
-	 0,				/* bitpos */
-	 complain_overflow_dont,	/* complain_on_overflow */
-	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_LARCH_TLS_DTPREL32",	/* name */
-	 true,				/* partial_inplace */
-	 0,				/* src_mask */
-	 0xffffffff,			/* dst_mask */
-	 false),			/* pcrel_offset */
-
-  HOWTO (R_LARCH_TLS_DTPREL64,		/* type (9).  */
-	 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_DTPREL64",	/* name */
-	 true,				/* partial_inplace */
-	 0,				/* src_mask */
-	 ALL_ONES,			/* dst_mask */
-	 false),			/* pcrel_offset */
-
-  HOWTO (R_LARCH_TLS_TPREL32,		/* type (10).  */
-	 0,				/* rightshift */
-	 2,				/* size */
-	 32,				/* bitsize */
-	 false,				/* pc_relative */
-	 0,				/* bitpos */
-	 complain_overflow_dont,	/* complain_on_overflow */
-	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_LARCH_TLS_TPREL32",		/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 0xffffffff,			/* dst_mask */
-	 false),			/* pcrel_offset */
-
-  HOWTO (R_LARCH_TLS_TPREL64,		/* type (11).  */
-	 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_TPREL64",		/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 ALL_ONES,			/* dst_mask */
-	 false),			/* pcrel_offset */
-
-  HOWTO (R_LARCH_IRELATIVE,		/* type (12).  */
-	 0,				/* rightshift */
-	 2,				/* size */
-	 32,				/* bitsize */
-	 false,				/* pc_relative */
-	 0,				/* bitpos */
-	 complain_overflow_dont,	/* complain_on_overflow */
-	 bfd_elf_generic_reloc,		/* special_function */
-	 "R_LARCH_IRELATIVE",		/* name */
-	 false,				/* partial_inplace */
-	 0,				/* src_mask */
-	 0xffffffff,			/* dst_mask */
-	 false),			/* pcrel_offset */
-
-  EMPTY_HOWTO(13),
-  EMPTY_HOWTO(14),
-  EMPTY_HOWTO(15),
-  EMPTY_HOWTO(16),
-  EMPTY_HOWTO(17),
-  EMPTY_HOWTO(18),
-  EMPTY_HOWTO(19),
-
-  HOWTO (R_LARCH_MARK_LA,			/* type (20).  */
+  LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD32,  /* type (6).  */
+	 0,				  /* rightshift */
+	 2,				  /* size */
+	 32,				  /* bitsize */
+	 false,				  /* pc_relative */
+	 0,				  /* bitpos */
+	 complain_overflow_dont,	  /* complain_on_overflow */
+	 bfd_elf_generic_reloc,		  /* special_function */
+	 "R_LARCH_TLS_DTPMOD32",	  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 ALL_ONES,			  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_DTPMOD32,	  /* bfd_reloc_code_real_type */
+	 NULL),				  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_DTPMOD64,  /* type (7).  */
+	 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_DTPMOD64",	  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 ALL_ONES,			  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_DTPMOD64,	  /* bfd_reloc_code_real_type */
+	 NULL),				  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL32,  /* type (8). */
+	 0,				  /* rightshift */
+	 2,				  /* size */
+	 32,				  /* bitsize */
+	 false,				  /* pc_relative */
+	 0,				  /* bitpos */
+	 complain_overflow_dont,	  /* complain_on_overflow */
+	 bfd_elf_generic_reloc,		  /* special_function */
+	 "R_LARCH_TLS_DTPREL32",	  /* name */
+	 true,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 ALL_ONES,			  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_DTPREL32,	  /* bfd_reloc_code_real_type */
+	 NULL),				  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_DTPREL64,  /* type (9).  */
+	 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_DTPREL64",	  /* name */
+	 true,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 ALL_ONES,			  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_DTPREL64,	  /* bfd_reloc_code_real_type */
+	 NULL),				  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_TPREL32,	  /* type (10).  */
+	 0,				  /* rightshift */
+	 2,				  /* size */
+	 32,				  /* bitsize */
+	 false,				  /* pc_relative */
+	 0,				  /* bitpos */
+	 complain_overflow_dont,	  /* complain_on_overflow */
+	 bfd_elf_generic_reloc,		  /* special_function */
+	 "R_LARCH_TLS_TPREL32",		  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 ALL_ONES,			  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_TPREL32,	  /* bfd_reloc_code_real_type */
+	 NULL),				  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_TLS_TPREL64,	  /* type (11).  */
+	 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_TPREL64",		  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 ALL_ONES,			  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_LARCH_TLS_TPREL64,	  /* bfd_reloc_code_real_type */
+	 NULL),				  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_IRELATIVE,	  /* type (12).  */
+	 0,				  /* rightshift */
+	 2,				  /* size */
+	 32,				  /* bitsize */
+	 false,				  /* pc_relative */
+	 0,				  /* bitpos */
+	 complain_overflow_dont,	  /* complain_on_overflow */
+	 bfd_elf_generic_reloc,		  /* special_function */
+	 "R_LARCH_IRELATIVE",		  /* name */
+	 false,				  /* partial_inplace */
+	 0,				  /* src_mask */
+	 ALL_ONES,			  /* dst_mask */
+	 false,				  /* pcrel_offset */
+	 BFD_RELOC_NONE,		  /* undefined?  */
+	 NULL),				  /* adjust_reloc_bits */
+
+  LOONGARCH_EMPTY_HOWTO(13),
+  LOONGARCH_EMPTY_HOWTO(14),
+  LOONGARCH_EMPTY_HOWTO(15),
+  LOONGARCH_EMPTY_HOWTO(16),
+  LOONGARCH_EMPTY_HOWTO(17),
+  LOONGARCH_EMPTY_HOWTO(18),
+  LOONGARCH_EMPTY_HOWTO(19),
+
+  LOONGARCH_HOWTO (R_LARCH_MARK_LA,		/* type (20).  */
 	 0,				   	/* rightshift.  */
 	 3,				   	/* size.  */
 	 0,				  	/* bitsize.  */
@@ -244,9 +293,11 @@ static reloc_howto_type howto_table[] =
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask.  */
 	 0,					/* dst_mask.  */
-	 false),			      	/* pcrel_offset.  */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_MARK_LA,		/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_MARK_PCREL,			/* type (21).  */
+  LOONGARCH_HOWTO (R_LARCH_MARK_PCREL,		/* type (21).  */
 	 0,				   	/* rightshift.  */
 	 3,				   	/* size.  */
 	 0,				  	/* bitsize.  */
@@ -258,9 +309,11 @@ static reloc_howto_type howto_table[] =
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask.  */
 	 0,					/* dst_mask.  */
-	 false),			      	/* pcrel_offset.  */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_MARK_PCREL,		/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_SOP_PUSH_PCREL,	      	/* type (22).  */
+  LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL,	/* type (22).  */
 	 2,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 32,				  	/* bitsize.  */
@@ -270,126 +323,144 @@ static reloc_howto_type howto_table[] =
 	 bfd_elf_generic_reloc,	       		/* special_function.  */
 	 "R_LARCH_SOP_PUSH_PCREL",	    	/* name.  */
 	 false,			       		/* partial_inplace.  */
-	 0x03ffffff,			  	/* src_mask.  */
-	 0x03ffffff,			  	/* dst_mask.  */
-	 false),			      	/* pcrel_offset.  */
+	 0x03ffffff,				/* src_mask.  */
+	 0x03ffffff,				/* dst_mask.  */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_SOP_PUSH_PCREL,	/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
   /* type 23-37.  */
-  LOONGARCH_HOWTO (SOP_PUSH_ABSOLUTE),
-  LOONGARCH_HOWTO (SOP_PUSH_DUP),
-  LOONGARCH_HOWTO (SOP_PUSH_GPREL),
-  LOONGARCH_HOWTO (SOP_PUSH_TLS_TPREL),
-  LOONGARCH_HOWTO (SOP_PUSH_TLS_GOT),
-  LOONGARCH_HOWTO (SOP_PUSH_TLS_GD),
-  LOONGARCH_HOWTO (SOP_PUSH_PLT_PCREL),
-  LOONGARCH_HOWTO (SOP_ASSERT),
-  LOONGARCH_HOWTO (SOP_NOT),
-  LOONGARCH_HOWTO (SOP_SUB),
-  LOONGARCH_HOWTO (SOP_SL),
-  LOONGARCH_HOWTO (SOP_SR),
-  LOONGARCH_HOWTO (SOP_ADD),
-  LOONGARCH_HOWTO (SOP_AND),
-  LOONGARCH_HOWTO (SOP_IF_ELSE),
-
-  HOWTO (R_LARCH_SOP_POP_32_S_10_5,	      	/* type (38).  */
-	 0,				   	/* rightshift.  */
-	 2,				   	/* size.  */
-	 5,				  	/* bitsize.  */
-	 false,					/* pc_relative.  */
-	 10,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_10_5",	    	/* name.  */
-	 false,			       		/* partial_inplace.  */
-	 0,					/* src_mask */
-	 0x7c00,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
-
-  HOWTO (R_LARCH_SOP_POP_32_U_10_12,	      	/* type (39).  */
-	 0,				   	/* rightshift.  */
-	 2,				   	/* size.  */
-	 12,				  	/* bitsize.  */
-	 false,					/* pc_relative.  */
-	 10,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SOP_POP_32_U_10_12",	    	/* name.  */
-	 false,			       		/* partial_inplace.  */
-	 0,					/* src_mask */
-	 0x3ffc00,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
-
-  HOWTO (R_LARCH_SOP_POP_32_S_10_12,	      	/* type (40).  */
-	 0,				   	/* rightshift.  */
-	 2,				   	/* size.  */
-	 12,				  	/* bitsize.  */
-	 false,					/* pc_relative.  */
-	 10,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_10_12",	    	/* name.  */
-	 false,			       		/* partial_inplace.  */
-	 0,					/* src_mask */
-	 0x3ffc00,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
-
-  HOWTO (R_LARCH_SOP_POP_32_S_10_16,	      	/* type (41).  */
-	 0,				   	/* rightshift.  */
-	 2,				   	/* size.  */
-	 16,				  	/* bitsize.  */
-	 false,					/* pc_relative.  */
-	 10,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_10_16",	    	/* name.  */
-	 false,			       		/* partial_inplace.  */
-	 0,					/* src_mask */
-	 0x3fffc00,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
-
-  HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2,	      	/* type (42).  */
-	 2,				   	/* rightshift.  */
-	 2,				   	/* size.  */
-	 16,				  	/* bitsize.  */
-	 false,					/* pc_relative.  */
-	 10,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_10_16_S2",    	/* name.  */
-	 false,			       		/* partial_inplace.  */
-	 0,					/* src_mask */
-	 0x3fffc00,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
-
-  HOWTO (R_LARCH_SOP_POP_32_S_5_20,	      	/* type (43).  */
-	 0,				   	/* rightshift.  */
-	 2,				   	/* size.  */
-	 20,				  	/* bitsize.  */
-	 false,					/* pc_relative.  */
-	 5,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_5_20",    	/* name.  */
-	 false,			       		/* partial_inplace.  */
-	 0,					/* src_mask */
-	 0x1fffe0,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
-
-  HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2,    	/* type (44).  */
-	 2,				   	/* rightshift.  */
-	 2,				   	/* size.  */
-	 21,				  	/* bitsize.  */
-	 false,					/* pc_relative.  */
-	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
-	 bfd_elf_generic_reloc,	       		/* special_function.  */
-	 "R_LARCH_SOP_POP_32_S_0_5_10_16_S2",  	/* name.  */
-	 false,			       		/* partial_inplace.  */
-	 0xfc0003e0,				/* src_mask */
-	 0xfc0003e0,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
-
-  HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2,   	/* type (45).  */
+  LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_ABSOLUTE),
+  LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_DUP),
+  LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_GPREL),
+  LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_TPREL),
+  LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GOT),
+  LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_TLS_GD),
+  LOONGARCH_DEFAULT_HOWTO (SOP_PUSH_PLT_PCREL),
+  LOONGARCH_DEFAULT_HOWTO (SOP_ASSERT),
+  LOONGARCH_DEFAULT_HOWTO (SOP_NOT),
+  LOONGARCH_DEFAULT_HOWTO (SOP_SUB),
+  LOONGARCH_DEFAULT_HOWTO (SOP_SL),
+  LOONGARCH_DEFAULT_HOWTO (SOP_SR),
+  LOONGARCH_DEFAULT_HOWTO (SOP_ADD),
+  LOONGARCH_DEFAULT_HOWTO (SOP_AND),
+  LOONGARCH_DEFAULT_HOWTO (SOP_IF_ELSE),
+
+  LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_5,	  /* type (38).  */
+	 0,				   	  /* rightshift.  */
+	 2,				   	  /* size.  */
+	 5,				  	  /* bitsize.  */
+	 false,					  /* pc_relative.  */
+	 10,				   	  /* bitpos.  */
+	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,	       		  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_10_5",	    	  /* name.  */
+	 false,			       		  /* partial_inplace.  */
+	 0,					  /* src_mask */
+	 0x7c00,				  /* dst_mask */
+	 false,					  /* pcrel_offset */
+	 BFD_RELOC_LARCH_SOP_POP_32_S_10_5,	  /* bfd_reloc_code_real_type */
+	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U_10_12,	  /* type (39).  */
+	 0,				   	  /* rightshift.  */
+	 2,				   	  /* size.  */
+	 12,				  	  /* bitsize.  */
+	 false,					  /* pc_relative.  */
+	 10,				   	  /* bitpos.  */
+	 complain_overflow_unsigned,	    	  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,	       		  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_U_10_12",	    	  /* name.  */
+	 false,			       		  /* partial_inplace.  */
+	 0,					  /* src_mask */
+	 0x3ffc00,				  /* dst_mask */
+	 false,					  /* pcrel_offset */
+	 BFD_RELOC_LARCH_SOP_POP_32_U_10_12,	  /* bfd_reloc_code_real_type */
+	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_12,	  /* type (40).  */
+	 0,				   	  /* rightshift.  */
+	 2,				   	  /* size.  */
+	 12,				  	  /* bitsize.  */
+	 false,					  /* pc_relative.  */
+	 10,				   	  /* bitpos.  */
+	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,	       		  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_10_12",	    	  /* name.  */
+	 false,			       		  /* partial_inplace.  */
+	 0,					  /* src_mask */
+	 0x3ffc00,				  /* dst_mask */
+	 false,					  /* pcrel_offset */
+	 BFD_RELOC_LARCH_SOP_POP_32_S_10_12,	  /* bfd_reloc_code_real_type */
+	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16,	  /* type (41).  */
+	 0,				   	  /* rightshift.  */
+	 2,				   	  /* size.  */
+	 16,				  	  /* bitsize.  */
+	 false,					  /* pc_relative.  */
+	 10,				   	  /* bitpos.  */
+	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,	       		  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_10_16",	    	  /* name.  */
+	 false,			       		  /* partial_inplace.  */
+	 0,					  /* src_mask */
+	 0x3fffc00,				  /* dst_mask */
+	 false,					  /* pcrel_offset */
+	 BFD_RELOC_LARCH_SOP_POP_32_S_10_16,	  /* bfd_reloc_code_real_type */
+	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_10_16_S2, /* type (42).  */
+	 2,					  /* rightshift.  */
+	 2,				   	  /* size.  */
+	 16,				  	  /* bitsize.  */
+	 false,					  /* pc_relative.  */
+	 10,				   	  /* bitpos.  */
+	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,	       		  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_10_16_S2",    	  /* name.  */
+	 false,			       		  /* partial_inplace.  */
+	 0,					  /* src_mask */
+	 0x3fffc00,				  /* dst_mask */
+	 false,					  /* pcrel_offset */
+	 BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2,	  /* bfd_reloc_code_real_type */
+	 loongarch_gen_adjust_reloc_bits),	  /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_5_20,	  /* type (43).  */
+	 0,				   	  /* rightshift.  */
+	 2,				   	  /* size.  */
+	 20,				  	  /* bitsize.  */
+	 false,					  /* pc_relative.  */
+	 5,				   	  /* bitpos.  */
+	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,	       		  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_5_20",    	  /* name.  */
+	 false,			       		  /* partial_inplace.  */
+	 0,					  /* src_mask */
+	 0x1ffffe0,				  /* dst_mask */
+	 false,					  /* pcrel_offset */
+	 BFD_RELOC_LARCH_SOP_POP_32_S_5_20,	  /* bfd_reloc_code_real_type */
+	 loongarch_gen_adjust_reloc_bits),        /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_5_10_16_S2,
+						  /* type (44).  */
+	 2,					  /* rightshift.  */
+	 2,					  /* size.  */
+	 21,				  	  /* bitsize.  */
+	 false,					  /* pc_relative.  */
+	 0,				   	  /* bitpos.  */
+	 complain_overflow_signed,	    	  /* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,	       		  /* special_function.  */
+	 "R_LARCH_SOP_POP_32_S_0_5_10_16_S2",  	  /* name.  */
+	 false,			       		  /* partial_inplace.  */
+	 0xfc0003e0,				  /* src_mask */
+	 0xfc0003e0,				  /* dst_mask */
+	 false,					  /* pcrel_offset */
+	 BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2,
+						  /* bfd_reloc_code_real_type */
+	 loongarch_adjust_reloc_bits_l16_xx5_h5), /* adjust_reloc_bits */
+
+  LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2,	/* type (45).  */
 	 2,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 26,				  	/* bitsize.  */
@@ -401,23 +472,28 @@ static reloc_howto_type howto_table[] =
 	 false,			       		/* partial_inplace.  */
 	 0xfc000000,				/* src_mask */
 	 0xfc000000,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2,
+						/* bfd_reloc_code_real_type */
+	 loongarch_adjust_reloc_bits_l16_h10),	/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_SOP_POP_32_U,	      		/* type (46).  */
+  LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U,	/* type (46).  */
 	 0,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 32,				  	/* bitsize.  */
 	 false,					/* pc_relative.  */
 	 0,				   	/* bitpos.  */
-	 complain_overflow_signed,	    	/* complain_on_overflow.  */
+	 complain_overflow_unsigned,	    	/* complain_on_overflow.  */
 	 bfd_elf_generic_reloc,	       		/* special_function.  */
 	 "R_LARCH_SOP_POP_32_S_U",    		/* name.  */
 	 false,			       		/* partial_inplace.  */
-	 0,					/* src_mask */
-	 0,					/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 0xffffffff00000000,			/* src_mask */
+	 0x00000000ffffffff,			/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_SOP_POP_32_U,		/* bfd_reloc_code_real_type */
+	 loongarch_gen_adjust_reloc_bits),	/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_ADD8,	      			/* type (47).  */
+  LOONGARCH_HOWTO (R_LARCH_ADD8,	      	/* type (47).  */
 	 0,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 8,				  	/* bitsize.  */
@@ -428,10 +504,12 @@ static reloc_howto_type howto_table[] =
 	 "R_LARCH_ADD8",    			/* name.  */
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask */
-	 0xffffffff,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 ALL_ONES,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_ADD8,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_ADD16,	      			/* type (48).  */
+  LOONGARCH_HOWTO (R_LARCH_ADD16,	      	/* type (48).  */
 	 0,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 16,				  	/* bitsize.  */
@@ -442,10 +520,12 @@ static reloc_howto_type howto_table[] =
 	 "R_LARCH_ADD16",    			/* name.  */
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask */
-	 0xffffffff,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 ALL_ONES,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_ADD16,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_ADD24,	      			/* type (49).  */
+  LOONGARCH_HOWTO (R_LARCH_ADD24,	      	/* type (49).  */
 	 0,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 24,				  	/* bitsize.  */
@@ -456,10 +536,12 @@ static reloc_howto_type howto_table[] =
 	 "R_LARCH_ADD24",    			/* name.  */
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask */
-	 0xffffffff,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 ALL_ONES,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_ADD24,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_ADD32,	      			/* type (50).  */
+  LOONGARCH_HOWTO (R_LARCH_ADD32,	      	/* type (50).  */
 	 0,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 32,				  	/* bitsize.  */
@@ -470,10 +552,12 @@ static reloc_howto_type howto_table[] =
 	 "R_LARCH_ADD32",    			/* name.  */
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask */
-	 0xffffffff,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 ALL_ONES,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_ADD32,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_ADD64,	      			/* type (51).  */
+  LOONGARCH_HOWTO (R_LARCH_ADD64,	      	/* type (51).  */
 	 0,				   	/* rightshift.  */
 	 4,				   	/* size.  */
 	 64,				  	/* bitsize.  */
@@ -485,9 +569,11 @@ static reloc_howto_type howto_table[] =
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_ADD64,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_SUB8,	      			/* type (52).  */
+  LOONGARCH_HOWTO (R_LARCH_SUB8,	      	/* type (52).  */
 	 0,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 8,				  	/* bitsize.  */
@@ -498,10 +584,12 @@ static reloc_howto_type howto_table[] =
 	 "R_LARCH_SUB8",    			/* name.  */
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask */
-	 0xffffffff,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 ALL_ONES,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_SUB8,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_SUB16,	      			/* type (53).  */
+  LOONGARCH_HOWTO (R_LARCH_SUB16,	      	/* type (53).  */
 	 0,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 16,				  	/* bitsize.  */
@@ -512,10 +600,12 @@ static reloc_howto_type howto_table[] =
 	 "R_LARCH_SUB16",    			/* name.  */
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask */
-	 0xffffffff,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 ALL_ONES,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_SUB16,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_SUB24,	      			/* type (54).  */
+  LOONGARCH_HOWTO (R_LARCH_SUB24,	      	/* type (54).  */
 	 0,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 24,				  	/* bitsize.  */
@@ -526,10 +616,12 @@ static reloc_howto_type howto_table[] =
 	 "R_LARCH_SUB24",    			/* name.  */
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask */
-	 0xffffffff,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 ALL_ONES,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_SUB24,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_SUB32,	      			/* type (55).  */
+  LOONGARCH_HOWTO (R_LARCH_SUB32,	      	/* type (55).  */
 	 0,				   	/* rightshift.  */
 	 2,				   	/* size.  */
 	 32,				  	/* bitsize.  */
@@ -540,10 +632,12 @@ static reloc_howto_type howto_table[] =
 	 "R_LARCH_SUB32",    			/* name.  */
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask */
-	 0xffffffff,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
+	 ALL_ONES,				/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_SUB32,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-  HOWTO (R_LARCH_SUB64,	      			/* type (56).  */
+  LOONGARCH_HOWTO (R_LARCH_SUB64,	      	/* type (56).  */
 	 0,				   	/* rightshift.  */
 	 4,				   	/* size.  */
 	 64,				  	/* bitsize.  */
@@ -555,79 +649,60 @@ static reloc_howto_type howto_table[] =
 	 false,			       		/* partial_inplace.  */
 	 0,					/* src_mask */
 	 ALL_ONES,				/* dst_mask */
-	 false),			      	/* pcrel_offset.  */
-
-};
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_LARCH_SUB64,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-struct elf_reloc_map
-{
-  bfd_reloc_code_real_type bfd_val;
-  enum elf_loongarch_reloc_type elf_val;
-};
+  LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT,      	/* type (57).  */
+	 0,				   	/* rightshift.  */
+	 0,				   	/* size.  */
+	 0,				  	/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,				   	/* bitpos.  */
+	 complain_overflow_signed,	    	/* complain_on_overflow.  */
+	 bfd_elf_generic_reloc,	       		/* special_function.  */
+	 "R_LARCH_GNU_VTINHERIT",  		/* name.  */
+	 false,			       		/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0,					/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_NONE,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 
-static const struct elf_reloc_map larch_reloc_map[] =
-{
-  { BFD_RELOC_NONE, R_LARCH_NONE },
-  { BFD_RELOC_32, R_LARCH_32 },
-  { BFD_RELOC_64, R_LARCH_64 },
-
-#define LOONGARCH_reloc_map(r_name)		   	\
-  {						  	\
-    BFD_RELOC_LARCH_##r_name, R_LARCH_##r_name		\
-  }
-  LOONGARCH_reloc_map (TLS_DTPMOD32),
-  LOONGARCH_reloc_map (TLS_DTPMOD64),
-  LOONGARCH_reloc_map (TLS_DTPREL32),
-  LOONGARCH_reloc_map (TLS_DTPREL64),
-  LOONGARCH_reloc_map (TLS_TPREL32),
-  LOONGARCH_reloc_map (TLS_TPREL64),
-
-  LOONGARCH_reloc_map (MARK_LA),
-  LOONGARCH_reloc_map (MARK_PCREL),
-  LOONGARCH_reloc_map (SOP_PUSH_PCREL),
-  LOONGARCH_reloc_map (SOP_PUSH_ABSOLUTE),
-  LOONGARCH_reloc_map (SOP_PUSH_DUP),
-  LOONGARCH_reloc_map (SOP_PUSH_GPREL),
-  LOONGARCH_reloc_map (SOP_PUSH_TLS_TPREL),
-  LOONGARCH_reloc_map (SOP_PUSH_TLS_GOT),
-  LOONGARCH_reloc_map (SOP_PUSH_TLS_GD),
-  LOONGARCH_reloc_map (SOP_PUSH_PLT_PCREL),
-  LOONGARCH_reloc_map (SOP_ASSERT),
-  LOONGARCH_reloc_map (SOP_NOT),
-  LOONGARCH_reloc_map (SOP_SUB),
-  LOONGARCH_reloc_map (SOP_SL),
-  LOONGARCH_reloc_map (SOP_SR),
-  LOONGARCH_reloc_map (SOP_ADD),
-  LOONGARCH_reloc_map (SOP_AND),
-  LOONGARCH_reloc_map (SOP_IF_ELSE),
-  LOONGARCH_reloc_map (SOP_POP_32_S_10_5),
-  LOONGARCH_reloc_map (SOP_POP_32_U_10_12),
-  LOONGARCH_reloc_map (SOP_POP_32_S_10_12),
-  LOONGARCH_reloc_map (SOP_POP_32_S_10_16),
-  LOONGARCH_reloc_map (SOP_POP_32_S_10_16_S2),
-  LOONGARCH_reloc_map (SOP_POP_32_S_5_20),
-  LOONGARCH_reloc_map (SOP_POP_32_S_0_5_10_16_S2),
-  LOONGARCH_reloc_map (SOP_POP_32_S_0_10_10_16_S2),
-  LOONGARCH_reloc_map (SOP_POP_32_U),
-  LOONGARCH_reloc_map (ADD8),
-  LOONGARCH_reloc_map (ADD16),
-  LOONGARCH_reloc_map (ADD24),
-  LOONGARCH_reloc_map (ADD32),
-  LOONGARCH_reloc_map (ADD64),
-  LOONGARCH_reloc_map (SUB8),
-  LOONGARCH_reloc_map (SUB16),
-  LOONGARCH_reloc_map (SUB24),
-  LOONGARCH_reloc_map (SUB32),
-  LOONGARCH_reloc_map (SUB64),
+  LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY,      	/* type (58).  */
+	 0,				   	/* rightshift.  */
+	 0,				   	/* size.  */
+	 0,				  	/* bitsize.  */
+	 false,					/* pc_relative.  */
+	 0,				   	/* bitpos.  */
+	 complain_overflow_signed,	    	/* complain_on_overflow.  */
+	 NULL,					/* special_function.  */
+	 "R_LARCH_GNU_VTENTRY",  		/* name.  */
+	 false,			       		/* partial_inplace.  */
+	 0,					/* src_mask */
+	 0,					/* dst_mask */
+	 false,					/* pcrel_offset */
+	 BFD_RELOC_NONE,			/* bfd_reloc_code_real_type */
+	 NULL),					/* adjust_reloc_bits */
 };
 
 reloc_howto_type *
 loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
 {
-  size_t i;
-  for (i = 0; i < ARRAY_SIZE (howto_table); i++)
-    if (howto_table[i].type == r_type)
-      return &howto_table[i];
+  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];
+
+      BFD_ASSERT (loongarch_howto_table[r_type].howto.type == r_type);
+
+      for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
+	if (loongarch_howto_table[i].howto.type == r_type)
+	  return (reloc_howto_type *)&loongarch_howto_table[i];
+    }
 
   (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"),
 			 abfd, r_type);
@@ -636,26 +711,181 @@ loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type)
 }
 
 reloc_howto_type *
-loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
-			     bfd_reloc_code_real_type code)
+loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
 {
-  unsigned int i;
-  for (i = 0; i < ARRAY_SIZE (larch_reloc_map); i++)
-    if (larch_reloc_map[i].bfd_val == code)
-      return loongarch_elf_rtype_to_howto (abfd,
-					   (int) larch_reloc_map[i].elf_val);
+  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
+	&& strcasecmp (loongarch_howto_table[i].howto.name, r_name) == 0)
+      return (reloc_howto_type *)&loongarch_howto_table[i];
+
+  (*_bfd_error_handler) (_("%pB: unsupported relocation type %s"),
+			 abfd, r_name);
+  bfd_set_error (bfd_error_bad_value);
 
   return NULL;
 }
 
+/* Cost so much.  */
 reloc_howto_type *
-loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
+loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+			     bfd_reloc_code_real_type code)
 {
-  unsigned int i;
+  BFD_ASSERT (ARRAY_SIZE (loongarch_howto_table) == R_LARCH_count);
 
-  for (i = 0; i < ARRAY_SIZE (howto_table); i++)
-    if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0)
-      return &howto_table[i];
+  for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
+    if (loongarch_howto_table[i].bfd_type == code)
+      return (reloc_howto_type *)&loongarch_howto_table[i];
+
+  (*_bfd_error_handler) (_("%pB: unsupported bfd relocation type %#x"),
+			 abfd, code);
+  bfd_set_error (bfd_error_bad_value);
 
   return NULL;
 }
+
+#define LARCH_RELOC_BFD_VMA_BIT_MASK(bitsize) \
+  (~((((bfd_vma)0x1) << (bitsize)) - 1))
+
+/* Adjust val to perform insn
+ * BFD_RELOC_LARCH_SOP_POP_32_S_10_5
+ * BFD_RELOC_LARCH_SOP_POP_32_S_10_12
+ * BFD_RELOC_LARCH_SOP_POP_32_U_10_12
+ * BFD_RELOC_LARCH_SOP_POP_32_S_10_16
+ * BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2
+ * BFD_RELOC_LARCH_SOP_POP_32_S_5_20
+ * BFD_RELOC_LARCH_SOP_POP_32_U.
+*/
+
+bool loongarch_gen_adjust_reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
+{
+  bfd_vma val = *fix_val;
+  /* Check val low bits if rightshift != 0, before rightshift  */
+  if (howto->rightshift
+      && (((0x1UL << howto->rightshift) - 1) & val))
+    return false;
+
+  int bitsize = howto->bitsize + howto->rightshift;
+
+  /* Return false if overflow.  */
+  if (howto->complain_on_overflow == complain_overflow_signed)
+    {
+      bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
+      /* If val < 0.  */
+      if (sig_bit)
+	{
+	  if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
+	      != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
+	    return false;
+	}
+      else
+	{
+	  if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
+	    return false;
+	}
+    }
+  else if (howto->complain_on_overflow == complain_overflow_unsigned)
+    {
+      if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
+	return false;
+    }
+  else
+    return false;
+
+  /* Perform insn bits field.  */
+  val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
+  val <<= howto->bitpos;
+
+  *fix_val = val;
+
+  return true;
+}
+
+/* Reloc type R_LARCH_SOP_POP_32_S_0_5_10_16_S2.  */
+bool loongarch_adjust_reloc_bits_l16_xx5_h5 (reloc_howto_type *howto,
+					     bfd_vma *fix_val)
+{
+  bfd_vma val = *fix_val;
+  /* Check val low bits if rightshift != 0, before rightshift  */
+  if (howto->rightshift
+      && (((0x1UL << howto->rightshift) - 1) & val))
+    return false;
+
+  /* Return false if overflow.  */
+  if (howto->complain_on_overflow != complain_overflow_signed)
+    return false;
+
+  int bitsize = howto->bitsize + howto->rightshift;
+  bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
+  /* If val < 0.  */
+  if (sig_bit)
+    {
+      if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
+	  != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
+	return false;
+    }
+  else
+    {
+      if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
+	return false;
+    }
+
+  /* Perform insn bits field.  */
+  val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
+
+  /* Perform insn bits field. 20:16>>16, 15:0<<10 */
+  val = ((val & 0xffff) << 10) | ((val >> 16) & 0x1f);
+
+  *fix_val = val;
+
+  return true;
+}
+
+/* Reloc type R_LARCH_SOP_POP_32_S_0_10_10_16_S2.  */
+bool loongarch_adjust_reloc_bits_l16_h10 (reloc_howto_type *howto,
+					  bfd_vma *fix_val)
+{
+  bfd_vma val = *fix_val;
+  /* Check val low bits if rightshift != 0, before rightshift  */
+  if (howto->rightshift
+      && (((0x1UL << howto->rightshift) - 1) & val))
+    return false;
+
+  /* Return false if overflow.  */
+  if (howto->complain_on_overflow != complain_overflow_signed)
+    return false;
+
+  int bitsize = howto->bitsize + howto->rightshift;
+  bfd_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
+  /* If val < 0.  */
+  if (sig_bit)
+    {
+      if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
+	  != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
+	return false;
+    }
+  else
+    {
+      if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
+	return false;
+    }
+
+  /* Perform insn bits field.  */
+  val = (val & ((0x1U << bitsize) - 1)) >> howto->rightshift;
+
+  /* Perform insn bits field. 25:16>>16, 15:0<<10 */
+  val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff);
+
+  *fix_val = val;
+
+  return true;
+}
+
+bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto,
+				       bfd_vma *fix_val)
+{
+  BFD_ASSERT (((loongarch_reloc_howto_type *)howto)->adjust_reloc_bits);
+  return ((loongarch_reloc_howto_type *)
+	  howto)->adjust_reloc_bits(howto, fix_val);
+}
diff --git a/bfd/elfxx-loongarch.h b/bfd/elfxx-loongarch.h
index 13699beed01..3b5c6361e06 100644
--- a/bfd/elfxx-loongarch.h
+++ b/bfd/elfxx-loongarch.h
@@ -29,3 +29,5 @@ loongarch_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code);
 
 extern reloc_howto_type *
 loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name);
+
+bool loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto, bfd_vma *fix_val);
diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c
index 2fe40adfc85..e1cce22da90 100644
--- a/gas/config/tc-loongarch.c
+++ b/gas/config/tc-loongarch.c
@@ -25,6 +25,7 @@
 #include "elf/loongarch.h"
 #include "opcode/loongarch.h"
 #include "obj-elf.h"
+#include "bfd/elfxx-loongarch.h"
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -1068,13 +1069,29 @@ md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
   return 0;
 }
 
+static void fix_reloc_insn (fixS *fixP, bfd_vma reloc_val, char *buf)
+{
+  reloc_howto_type *howto;
+  insn_t insn;
+  howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+
+  insn = bfd_getl32 (buf);
+
+  if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val))
+    as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
+
+  insn = (insn & (insn_t)howto->src_mask)
+    | ((insn & (~(insn_t)howto->dst_mask)) | reloc_val);
+
+  bfd_putl32 (insn, buf);
+}
+
 void
 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
 {
   static int64_t stack_top;
   static int last_reloc_is_sop_push_pcrel_1 = 0;
   int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1;
-  insn_t insn;
   last_reloc_is_sop_push_pcrel_1 = 0;
 
   char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
@@ -1083,17 +1100,17 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
     case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL:
     case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD:
     case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT:
-      if (fixP->fx_addsy)
-	S_SET_THREAD_LOCAL (fixP->fx_addsy);
-      else
-	as_bad_where (fixP->fx_file, fixP->fx_line,
-		      _("Relocation against a constant"));
-      break;
     case BFD_RELOC_LARCH_SOP_PUSH_PCREL:
     case BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL:
       if (fixP->fx_addsy == NULL)
 	as_bad_where (fixP->fx_file, fixP->fx_line,
 		      _("Relocation against a constant"));
+
+      if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL
+	  || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GD
+	  || fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT)
+	S_SET_THREAD_LOCAL (fixP->fx_addsy);
+
       if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_PCREL)
 	{
 	  last_reloc_is_sop_push_pcrel_1 = 1;
@@ -1106,111 +1123,18 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
       break;
 
     case BFD_RELOC_LARCH_SOP_POP_32_S_10_5:
-      if (!last_reloc_is_sop_push_pcrel)
-	break;
-      if ((stack_top & ~(uint64_t) 0xf) != 0x0
-	  && (stack_top & ~(uint64_t) 0xf) != ~(uint64_t) 0xf)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      insn = bfd_getl32 (buf);
-      insn = (insn & (~(uint32_t) 0x7c00)) | ((stack_top & 0x1f) << 10);
-      bfd_putl32 (insn, buf);
-      break;
-
-    case BFD_RELOC_LARCH_SOP_POP_32_U_10_12:
-      if (!last_reloc_is_sop_push_pcrel)
-	break;
-      if (stack_top & ~(uint64_t) 0xfff)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      insn = bfd_getl32 (buf);
-      insn = (insn & (~(uint32_t) 0x3ffc00)) | ((stack_top & 0xfff) << 10);
-      bfd_putl32 (insn, buf);
-      break;
-
     case BFD_RELOC_LARCH_SOP_POP_32_S_10_12:
-      if (!last_reloc_is_sop_push_pcrel)
-	break;
-      if ((stack_top & ~(uint64_t) 0x7ff) != 0x0
-	  && (stack_top & ~(uint64_t) 0x7ff) != ~(uint64_t) 0x7ff)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      insn = bfd_getl32 (buf);
-      insn = (insn & (~(uint32_t) 0x3ffc00)) | ((stack_top & 0xfff) << 10);
-      bfd_putl32 (insn, buf);
-      break;
-
+    case BFD_RELOC_LARCH_SOP_POP_32_U_10_12:
     case BFD_RELOC_LARCH_SOP_POP_32_S_10_16:
-      if (!last_reloc_is_sop_push_pcrel)
-	break;
-      if ((stack_top & ~(uint64_t) 0x7fff) != 0x0
-	  && (stack_top & ~(uint64_t) 0x7fff) != ~(uint64_t) 0x7fff)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      insn = bfd_getl32 (buf);
-      insn = (insn & 0xfc0003ff) | ((stack_top & 0xffff) << 10);
-      bfd_putl32 (insn, buf);
-      break;
-
     case BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2:
-      if (!last_reloc_is_sop_push_pcrel)
-	break;
-      if ((stack_top & 0x3) != 0)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      stack_top >>= 2;
-      if ((stack_top & ~(uint64_t) 0x7fff) != 0x0
-	  && (stack_top & ~(uint64_t) 0x7fff) != ~(uint64_t) 0x7fff)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      insn = bfd_getl32 (buf);
-      insn = (insn & 0xfc0003ff) | ((stack_top & 0xffff) << 10);
-      bfd_putl32 (insn, buf);
-      break;
-
-    case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2:
-      if (!last_reloc_is_sop_push_pcrel)
-	break;
-      if ((stack_top & 0x3) != 0)
-	break;
-      stack_top >>= 2;
-      if ((stack_top & ~(uint64_t) 0xfffff) != 0x0
-	  && (stack_top & ~(uint64_t) 0xfffff) != ~(uint64_t) 0xfffff)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      insn = bfd_getl32 (buf);
-      insn = ((insn & 0xfc0003e0)
-	      | ((stack_top & 0xffff) << 10)
-	      | ((stack_top & 0x1f0000) >> 16));
-      bfd_putl32 (insn, buf);
-      break;
-
     case BFD_RELOC_LARCH_SOP_POP_32_S_5_20:
-      if (!last_reloc_is_sop_push_pcrel)
-	break;
-      if ((stack_top & ~(uint64_t) 0x7ffff) != 0x0
-	  && (stack_top & ~(uint64_t) 0x7ffff) != ~(uint64_t) 0x7ffff)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      insn = bfd_getl32 (buf);
-      insn = (insn & (~(uint32_t) 0x1ffffe0)) | ((stack_top & 0xfffff) << 5);
-      bfd_putl32 (insn, buf);
-      break;
-
+    case BFD_RELOC_LARCH_SOP_POP_32_U:
+    case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2:
     case BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2:
       if (!last_reloc_is_sop_push_pcrel)
 	break;
-      if ((stack_top & 0x3) != 0)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      stack_top >>= 2;
-      if ((stack_top & ~(uint64_t) 0x1ffffff) != 0x0
-	  && (stack_top & ~(uint64_t) 0x1ffffff) != ~(uint64_t) 0x1ffffff)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      insn = bfd_getl32 (buf);
-      insn = ((insn & 0xfc000000)
-	      | ((stack_top & 0xffff) << 10)
-	      | ((stack_top & 0x3ff0000) >> 16));
-      bfd_putl32 (insn, buf);
-      break;
 
-    case BFD_RELOC_LARCH_SOP_POP_32_U:
-      if (!last_reloc_is_sop_push_pcrel)
-	break;
-      if (stack_top & ~(uint64_t) 0xffffffff)
-	as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow");
-      bfd_putl32 (stack_top, buf);
+      fix_reloc_insn (fixP, (bfd_vma)stack_top, buf);
       break;
 
     case BFD_RELOC_64:


More information about the Binutils-cvs mailing list