This commit will revert the gdb specific changes of longaarch [1][2]. Same as
the previous patch, the longaarch related gdb changes have already been
integrated in gdb v16.2, so no longer needed and should be reverted.
[1]: 35a2472e7a3087 ("Add LoongArch64 framework code support")
[2]: 3f205d1d4af5a1 ("LoongArch64: Fixed link errors when build on
LOONGARCH64 machine")
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
gdb-10.2.patch | 12853 -----------------------------------------------
1 file changed, 12853 deletions(-)
diff --git a/gdb-10.2.patch b/gdb-10.2.patch
index 46e24e8..de59c61 100644
--- a/gdb-10.2.patch
+++ b/gdb-10.2.patch
@@ -14,8 +14,6 @@ tar xvzmf gdb-10.2.tar.gz \
gdb-10.2/gdb/symfile.c \
gdb-10.2/gdb/Makefile.in \
gdb-10.2/gdb/dwarf2/read.c \
- gdb-10.2/gdb/ada-lang.c \
- gdb-10.2/gdb/objfiles.h \
gdb-10.2/bfd/elf-bfd.h \
gdb-10.2/gdb/stack.c \
gdb-10.2/gdb/ui-file.h
@@ -2218,12857 +2216,6 @@ exit 0
for (compunit_symtab *cust : objfile->compunits ())
{
---- gdb-10.2/bfd/Makefile.am.orig
-+++ gdb-10.2/bfd/Makefile.am
-@@ -118,6 +118,7 @@ ALL_MACHINES = \
- cpu-ip2k.lo \
- cpu-iq2000.lo \
- cpu-lm32.lo \
-+ cpu-loongarch.lo \
- cpu-m10200.lo \
- cpu-m10300.lo \
- cpu-m32c.lo \
-@@ -202,6 +203,7 @@ ALL_MACHINES_CFILES = \
- cpu-ip2k.c \
- cpu-iq2000.c \
- cpu-lm32.c \
-+ cpu-loongarch.c \
- cpu-m10200.c \
- cpu-m10300.c \
- cpu-m32c.c \
-@@ -548,6 +550,9 @@ BFD64_BACKENDS = \
- elf64-ia64.lo \
- elf64-ia64-vms.lo \
- elfxx-ia64.lo \
-+ elf32-loongarch.lo \
-+ elf64-loongarch.lo \
-+ elfxx-loongarch.lo \
- elfn32-mips.lo \
- elf64-mips.lo \
- elfxx-mips.lo \
-@@ -601,6 +606,7 @@ BFD64_BACKENDS_CFILES = \
- elfn32-mips.c \
- elfxx-aarch64.c \
- elfxx-ia64.c \
-+ elfxx-loongarch.c \
- elfxx-mips.c \
- elfxx-riscv.c \
- mach-o-aarch64.c \
-@@ -665,6 +671,7 @@ SOURCE_CFILES = \
- BUILD_CFILES = \
- elf32-aarch64.c elf64-aarch64.c \
- elf32-ia64.c elf64-ia64.c \
-+ elf32-loongarch.c elf64-loongarch.c \
- elf32-riscv.c elf64-riscv.c \
- peigen.c pepigen.c pex64igen.c
-
-@@ -686,7 +693,7 @@ SOURCE_HFILES = \
- elf-bfd.h elfcode.h elfcore.h elf-hppa.h elf-linker-x86.h \
- elf-linux-core.h elf-nacl.h elf-s390.h elf-vxworks.h \
- elfxx-aarch64.h elfxx-ia64.h elfxx-mips.h elfxx-riscv.h \
-- elfxx-sparc.h elfxx-tilegx.h elfxx-x86.h \
-+ elfxx-sparc.h elfxx-tilegx.h elfxx-x86.h elfxx-loongarch.h \
- genlink.h go32stub.h \
- libaout.h libbfd.h libcoff.h libecoff.h libhppa.h \
- libpei.h libxcoff.h \
-@@ -842,6 +849,14 @@ elf64-ia64.c : elfnn-ia64.c
- echo "#line 1 \"elfnn-ia64.c\"" > $@
- $(SED) -e s/NN/64/g < $< >> $@
-
-+elf32-loongarch.c : elfnn-loongarch.c
-+ echo "#line 1 \"elfnn-loongarch.c\"" > $@
-+ $(SED) -e s/NN/32/g < $< >> $@
-+
-+elf64-loongarch.c : elfnn-loongarch.c
-+ echo "#line 1 \"elfnn-loongarch.c\"" > $@
-+ $(SED) -e s/NN/64/g < $< >> $@
-+
- elf32-riscv.c : elfnn-riscv.c
- echo "#line 1 \"elfnn-riscv.c\"" > $@
- $(SED) -e s/NN/32/g < $< >> $@
---- gdb-10.2/bfd/Makefile.in.orig
-+++ gdb-10.2/bfd/Makefile.in
-@@ -543,6 +543,7 @@ ALL_MACHINES = \
- cpu-ip2k.lo \
- cpu-iq2000.lo \
- cpu-lm32.lo \
-+ cpu-loongarch.lo \
- cpu-m10200.lo \
- cpu-m10300.lo \
- cpu-m32c.lo \
-@@ -627,6 +628,7 @@ ALL_MACHINES_CFILES = \
- cpu-ip2k.c \
- cpu-iq2000.c \
- cpu-lm32.c \
-+ cpu-loongarch.c \
- cpu-m10200.c \
- cpu-m10300.c \
- cpu-m32c.c \
-@@ -975,6 +977,9 @@ BFD64_BACKENDS = \
- elf64-ia64.lo \
- elf64-ia64-vms.lo \
- elfxx-ia64.lo \
-+ elf32-loongarch.lo \
-+ elf64-loongarch.lo \
-+ elfxx-loongarch.lo \
- elfn32-mips.lo \
- elf64-mips.lo \
- elfxx-mips.lo \
-@@ -1028,6 +1033,7 @@ BFD64_BACKENDS_CFILES = \
- elfn32-mips.c \
- elfxx-aarch64.c \
- elfxx-ia64.c \
-+ elfxx-loongarch.c \
- elfxx-mips.c \
- elfxx-riscv.c \
- mach-o-aarch64.c \
-@@ -1091,6 +1097,7 @@ SOURCE_CFILES = \
- BUILD_CFILES = \
- elf32-aarch64.c elf64-aarch64.c \
- elf32-ia64.c elf64-ia64.c \
-+ elf32-loongarch.c elf64-loongarch.c \
- elf32-riscv.c elf64-riscv.c \
- peigen.c pepigen.c pex64igen.c
-
-@@ -1109,7 +1116,7 @@ SOURCE_HFILES = \
- elf-bfd.h elfcode.h elfcore.h elf-hppa.h elf-linker-x86.h \
- elf-linux-core.h elf-nacl.h elf-s390.h elf-vxworks.h \
- elfxx-aarch64.h elfxx-ia64.h elfxx-mips.h elfxx-riscv.h \
-- elfxx-sparc.h elfxx-tilegx.h elfxx-x86.h \
-+ elfxx-sparc.h elfxx-tilegx.h elfxx-x86.h elfxx-loongarch.h \
- genlink.h go32stub.h \
- libaout.h libbfd.h libcoff.h libecoff.h libhppa.h \
- libpei.h libxcoff.h \
-@@ -1349,6 +1356,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-k1om.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-l1om.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-lm32.Plo(a)am__quote@
-+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-loongarch.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m10200.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m10300.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m32c.Plo(a)am__quote@
-@@ -1442,6 +1450,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-ip2k.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-iq2000.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-lm32.Plo(a)am__quote@
-+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-loongarch.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m32c.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m32r.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m68hc11.Plo(a)am__quote@
-@@ -1492,6 +1501,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-hppa.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ia64-vms.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ia64.Plo(a)am__quote@
-+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-loongarch.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mips.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mmix.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-nfp.Plo(a)am__quote@
-@@ -1506,6 +1516,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfn32-mips.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-aarch64.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-ia64.Plo(a)am__quote@
-+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-loongarch.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-mips.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-riscv.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-sparc.Plo(a)am__quote@
-@@ -1972,6 +1983,14 @@ elf64-ia64.c : elfnn-ia64.c
- echo "#line 1 \"elfnn-ia64.c\"" > $@
- $(SED) -e s/NN/64/g < $< >> $@
-
-+elf32-loongarch.c : elfnn-loongarch.c
-+ echo "#line 1 \"elfnn-loongarch.c\"" > $@
-+ $(SED) -e s/NN/32/g < $< >> $@
-+
-+elf64-loongarch.c : elfnn-loongarch.c
-+ echo "#line 1 \"elfnn-loongarch.c\"" > $@
-+ $(SED) -e s/NN/64/g < $< >> $@
-+
- elf32-riscv.c : elfnn-riscv.c
- echo "#line 1 \"elfnn-riscv.c\"" > $@
- $(SED) -e s/NN/32/g < $< >> $@
---- gdb-10.2/bfd/archures.c.orig
-+++ gdb-10.2/bfd/archures.c
-@@ -555,6 +555,9 @@ DESCRIPTION
- .#define bfd_mach_ck807 6
- .#define bfd_mach_ck810 7
- .#define bfd_mach_ck860 8
-+. bfd_arch_loongarch, {* LoongArch *}
-+.#define bfd_mach_loongarch32 1
-+.#define bfd_mach_loongarch64 2
- . bfd_arch_last
- . };
- */
-@@ -636,6 +639,7 @@ extern const bfd_arch_info_type bfd_iq2000_arch;
- extern const bfd_arch_info_type bfd_k1om_arch;
- extern const bfd_arch_info_type bfd_l1om_arch;
- extern const bfd_arch_info_type bfd_lm32_arch;
-+extern const bfd_arch_info_type bfd_loongarch_arch;
- extern const bfd_arch_info_type bfd_m32c_arch;
- extern const bfd_arch_info_type bfd_m32r_arch;
- extern const bfd_arch_info_type bfd_m68hc11_arch;
-@@ -725,6 +729,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] =
- &bfd_k1om_arch,
- &bfd_l1om_arch,
- &bfd_lm32_arch,
-+ &bfd_loongarch_arch,
- &bfd_m32c_arch,
- &bfd_m32r_arch,
- &bfd_m68hc11_arch,
---- gdb-10.2/bfd/bfd-in2.h.orig
-+++ gdb-10.2/bfd/bfd-in2.h
-@@ -1955,6 +1955,9 @@ enum bfd_architecture
- #define bfd_mach_ck807 6
- #define bfd_mach_ck810 7
- #define bfd_mach_ck860 8
-+ bfd_arch_loongarch, /* LoongArch */
-+#define bfd_mach_loongarch32 1
-+#define bfd_mach_loongarch64 2
- bfd_arch_last
- };
-
-@@ -6273,6 +6276,88 @@ assembler and not (currently) written to any object files. */
-
- /* S12Z relocations. */
- BFD_RELOC_S12Z_OPR,
-+
-+/* LARCH relocations. */
-+ BFD_RELOC_LARCH_TLS_DTPMOD32,
-+ BFD_RELOC_LARCH_TLS_DTPREL32,
-+ BFD_RELOC_LARCH_TLS_DTPMOD64,
-+ BFD_RELOC_LARCH_TLS_DTPREL64,
-+ BFD_RELOC_LARCH_TLS_TPREL32,
-+ BFD_RELOC_LARCH_TLS_TPREL64,
-+ BFD_RELOC_LARCH_MARK_LA,
-+ BFD_RELOC_LARCH_MARK_PCREL,
-+ BFD_RELOC_LARCH_SOP_PUSH_PCREL,
-+ BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE,
-+ BFD_RELOC_LARCH_SOP_PUSH_DUP,
-+ BFD_RELOC_LARCH_SOP_PUSH_GPREL,
-+ BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL,
-+ BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT,
-+ BFD_RELOC_LARCH_SOP_PUSH_TLS_GD,
-+ BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL,
-+ BFD_RELOC_LARCH_SOP_ASSERT,
-+ BFD_RELOC_LARCH_SOP_NOT,
-+ BFD_RELOC_LARCH_SOP_SUB,
-+ BFD_RELOC_LARCH_SOP_SL,
-+ BFD_RELOC_LARCH_SOP_SR,
-+ BFD_RELOC_LARCH_SOP_ADD,
-+ BFD_RELOC_LARCH_SOP_AND,
-+ BFD_RELOC_LARCH_SOP_IF_ELSE,
-+ BFD_RELOC_LARCH_SOP_POP_32_S_10_5,
-+ BFD_RELOC_LARCH_SOP_POP_32_U_10_12,
-+ BFD_RELOC_LARCH_SOP_POP_32_S_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_S_0_5_10_16_S2,
-+ BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2,
-+ BFD_RELOC_LARCH_SOP_POP_32_U,
-+ BFD_RELOC_LARCH_ADD8,
-+ BFD_RELOC_LARCH_ADD16,
-+ BFD_RELOC_LARCH_ADD24,
-+ BFD_RELOC_LARCH_ADD32,
-+ BFD_RELOC_LARCH_ADD64,
-+ BFD_RELOC_LARCH_SUB8,
-+ BFD_RELOC_LARCH_SUB16,
-+ BFD_RELOC_LARCH_SUB24,
-+ BFD_RELOC_LARCH_SUB32,
-+ BFD_RELOC_LARCH_SUB64,
-+ BFD_RELOC_LARCH_B16,
-+ BFD_RELOC_LARCH_B21,
-+ BFD_RELOC_LARCH_B26,
-+ BFD_RELOC_LARCH_ABS_HI20,
-+ BFD_RELOC_LARCH_ABS_LO12,
-+ BFD_RELOC_LARCH_ABS64_LO20,
-+ BFD_RELOC_LARCH_ABS64_HI12,
-+ BFD_RELOC_LARCH_PCALA_HI20,
-+ BFD_RELOC_LARCH_PCALA_LO12,
-+ BFD_RELOC_LARCH_PCALA64_LO20,
-+ BFD_RELOC_LARCH_PCALA64_HI12,
-+ BFD_RELOC_LARCH_GOT_PC_HI20,
-+ BFD_RELOC_LARCH_GOT_PC_LO12,
-+ BFD_RELOC_LARCH_GOT64_PC_LO20,
-+ BFD_RELOC_LARCH_GOT64_PC_HI12,
-+ BFD_RELOC_LARCH_GOT_HI20,
-+ BFD_RELOC_LARCH_GOT_LO12,
-+ BFD_RELOC_LARCH_GOT64_LO20,
-+ BFD_RELOC_LARCH_GOT64_HI12,
-+ BFD_RELOC_LARCH_TLS_LE_HI20,
-+ BFD_RELOC_LARCH_TLS_LE_LO12,
-+ BFD_RELOC_LARCH_TLS_LE64_LO20,
-+ BFD_RELOC_LARCH_TLS_LE64_HI12,
-+ BFD_RELOC_LARCH_TLS_IE_PC_HI20,
-+ BFD_RELOC_LARCH_TLS_IE_PC_LO12,
-+ BFD_RELOC_LARCH_TLS_IE64_PC_LO20,
-+ BFD_RELOC_LARCH_TLS_IE64_PC_HI12,
-+ BFD_RELOC_LARCH_TLS_IE_HI20,
-+ BFD_RELOC_LARCH_TLS_IE_LO12,
-+ BFD_RELOC_LARCH_TLS_IE64_LO20,
-+ BFD_RELOC_LARCH_TLS_IE64_HI12,
-+ BFD_RELOC_LARCH_TLS_LD_PC_HI20,
-+ BFD_RELOC_LARCH_TLS_LD_HI20,
-+ BFD_RELOC_LARCH_TLS_GD_PC_HI20,
-+ BFD_RELOC_LARCH_TLS_GD_HI20,
-+ BFD_RELOC_LARCH_32_PCREL,
-+ BFD_RELOC_LARCH_RELAX,
- BFD_RELOC_UNUSED };
-
- typedef enum bfd_reloc_code_real bfd_reloc_code_real_type;
---- gdb-10.2/bfd/config.bfd.orig
-+++ gdb-10.2/bfd/config.bfd
-@@ -183,6 +183,7 @@ hppa*) targ_archs=bfd_hppa_arch ;;
- i[3-7]86) targ_archs=bfd_i386_arch ;;
- ia16) targ_archs=bfd_i386_arch ;;
- lm32) targ_archs=bfd_lm32_arch ;;
-+loongarch*) targ_archs=bfd_loongarch_arch ;;
- m6811*|m68hc11*) targ_archs="bfd_m68hc11_arch bfd_m68hc12_arch bfd_m9s12x_arch
bfd_m9s12xg_arch" ;;
- m6812*|m68hc12*) targ_archs="bfd_m68hc12_arch bfd_m68hc11_arch bfd_m9s12x_arch
bfd_m9s12xg_arch" ;;
- m68*) targ_archs=bfd_m68k_arch ;;
-@@ -1401,6 +1402,20 @@ case "${targ}" in
- targ_underscore=yes
- ;;
-
-+#ifdef BFD64
-+ loongarch32-*)
-+ targ_defvec=loongarch_elf32_vec
-+ targ_selvecs="loongarch_elf32_vec"
-+ want64=true
-+ ;;
-+
-+ loongarch64-*)
-+ targ_defvec=loongarch_elf64_vec
-+ targ_selvecs="loongarch_elf32_vec loongarch_elf64_vec"
-+ want64=true
-+ ;;
-+#endif
-+
- # END OF targmatch.h
- bpf-*-*)
- echo "*** Configuration $targ is not fully supported." >&2
---- gdb-10.2/bfd/configure.orig
-+++ gdb-10.2/bfd/configure
-@@ -14836,6 +14836,8 @@ do
- l1om_elf64_fbsd_vec) tb="$tb elf64-x86-64.lo elfxx-x86.lo elf-ifunc.lo
elf64.lo $elf"; target_size=64 ;;
- lm32_elf32_vec) tb="$tb elf32-lm32.lo elf32.lo $elf" ;;
- lm32_elf32_fdpic_vec) tb="$tb elf32-lm32.lo elf32.lo $elf" ;;
-+ loongarch_elf32_vec) tb="$tb elf32-loongarch.lo elfxx-loongarch.lo elf32.lo
elf-ifunc.lo $elf" ;;
-+ loongarch_elf64_vec) tb="$tb elf64-loongarch.lo elf64.lo elfxx-loongarch.lo
elf32.lo elf-ifunc.lo $elf"; target_size=64 ;;
- m32c_elf32_vec) tb="$tb elf32-m32c.lo elf32.lo $elf" ;;
- m32r_elf32_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;;
- m32r_elf32_le_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;;
---- gdb-10.2/bfd/configure.ac.orig
-+++ gdb-10.2/bfd/configure.ac
-@@ -542,6 +542,8 @@ do
- l1om_elf64_fbsd_vec) tb="$tb elf64-x86-64.lo elfxx-x86.lo elf-ifunc.lo
elf64.lo $elf"; target_size=64 ;;
- lm32_elf32_vec) tb="$tb elf32-lm32.lo elf32.lo $elf" ;;
- lm32_elf32_fdpic_vec) tb="$tb elf32-lm32.lo elf32.lo $elf" ;;
-+ loongarch_elf32_vec) tb="$tb elf32-loongarch.lo elfxx-loongarch.lo elf32.lo
elf-ifunc.lo $elf" ;;
-+ loongarch_elf64_vec) tb="$tb elf64-loongarch.lo elf64.lo elfxx-loongarch.lo
elf32.lo elf-ifunc.lo $elf"; target_size=64 ;;
- m32c_elf32_vec) tb="$tb elf32-m32c.lo elf32.lo $elf" ;;
- m32r_elf32_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;;
- m32r_elf32_le_vec) tb="$tb elf32-m32r.lo elf32.lo $elf" ;;
---- /dev/null
-+++ gdb-10.2/bfd/cpu-loongarch.c
-@@ -0,0 +1,61 @@
-+/* BFD support for LoongArch.
-+ Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of BFD, the Binary File Descriptor library.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING3. If not,
-+ see <
http://www.gnu.org/licenses/>. */
-+
-+#include "sysdep.h"
-+#include "bfd.h"
-+#include "libbfd.h"
-+
-+static const bfd_arch_info_type bfd_loongarch32_arch =
-+{
-+ 32, /* 32 bits in a word. */
-+ 32, /* 64 bits in an address. */
-+ 8, /* 8 bits in a byte. */
-+ bfd_arch_loongarch, /* Architecture. */
-+ bfd_mach_loongarch32, /* Machine number - 0 for now. */
-+ "loongarch32", /* Architecture name. */
-+ "Loongarch32", /* Printable name. */
-+ 3, /* Section align power. */
-+ TRUE, /* This is the default architecture. */
-+ bfd_default_compatible, /* Architecture comparison function. */
-+ bfd_default_scan, /* String to architecture conversion. */
-+ bfd_arch_default_fill, /* Default fill. */
-+ NULL, /* Next in list. */
-+ 0,
-+};
-+
-+const bfd_arch_info_type bfd_loongarch_arch =
-+{
-+ 32, /* 32 bits in a word. */
-+ 64, /* 64 bits in an address. */
-+ 8, /* 8 bits in a byte. */
-+ bfd_arch_loongarch, /* Architecture. */
-+ /* Machine number of LoongArch64 is larger
-+ * so that LoongArch64 is compatible to LoongArch32. */
-+ bfd_mach_loongarch64,
-+ "loongarch64", /* Architecture name. */
-+ "Loongarch64", /* Printable name. */
-+ 3, /* Section align power. */
-+ TRUE, /* This is the default architecture. */
-+ bfd_default_compatible, /* Architecture comparison function. */
-+ bfd_default_scan, /* String to architecture conversion. */
-+ bfd_arch_default_fill, /* Default fill. */
-+ &bfd_loongarch32_arch, /* Next in list. */
-+ 0,
-+};
---- gdb-10.2/bfd/elf-bfd.h.orig
-+++ gdb-10.2/bfd/elf-bfd.h
-@@ -502,6 +502,7 @@ enum elf_target_id
- I386_ELF_DATA,
- IA64_ELF_DATA,
- LM32_ELF_DATA,
-+ LARCH_ELF_DATA,
- M32R_ELF_DATA,
- M68HC11_ELF_DATA,
- M68K_ELF_DATA,
-@@ -2801,6 +2802,14 @@ extern char *elfcore_write_lwpstatus
- (bfd *, char *, int *, long, int, const void *);
- extern char *elfcore_write_register_note
- (bfd *, char *, int *, const char *, const void *, int);
-+extern char *elfcore_write_loongarch_cpucfg
-+ (bfd *, char *, int *, const void*, int);
-+extern char *elfcore_write_loongarch_lbt
-+ (bfd *, char *, int *, const void*, int);
-+extern char *elfcore_write_loongarch_lsx
-+ (bfd *, char *, int *, const void*, int);
-+extern char *elfcore_write_loongarch_lasx
-+ (bfd *, char *, int *, const void*, int);
-
- /* Internal structure which holds information to be included in the
- PRPSINFO section of Linux core files.
---- gdb-10.2/bfd/elf.c.orig
-+++ gdb-10.2/bfd/elf.c
-@@ -4391,7 +4391,7 @@ get_program_header_size (bfd *abfd, struct bfd_link_info *info)
- {
- /* If we have a loadable interpreter section, we need a
- PT_INTERP segment. In this case, assume we also need a
-- PT_PHDR segment, although that may not be true for all
-+ PT_PHDR segment, although that may not be TRUE for all
- targets. */
- segs += 2;
- }
-@@ -9903,6 +9903,30 @@ elfcore_grok_arc_v2 (bfd *abfd, Elf_Internal_Note *note)
- return elfcore_make_note_pseudosection (abfd, ".reg-arc-v2", note);
- }
-
-+static bfd_boolean
-+elfcore_grok_loongarch_cpucfg (bfd *abfd, Elf_Internal_Note *note)
-+{
-+ return elfcore_make_note_pseudosection (abfd, ".reg-loongarch-cpucfg",
note);
-+}
-+
-+static bfd_boolean
-+elfcore_grok_loongarch_lbt (bfd *abfd, Elf_Internal_Note *note)
-+{
-+ return elfcore_make_note_pseudosection (abfd, ".reg-loongarch-lbt", note);
-+}
-+
-+static bfd_boolean
-+elfcore_grok_loongarch_lsx (bfd *abfd, Elf_Internal_Note *note)
-+{
-+ return elfcore_make_note_pseudosection (abfd, ".reg-loongarch-lsx", note);
-+}
-+
-+static bfd_boolean
-+elfcore_grok_loongarch_lasx (bfd *abfd, Elf_Internal_Note *note)
-+{
-+ return elfcore_make_note_pseudosection (abfd, ".reg-loongarch-lasx", note);
-+}
-+
- #if defined (HAVE_PRPSINFO_T)
- typedef prpsinfo_t elfcore_psinfo_t;
- #if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
-@@ -10560,6 +10584,34 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
- else
- return TRUE;
-
-+ case NT_LARCH_CPUCFG:
-+ if (note->namesz == 6
-+ && strcmp (note->namedata, "LINUX") == 0)
-+ return elfcore_grok_loongarch_cpucfg (abfd, note);
-+ else
-+ return TRUE;
-+
-+ case NT_LARCH_LBT:
-+ if (note->namesz == 6
-+ && strcmp (note->namedata, "LINUX") == 0)
-+ return elfcore_grok_loongarch_lbt (abfd, note);
-+ else
-+ return TRUE;
-+
-+ case NT_LARCH_LSX:
-+ if (note->namesz == 6
-+ && strcmp (note->namedata, "LINUX") == 0)
-+ return elfcore_grok_loongarch_lsx (abfd, note);
-+ else
-+ return TRUE;
-+
-+ case NT_LARCH_LASX:
-+ if (note->namesz == 6
-+ && strcmp (note->namedata, "LINUX") == 0)
-+ return elfcore_grok_loongarch_lasx (abfd, note);
-+ else
-+ return TRUE;
-+
- case NT_PRPSINFO:
- case NT_PSINFO:
- if (bed->elf_backend_grok_psinfo)
-@@ -11941,6 +11993,55 @@ elfcore_write_arc_v2 (bfd *abfd,
- note_name, NT_ARC_V2, arc_v2, size);
- }
-
-+char *
-+elfcore_write_loongarch_cpucfg (bfd *abfd,
-+ char *buf,
-+ int *bufsiz,
-+ const void *loongarch_cpucfg,
-+ int size)
-+{
-+ char *note_name = "LINUX";
-+ return elfcore_write_note (abfd, buf, bufsiz,
-+ note_name, NT_LARCH_CPUCFG,
-+ loongarch_cpucfg, size);
-+}
-+
-+char *
-+elfcore_write_loongarch_lbt (bfd *abfd,
-+ char *buf,
-+ int *bufsiz,
-+ const void *loongarch_lbt,
-+ int size)
-+{
-+ char *note_name = "LINUX";
-+ return elfcore_write_note (abfd, buf, bufsiz,
-+ note_name, NT_LARCH_LBT, loongarch_lbt, size);
-+}
-+
-+char *
-+elfcore_write_loongarch_lsx (bfd *abfd,
-+ char *buf,
-+ int *bufsiz,
-+ const void *loongarch_lsx,
-+ int size)
-+{
-+ char *note_name = "LINUX";
-+ return elfcore_write_note (abfd, buf, bufsiz,
-+ note_name, NT_LARCH_LSX, loongarch_lsx, size);
-+}
-+
-+char *
-+elfcore_write_loongarch_lasx (bfd *abfd,
-+ char *buf,
-+ int *bufsiz,
-+ const void *loongarch_lasx,
-+ int size)
-+{
-+ char *note_name = "LINUX";
-+ return elfcore_write_note (abfd, buf, bufsiz,
-+ note_name, NT_LARCH_LASX, loongarch_lasx, size);
-+}
-+
- char *
- elfcore_write_register_note (bfd *abfd,
- char *buf,
-@@ -12025,6 +12126,15 @@ elfcore_write_register_note (bfd *abfd,
- return elfcore_write_aarch_pauth (abfd, buf, bufsiz, data, size);
- if (strcmp (section, ".reg-arc-v2") == 0)
- return elfcore_write_arc_v2 (abfd, buf, bufsiz, data, size);
-+ if (strcmp (section, ".reg-loongarch-cpucfg") == 0)
-+ return elfcore_write_loongarch_cpucfg (abfd, buf, bufsiz, data, size);
-+ if (strcmp (section, ".reg-loongarch-lbt") == 0)
-+ return elfcore_write_loongarch_lbt (abfd, buf, bufsiz, data, size);
-+ if (strcmp (section, ".reg-loongarch-lsx") == 0)
-+ return elfcore_write_loongarch_lsx (abfd, buf, bufsiz, data, size);
-+ if (strcmp (section, ".reg-loongarch-lasx") == 0)
-+ return elfcore_write_loongarch_lasx (abfd, buf, bufsiz, data, size);
-+
- return NULL;
- }
-
-@@ -12491,7 +12601,7 @@ _bfd_elf_final_write_processing (bfd *abfd)
-
- /* Return TRUE for ELF symbol types that represent functions.
- This is the default version of this function, which is sufficient for
-- most targets. It returns true if TYPE is STT_FUNC or STT_GNU_IFUNC. */
-+ most targets. It returns TRUE if TYPE is STT_FUNC or STT_GNU_IFUNC. */
-
- bfd_boolean
- _bfd_elf_is_function_type (unsigned int type)
---- /dev/null
-+++ gdb-10.2/bfd/elfnn-loongarch.c
-@@ -0,0 +1,4128 @@
-+/* LoongArch-specific support for NN-bit ELF.
-+ Copyright (C) 2021-2022 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of BFD, the Binary File Descriptor library.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING3. If not,
-+ see <
http://www.gnu.org/licenses/>. */
-+
-+#include "ansidecl.h"
-+#include "sysdep.h"
-+#include "bfd.h"
-+#include "libbfd.h"
-+#define ARCH_SIZE NN
-+#include "elf-bfd.h"
-+#include "objalloc.h"
-+#include "elf/loongarch.h"
-+#include "elfxx-loongarch.h"
-+
-+static bfd_boolean
-+loongarch_info_to_howto_rela (bfd *abfd, arelent *cache_ptr,
-+ Elf_Internal_Rela *dst)
-+{
-+ cache_ptr->howto = loongarch_elf_rtype_to_howto (abfd,
-+ ELFNN_R_TYPE (dst->r_info));
-+ return cache_ptr->howto != NULL;
-+}
-+
-+/* LoongArch ELF linker hash entry. */
-+struct loongarch_elf_link_hash_entry
-+{
-+ struct elf_link_hash_entry elf;
-+
-+#define GOT_UNKNOWN 0
-+#define GOT_NORMAL 1
-+#define GOT_TLS_GD 2
-+#define GOT_TLS_IE 4
-+#define GOT_TLS_LE 8
-+ char tls_type;
-+};
-+
-+#define loongarch_elf_hash_entry(ent) \
-+ ((struct loongarch_elf_link_hash_entry *) (ent))
-+
-+struct _bfd_loongarch_elf_obj_tdata
-+{
-+ struct elf_obj_tdata root;
-+
-+ /* The tls_type for each local got entry. */
-+ char *local_got_tls_type;
-+};
-+
-+#define _bfd_loongarch_elf_tdata(abfd) \
-+ ((struct _bfd_loongarch_elf_obj_tdata *) (abfd)->tdata.any)
-+
-+#define _bfd_loongarch_elf_local_got_tls_type(abfd) \
-+ (_bfd_loongarch_elf_tdata (abfd)->local_got_tls_type)
-+
-+#define _bfd_loongarch_elf_tls_type(abfd, h, symndx) \
-+ (*((h) != NULL \
-+ ? &loongarch_elf_hash_entry (h)->tls_type \
-+ : &_bfd_loongarch_elf_local_got_tls_type (abfd)[symndx]))
-+
-+#define is_loongarch_elf(bfd) \
-+ (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
-+ && elf_tdata (bfd) != NULL \
-+ && elf_object_id (bfd) == LARCH_ELF_DATA)
-+
-+struct loongarch_elf_link_hash_table
-+{
-+ struct elf_link_hash_table elf;
-+
-+ /* Short-cuts to get to dynamic linker sections. */
-+ asection *sdyntdata;
-+
-+ /* Small local sym to section mapping cache. */
-+ struct sym_cache sym_cache;
-+
-+ /* Used by local STT_GNU_IFUNC symbols. */
-+ htab_t loc_hash_table;
-+ void *loc_hash_memory;
-+
-+ /* The max alignment of output sections. */
-+ bfd_vma max_alignment;
-+};
-+
-+/* Get the LoongArch ELF linker hash table from a link_info structure. */
-+#define loongarch_elf_hash_table(p) \
-+ (elf_hash_table_id (elf_hash_table (p)) == LARCH_ELF_DATA \
-+ ? ((struct loongarch_elf_link_hash_table *) ((p)->hash)) \
-+ : NULL)
-+
-+#define MINUS_ONE ((bfd_vma) 0 - 1)
-+
-+#define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
-+
-+#define LARCH_ELF_LOG_WORD_BYTES (ARCH_SIZE == 32 ? 2 : 3)
-+#define LARCH_ELF_WORD_BYTES (1 << LARCH_ELF_LOG_WORD_BYTES)
-+
-+#define PLT_HEADER_INSNS 8
-+#define PLT_HEADER_SIZE (PLT_HEADER_INSNS * 4)
-+
-+#define PLT_ENTRY_INSNS 4
-+#define PLT_ENTRY_SIZE (PLT_ENTRY_INSNS * 4)
-+
-+#define GOT_ENTRY_SIZE (LARCH_ELF_WORD_BYTES)
-+
-+#define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2)
-+
-+#define elf_backend_want_got_plt 1
-+
-+#define elf_backend_plt_readonly 1
-+
-+#define elf_backend_want_plt_sym 1
-+#define elf_backend_plt_alignment 4
-+#define elf_backend_can_gc_sections 1
-+#define elf_backend_can_refcount 1
-+#define elf_backend_want_got_sym 1
-+
-+#define elf_backend_got_header_size (GOT_ENTRY_SIZE * 1)
-+
-+#define elf_backend_want_dynrelro 1
-+#define elf_backend_rela_normal 1
-+#define elf_backend_default_execstack 0
-+
-+/* Generate a PLT header. */
-+
-+static bfd_boolean
-+loongarch_make_plt_header (bfd_vma got_plt_addr, bfd_vma plt_header_addr,
-+ uint32_t *entry)
-+{
-+ bfd_vma pcrel = got_plt_addr - plt_header_addr;
-+ bfd_vma hi, lo;
-+
-+ if (pcrel + 0x80000800 > 0xffffffff)
-+ {
-+ _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t)
pcrel);
-+ bfd_set_error (bfd_error_bad_value);
-+ return FALSE;
-+ }
-+ hi = ((pcrel + 0x800) >> 12) & 0xfffff;
-+ lo = pcrel & 0xfff;
-+
-+ /* pcaddu12i $t2, %hi(%pcrel(.got.plt))
-+ sub.[wd] $t1, $t1, $t3
-+ ld.[wd] $t3, $t2, %lo(%pcrel(.got.plt)) # _dl_runtime_resolve
-+ addi.[wd] $t1, $t1, -(PLT_HEADER_SIZE + 12)
-+ addi.[wd] $t0, $t2, %lo(%pcrel(.got.plt))
-+ srli.[wd] $t1, $t1, log2(16 / GOT_ENTRY_SIZE)
-+ ld.[wd] $t0, $t0, GOT_ENTRY_SIZE
-+ jirl $r0, $t3, 0 */
-+
-+ if (GOT_ENTRY_SIZE == 8)
-+ {
-+ entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
-+ entry[1] = 0x0011bdad;
-+ entry[2] = 0x28c001cf | (lo & 0xfff) << 10;
-+ entry[3] = 0x02c001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
-+ entry[4] = 0x02c001cc | (lo & 0xfff) << 10;
-+ entry[5] = 0x004501ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
-+ entry[6] = 0x28c0018c | GOT_ENTRY_SIZE << 10;
-+ entry[7] = 0x4c0001e0;
-+ }
-+ else
-+ {
-+ entry[0] = 0x1c00000e | (hi & 0xfffff) << 5;
-+ entry[1] = 0x00113dad;
-+ entry[2] = 0x288001cf | (lo & 0xfff) << 10;
-+ entry[3] = 0x028001ad | ((-(PLT_HEADER_SIZE + 12)) & 0xfff) << 10;
-+ entry[4] = 0x028001cc | (lo & 0xfff) << 10;
-+ entry[5] = 0x004481ad | (4 - LARCH_ELF_LOG_WORD_BYTES) << 10;
-+ entry[6] = 0x2880018c | GOT_ENTRY_SIZE << 10;
-+ entry[7] = 0x4c0001e0;
-+ }
-+ return TRUE;
-+}
-+
-+/* Generate a PLT entry. */
-+
-+static bfd_boolean
-+loongarch_make_plt_entry (bfd_vma got_plt_entry_addr, bfd_vma plt_entry_addr,
-+ uint32_t *entry)
-+{
-+ bfd_vma pcrel = got_plt_entry_addr - plt_entry_addr;
-+ bfd_vma hi, lo;
-+
-+ if (pcrel + 0x80000800 > 0xffffffff)
-+ {
-+ _bfd_error_handler (_("%#" PRIx64 " invaild imm"), (uint64_t)
pcrel);
-+ bfd_set_error (bfd_error_bad_value);
-+ return FALSE;
-+ }
-+ hi = ((pcrel + 0x800) >> 12) & 0xfffff;
-+ lo = pcrel & 0xfff;
-+
-+ entry[0] = 0x1c00000f | (hi & 0xfffff) << 5;
-+ entry[1] = ((GOT_ENTRY_SIZE == 8 ? 0x28c001ef : 0x288001ef)
-+ | (lo & 0xfff) << 10);
-+ entry[2] = 0x4c0001ed; /* jirl $r13, $15, 0 */
-+ entry[3] = 0x03400000; /* nop */
-+
-+ return TRUE;
-+}
-+
-+/* Create an entry in an LoongArch ELF linker hash table. */
-+
-+static struct bfd_hash_entry *
-+link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_hash_table *table,
-+ const char *string)
-+{
-+ struct loongarch_elf_link_hash_entry *eh;
-+
-+ /* Allocate the structure if it has not already been allocated by a
-+ subclass. */
-+ if (entry == NULL)
-+ {
-+ entry = bfd_hash_allocate (table, sizeof (*eh));
-+ if (entry == NULL)
-+ return entry;
-+ }
-+
-+ /* Call the allocation method of the superclass. */
-+ entry = _bfd_elf_link_hash_newfunc (entry, table, string);
-+ if (entry != NULL)
-+ {
-+ eh = (struct loongarch_elf_link_hash_entry *) entry;
-+ eh->tls_type = GOT_UNKNOWN;
-+ }
-+
-+ return entry;
-+}
-+
-+/* Compute a hash of a local hash entry. We use elf_link_hash_entry
-+ for local symbol so that we can handle local STT_GNU_IFUNC symbols
-+ as global symbol. We reuse indx and dynstr_index for local symbol
-+ hash since they aren't used by global symbols in this backend. */
-+
-+static hashval_t
-+elfNN_loongarch_local_htab_hash (const void *ptr)
-+{
-+ struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) ptr;
-+ return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index);
-+}
-+
-+/* Compare local hash entries. */
-+
-+static int
-+elfNN_loongarch_local_htab_eq (const void *ptr1, const void *ptr2)
-+{
-+ struct elf_link_hash_entry *h1 = (struct elf_link_hash_entry *) ptr1;
-+ struct elf_link_hash_entry *h2 = (struct elf_link_hash_entry *) ptr2;
-+
-+ return h1->indx == h2->indx && h1->dynstr_index ==
h2->dynstr_index;
-+}
-+
-+/* Find and/or create a hash entry for local symbol. */
-+static struct elf_link_hash_entry *
-+elfNN_loongarch_get_local_sym_hash (struct loongarch_elf_link_hash_table *htab,
-+ bfd *abfd, const Elf_Internal_Rela *rel,
-+ bfd_boolean create)
-+{
-+ struct loongarch_elf_link_hash_entry e, *ret;
-+ asection *sec = abfd->sections;
-+ hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id, ELFNN_R_SYM (rel->r_info));
-+ void **slot;
-+
-+ e.elf.indx = sec->id;
-+ e.elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
-+ slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
-+ create ? INSERT : NO_INSERT);
-+
-+ if (!slot)
-+ return NULL;
-+
-+ if (*slot)
-+ {
-+ ret = (struct loongarch_elf_link_hash_entry *) *slot;
-+ return &ret->elf;
-+ }
-+
-+ ret = ((struct loongarch_elf_link_hash_entry *)
-+ objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
-+ sizeof (struct loongarch_elf_link_hash_entry)));
-+ if (ret)
-+ {
-+ memset (ret, 0, sizeof (*ret));
-+ ret->elf.indx = sec->id;
-+ ret->elf.pointer_equality_needed = 0;
-+ ret->elf.dynstr_index = ELFNN_R_SYM (rel->r_info);
-+ ret->elf.dynindx = -1;
-+ ret->elf.needs_plt = 0;
-+ ret->elf.plt.refcount = -1;
-+ ret->elf.got.refcount = -1;
-+ ret->elf.def_dynamic = 0;
-+ ret->elf.def_regular = 1;
-+ ret->elf.ref_dynamic = 0; /* This should be always 0 for local. */
-+ ret->elf.ref_regular = 0;
-+ ret->elf.forced_local = 1;
-+ ret->elf.root.type = bfd_link_hash_defined;
-+ *slot = ret;
-+ }
-+ return &ret->elf;
-+}
-+
-+/* Destroy an LoongArch elf linker hash table. */
-+
-+static void
-+elfNN_loongarch_link_hash_table_free (bfd *obfd)
-+{
-+ struct loongarch_elf_link_hash_table *ret;
-+ ret = (struct loongarch_elf_link_hash_table *) obfd->link.hash;
-+
-+ if (ret->loc_hash_table)
-+ htab_delete (ret->loc_hash_table);
-+ if (ret->loc_hash_memory)
-+ objalloc_free ((struct objalloc *) ret->loc_hash_memory);
-+
-+ _bfd_elf_link_hash_table_free (obfd);
-+}
-+
-+/* Create a LoongArch ELF linker hash table. */
-+
-+static struct bfd_link_hash_table *
-+loongarch_elf_link_hash_table_create (bfd *abfd)
-+{
-+ struct loongarch_elf_link_hash_table *ret;
-+ bfd_size_type amt = sizeof (struct loongarch_elf_link_hash_table);
-+
-+ ret = (struct loongarch_elf_link_hash_table *) bfd_zmalloc (amt);
-+ if (ret == NULL)
-+ return NULL;
-+
-+ if (!_bfd_elf_link_hash_table_init
-+ (&ret->elf, abfd, link_hash_newfunc,
-+ sizeof (struct loongarch_elf_link_hash_entry), LARCH_ELF_DATA))
-+ {
-+ free (ret);
-+ return NULL;
-+ }
-+
-+ ret->max_alignment = MINUS_ONE;
-+
-+ ret->loc_hash_table = htab_try_create (1024, elfNN_loongarch_local_htab_hash,
-+ elfNN_loongarch_local_htab_eq, NULL);
-+ ret->loc_hash_memory = objalloc_create ();
-+ if (!ret->loc_hash_table || !ret->loc_hash_memory)
-+ {
-+ elfNN_loongarch_link_hash_table_free (abfd);
-+ return NULL;
-+ }
-+ ret->elf.root.hash_table_free = elfNN_loongarch_link_hash_table_free;
-+
-+ return &ret->elf.root;
-+}
-+
-+/* Merge backend specific data from an object file to the output
-+ object file when linking. */
-+
-+static bfd_boolean
-+elfNN_loongarch_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
-+{
-+ bfd *obfd = info->output_bfd;
-+ flagword in_flags = elf_elfheader (ibfd)->e_flags;
-+ flagword out_flags = elf_elfheader (obfd)->e_flags;
-+
-+ if (!is_loongarch_elf (ibfd) || !is_loongarch_elf (obfd))
-+ return TRUE;
-+
-+ if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0)
-+ {
-+ _bfd_error_handler (_("%pB: ABI is incompatible with that of "
-+ "the selected emulation:\n"
-+ " target emulation `%s' does not match `%s'"),
-+ ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
-+ return FALSE;
-+ }
-+
-+ if (!_bfd_elf_merge_object_attributes (ibfd, info))
-+ return FALSE;
-+
-+ /* If the input BFD is not a dynamic object and it does not contain any
-+ non-data sections, do not account its ABI. For example, various
-+ packages produces such data-only relocatable objects with
-+ `ld -r -b binary` or `objcopy`, and these objects have zero e_flags.
-+ But they are compatible with all ABIs. */
-+ if (!(ibfd->flags & DYNAMIC))
-+ {
-+ asection *sec;
-+ bfd_boolean have_code_sections = FALSE;
-+ for (sec = ibfd->sections; sec != NULL; sec = sec->next)
-+ if ((bfd_section_flags (sec)
-+ & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
-+ == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS))
-+ {
-+ have_code_sections = TRUE;
-+ break;
-+ }
-+ if (!have_code_sections)
-+ return TRUE;
-+ }
-+
-+ if (!elf_flags_init (obfd))
-+ {
-+ elf_flags_init (obfd) = TRUE;
-+ elf_elfheader (obfd)->e_flags = in_flags;
-+ return TRUE;
-+ }
-+
-+ /* Disallow linking different ABIs. */
-+ if (EF_LOONGARCH_ABI(out_flags ^ in_flags) & EF_LOONGARCH_ABI_MASK)
-+ {
-+ _bfd_error_handler (_("%pB: can't link different ABI object."),
ibfd);
-+ goto fail;
-+ }
-+
-+ return TRUE;
-+
-+ fail:
-+ bfd_set_error (bfd_error_bad_value);
-+ return FALSE;
-+}
-+
-+/* Create the .got section. */
-+
-+static bfd_boolean
-+loongarch_elf_create_got_section (bfd *abfd, struct bfd_link_info *info)
-+{
-+ flagword flags;
-+ char *name;
-+ asection *s, *s_got;
-+ struct elf_link_hash_entry *h;
-+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-+ struct elf_link_hash_table *htab = elf_hash_table (info);
-+
-+ /* This function may be called more than once. */
-+ if (htab->sgot != NULL)
-+ return TRUE;
-+
-+ flags = bed->dynamic_sec_flags;
-+ name = bed->rela_plts_and_copies_p ? ".rela.got" : ".rel.got";
-+ s = bfd_make_section_anyway_with_flags (abfd, name, flags | SEC_READONLY);
-+
-+ if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
-+ return FALSE;
-+ htab->srelgot = s;
-+
-+ s = s_got = bfd_make_section_anyway_with_flags (abfd, ".got", flags);
-+ if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
-+ return FALSE;
-+ htab->sgot = s;
-+
-+ /* The first bit of the global offset table is the header. */
-+ s->size += bed->got_header_size;
-+
-+ if (bed->want_got_plt)
-+ {
-+ s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags);
-+ if (s == NULL || !bfd_set_section_alignment (s, bed->s->log_file_align))
-+ return FALSE;
-+ htab->sgotplt = s;
-+
-+ /* Reserve room for the header. */
-+ s->size = GOTPLT_HEADER_SIZE;
-+ }
-+
-+ if (bed->want_got_sym)
-+ {
-+ /* Define the symbol _GLOBAL_OFFSET_TABLE_ at the start of the .got
-+ section. We don't do this in the linker script because we don't want
-+ to define the symbol if we are not creating a global offset table. */
-+ h = _bfd_elf_define_linkage_sym (abfd, info, s_got,
-+ "_GLOBAL_OFFSET_TABLE_");
-+ elf_hash_table (info)->hgot = h;
-+ if (h == NULL)
-+ return FALSE;
-+ }
-+ return TRUE;
-+}
-+
-+/* Create .plt, .rela.plt, .got, .got.plt, .rela.got, .dynbss, and
-+ .rela.bss sections in DYNOBJ, and set up shortcuts to them in our
-+ hash table. */
-+
-+static bfd_boolean
-+loongarch_elf_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
-+{
-+ struct loongarch_elf_link_hash_table *htab;
-+
-+ htab = loongarch_elf_hash_table (info);
-+ BFD_ASSERT (htab != NULL);
-+
-+ if (!loongarch_elf_create_got_section (dynobj, info))
-+ return FALSE;
-+
-+ if (!_bfd_elf_create_dynamic_sections (dynobj, info))
-+ return FALSE;
-+
-+ if (!bfd_link_pic (info))
-+ htab->sdyntdata
-+ = bfd_make_section_anyway_with_flags (dynobj, ".tdata.dyn",
-+ SEC_ALLOC | SEC_THREAD_LOCAL);
-+
-+ if (!htab->elf.splt || !htab->elf.srelplt || !htab->elf.sdynbss
-+ || (!bfd_link_pic (info) && (!htab->elf.srelbss ||
!htab->sdyntdata)))
-+ abort ();
-+
-+ return TRUE;
-+}
-+
-+static bfd_boolean
-+loongarch_elf_record_tls_and_got_reference (bfd *abfd,
-+ struct bfd_link_info *info,
-+ struct elf_link_hash_entry *h,
-+ unsigned long symndx,
-+ char tls_type)
-+{
-+ struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
-+ Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-+
-+ /* This is a global offset table entry for a local symbol. */
-+ if (elf_local_got_refcounts (abfd) == NULL)
-+ {
-+ bfd_size_type size =
-+ symtab_hdr->sh_info * (sizeof (bfd_vma) + sizeof (tls_type));
-+ if (!(elf_local_got_refcounts (abfd) = bfd_zalloc (abfd, size)))
-+ return FALSE;
-+ _bfd_loongarch_elf_local_got_tls_type (abfd) =
-+ (char *) (elf_local_got_refcounts (abfd) + symtab_hdr->sh_info);
-+ }
-+
-+ switch (tls_type)
-+ {
-+ case GOT_NORMAL:
-+ case GOT_TLS_GD:
-+ case GOT_TLS_IE:
-+ /* Need GOT. */
-+ if (htab->elf.sgot == NULL
-+ && !loongarch_elf_create_got_section (htab->elf.dynobj, info))
-+ return FALSE;
-+ if (h)
-+ {
-+ if (h->got.refcount < 0)
-+ h->got.refcount = 0;
-+ h->got.refcount++;
-+ }
-+ else
-+ elf_local_got_refcounts (abfd)[symndx]++;
-+ break;
-+ case GOT_TLS_LE:
-+ /* No need for GOT. */
-+ break;
-+ default:
-+ _bfd_error_handler (_("Internal error: unreachable."));
-+ return FALSE;
-+ }
-+
-+ char *new_tls_type = &_bfd_loongarch_elf_tls_type (abfd, h, symndx);
-+ *new_tls_type |= tls_type;
-+ if ((*new_tls_type & GOT_NORMAL) && (*new_tls_type & ~GOT_NORMAL))
-+ {
-+ _bfd_error_handler (_("%pB: `%s' accessed both as normal and "
-+ "thread local symbol"),
-+ abfd,
-+ h ? h->root.root.string : "<local>");
-+ return FALSE;
-+ }
-+
-+ return TRUE;
-+}
-+
-+/* Look through the relocs for a section during the first phase, and
-+ allocate space in the global offset table or procedure linkage
-+ table. */
-+
-+static bfd_boolean
-+loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
-+ asection *sec, const Elf_Internal_Rela *relocs)
-+{
-+ struct loongarch_elf_link_hash_table *htab;
-+ Elf_Internal_Shdr *symtab_hdr;
-+ struct elf_link_hash_entry **sym_hashes;
-+ const Elf_Internal_Rela *rel;
-+ asection *sreloc = NULL;
-+
-+ if (bfd_link_relocatable (info))
-+ return TRUE;
-+
-+ htab = loongarch_elf_hash_table (info);
-+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
-+ sym_hashes = elf_sym_hashes (abfd);
-+
-+ if (htab->elf.dynobj == NULL)
-+ htab->elf.dynobj = abfd;
-+
-+ for (rel = relocs; rel < relocs + sec->reloc_count; rel++)
-+ {
-+ unsigned int r_type;
-+ unsigned int r_symndx;
-+ struct elf_link_hash_entry *h;
-+ Elf_Internal_Sym *isym = NULL;
-+
-+ r_symndx = ELFNN_R_SYM (rel->r_info);
-+ r_type = ELFNN_R_TYPE (rel->r_info);
-+
-+ if (r_symndx >= NUM_SHDR_ENTRIES (symtab_hdr))
-+ {
-+ _bfd_error_handler (_("%pB: bad symbol index: %d"), abfd, r_symndx);
-+ return FALSE;
-+ }
-+
-+ if (r_symndx < symtab_hdr->sh_info)
-+ {
-+ /* A local symbol. */
-+ isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache, abfd, r_symndx);
-+ if (isym == NULL)
-+ return FALSE;
-+
-+ if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
-+ {
-+ h = elfNN_loongarch_get_local_sym_hash (htab, abfd, rel, TRUE);
-+ if (h == NULL)
-+ return FALSE;
-+
-+ h->type = STT_GNU_IFUNC;
-+ h->ref_regular = 1;
-+ }
-+ else
-+ h = NULL;
-+ }
-+ else
-+ {
-+ h = sym_hashes[r_symndx - symtab_hdr->sh_info];
-+ while (h->root.type == bfd_link_hash_indirect
-+ || h->root.type == bfd_link_hash_warning)
-+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
-+ }
-+
-+ /* It is referenced by a non-shared object. */
-+ if (h != NULL)
-+ h->ref_regular = 1;
-+
-+ if (h && h->type == STT_GNU_IFUNC)
-+ {
-+ if (htab->elf.dynobj == NULL)
-+ htab->elf.dynobj = abfd;
-+
-+ /* Create 'irelifunc' in PIC object. */
-+ if (bfd_link_pic (info)
-+ && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
-+ return FALSE;
-+ /* If '.plt' not represent, create '.iplt' to deal with ifunc. */
-+ else if (!htab->elf.splt
-+ && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
-+ return FALSE;
-+ /* Create the ifunc sections, iplt and ipltgot, for static
-+ executables. */
-+ if ((r_type == R_LARCH_64 || r_type == R_LARCH_32)
-+ && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
-+ return FALSE;
-+
-+ if (h->plt.refcount < 0)
-+ h->plt.refcount = 0;
-+ h->plt.refcount++;
-+ h->needs_plt = 1;
-+
-+ elf_tdata (info->output_bfd)->has_gnu_osabi |= elf_gnu_osabi_ifunc;
-+ }
-+
-+ int need_dynreloc = 0;
-+ int only_need_pcrel = 0;
-+
-+ switch (r_type)
-+ {
-+ case R_LARCH_GOT_PC_HI20:
-+ case R_LARCH_GOT_HI20:
-+ case R_LARCH_SOP_PUSH_GPREL:
-+ /* For la.global. */
-+ if (h)
-+ h->pointer_equality_needed = 1;
-+ if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
-+ r_symndx,
-+ GOT_NORMAL))
-+ return FALSE;
-+ break;
-+
-+ case R_LARCH_TLS_LD_PC_HI20:
-+ case R_LARCH_TLS_LD_HI20:
-+ case R_LARCH_TLS_GD_PC_HI20:
-+ case R_LARCH_TLS_GD_HI20:
-+ case R_LARCH_SOP_PUSH_TLS_GD:
-+ if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
-+ r_symndx,
-+ GOT_TLS_GD))
-+ return FALSE;
-+ break;
-+
-+ case R_LARCH_TLS_IE_PC_HI20:
-+ case R_LARCH_TLS_IE_HI20:
-+ case R_LARCH_SOP_PUSH_TLS_GOT:
-+ if (bfd_link_pic (info))
-+ /* May fail for lazy-bind. */
-+ info->flags |= DF_STATIC_TLS;
-+
-+ if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
-+ r_symndx,
-+ GOT_TLS_IE))
-+ return FALSE;
-+ break;
-+
-+ case R_LARCH_TLS_LE_HI20:
-+ case R_LARCH_SOP_PUSH_TLS_TPREL:
-+ if (!bfd_link_executable (info))
-+ return FALSE;
-+
-+ info->flags |= DF_STATIC_TLS;
-+
-+ if (!loongarch_elf_record_tls_and_got_reference (abfd, info, h,
-+ r_symndx,
-+ GOT_TLS_LE))
-+ return FALSE;
-+ break;
-+
-+ case R_LARCH_ABS_HI20:
-+ case R_LARCH_SOP_PUSH_ABSOLUTE:
-+ if (h != NULL)
-+ /* If this reloc is in a read-only section, we might
-+ need a copy reloc. We can't check reliably at this
-+ stage whether the section is read-only, as input
-+ sections have not yet been mapped to output sections.
-+ Tentatively set the flag for now, and correct in
-+ adjust_dynamic_symbol. */
-+ h->non_got_ref = 1;
-+ break;
-+
-+ case R_LARCH_PCALA_HI20:
-+ if (h != NULL)
-+ {
-+ h->non_got_ref = 1;
-+ h->pointer_equality_needed = 1;
-+ }
-+
-+ break;
-+
-+ case R_LARCH_B21:
-+ case R_LARCH_B16:
-+ case R_LARCH_B26:
-+ if (h != NULL)
-+ {
-+ h->needs_plt = 1;
-+ if (!bfd_link_pic (info))
-+ h->non_got_ref = 1;
-+
-+ /* We try to create PLT stub for all non-local function. */
-+ if (h->plt.refcount < 0)
-+ h->plt.refcount = 0;
-+ h->plt.refcount++;
-+ }
-+
-+ break;
-+
-+ case R_LARCH_SOP_PUSH_PCREL:
-+ if (h != NULL)
-+ {
-+ if (!bfd_link_pic (info))
-+ h->non_got_ref = 1;
-+
-+ /* We try to create PLT stub for all non-local function. */
-+ if (h->plt.refcount < 0)
-+ h->plt.refcount = 0;
-+ h->plt.refcount++;
-+ h->pointer_equality_needed = 1;
-+ }
-+
-+ break;
-+
-+ case R_LARCH_SOP_PUSH_PLT_PCREL:
-+ /* This symbol requires a procedure linkage table entry. We
-+ actually build the entry in adjust_dynamic_symbol,
-+ because this might be a case of linking PIC code without
-+ linking in any dynamic objects, in which case we don't
-+ need to generate a procedure linkage table after all. */
-+ if (h != NULL)
-+ {
-+ h->needs_plt = 1;
-+ if (h->plt.refcount < 0)
-+ h->plt.refcount = 0;
-+ h->plt.refcount++;
-+ }
-+ break;
-+
-+ case R_LARCH_TLS_DTPREL32:
-+ case R_LARCH_TLS_DTPREL64:
-+ need_dynreloc = 1;
-+ only_need_pcrel = 1;
-+ break;
-+
-+ case R_LARCH_JUMP_SLOT:
-+ case R_LARCH_32:
-+ case R_LARCH_64:
-+
-+ need_dynreloc = 1;
-+
-+ /* If resolved symbol is defined in this object,
-+ 1. Under pie, the symbol is known. We convert it
-+ into R_LARCH_RELATIVE and need load-addr still.
-+ 2. Under pde, the symbol is known and we can discard R_LARCH_NN.
-+ 3. Under dll, R_LARCH_NN can't be changed normally, since
-+ its defination could be covered by the one in executable.
-+ For symbolic, we convert it into R_LARCH_RELATIVE.
-+ Thus, only under pde, it needs pcrel only. We discard it. */
-+ only_need_pcrel = bfd_link_pde (info);
-+
-+ if (h != NULL
-+ && (!bfd_link_pic (info)
-+ || h->type == STT_GNU_IFUNC))
-+ {
-+ /* This reloc might not bind locally. */
-+ h->non_got_ref = 1;
-+ h->pointer_equality_needed = 1;
-+
-+ if (!h->def_regular
-+ || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
-+ {
-+ /* We may need a .plt entry if the symbol is a function
-+ defined in a shared lib or is a function referenced
-+ from the code or read-only section. */
-+ h->plt.refcount += 1;
-+ }
-+ }
-+ break;
-+
-+ case R_LARCH_GNU_VTINHERIT:
-+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
-+ return FALSE;
-+ break;
-+
-+ case R_LARCH_GNU_VTENTRY:
-+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
-+ return FALSE;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ /* Record some info for sizing and allocating dynamic entry. */
-+ if (need_dynreloc && (sec->flags & SEC_ALLOC))
-+ {
-+ /* When creating a shared object, we must copy these
-+ relocs into the output file. We create a reloc
-+ section in dynobj and make room for the reloc. */
-+ struct elf_dyn_relocs *p;
-+ struct elf_dyn_relocs **head;
-+
-+ if (sreloc == NULL)
-+ {
-+ sreloc
-+ = _bfd_elf_make_dynamic_reloc_section (sec, htab->elf.dynobj,
-+ LARCH_ELF_LOG_WORD_BYTES,
-+ abfd, /*rela?*/ TRUE);
-+ if (sreloc == NULL)
-+ return FALSE;
-+ }
-+
-+ /* If this is a global symbol, we count the number of
-+ relocations we need for this symbol. */
-+ if (h != NULL)
-+ head = &h->dyn_relocs;
-+ else
-+ {
-+ /* Track dynamic relocs needed for local syms too.
-+ We really need local syms available to do this
-+ easily. Oh well. */
-+
-+ asection *s;
-+ void *vpp;
-+
-+ s = bfd_section_from_elf_index (abfd, isym->st_shndx);
-+ if (s == NULL)
-+ s = sec;
-+
-+ vpp = &elf_section_data (s)->local_dynrel;
-+ head = (struct elf_dyn_relocs **) vpp;
-+ }
-+
-+ p = *head;
-+ if (p == NULL || p->sec != sec)
-+ {
-+ bfd_size_type amt = sizeof *p;
-+ p = (struct elf_dyn_relocs *) bfd_alloc (htab->elf.dynobj, amt);
-+ if (p == NULL)
-+ return FALSE;
-+ p->next = *head;
-+ *head = p;
-+ p->sec = sec;
-+ p->count = 0;
-+ p->pc_count = 0;
-+ }
-+
-+ p->count++;
-+ p->pc_count += only_need_pcrel;
-+ }
-+ }
-+
-+ return TRUE;
-+}
-+
-+/* Find dynamic relocs for H that apply to read-only sections. */
-+
-+static asection *
-+readonly_dynrelocs (struct elf_link_hash_entry *h)
-+{
-+ struct elf_dyn_relocs *p;
-+
-+ for (p = h->dyn_relocs; p != NULL; p = p->next)
-+ {
-+ asection *s = p->sec->output_section;
-+
-+ if (s != NULL && (s->flags & SEC_READONLY) != 0)
-+ return p->sec;
-+ }
-+ return NULL;
-+}
-+
-+/* Adjust a symbol defined by a dynamic object and referenced by a
-+ regular object. The current definition is in some section of the
-+ dynamic object, but we're not including those sections. We have to
-+ change the definition to something the rest of the link can
-+ understand. */
-+static bfd_boolean
-+loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
-+ struct elf_link_hash_entry *h)
-+{
-+ struct loongarch_elf_link_hash_table *htab;
-+ bfd *dynobj;
-+
-+ htab = loongarch_elf_hash_table (info);
-+ BFD_ASSERT (htab != NULL);
-+
-+ dynobj = htab->elf.dynobj;
-+
-+ /* Make sure we know what is going on here. */
-+ BFD_ASSERT (dynobj != NULL
-+ && (h->needs_plt || h->type == STT_GNU_IFUNC || h->is_weakalias
-+ || (h->def_dynamic && h->ref_regular &&
!h->def_regular)));
-+
-+ /* If this is a function, put it in the procedure linkage table. We
-+ will fill in the contents of the procedure linkage table later
-+ (although we could actually do it here). */
-+ if (h->type == STT_FUNC || h->type == STT_GNU_IFUNC || h->needs_plt)
-+ {
-+ if (h->plt.refcount < 0
-+ || (h->type != STT_GNU_IFUNC
-+ && (SYMBOL_REFERENCES_LOCAL (info, h)
-+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
-+ && h->root.type == bfd_link_hash_undefweak))))
-+ {
-+ /* This case can occur if we saw a R_LARCH_SOP_PUSH_PLT_PCREL reloc
-+ in an input file, but the symbol was never referred to by a
-+ dynamic object, or if all references were garbage collected.
-+ In such a case, we don't actually need to build a PLT entry. */
-+ h->plt.offset = MINUS_ONE;
-+ h->needs_plt = 0;
-+ }
-+ else
-+ h->needs_plt = 1;
-+
-+ return TRUE;
-+ }
-+ else
-+ h->plt.offset = MINUS_ONE;
-+
-+ /* If this is a weak symbol, and there is a real definition, the
-+ processor independent code will have arranged for us to see the
-+ real definition first, and we can just use the same value. */
-+ if (h->is_weakalias)
-+ {
-+ struct elf_link_hash_entry *def = weakdef (h);
-+ BFD_ASSERT (def->root.type == bfd_link_hash_defined);
-+ h->root.u.def.section = def->root.u.def.section;
-+ h->root.u.def.value = def->root.u.def.value;
-+ return TRUE;
-+ }
-+
-+ /* R_LARCH_COPY is not adept glibc, not to generate. */
-+ /* Can not print anything, because make check ld. */
-+ return TRUE;
-+}
-+
-+/* Allocate space in .plt, .got and associated reloc sections for
-+ dynamic relocs. */
-+
-+static bfd_boolean
-+allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
-+{
-+ struct bfd_link_info *info;
-+ struct loongarch_elf_link_hash_table *htab;
-+ struct elf_dyn_relocs *p;
-+
-+ if (h->root.type == bfd_link_hash_indirect)
-+ return TRUE;
-+
-+ if (h->type == STT_GNU_IFUNC
-+ && h->def_regular)
-+ return TRUE;
-+
-+ info = (struct bfd_link_info *) inf;
-+ htab = loongarch_elf_hash_table (info);
-+ bfd_boolean dyn = htab->elf.dynamic_sections_created;
-+ BFD_ASSERT (htab != NULL);
-+
-+ do
-+ {
-+ asection *plt, *gotplt, *relplt;
-+
-+ if (!h->needs_plt)
-+ break;
-+
-+ h->needs_plt = 0;
-+
-+ if (htab->elf.splt)
-+ {
-+ if (h->dynindx == -1 && !h->forced_local && dyn
-+ && h->root.type == bfd_link_hash_undefweak)
-+ {
-+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
-+ return FALSE;
-+ }
-+
-+ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h)
-+ && h->type != STT_GNU_IFUNC)
-+ break;
-+
-+ plt = htab->elf.splt;
-+ gotplt = htab->elf.sgotplt;
-+ relplt = htab->elf.srelplt;
-+ }
-+ else if (htab->elf.iplt)
-+ {
-+ /* .iplt only for IFUNC. */
-+ if (h->type != STT_GNU_IFUNC)
-+ break;
-+
-+ plt = htab->elf.iplt;
-+ gotplt = htab->elf.igotplt;
-+ relplt = htab->elf.irelplt;
-+ }
-+ else
-+ break;
-+
-+ if (plt->size == 0)
-+ plt->size = PLT_HEADER_SIZE;
-+
-+ h->plt.offset = plt->size;
-+ plt->size += PLT_ENTRY_SIZE;
-+ gotplt->size += GOT_ENTRY_SIZE;
-+ relplt->size += sizeof (ElfNN_External_Rela);
-+
-+ /* If this symbol is not defined in a regular file, and we are
-+ not generating a shared library, then set the symbol to this
-+ location in the .plt. This is required to make function
-+ pointers compare as equal between the normal executable and
-+ the shared library. */
-+ if (!bfd_link_pic (info)
-+ && !h->def_regular)
-+ {
-+ h->root.u.def.section = plt;
-+ h->root.u.def.value = h->plt.offset;
-+ }
-+
-+ h->needs_plt = 1;
-+ }
-+ while (0);
-+
-+ if (!h->needs_plt)
-+ h->plt.offset = MINUS_ONE;
-+
-+ if (0 < h->got.refcount)
-+ {
-+ asection *s;
-+ int tls_type = loongarch_elf_hash_entry (h)->tls_type;
-+
-+ /* Make sure this symbol is output as a dynamic symbol.
-+ Undefined weak syms won't yet be marked as dynamic. */
-+ if (h->dynindx == -1 && !h->forced_local && dyn
-+ && h->root.type == bfd_link_hash_undefweak)
-+ {
-+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
-+ return FALSE;
-+ }
-+
-+ s = htab->elf.sgot;
-+ h->got.offset = s->size;
-+ if (tls_type & (GOT_TLS_GD | GOT_TLS_IE))
-+ {
-+ /* TLS_GD needs two dynamic relocs and two GOT slots. */
-+ if (tls_type & GOT_TLS_GD)
-+ {
-+ s->size += 2 * GOT_ENTRY_SIZE;
-+ if (bfd_link_executable (info))
-+ {
-+ /* Link exe and not defined local. */
-+ if (!SYMBOL_REFERENCES_LOCAL (info, h))
-+ htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
-+ }
-+ else
-+ {
-+ if (SYMBOL_REFERENCES_LOCAL (info, h))
-+ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
-+ else
-+ htab->elf.srelgot->size += 2 * sizeof (ElfNN_External_Rela);
-+ }
-+ }
-+
-+ /* TLS_IE needs one dynamic reloc and one GOT slot. */
-+ if (tls_type & GOT_TLS_IE)
-+ {
-+ s->size += GOT_ENTRY_SIZE;
-+
-+ if (bfd_link_executable (info))
-+ {
-+ /* Link exe and not defined local. */
-+ if (!SYMBOL_REFERENCES_LOCAL (info, h))
-+ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
-+ }
-+ else
-+ {
-+ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
-+ }
-+ }
-+ }
-+ else
-+ {
-+ s->size += GOT_ENTRY_SIZE;
-+ if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
-+ || h->root.type != bfd_link_hash_undefweak)
-+ && (bfd_link_pic (info)
-+ || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info),
-+ h))
-+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
-+ /* Undefined weak symbol in static PIE resolves to 0 without
-+ any dynamic relocations. */
-+ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela);
-+ }
-+ }
-+ else
-+ h->got.offset = MINUS_ONE;
-+
-+ if (h->dyn_relocs == NULL)
-+ return TRUE;
-+
-+ /* Extra dynamic relocate,
-+ * R_LARCH_64
-+ * R_LARCH_TLS_DTPRELNN
-+ * R_LARCH_JUMP_SLOT
-+ * R_LARCH_NN. */
-+
-+ if (SYMBOL_CALLS_LOCAL (info, h))
-+ {
-+ struct elf_dyn_relocs **pp;
-+
-+ for (pp = &h->dyn_relocs; (p = *pp) != NULL;)
-+ {
-+ p->count -= p->pc_count;
-+ p->pc_count = 0;
-+ if (p->count == 0)
-+ *pp = p->next;
-+ else
-+ pp = &p->next;
-+ }
-+ }
-+
-+ if (h->root.type == bfd_link_hash_undefweak)
-+ {
-+ if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
-+ || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
-+ || (!bfd_link_pic (info) && h->non_got_ref))
-+ h->dyn_relocs = NULL;
-+ else if (h->dynindx == -1 && !h->forced_local)
-+ {
-+ /* Make sure this symbol is output as a dynamic symbol.
-+ Undefined weak syms won't yet be marked as dynamic. */
-+ if (!bfd_elf_link_record_dynamic_symbol (info, h))
-+ return FALSE;
-+
-+ if (h->dynindx == -1)
-+ h->dyn_relocs = NULL;
-+ }
-+ }
-+
-+ for (p = h->dyn_relocs; p != NULL; p = p->next)
-+ {
-+ asection *sreloc = elf_section_data (p->sec)->sreloc;
-+ sreloc->size += p->count * sizeof (ElfNN_External_Rela);
-+ }
-+
-+ return TRUE;
-+}
-+
-+/* A modified version of _bfd_elf_allocate_ifunc_dyn_relocs.
-+ For local def and ref ifunc,
-+ dynamic relocations are stored in
-+ 1. rela.srelgot section in dynamic object (dll or exec).
-+ 2. rela.irelplt section in static executable.
-+ Unlike _bfd_elf_allocate_ifunc_dyn_relocs, rela.srelgot is used
-+ instead of rela.srelplt. Glibc ELF loader will not support
-+ R_LARCH_IRELATIVE relocation in rela.plt. */
-+
-+static bfd_boolean
-+local_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
-+ struct elf_link_hash_entry *h,
-+ struct elf_dyn_relocs **head,
-+ unsigned int plt_entry_size,
-+ unsigned int plt_header_size,
-+ unsigned int got_entry_size,
-+ bfd_boolean avoid_plt)
-+{
-+ asection *plt, *gotplt, *relplt;
-+ struct elf_dyn_relocs *p;
-+ unsigned int sizeof_reloc;
-+ const struct elf_backend_data *bed;
-+ struct elf_link_hash_table *htab;
-+ /* If AVOID_PLT is TRUE, don't use PLT if possible. */
-+ bfd_boolean use_plt = !avoid_plt || h->plt.refcount > 0;
-+ bfd_boolean need_dynreloc = !use_plt || bfd_link_pic (info);
-+
-+ /* When a PIC object references a STT_GNU_IFUNC symbol defined
-+ in executable or it isn't referenced via PLT, the address of
-+ the resolved function may be used. But in non-PIC executable,
-+ the address of its plt slot may be used. Pointer equality may
-+ not work correctly. PIE or non-PLT reference should be used if
-+ pointer equality is required here.
-+
-+ If STT_GNU_IFUNC symbol is defined in position-dependent executable,
-+ backend should change it to the normal function and set its address
-+ to its PLT entry which should be resolved by R_*_IRELATIVE at
-+ run-time. All external references should be resolved to its PLT in
-+ executable. */
-+ if (!need_dynreloc
-+ && !(bfd_link_pde (info) && h->def_regular)
-+ && (h->dynindx != -1
-+ || info->export_dynamic)
-+ && h->pointer_equality_needed)
-+ {
-+ info->callbacks->einfo
-+ /* xgettext:c-format. */
-+ (_("%F%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer "
-+ "equality in `%pB' can not be used when making an "
-+ "executable; recompile with -fPIE and relink with -pie\n"),
-+ h->root.root.string,
-+ h->root.u.def.section->owner);
-+ bfd_set_error (bfd_error_bad_value);
-+ return FALSE;
-+ }
-+
-+ htab = elf_hash_table (info);
-+
-+ /* When the symbol is marked with regular reference, if PLT isn't used
-+ or we are building a PIC object, we must keep dynamic relocation
-+ if there is non-GOT reference and use PLT if there is PC-relative
-+ reference. */
-+ if (need_dynreloc && h->ref_regular)
-+ {
-+ bfd_boolean keep = FALSE;
-+ for (p = *head; p != NULL; p = p->next)
-+ if (p->count)
-+ {
-+ h->non_got_ref = 1;
-+ /* Need dynamic relocations for non-GOT reference. */
-+ keep = TRUE;
-+ if (p->pc_count)
-+ {
-+ /* Must use PLT for PC-relative reference. */
-+ use_plt = TRUE;
-+ need_dynreloc = bfd_link_pic (info);
-+ break;
-+ }
-+ }
-+ if (keep)
-+ goto keep;
-+ }
-+
-+ /* Support garbage collection against STT_GNU_IFUNC symbols. */
-+ if (h->plt.refcount <= 0 && h->got.refcount <= 0)
-+ {
-+ h->got = htab->init_got_offset;
-+ h->plt = htab->init_plt_offset;
-+ *head = NULL;
-+ return TRUE;
-+ }
-+
-+ /* Return and discard space for dynamic relocations against it if
-+ it is never referenced. */
-+ if (!h->ref_regular)
-+ {
-+ if (h->plt.refcount > 0
-+ || h->got.refcount > 0)
-+ abort ();
-+ h->got = htab->init_got_offset;
-+ h->plt = htab->init_plt_offset;
-+ *head = NULL;
-+ return TRUE;
-+ }
-+
-+ keep:
-+ bed = get_elf_backend_data (info->output_bfd);
-+ if (bed->rela_plts_and_copies_p)
-+ sizeof_reloc = bed->s->sizeof_rela;
-+ else
-+ sizeof_reloc = bed->s->sizeof_rel;
-+
-+ /* When building a static executable, use iplt, igot.plt and
-+ rela.iplt sections for STT_GNU_IFUNC symbols. */
-+ if (htab->splt != NULL)
-+ {
-+ plt = htab->splt;
-+ gotplt = htab->sgotplt;
-+ /* Change dynamic info of ifunc gotplt from srelplt to srelgot. */
-+ relplt = htab->srelgot;
-+
-+ /* If this is the first plt entry and PLT is used, make room for
-+ the special first entry. */
-+ if (plt->size == 0 && use_plt)
-+ plt->size += plt_header_size;
-+ }
-+ else
-+ {
-+ plt = htab->iplt;
-+ gotplt = htab->igotplt;
-+ relplt = htab->irelplt;
-+ }
-+
-+ if (use_plt)
-+ {
-+ /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need
-+ the original value for R_*_IRELATIVE. */
-+ h->plt.offset = plt->size;
-+
-+ /* Make room for this entry in the plt/iplt section. */
-+ plt->size += plt_entry_size;
-+
-+ /* We also need to make an entry in the got.plt/got.iplt section,
-+ which will be placed in the got section by the linker script. */
-+ gotplt->size += got_entry_size;
-+ }
-+
-+ /* We also need to make an entry in the rela.plt/.rela.iplt
-+ section for GOTPLT relocation if PLT is used. */
-+ if (use_plt)
-+ {
-+ relplt->size += sizeof_reloc;
-+ relplt->reloc_count++;
-+ }
-+
-+ /* We need dynamic relocation for STT_GNU_IFUNC symbol only when
-+ there is a non-GOT reference in a PIC object or PLT isn't used. */
-+ if (!need_dynreloc || !h->non_got_ref)
-+ *head = NULL;
-+
-+ /* Finally, allocate space. */
-+ p = *head;
-+ if (p != NULL)
-+ {
-+ bfd_size_type count = 0;
-+ do
-+ {
-+ count += p->count;
-+ p = p->next;
-+ }
-+ while (p != NULL);
-+
-+ htab->ifunc_resolvers = count != 0;
-+
-+ /* Dynamic relocations are stored in
-+ 1. rela.srelgot section in PIC object.
-+ 2. rela.srelgot section in dynamic executable.
-+ 3. rela.irelplt section in static executable. */
-+ if (htab->splt != NULL)
-+ htab->srelgot->size += count * sizeof_reloc;
-+ else
-+ {
-+ relplt->size += count * sizeof_reloc;
-+ relplt->reloc_count += count;
-+ }
-+ }
-+
-+ /* For STT_GNU_IFUNC symbol, got.plt has the real function address
-+ and got has the PLT entry adddress. We will load the GOT entry
-+ with the PLT entry in finish_dynamic_symbol if it is used. For
-+ branch, it uses got.plt. For symbol value, if PLT is used,
-+ 1. Use got.plt in a PIC object if it is forced local or not
-+ dynamic.
-+ 2. Use got.plt in a non-PIC object if pointer equality isn't
-+ needed.
-+ 3. Use got.plt in PIE.
-+ 4. Use got.plt if got isn't used.
-+ 5. Otherwise use got so that it can be shared among different
-+ objects at run-time.
-+ If PLT isn't used, always use got for symbol value.
-+ We only need to relocate got entry in PIC object or in dynamic
-+ executable without PLT. */
-+ if (use_plt
-+ && (h->got.refcount <= 0
-+ || (bfd_link_pic (info)
-+ && (h->dynindx == -1
-+ || h->forced_local))
-+ || (
-+ !h->pointer_equality_needed)
-+ || htab->sgot == NULL))
-+ {
-+ /* Use got.plt. */
-+ h->got.offset = (bfd_vma) -1;
-+ }
-+ else
-+ {
-+ if (!use_plt)
-+ {
-+ /* PLT isn't used. */
-+ h->plt.offset = (bfd_vma) -1;
-+ }
-+ if (h->got.refcount <= 0)
-+ {
-+ /* GOT isn't need when there are only relocations for static
-+ pointers. */
-+ h->got.offset = (bfd_vma) -1;
-+ }
-+ else
-+ {
-+ h->got.offset = htab->sgot->size;
-+ htab->sgot->size += got_entry_size;
-+ /* Need to relocate the GOT entry in a PIC object or PLT isn't
-+ used. Otherwise, the GOT entry will be filled with the PLT
-+ entry and dynamic GOT relocation isn't needed. */
-+ if (need_dynreloc)
-+ {
-+ /* For non-static executable, dynamic GOT relocation is in
-+ rela.got section, but for static executable, it is
-+ in rela.iplt section. */
-+ if (htab->splt != NULL)
-+ htab->srelgot->size += sizeof_reloc;
-+ else
-+ {
-+ relplt->size += sizeof_reloc;
-+ relplt->reloc_count++;
-+ }
-+ }
-+ }
-+ }
-+
-+ return TRUE;
-+}
-+
-+/* Allocate space in .plt, .got and associated reloc sections for
-+ ifunc dynamic relocs. */
-+
-+static bfd_boolean
-+elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf)
-+{
-+ struct bfd_link_info *info;
-+ /* An example of a bfd_link_hash_indirect symbol is versioned
-+ symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect)
-+ -> __gxx_personality_v0(bfd_link_hash_defined)
-+
-+ There is no need to process bfd_link_hash_indirect symbols here
-+ because we will also be presented with the concrete instance of
-+ the symbol and loongarch_elf_copy_indirect_symbol () will have been
-+ called to copy all relevant data from the generic to the concrete
-+ symbol instance. */
-+ if (h->root.type == bfd_link_hash_indirect)
-+ return TRUE;
-+
-+ if (h->root.type == bfd_link_hash_warning)
-+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
-+
-+ info = (struct bfd_link_info *) inf;
-+
-+ /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it
-+ here if it is defined and referenced in a non-shared object. */
-+ if (h->type == STT_GNU_IFUNC && h->def_regular)
-+ {
-+ if (SYMBOL_REFERENCES_LOCAL (info, h))
-+ return local_allocate_ifunc_dyn_relocs (info, h,
-+ &h->dyn_relocs,
-+ PLT_ENTRY_SIZE,
-+ PLT_HEADER_SIZE,
-+ GOT_ENTRY_SIZE,
-+ FALSE);
-+ else
-+ return _bfd_elf_allocate_ifunc_dyn_relocs (info, h,
-+ &h->dyn_relocs,
-+ PLT_ENTRY_SIZE,
-+ PLT_HEADER_SIZE,
-+ GOT_ENTRY_SIZE,
-+ FALSE);
-+ }
-+
-+ return TRUE;
-+}
-+
-+/* Allocate space in .plt, .got and associated reloc sections for
-+ ifunc dynamic relocs. */
-+
-+static bfd_boolean
-+elfNN_allocate_local_ifunc_dynrelocs (void **slot, void *inf)
-+{
-+ struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
-+
-+ if (h->type != STT_GNU_IFUNC
-+ || !h->def_regular
-+ || !h->ref_regular
-+ || !h->forced_local
-+ || h->root.type != bfd_link_hash_defined)
-+ abort ();
-+
-+ return elfNN_allocate_ifunc_dynrelocs (h, inf);
-+}
-+
-+/* Set DF_TEXTREL if we find any dynamic relocs that apply to
-+ read-only sections. */
-+
-+static bfd_boolean
-+maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p)
-+{
-+ asection *sec;
-+
-+ if (h->root.type == bfd_link_hash_indirect)
-+ return TRUE;
-+
-+ sec = readonly_dynrelocs (h);
-+ if (sec != NULL)
-+ {
-+ struct bfd_link_info *info = (struct bfd_link_info *) info_p;
-+
-+ info->flags |= DF_TEXTREL;
-+ info->callbacks->minfo (_("%pB: dynamic relocation against `%pT' in
"
-+ "read-only section `%pA'\n"),
-+ sec->owner, h->root.root.string, sec);
-+
-+ /* Not an error, just cut short the traversal. */
-+ return FALSE;
-+ }
-+ return TRUE;
-+}
-+
-+static bfd_boolean
-+loongarch_elf_size_dynamic_sections (bfd *output_bfd,
-+ struct bfd_link_info *info)
-+{
-+ struct loongarch_elf_link_hash_table *htab;
-+ bfd *dynobj;
-+ asection *s;
-+ bfd *ibfd;
-+
-+ htab = loongarch_elf_hash_table (info);
-+ BFD_ASSERT (htab != NULL);
-+ dynobj = htab->elf.dynobj;
-+ BFD_ASSERT (dynobj != NULL);
-+
-+ if (htab->elf.dynamic_sections_created)
-+ {
-+ /* Set the contents of the .interp section to the interpreter. */
-+ if (bfd_link_executable (info) && !info->nointerp)
-+ {
-+ const char *interpreter;
-+ flagword flags = elf_elfheader (output_bfd)->e_flags;
-+ s = bfd_get_linker_section (dynobj, ".interp");
-+ BFD_ASSERT (s != NULL);
-+ if (EF_LOONGARCH_IS_ILP32 (flags))
-+ interpreter = "/lib32/ld.so.1";
-+ else if (EF_LOONGARCH_IS_LP64 (flags))
-+ interpreter = "/lib64/ld.so.1";
-+ else
-+ interpreter = "/lib/ld.so.1";
-+ s->contents = (unsigned char *) interpreter;
-+ s->size = strlen (interpreter) + 1;
-+ }
-+ }
-+
-+ /* Set up .got offsets for local syms, and space for local dynamic
-+ relocs. */
-+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
-+ {
-+ bfd_signed_vma *local_got;
-+ bfd_signed_vma *end_local_got;
-+ char *local_tls_type;
-+ bfd_size_type locsymcount;
-+ Elf_Internal_Shdr *symtab_hdr;
-+ asection *srel;
-+
-+ if (!is_loongarch_elf (ibfd))
-+ continue;
-+
-+ for (s = ibfd->sections; s != NULL; s = s->next)
-+ {
-+ struct elf_dyn_relocs *p;
-+
-+ for (p = elf_section_data (s)->local_dynrel; p != NULL; p = p->next)
-+ {
-+ p->count -= p->pc_count;
-+ if (!bfd_is_abs_section (p->sec)
-+ && bfd_is_abs_section (p->sec->output_section))
-+ {
-+ /* Input section has been discarded, either because
-+ it is a copy of a linkonce section or due to
-+ linker script /DISCARD/, so we'll be discarding
-+ the relocs too. */
-+ }
-+ else if (0 < p->count)
-+ {
-+ srel = elf_section_data (p->sec)->sreloc;
-+ srel->size += p->count * sizeof (ElfNN_External_Rela);
-+ if ((p->sec->output_section->flags & SEC_READONLY) != 0)
-+ info->flags |= DF_TEXTREL;
-+ }
-+ }
-+ }
-+
-+ local_got = elf_local_got_refcounts (ibfd);
-+ if (!local_got)
-+ continue;
-+
-+ symtab_hdr = &elf_symtab_hdr (ibfd);
-+ locsymcount = symtab_hdr->sh_info;
-+ end_local_got = local_got + locsymcount;
-+ local_tls_type = _bfd_loongarch_elf_local_got_tls_type (ibfd);
-+ s = htab->elf.sgot;
-+ srel = htab->elf.srelgot;
-+ for (; local_got < end_local_got; ++local_got, ++local_tls_type)
-+ {
-+ if (0 < *local_got)
-+ {
-+ *local_got = s->size;
-+
-+ /* 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;
-+
-+ if (bfd_link_executable (info)
-+ && (*local_tls_type & (GOT_TLS_GD| GOT_TLS_IE)))
-+ ;/* Do nothing. */
-+ else
-+ {
-+ srel->size += sizeof (ElfNN_External_Rela);
-+ }
-+ }
-+ else
-+ *local_got = MINUS_ONE;
-+ }
-+ }
-+
-+ /* Allocate global sym .plt and .got entries, and space for global
-+ sym dynamic relocs. */
-+ elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info);
-+
-+ /* Allocate global ifunc sym .plt and .got entries, and space for global
-+ ifunc sym dynamic relocs. */
-+ elf_link_hash_traverse (&htab->elf, elfNN_allocate_ifunc_dynrelocs, info);
-+
-+ /* Allocate .plt and .got entries, and space for local ifunc symbols. */
-+ htab_traverse (htab->loc_hash_table,
-+ (void *) elfNN_allocate_local_ifunc_dynrelocs, info);
-+
-+ /* Don't allocate .got.plt section if there are no PLT. */
-+ if (htab->elf.sgotplt && htab->elf.sgotplt->size ==
GOTPLT_HEADER_SIZE
-+ && (htab->elf.splt == NULL || htab->elf.splt->size == 0))
-+ htab->elf.sgotplt->size = 0;
-+
-+ /* The check_relocs and adjust_dynamic_symbol entry points have
-+ determined the sizes of the various dynamic sections. Allocate
-+ memory for them. */
-+ for (s = dynobj->sections; s != NULL; s = s->next)
-+ {
-+ if ((s->flags & SEC_LINKER_CREATED) == 0)
-+ continue;
-+
-+ if (s == htab->elf.splt || s == htab->elf.iplt || s == htab->elf.sgot
-+ || s == htab->elf.sgotplt || s == htab->elf.igotplt
-+ || s == htab->elf.sdynbss || s == htab->elf.sdynrelro)
-+ {
-+ /* Strip this section if we don't need it; see the
-+ comment below. */
-+ }
-+ else if (strncmp (s->name, ".rela", 5) == 0)
-+ {
-+ if (s->size != 0)
-+ {
-+ /* We use the reloc_count field as a counter if we need
-+ to copy relocs into the output file. */
-+ s->reloc_count = 0;
-+ }
-+ }
-+ else
-+ {
-+ /* It's not one of our sections. */
-+ continue;
-+ }
-+
-+ if (s->size == 0)
-+ {
-+ /* If we don't need this section, strip it from the
-+ output file. This is mostly to handle .rela.bss and
-+ .rela.plt. We must create both sections in
-+ create_dynamic_sections, because they must be created
-+ before the linker maps input sections to output
-+ sections. The linker does that before
-+ adjust_dynamic_symbol is called, and it is that
-+ function which decides whether anything needs to go
-+ into these sections. */
-+ s->flags |= SEC_EXCLUDE;
-+ continue;
-+ }
-+
-+ if ((s->flags & SEC_HAS_CONTENTS) == 0)
-+ continue;
-+
-+ /* Allocate memory for the section contents. Zero the memory
-+ for the benefit of .rela.plt, which has 4 unused entries
-+ at the beginning, and we don't want garbage. */
-+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
-+ if (s->contents == NULL)
-+ return FALSE;
-+ }
-+
-+ if (elf_hash_table (info)->dynamic_sections_created)
-+ {
-+ /* Add some entries to the .dynamic section. We fill in the
-+ values later, in loongarch_elf_finish_dynamic_sections, but we
-+ must add the entries now so that we get the correct size for
-+ the .dynamic section. The DT_DEBUG entry is filled in by the
-+ dynamic linker and used by the debugger. */
-+#define add_dynamic_entry(TAG, VAL) _bfd_elf_add_dynamic_entry (info, TAG, VAL)
-+
-+ if (bfd_link_executable (info))
-+ {
-+ if (!add_dynamic_entry (DT_DEBUG, 0))
-+ return FALSE;
-+ }
-+
-+ if (htab->elf.srelplt->size != 0)
-+ {
-+ if (!add_dynamic_entry (DT_PLTGOT, 0)
-+ || !add_dynamic_entry (DT_PLTRELSZ, 0)
-+ || !add_dynamic_entry (DT_PLTREL, DT_RELA)
-+ || !add_dynamic_entry (DT_JMPREL, 0))
-+ return FALSE;
-+ }
-+
-+ if (!add_dynamic_entry (DT_RELA, 0)
-+ || !add_dynamic_entry (DT_RELASZ, 0)
-+ || !add_dynamic_entry (DT_RELAENT, sizeof (ElfNN_External_Rela)))
-+ return FALSE;
-+
-+ /* If any dynamic relocs apply to a read-only section,
-+ then we need a DT_TEXTREL entry. */
-+ if ((info->flags & DF_TEXTREL) == 0)
-+ elf_link_hash_traverse (&htab->elf, maybe_set_textrel, info);
-+
-+ if (info->flags & DF_TEXTREL)
-+ {
-+ if (!add_dynamic_entry (DT_TEXTREL, 0))
-+ return FALSE;
-+ /* Clear the DF_TEXTREL flag. It will be set again if we
-+ write out an actual text relocation; we may not, because
-+ at this point we do not know whether e.g. any .eh_frame
-+ absolute relocations have been converted to PC-relative. */
-+ info->flags &= ~DF_TEXTREL;
-+ }
-+ }
-+#undef add_dynamic_entry
-+
-+ return TRUE;
-+}
-+
-+#define LARCH_LD_STACK_DEPTH 16
-+static int64_t larch_opc_stack[LARCH_LD_STACK_DEPTH];
-+static size_t larch_stack_top = 0;
-+
-+static bfd_reloc_status_type
-+loongarch_push (int64_t val)
-+{
-+ if (LARCH_LD_STACK_DEPTH <= larch_stack_top)
-+ return bfd_reloc_outofrange;
-+ larch_opc_stack[larch_stack_top++] = val;
-+ return bfd_reloc_ok;
-+}
-+
-+static bfd_reloc_status_type
-+loongarch_pop (int64_t *val)
-+{
-+ if (larch_stack_top == 0)
-+ return bfd_reloc_outofrange;
-+ BFD_ASSERT (val);
-+ *val = larch_opc_stack[--larch_stack_top];
-+ return bfd_reloc_ok;
-+}
-+
-+static bfd_reloc_status_type
-+loongarch_top (int64_t *val)
-+{
-+ if (larch_stack_top == 0)
-+ return bfd_reloc_outofrange;
-+ BFD_ASSERT (val);
-+ *val = larch_opc_stack[larch_stack_top - 1];
-+ return bfd_reloc_ok;
-+}
-+
-+static void
-+loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel)
-+{
-+ BFD_ASSERT (s && s->contents);
-+ const struct elf_backend_data *bed;
-+ bfd_byte *loc;
-+
-+ bed = get_elf_backend_data (abfd);
-+ if (!(s->size > s->reloc_count * bed->s->sizeof_rela))
-+ BFD_ASSERT (s->size > s->reloc_count * bed->s->sizeof_rela);
-+ loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela);
-+ bed->s->swap_reloca_out (abfd, rel, loc);
-+}
-+
-+/* Check rel->r_offset in range of contents. */
-+static bfd_reloc_status_type
-+loongarch_check_offset (const Elf_Internal_Rela *rel,
-+ const asection *input_section)
-+{
-+ if (0 == strcmp(input_section->name, ".text")
-+ && rel->r_offset > input_section->size)
-+ return bfd_reloc_overflow;
-+
-+ return bfd_reloc_ok;
-+}
-+
-+#define LARCH_RELOC_PERFORM_3OP(op1, op2, op3) \
-+ ({ \
-+ bfd_reloc_status_type ret = loongarch_pop (&op2); \
-+ if (ret == bfd_reloc_ok) \
-+ { \
-+ ret = loongarch_pop (&op1); \
-+ if (ret == bfd_reloc_ok) \
-+ ret = loongarch_push (op3); \
-+ } \
-+ ret; \
-+ })
-+
-+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, bfd_vma reloc_val)
-+{
-+ int bits = bfd_get_reloc_size (howto) * 8;
-+ uint32_t insn = bfd_get (bits, input_bfd, contents + rel->r_offset);
-+
-+ if (!loongarch_adjust_reloc_bitsfield(howto, &reloc_val))
-+ 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;
-+}
-+
-+static bfd_reloc_status_type
-+perform_relocation (const Elf_Internal_Rela *rel, asection *input_section,
-+ reloc_howto_type *howto, bfd_vma value,
-+ bfd *input_bfd, bfd_byte *contents)
-+{
-+ int64_t opr1, opr2, opr3;
-+ bfd_reloc_status_type r = bfd_reloc_ok;
-+ int bits = bfd_get_reloc_size (howto) * 8;
-+
-+ switch (ELFNN_R_TYPE (rel->r_info))
-+ {
-+ case R_LARCH_SOP_PUSH_PCREL:
-+ case R_LARCH_SOP_PUSH_ABSOLUTE:
-+ case R_LARCH_SOP_PUSH_GPREL:
-+ case R_LARCH_SOP_PUSH_TLS_TPREL:
-+ case R_LARCH_SOP_PUSH_TLS_GOT:
-+ case R_LARCH_SOP_PUSH_TLS_GD:
-+ case R_LARCH_SOP_PUSH_PLT_PCREL:
-+ r = loongarch_push (value);
-+ break;
-+
-+ case R_LARCH_SOP_PUSH_DUP:
-+ r = loongarch_pop (&opr1);
-+ if (r == bfd_reloc_ok)
-+ {
-+ r = loongarch_push (opr1);
-+ if (r == bfd_reloc_ok)
-+ r = loongarch_push (opr1);
-+ }
-+ break;
-+
-+ case R_LARCH_SOP_ASSERT:
-+ r = loongarch_pop (&opr1);
-+ if (r != bfd_reloc_ok || !opr1)
-+ r = bfd_reloc_notsupported;
-+ break;
-+
-+ case R_LARCH_SOP_NOT:
-+ r = loongarch_pop (&opr1);
-+ if (r == bfd_reloc_ok)
-+ r = loongarch_push (!opr1);
-+ break;
-+
-+ case R_LARCH_SOP_SUB:
-+ r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 - opr2);
-+ break;
-+
-+ case R_LARCH_SOP_SL:
-+ r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 << opr2);
-+ break;
-+
-+ case R_LARCH_SOP_SR:
-+ r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 >> opr2);
-+ break;
-+
-+ case R_LARCH_SOP_AND:
-+ r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 & opr2);
-+ break;
-+
-+ case R_LARCH_SOP_ADD:
-+ r = LARCH_RELOC_PERFORM_3OP (opr1, opr2, opr1 + opr2);
-+ break;
-+
-+ case R_LARCH_SOP_IF_ELSE:
-+ r = loongarch_pop (&opr3);
-+ if (r == bfd_reloc_ok)
-+ {
-+ r = loongarch_pop (&opr2);
-+ if (r == bfd_reloc_ok)
-+ {
-+ r = loongarch_pop (&opr1);
-+ if (r == bfd_reloc_ok)
-+ r = loongarch_push (opr1 ? opr2 : opr3);
-+ }
-+ }
-+ break;
-+
-+ case R_LARCH_SOP_POP_32_S_10_5:
-+ case R_LARCH_SOP_POP_32_S_10_12:
-+ 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_0_5_10_16_S2:
-+ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2:
-+ case R_LARCH_SOP_POP_32_S_5_20:
-+ 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;
-+ 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, (bfd_vma)opr1);
-+ break;
-+
-+ case R_LARCH_TLS_DTPREL32:
-+ case R_LARCH_32:
-+ case R_LARCH_TLS_DTPREL64:
-+ case R_LARCH_64:
-+ r = loongarch_check_offset (rel, input_section);
-+ if (r != bfd_reloc_ok)
-+ break;
-+
-+ bfd_put (bits, input_bfd, value, contents + rel->r_offset);
-+ break;
-+
-+ case R_LARCH_ADD8:
-+ case R_LARCH_ADD16:
-+ case R_LARCH_ADD24:
-+ case R_LARCH_ADD32:
-+ case R_LARCH_ADD64:
-+ r = loongarch_check_offset (rel, input_section);
-+ if (r != bfd_reloc_ok)
-+ break;
-+
-+ opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
-+ bfd_put (bits, input_bfd, opr1 + value, contents + rel->r_offset);
-+ break;
-+
-+ case R_LARCH_SUB8:
-+ case R_LARCH_SUB16:
-+ case R_LARCH_SUB24:
-+ case R_LARCH_SUB32:
-+ case R_LARCH_SUB64:
-+ r = loongarch_check_offset (rel, input_section);
-+ if (r != bfd_reloc_ok)
-+ break;
-+
-+ opr1 = bfd_get (bits, input_bfd, contents + rel->r_offset);
-+ bfd_put (bits, input_bfd, opr1 - value, contents + rel->r_offset);
-+ break;
-+
-+ /* For eh_frame and debug info. */
-+ case R_LARCH_32_PCREL:
-+ value -= sec_addr (input_section) + rel->r_offset;
-+ value += rel->r_addend;
-+ bfd_vma word = bfd_get (howto->bitsize, input_bfd,
-+ contents + rel->r_offset);
-+ word = (word & ~howto->dst_mask) | (value & howto->dst_mask);
-+ bfd_put (howto->bitsize, input_bfd, word, contents + rel->r_offset);
-+ r = bfd_reloc_ok;
-+ break;
-+
-+ /* New reloc type.
-+ R_LARCH_B16 ~ R_LARCH_TLS_GD_HI20. */
-+ case R_LARCH_B16:
-+ case R_LARCH_B21:
-+ case R_LARCH_B26:
-+ case R_LARCH_ABS_HI20:
-+ case R_LARCH_ABS_LO12:
-+ case R_LARCH_ABS64_LO20:
-+ case R_LARCH_ABS64_HI12:
-+ case R_LARCH_PCALA_HI20:
-+ case R_LARCH_PCALA_LO12:
-+ case R_LARCH_PCALA64_LO20:
-+ case R_LARCH_PCALA64_HI12:
-+ case R_LARCH_GOT_PC_HI20:
-+ case R_LARCH_GOT_PC_LO12:
-+ case R_LARCH_GOT64_PC_LO20:
-+ case R_LARCH_GOT64_PC_HI12:
-+ case R_LARCH_GOT_HI20:
-+ case R_LARCH_GOT_LO12:
-+ case R_LARCH_GOT64_LO20:
-+ case R_LARCH_GOT64_HI12:
-+ case R_LARCH_TLS_LE_HI20:
-+ case R_LARCH_TLS_LE_LO12:
-+ case R_LARCH_TLS_LE64_LO20:
-+ case R_LARCH_TLS_LE64_HI12:
-+ case R_LARCH_TLS_IE_PC_HI20:
-+ case R_LARCH_TLS_IE_PC_LO12:
-+ case R_LARCH_TLS_IE64_PC_LO20:
-+ case R_LARCH_TLS_IE64_PC_HI12:
-+ case R_LARCH_TLS_IE_HI20:
-+ case R_LARCH_TLS_IE_LO12:
-+ case R_LARCH_TLS_IE64_LO20:
-+ case R_LARCH_TLS_IE64_HI12:
-+ case R_LARCH_TLS_LD_PC_HI20:
-+ case R_LARCH_TLS_LD_HI20:
-+ case R_LARCH_TLS_GD_PC_HI20:
-+ case R_LARCH_TLS_GD_HI20:
-+ 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, value);
-+ break;
-+
-+ case R_LARCH_RELAX:
-+ break;
-+
-+ default:
-+ r = bfd_reloc_notsupported;
-+ }
-+ return r;
-+}
-+
-+#define LARCH_RECENT_RELOC_QUEUE_LENGTH 72
-+static struct
-+{
-+ bfd *bfd;
-+ asection *section;
-+ bfd_vma r_offset;
-+ int r_type;
-+ bfd_vma relocation;
-+ Elf_Internal_Sym *sym;
-+ struct elf_link_hash_entry *h;
-+ bfd_vma addend;
-+ int64_t top_then;
-+} larch_reloc_queue[LARCH_RECENT_RELOC_QUEUE_LENGTH];
-+static size_t larch_reloc_queue_head = 0;
-+static size_t larch_reloc_queue_tail = 0;
-+
-+static const char *
-+loongarch_sym_name (bfd *input_bfd, struct elf_link_hash_entry *h,
-+ Elf_Internal_Sym *sym)
-+{
-+ const char *ret = NULL;
-+ if (sym)
-+ ret = bfd_elf_string_from_elf_section (input_bfd,
-+ elf_symtab_hdr (input_bfd).sh_link,
-+ sym->st_name);
-+ else if (h)
-+ ret = h->root.root.string;
-+
-+ if (ret == NULL || *ret == '\0')
-+ ret = "<nameless>";
-+ return ret;
-+}
-+
-+static void
-+loongarch_record_one_reloc (bfd *abfd, asection *section, int r_type,
-+ bfd_vma r_offset, Elf_Internal_Sym *sym,
-+ struct elf_link_hash_entry *h, bfd_vma addend)
-+{
-+ if ((larch_reloc_queue_head == 0
-+ && larch_reloc_queue_tail == LARCH_RECENT_RELOC_QUEUE_LENGTH - 1)
-+ || larch_reloc_queue_head == larch_reloc_queue_tail + 1)
-+ larch_reloc_queue_head =
-+ (larch_reloc_queue_head + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
-+ larch_reloc_queue[larch_reloc_queue_tail].bfd = abfd;
-+ larch_reloc_queue[larch_reloc_queue_tail].section = section;
-+ larch_reloc_queue[larch_reloc_queue_tail].r_offset = r_offset;
-+ larch_reloc_queue[larch_reloc_queue_tail].r_type = r_type;
-+ larch_reloc_queue[larch_reloc_queue_tail].sym = sym;
-+ larch_reloc_queue[larch_reloc_queue_tail].h = h;
-+ larch_reloc_queue[larch_reloc_queue_tail].addend = addend;
-+ loongarch_top (&larch_reloc_queue[larch_reloc_queue_tail].top_then);
-+ larch_reloc_queue_tail =
-+ (larch_reloc_queue_tail + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
-+}
-+
-+static void
-+loongarch_dump_reloc_record (void (*p) (const char *fmt, ...))
-+{
-+ size_t i = larch_reloc_queue_head;
-+ bfd *a_bfd = NULL;
-+ asection *section = NULL;
-+ bfd_vma r_offset = 0;
-+ int inited = 0;
-+ p ("Dump relocate record:\n");
-+ p ("stack top\t\trelocation name\t\tsymbol");
-+ while (i != larch_reloc_queue_tail)
-+ {
-+ if (a_bfd != larch_reloc_queue[i].bfd
-+ || section != larch_reloc_queue[i].section
-+ || r_offset != larch_reloc_queue[i].r_offset)
-+ {
-+ a_bfd = larch_reloc_queue[i].bfd;
-+ section = larch_reloc_queue[i].section;
-+ r_offset = larch_reloc_queue[i].r_offset;
-+ p ("\nat %pB(%pA+0x%v):\n", larch_reloc_queue[i].bfd,
-+ larch_reloc_queue[i].section, larch_reloc_queue[i].r_offset);
-+ }
-+
-+ if (!inited)
-+ inited = 1, p ("...\n");
-+
-+ reloc_howto_type *howto =
-+ loongarch_elf_rtype_to_howto (larch_reloc_queue[i].bfd,
-+ larch_reloc_queue[i].r_type);
-+ p ("0x%V %s\t`%s'", (bfd_vma) larch_reloc_queue[i].top_then,
-+ howto ? howto->name : "<unknown reloc>",
-+ loongarch_sym_name (larch_reloc_queue[i].bfd, larch_reloc_queue[i].h,
-+ larch_reloc_queue[i].sym));
-+
-+ long addend = larch_reloc_queue[i].addend;
-+ if (addend < 0)
-+ p (" - %ld", -addend);
-+ else if (0 < addend)
-+ p (" + %ld(0x%v)", addend, larch_reloc_queue[i].addend);
-+
-+ p ("\n");
-+ i = (i + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH;
-+ }
-+ p ("\n"
-+ "-- Record dump end --\n\n");
-+}
-+
-+static bfd_boolean
-+loongarch_reloc_is_fatal (struct bfd_link_info *info,
-+ bfd *input_bfd,
-+ asection *input_section,
-+ Elf_Internal_Rela *rel,
-+ reloc_howto_type *howto,
-+ bfd_reloc_status_type rtype,
-+ bfd_boolean is_undefweak,
-+ const char *name,
-+ const char *msg)
-+{
-+ bfd_boolean fatal = TRUE;
-+ switch (rtype)
-+ {
-+ /* 'dangerous' means we do it but can't promise it's ok
-+ 'unsupport' means out of ability of relocation type
-+ 'undefined' means we can't deal with the undefined symbol. */
-+ case bfd_reloc_undefined:
-+ info->callbacks->undefined_symbol (info, name, input_bfd, input_section,
-+ rel->r_offset, TRUE);
-+ info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against
%s`%s':\n%s\n",
-+ input_bfd, input_section, rel->r_offset,
-+ howto->name,
-+ is_undefweak ? "[undefweak] " : "", name, msg);
-+ break;
-+ case bfd_reloc_dangerous:
-+ info->callbacks->info ("%pB(%pA+0x%v): warning: %s against
%s`%s':\n%s\n",
-+ input_bfd, input_section, rel->r_offset,
-+ howto->name,
-+ is_undefweak ? "[undefweak] " : "", name, msg);
-+ fatal = FALSE;
-+ break;
-+ case bfd_reloc_notsupported:
-+ info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against
%s`%s':\n%s\n",
-+ input_bfd, input_section, rel->r_offset,
-+ howto->name,
-+ is_undefweak ? "[undefweak] " : "", name, msg);
-+ break;
-+ default:
-+ break;
-+ }
-+ return fatal;
-+}
-+
-+#define RELOCATE_CALC_PC32_HI20(relocation, pc) \
-+ ({ \
-+ bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \
-+ pc = pc & (~(bfd_vma)0xfff); \
-+ if (lo > 0x7ff) \
-+ { \
-+ relocation += 0x1000; \
-+ } \
-+ relocation &= ~(bfd_vma)0xfff; \
-+ relocation -= pc; \
-+ })
-+
-+#define RELOCATE_CALC_PC64_HI32(relocation, pc) \
-+ ({ \
-+ bfd_vma lo = (relocation) & ((bfd_vma)0xfff); \
-+ if (lo > 0x7ff) \
-+ { \
-+ relocation -= 0x100000000; \
-+ } \
-+ relocation -= (pc & ~(bfd_vma)0xffffffff); \
-+ })
-+
-+static int
-+loongarch_elf_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
-+ bfd *input_bfd, asection *input_section,
-+ bfd_byte *contents, Elf_Internal_Rela *relocs,
-+ Elf_Internal_Sym *local_syms,
-+ asection **local_sections)
-+{
-+ Elf_Internal_Rela *rel;
-+ Elf_Internal_Rela *relend;
-+ bfd_boolean fatal = FALSE;
-+ asection *sreloc = elf_section_data (input_section)->sreloc;
-+ struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
-+ Elf_Internal_Shdr *symtab_hdr = &elf_symtab_hdr (input_bfd);
-+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
-+ bfd_vma *local_got_offsets = elf_local_got_offsets (input_bfd);
-+ bfd_boolean is_pic = bfd_link_pic (info);
-+ bfd_boolean is_dyn = elf_hash_table (info)->dynamic_sections_created;
-+ asection *plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
-+ asection *got = htab->elf.sgot;
-+
-+ relend = relocs + input_section->reloc_count;
-+ for (rel = relocs; rel < relend; rel++)
-+ {
-+ 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;
-+ asection *sec = NULL;
-+ Elf_Internal_Sym *sym = NULL;
-+ struct elf_link_hash_entry *h = NULL;
-+ const char *name;
-+ bfd_reloc_status_type r = bfd_reloc_ok;
-+ bfd_boolean is_ie, is_undefweak, unresolved_reloc, defined_local;
-+ bfd_boolean resolved_local, resolved_dynly, resolved_to_const;
-+ char tls_type;
-+ bfd_vma relocation, off, ie_off;
-+ int i, j;
-+
-+ howto = loongarch_elf_rtype_to_howto (input_bfd, r_type);
-+ if (howto == NULL || r_type == R_LARCH_GNU_VTINHERIT
-+ || r_type == R_LARCH_GNU_VTENTRY)
-+ continue;
-+
-+ /* This is a final link. */
-+ if (r_symndx < symtab_hdr->sh_info)
-+ {
-+ is_undefweak = FALSE;
-+ unresolved_reloc = FALSE;
-+ sym = local_syms + r_symndx;
-+ sec = local_sections[r_symndx];
-+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
-+
-+ /* Relocate against local STT_GNU_IFUNC symbol. */
-+ if (!bfd_link_relocatable (info)
-+ && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
-+ {
-+ h = elfNN_loongarch_get_local_sym_hash (htab, input_bfd, rel,
-+ FALSE);
-+ if (h == NULL)
-+ abort ();
-+
-+ /* Set STT_GNU_IFUNC symbol value. */
-+ h->root.u.def.value = sym->st_value;
-+ h->root.u.def.section = sec;
-+ }
-+ defined_local = TRUE;
-+ resolved_local = TRUE;
-+ resolved_dynly = FALSE;
-+ resolved_to_const = FALSE;
-+
-+ /* Calc in funtion elf_link_input_bfd,
-+ * if #define elf_backend_rela_normal to 1. */
-+ if (bfd_link_relocatable (info)
-+ && ELF_ST_TYPE (sym->st_info) == STT_SECTION)
-+ continue;
-+ }
-+ else
-+ {
-+ bfd_boolean warned, ignored;
-+
-+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
-+ r_symndx, symtab_hdr, sym_hashes,
-+ h, sec, relocation,
-+ unresolved_reloc, warned, ignored);
-+ /* Here means symbol isn't local symbol only and 'h != NULL'. */
-+
-+ /* The 'unresolved_syms_in_objects' specify how to deal with undefined
-+ symbol. And 'dynamic_undefined_weak' specify what to do when
-+ meeting undefweak. */
-+
-+ if ((is_undefweak = h->root.type == bfd_link_hash_undefweak))
-+ {
-+ defined_local = FALSE;
-+ resolved_local = FALSE;
-+ resolved_to_const = (!is_dyn || h->dynindx == -1
-+ || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
-+ resolved_dynly = !resolved_local && !resolved_to_const;
-+ }
-+ else if (warned)
-+ {
-+ /* Symbol undefined offen means failed already. I don't know why
-+ 'warned' here but I guess it want to continue relocating as if
-+ no error occures to find other errors as more as possible. */
-+
-+ /* To avoid generating warning messages about truncated
-+ relocations, set the relocation's address to be the same as
-+ the start of this section. */
-+ relocation = (input_section->output_section
-+ ? input_section->output_section->vma
-+ : 0);
-+
-+ defined_local = relocation != 0;
-+ resolved_local = defined_local;
-+ resolved_to_const = !resolved_local;
-+ resolved_dynly = FALSE;
-+ }
-+ else
-+ {
-+ defined_local = !unresolved_reloc && !ignored;
-+ resolved_local =
-+ defined_local && SYMBOL_REFERENCES_LOCAL (info, h);
-+ resolved_dynly = !resolved_local;
-+ resolved_to_const = !resolved_local && !resolved_dynly;
-+ }
-+ }
-+
-+ name = loongarch_sym_name (input_bfd, h, sym);
-+
-+ if (sec != NULL && discarded_section (sec))
-+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section, rel,
-+ 1, relend, howto, 0, contents);
-+
-+ if (bfd_link_relocatable (info))
-+ continue;
-+
-+ /* The r_symndx will be STN_UNDEF (zero) only for relocs against symbols
-+ from removed linkonce sections, or sections discarded by a linker
-+ script. Also for R_*_SOP_PUSH_ABSOLUTE and PCREL to specify const. */
-+ if (r_symndx == STN_UNDEF || bfd_is_abs_section (sec))
-+ {
-+ defined_local = FALSE;
-+ resolved_local = FALSE;
-+ resolved_dynly = FALSE;
-+ resolved_to_const = TRUE;
-+ }
-+
-+ /* The ifunc reference generate plt. */
-+ if (h && h->type == STT_GNU_IFUNC && h->plt.offset !=
MINUS_ONE)
-+ {
-+ defined_local = TRUE;
-+ resolved_local = TRUE;
-+ resolved_dynly = FALSE;
-+ resolved_to_const = FALSE;
-+ relocation = sec_addr (plt) + h->plt.offset;
-+ }
-+
-+ unresolved_reloc = resolved_dynly;
-+
-+ BFD_ASSERT (resolved_local + resolved_dynly + resolved_to_const == 1);
-+
-+ /* BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1));. */
-+
-+ BFD_ASSERT (!resolved_local || defined_local);
-+
-+ is_ie = FALSE;
-+ switch (r_type)
-+ {
-+ case R_LARCH_MARK_PCREL:
-+ case R_LARCH_MARK_LA:
-+ case R_LARCH_NONE:
-+ r = bfd_reloc_continue;
-+ unresolved_reloc = FALSE;
-+ break;
-+
-+ case R_LARCH_32:
-+ case R_LARCH_64:
-+ if (resolved_dynly || (is_pic && resolved_local))
-+ {
-+ Elf_Internal_Rela outrel;
-+
-+ /* When generating a shared object, these relocations are copied
-+ into the output file to be resolved at run time. */
-+
-+ outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
-+ input_section,
-+ rel->r_offset);
-+
-+ unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
-+ && (input_section->flags & SEC_ALLOC));
-+
-+ outrel.r_offset += sec_addr (input_section);
-+
-+ /* A pointer point to a ifunc symbol. */
-+ if (h && h->type == STT_GNU_IFUNC)
-+ {
-+ if (h->dynindx == -1)
-+ {
-+ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
-+ outrel.r_addend = (h->root.u.def.value
-+ + h->root.u.def.section->output_section->vma
-+ + h->root.u.def.section->output_offset);
-+ }
-+ else
-+ {
-+ outrel.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
-+ outrel.r_addend = 0;
-+ }
-+
-+ if (SYMBOL_REFERENCES_LOCAL (info, h))
-+ {
-+
-+ if (htab->elf.splt != NULL)
-+ sreloc = htab->elf.srelgot;
-+ else
-+ sreloc = htab->elf.irelplt;
-+ }
-+ else
-+ {
-+
-+ if (bfd_link_pic (info))
-+ sreloc = htab->elf.irelifunc;
-+ else if (htab->elf.splt != NULL)
-+ sreloc = htab->elf.srelgot;
-+ else
-+ sreloc = htab->elf.irelplt;
-+ }
-+ }
-+ else if (resolved_dynly)
-+ {
-+ if (h->dynindx == -1)
-+ {
-+ if (h->root.type == bfd_link_hash_undefined)
-+ (*info->callbacks->undefined_symbol)
-+ (info, name, input_bfd, input_section,
-+ rel->r_offset, TRUE);
-+
-+ outrel.r_info = ELFNN_R_INFO (0, r_type);
-+ }
-+ else
-+ outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
-+
-+ outrel.r_addend = rel->r_addend;
-+ }
-+ else
-+ {
-+ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
-+ outrel.r_addend = relocation + rel->r_addend;
-+ }
-+
-+ /* No alloc space of func allocate_dynrelocs. */
-+ if (unresolved_reloc
-+ && !(h && (h->is_weakalias || !h->dyn_relocs)))
-+ loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
-+ }
-+
-+ relocation += rel->r_addend;
-+ break;
-+
-+ case R_LARCH_ADD8:
-+ case R_LARCH_ADD16:
-+ case R_LARCH_ADD24:
-+ case R_LARCH_ADD32:
-+ case R_LARCH_ADD64:
-+ case R_LARCH_SUB8:
-+ case R_LARCH_SUB16:
-+ case R_LARCH_SUB24:
-+ case R_LARCH_SUB32:
-+ case R_LARCH_SUB64:
-+ if (resolved_dynly)
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_undefined, is_undefweak, name,
-+ "Can't be resolved dynamically. "
-+ "If this procedure is hand-written assembly,\n"
-+ "there must be something like '.dword sym1 - sym2' "
-+ "to generate these relocs\n"
-+ "and we can't get known link-time address of "
-+ "these symbols."));
-+ else
-+ relocation += rel->r_addend;
-+ break;
-+
-+ case R_LARCH_TLS_DTPREL32:
-+ case R_LARCH_TLS_DTPREL64:
-+ if (resolved_dynly)
-+ {
-+ Elf_Internal_Rela outrel;
-+
-+ outrel.r_offset = _bfd_elf_section_offset (output_bfd, info,
-+ input_section,
-+ rel->r_offset);
-+ unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset)
-+ && (input_section->flags & SEC_ALLOC));
-+ outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
-+ outrel.r_offset += sec_addr (input_section);
-+ outrel.r_addend = rel->r_addend;
-+ if (unresolved_reloc)
-+ loongarch_elf_append_rela (output_bfd, sreloc, &outrel);
-+ break;
-+ }
-+
-+ if (resolved_to_const)
-+ fatal = loongarch_reloc_is_fatal (info, input_bfd, input_section,
-+ rel, howto,
-+ bfd_reloc_notsupported,
-+ is_undefweak, name,
-+ "Internal:");
-+ if (resolved_local)
-+ {
-+ if (!elf_hash_table (info)->tls_sec)
-+ {
-+ fatal = loongarch_reloc_is_fatal (info, input_bfd,
-+ input_section, rel, howto, bfd_reloc_notsupported,
-+ is_undefweak, name, "TLS section not be created");
-+ }
-+ else
-+ relocation -= elf_hash_table (info)->tls_sec->vma;
-+ }
-+ else
-+ {
-+ fatal = loongarch_reloc_is_fatal (info, input_bfd,
-+ input_section, rel, howto, bfd_reloc_undefined,
-+ is_undefweak, name,
-+ "TLS LE just can be resolved local only.");
-+ }
-+
-+ break;
-+
-+ case R_LARCH_SOP_PUSH_TLS_TPREL:
-+ if (resolved_local)
-+ {
-+ if (!elf_hash_table (info)->tls_sec)
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_notsupported, is_undefweak, name,
-+ "TLS section not be created"));
-+ else
-+ relocation -= elf_hash_table (info)->tls_sec->vma;
-+ }
-+ else
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_undefined, is_undefweak, name,
-+ "TLS LE just can be resolved local only."));
-+ break;
-+
-+ case R_LARCH_SOP_PUSH_ABSOLUTE:
-+ if (is_undefweak)
-+ {
-+ if (resolved_dynly)
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_dangerous, is_undefweak, name,
-+ "Someone require us to resolve undefweak "
-+ "symbol dynamically. \n"
-+ "But this reloc can't be done. "
-+ "I think I can't throw error "
-+ "for this\n"
-+ "so I resolved it to 0. "
-+ "I suggest to re-compile with '-fpic'."));
-+
-+ relocation = 0;
-+ unresolved_reloc = FALSE;
-+ break;
-+ }
-+
-+ if (resolved_to_const)
-+ {
-+ relocation += rel->r_addend;
-+ break;
-+ }
-+
-+ if (is_pic)
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_notsupported, is_undefweak, name,
-+ "Under PIC we don't know load address. Re-compile "
-+ "with '-fpic'?"));
-+ break;
-+ }
-+
-+ if (resolved_dynly)
-+ {
-+ if (!(plt && h && h->plt.offset != MINUS_ONE))
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_undefined, is_undefweak, name,
-+ "Can't be resolved dynamically. Try to re-compile "
-+ "with '-fpic'?"));
-+ break;
-+ }
-+
-+ if (rel->r_addend != 0)
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_notsupported, is_undefweak, name,
-+ "Shouldn't be with r_addend."));
-+ break;
-+ }
-+
-+ relocation = sec_addr (plt) + h->plt.offset;
-+ unresolved_reloc = FALSE;
-+ break;
-+ }
-+
-+ if (resolved_local)
-+ {
-+ relocation += rel->r_addend;
-+ break;
-+ }
-+
-+ break;
-+
-+ case R_LARCH_SOP_PUSH_PCREL:
-+ case R_LARCH_SOP_PUSH_PLT_PCREL:
-+ unresolved_reloc = FALSE;
-+
-+ if (is_undefweak)
-+ {
-+ i = 0, j = 0;
-+ relocation = 0;
-+ if (resolved_dynly)
-+ {
-+ if (h && h->plt.offset != MINUS_ONE)
-+ i = 1, j = 2;
-+ else
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_dangerous, is_undefweak, name,
-+ "Undefweak need to be resolved dynamically, "
-+ "but PLT stub doesn't represent."));
-+ }
-+ }
-+ else
-+ {
-+ if (!(defined_local || (h && h->plt.offset != MINUS_ONE)))
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_undefined, is_undefweak, name,
-+ "PLT stub does not represent and "
-+ "symbol not defined."));
-+ break;
-+ }
-+
-+ if (resolved_local)
-+ i = 0, j = 2;
-+ else /* if (resolved_dynly) */
-+ {
-+ if (!(h && h->plt.offset != MINUS_ONE))
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_dangerous, is_undefweak, name,
-+ "Internal: PLT stub doesn't represent. "
-+ "Resolve it with pcrel"));
-+ i = 1, j = 3;
-+ }
-+ }
-+
-+ for (; i < j; i++)
-+ {
-+ if ((i & 1) == 0 && defined_local)
-+ {
-+ relocation -= pc;
-+ relocation += rel->r_addend;
-+ break;
-+ }
-+
-+ if ((i & 1) && h && h->plt.offset != MINUS_ONE)
-+ {
-+ if (rel->r_addend != 0)
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_notsupported, is_undefweak, name,
-+ "PLT shouldn't be with r_addend."));
-+ break;
-+ }
-+ relocation = sec_addr (plt) + h->plt.offset - pc;
-+ break;
-+ }
-+ }
-+ break;
-+
-+ case R_LARCH_SOP_PUSH_GPREL:
-+ unresolved_reloc = FALSE;
-+
-+ if (rel->r_addend != 0)
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_notsupported, is_undefweak, name,
-+ "Shouldn't be with r_addend."));
-+ break;
-+ }
-+
-+ if (h != NULL)
-+ {
-+ off = h->got.offset & (~1);
-+
-+ if (h->got.offset == MINUS_ONE && h->type != STT_GNU_IFUNC)
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_notsupported, is_undefweak, name,
-+ "Internal: GOT entry doesn't represent."));
-+ break;
-+ }
-+
-+ /* Hidden symbol not has .got entry, only .got.plt entry
-+ so gprel is (plt - got). */
-+ if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
-+ {
-+ if (h->plt.offset == (bfd_vma) -1)
-+ {
-+ abort();
-+ }
-+
-+ bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE;
-+ off = plt_index * GOT_ENTRY_SIZE;
-+
-+ if (htab->elf.splt != NULL)
-+ {
-+ /* Section .plt header is 2 times of plt entry. */
-+ off = sec_addr (htab->elf.sgotplt) + off
-+ - sec_addr (htab->elf.sgot);
-+ }
-+ else
-+ {
-+ /* Section iplt not has plt header. */
-+ off = sec_addr (htab->elf.igotplt) + off
-+ - sec_addr (htab->elf.sgot);
-+ }
-+ }
-+
-+ if ((h->got.offset & 1) == 0)
-+ {
-+ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
-+ bfd_link_pic (info), h)
-+ && ((bfd_link_pic (info)
-+ && SYMBOL_REFERENCES_LOCAL (info, h))))
-+ {
-+ /* This is actually a static link, or it is a
-+ -Bsymbolic link and the symbol is defined
-+ locally, or the symbol was forced to be local
-+ because of a version file. We must initialize
-+ this entry in the global offset table. Since the
-+ offset must always be a multiple of the word size,
-+ we use the least significant bit to record whether
-+ we have initialized it already.
-+
-+ When doing a dynamic link, we create a rela.got
-+ relocation entry to initialize the value. This
-+ is done in the finish_dynamic_symbol routine. */
-+
-+ if (resolved_dynly)
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_dangerous, is_undefweak, name,
-+ "Internal: here shouldn't dynamic."));
-+ }
-+
-+ if (!(defined_local || resolved_to_const))
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_undefined, is_undefweak, name,
-+ "Internal: "));
-+ break;
-+ }
-+
-+ asection *s;
-+ Elf_Internal_Rela outrel;
-+ /* We need to generate a R_LARCH_RELATIVE reloc
-+ for the dynamic linker. */
-+ s = htab->elf.srelgot;
-+ if (!s)
-+ {
-+ fatal = loongarch_reloc_is_fatal
-+ (info, input_bfd,
-+ input_section, rel, howto,
-+ bfd_reloc_notsupported, is_undefweak, name,
-+ "Internal: '.rel.got' not represent");
-+ break;
-+ }
-+
-+ outrel.r_offset = sec_addr (got) + off;
-+ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
-+ outrel.r_addend = relocation; /* Link-time addr. */
-+ loongarch_elf_append_rela (output_bfd, s, &outrel);
-+ }
-+ bfd_put_NN (output_bfd, relocation, got->contents + off);
-+ h->got.offset |= 1;
-+ }
-+ }
-+ else
-+ {
-+ if (!local_got_offsets)
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_notsupported, is_undefweak, name,
-+ "Internal: local got offsets not reporesent."));
-+ break;
-+ }
-+
-+ off = local_got_offsets[r_symndx] & (~1);
-+
-+ if (local_got_offsets[r_symndx] == MINUS_ONE)
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_notsupported, is_undefweak, name,
-+ "Internal: GOT entry doesn't represent."));
-+ break;
-+ }
-+
-+ /* The offset must always be a multiple of the word size.
-+ So, we can use the least significant bit to record
-+ whether we have already processed this entry. */
-+ if (local_got_offsets[r_symndx] == 0)
-+ {
-+ if (is_pic)
-+ {
-+ asection *s;
-+ Elf_Internal_Rela outrel;
-+ /* We need to generate a R_LARCH_RELATIVE reloc
-+ for the dynamic linker. */
-+ s = htab->elf.srelgot;
-+ if (!s)
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_notsupported, is_undefweak, name,
-+ "Internal: '.rel.got' not represent"));
-+ break;
-+ }
-+
-+ outrel.r_offset = sec_addr (got) + off;
-+ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
-+ outrel.r_addend = relocation; /* Link-time addr. */
-+ loongarch_elf_append_rela (output_bfd, s, &outrel);
-+ }
-+
-+ bfd_put_NN (output_bfd, relocation, got->contents + off);
-+ local_got_offsets[r_symndx] |= 1;
-+ }
-+ }
-+ relocation = off;
-+
-+ break;
-+
-+ case R_LARCH_SOP_PUSH_TLS_GOT:
-+ case R_LARCH_SOP_PUSH_TLS_GD:
-+ {
-+ unresolved_reloc = FALSE;
-+ if (r_type == R_LARCH_SOP_PUSH_TLS_GOT)
-+ is_ie = TRUE;
-+
-+ bfd_vma got_off = 0;
-+ if (h != NULL)
-+ {
-+ got_off = h->got.offset;
-+ h->got.offset |= 1;
-+ }
-+ else
-+ {
-+ got_off = local_got_offsets[r_symndx];
-+ local_got_offsets[r_symndx] |= 1;
-+ }
-+
-+ 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))
-+ ie_off = 2 * GOT_ENTRY_SIZE;
-+
-+ if ((got_off & 1) == 0)
-+ {
-+ Elf_Internal_Rela rela;
-+ asection *srel = htab->elf.srelgot;
-+ bfd_vma tls_block_off = 0;
-+
-+ if (SYMBOL_REFERENCES_LOCAL (info, h))
-+ {
-+ BFD_ASSERT (elf_hash_table (info)->tls_sec);
-+ tls_block_off = relocation
-+ - elf_hash_table (info)->tls_sec->vma;
-+ }
-+
-+ if (tls_type & GOT_TLS_GD)
-+ {
-+ rela.r_offset = sec_addr (got) + got_off;
-+ rela.r_addend = 0;
-+ if (SYMBOL_REFERENCES_LOCAL (info, h))
-+ {
-+ /* Local sym, used in exec, set module id 1. */
-+ if (bfd_link_executable (info))
-+ bfd_put_NN (output_bfd, 1, got->contents + got_off);
-+ else
-+ {
-+ rela.r_info = ELFNN_R_INFO (0,
-+ R_LARCH_TLS_DTPMODNN);
-+ loongarch_elf_append_rela (output_bfd, srel, &rela);
-+ }
-+
-+ bfd_put_NN (output_bfd, tls_block_off,
-+ got->contents + got_off + GOT_ENTRY_SIZE);
-+ }
-+ /* Dynamic resolved. */
-+ else
-+ {
-+ /* Dynamic relocate module id. */
-+ rela.r_info = ELFNN_R_INFO (h->dynindx,
-+ R_LARCH_TLS_DTPMODNN);
-+ loongarch_elf_append_rela (output_bfd, srel, &rela);
-+
-+ /* Dynamic relocate offset of block. */
-+ rela.r_offset += GOT_ENTRY_SIZE;
-+ rela.r_info = ELFNN_R_INFO (h->dynindx,
-+ R_LARCH_TLS_DTPRELNN);
-+ loongarch_elf_append_rela (output_bfd, srel, &rela);
-+ }
-+ }
-+ if (tls_type & GOT_TLS_IE)
-+ {
-+ rela.r_offset = sec_addr (got) + got_off + ie_off;
-+ if (SYMBOL_REFERENCES_LOCAL (info, h))
-+ {
-+ /* Local sym, used in exec, set module id 1. */
-+ if (!bfd_link_executable (info))
-+ {
-+ rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
-+ rela.r_addend = tls_block_off;
-+ loongarch_elf_append_rela (output_bfd, srel, &rela);
-+ }
-+
-+ bfd_put_NN (output_bfd, tls_block_off,
-+ got->contents + got_off + ie_off);
-+ }
-+ /* Dynamic resolved. */
-+ else
-+ {
-+ /* Dynamic relocate offset of block. */
-+ rela.r_info = ELFNN_R_INFO (h->dynindx,
-+ R_LARCH_TLS_TPRELNN);
-+ rela.r_addend = 0;
-+ loongarch_elf_append_rela (output_bfd, srel, &rela);
-+ }
-+ }
-+ }
-+
-+ relocation = (got_off & (~(bfd_vma)1)) + (is_ie ? ie_off : 0);
-+ }
-+ break;
-+
-+ /* New reloc types. */
-+ case R_LARCH_B21:
-+ case R_LARCH_B26:
-+ case R_LARCH_B16:
-+ unresolved_reloc = FALSE;
-+ if (is_undefweak)
-+ {
-+ relocation = 0;
-+ }
-+
-+ if (resolved_local)
-+ {
-+ relocation -= pc;
-+ relocation += rel->r_addend;
-+ }
-+ else if (resolved_dynly)
-+ {
-+ BFD_ASSERT (h
-+ && (h->plt.offset != MINUS_ONE
-+ || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-+ && rel->r_addend == 0);
-+ if (h && h->plt.offset == MINUS_ONE
-+ && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-+ {
-+ relocation -= pc;
-+ relocation += rel->r_addend;
-+ }
-+ else
-+ relocation = sec_addr (plt) + h->plt.offset - pc;
-+ }
-+
-+ break;
-+
-+ case R_LARCH_ABS_HI20:
-+ case R_LARCH_ABS_LO12:
-+ case R_LARCH_ABS64_LO20:
-+ case R_LARCH_ABS64_HI12:
-+ BFD_ASSERT (!is_pic);
-+
-+ if (is_undefweak)
-+ {
-+ BFD_ASSERT (resolved_dynly);
-+ relocation = 0;
-+ break;
-+ }
-+ else if (resolved_to_const || resolved_local)
-+ {
-+ relocation += rel->r_addend;
-+ }
-+ else if (resolved_dynly)
-+ {
-+ unresolved_reloc = FALSE;
-+ BFD_ASSERT ((plt && h && h->plt.offset != MINUS_ONE)
-+ && rel->r_addend == 0);
-+ relocation = sec_addr (plt) + h->plt.offset;
-+ }
-+
-+ break;
-+
-+ case R_LARCH_PCALA_HI20:
-+ unresolved_reloc = FALSE;
-+ if (h && h->plt.offset != MINUS_ONE)
-+ relocation = sec_addr (plt) + h->plt.offset;
-+ else
-+ relocation += rel->r_addend;
-+
-+ RELOCATE_CALC_PC32_HI20 (relocation, pc);
-+
-+ break;
-+
-+ case R_LARCH_PCALA_LO12:
-+ /* Not support if sym_addr in 2k page edge.
-+ pcalau12i pc_hi20 (sym_addr)
-+ ld.w/d pc_lo12 (sym_addr)
-+ ld.w/d pc_lo12 (sym_addr + x)
-+ ...
-+ can not calc correct address
-+ if sym_addr < 0x800 && sym_addr + x >= 0x800. */
-+
-+ if (h && h->plt.offset != MINUS_ONE)
-+ relocation = sec_addr (plt) + h->plt.offset;
-+ else
-+ relocation += rel->r_addend;
-+
-+ {
-+ relocation &= 0xfff;
-+ /* Signed extend. */
-+ relocation = (relocation ^ 0x800) - 0x800;
-+
-+ /* For 2G jump, generate pcalau12i, jirl. */
-+ /* If use jirl, turns to R_LARCH_B16. */
-+ uint32_t insn = bfd_get (32, input_bfd, contents + rel->r_offset);
-+ if ((insn & 0x4c000000) == 0x4c000000)
-+ {
-+ rel->r_info = ELFNN_R_INFO (r_symndx, R_LARCH_B16);
-+ howto = loongarch_elf_rtype_to_howto (input_bfd, R_LARCH_B16);
-+ }
-+ }
-+ break;
-+
-+ case R_LARCH_PCALA64_LO20:
-+ case R_LARCH_PCALA64_HI12:
-+ if (h && h->plt.offset != MINUS_ONE)
-+ relocation = sec_addr (plt) + h->plt.offset;
-+ else
-+ relocation += rel->r_addend;
-+
-+ RELOCATE_CALC_PC64_HI32 (relocation, pc);
-+
-+ break;
-+
-+ case R_LARCH_GOT_PC_HI20:
-+ case R_LARCH_GOT_HI20:
-+ /* Calc got offset. */
-+ {
-+ unresolved_reloc = FALSE;
-+ BFD_ASSERT (rel->r_addend == 0);
-+
-+ bfd_vma got_off = 0;
-+ if (h != NULL)
-+ {
-+ /* GOT ref or ifunc. */
-+ BFD_ASSERT (h->got.offset != MINUS_ONE
-+ || h->type == STT_GNU_IFUNC);
-+
-+ got_off = h->got.offset & (~(bfd_vma)1);
-+ /* Hidden symbol not has got entry,
-+ * only got.plt entry so it is (plt - got). */
-+ if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC)
-+ {
-+ bfd_vma idx;
-+ if (htab->elf.splt != NULL)
-+ {
-+ idx = (h->plt.offset - PLT_HEADER_SIZE)
-+ / PLT_ENTRY_SIZE;
-+ got_off = sec_addr (htab->elf.sgotplt)
-+ + GOTPLT_HEADER_SIZE
-+ + (idx * GOT_ENTRY_SIZE)
-+ - sec_addr (htab->elf.sgot);
-+ }
-+ else
-+ {
-+ idx = h->plt.offset / PLT_ENTRY_SIZE;
-+ got_off = sec_addr (htab->elf.sgotplt)
-+ + (idx * GOT_ENTRY_SIZE)
-+ - sec_addr (htab->elf.sgot);
-+ }
-+ }
-+
-+ if ((h->got.offset & 1) == 0)
-+ {
-+ /* We need to generate a R_LARCH_RELATIVE reloc once
-+ * in loongarch_elf_finish_dynamic_symbol or now,
-+ * call finish_dyn && nopic
-+ * or !call finish_dyn && pic. */
-+ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn,
-+ bfd_link_pic (info),
-+ h)
-+ && bfd_link_pic (info)
-+ && SYMBOL_REFERENCES_LOCAL (info, h))
-+ {
-+ Elf_Internal_Rela rela;
-+ rela.r_offset = sec_addr (got) + got_off;
-+ rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
-+ rela.r_addend = relocation;
-+ loongarch_elf_append_rela (output_bfd,
-+ htab->elf.srelgot, &rela);
-+ }
-+ h->got.offset |= 1;
-+ }
-+ }
-+ else
-+ {
-+ BFD_ASSERT (local_got_offsets
-+ && local_got_offsets[r_symndx] != MINUS_ONE);
-+
-+ got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
-+ if ((local_got_offsets[r_symndx] & 1) == 0)
-+ {
-+ if (bfd_link_pic (info))
-+ {
-+ Elf_Internal_Rela rela;
-+ rela.r_offset = sec_addr (got) + got_off;
-+ rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
-+ rela.r_addend = relocation;
-+ loongarch_elf_append_rela (output_bfd,
-+ htab->elf.srelgot, &rela);
-+ }
-+ local_got_offsets[r_symndx] |= 1;
-+ }
-+ }
-+
-+ bfd_put_NN (output_bfd, relocation, got->contents + got_off);
-+
-+ relocation = got_off + sec_addr (got);
-+ }
-+
-+ if (r_type == R_LARCH_GOT_PC_HI20)
-+ RELOCATE_CALC_PC32_HI20 (relocation, pc);
-+
-+ break;
-+
-+ case R_LARCH_GOT_PC_LO12:
-+ case R_LARCH_GOT64_PC_LO20:
-+ case R_LARCH_GOT64_PC_HI12:
-+ case R_LARCH_GOT_LO12:
-+ case R_LARCH_GOT64_LO20:
-+ case R_LARCH_GOT64_HI12:
-+ {
-+ unresolved_reloc = FALSE;
-+ bfd_vma got_off;
-+ if (h)
-+ got_off = h->got.offset & (~(bfd_vma)1);
-+ else
-+ got_off = local_got_offsets[r_symndx] & (~(bfd_vma)1);
-+
-+ if (h && h->got.offset == MINUS_ONE && h->type ==
STT_GNU_IFUNC)
-+ {
-+ bfd_vma idx;
-+ if (htab->elf.splt != NULL)
-+ idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
-+ else
-+ idx = h->plt.offset / PLT_ENTRY_SIZE;
-+
-+ got_off = sec_addr (htab->elf.sgotplt)
-+ + GOTPLT_HEADER_SIZE
-+ + (idx * GOT_ENTRY_SIZE)
-+ - sec_addr (htab->elf.sgot);
-+ }
-+ relocation = got_off + sec_addr (got);
-+ }
-+
-+ if (r_type == R_LARCH_GOT_PC_LO12)
-+ relocation &= (bfd_vma)0xfff;
-+ else if (r_type == R_LARCH_GOT64_PC_LO20
-+ || r_type == R_LARCH_GOT64_PC_HI12)
-+ RELOCATE_CALC_PC64_HI32 (relocation, pc);
-+
-+ break;
-+
-+ case R_LARCH_TLS_LE_HI20:
-+ case R_LARCH_TLS_LE_LO12:
-+ case R_LARCH_TLS_LE64_LO20:
-+ case R_LARCH_TLS_LE64_HI12:
-+ BFD_ASSERT (resolved_local && elf_hash_table (info)->tls_sec);
-+
-+ relocation -= elf_hash_table (info)->tls_sec->vma;
-+ break;
-+
-+ /* TLS IE LD/GD process separately is troublesome.
-+ When a symbol is both ie and LD/GD, h->got.off |= 1
-+ make only one type be relocated. We must use
-+ h->got.offset |= 1 and h->got.offset |= 2
-+ diff IE and LD/GD. And all (got_off & (~(bfd_vma)1))
-+ (IE LD/GD and reusable GOT reloc) must change to
-+ (got_off & (~(bfd_vma)3)), beause we use lowest 2 bits
-+ as a tag.
-+ Now, LD and GD is both GOT_TLS_GD type, LD seems to
-+ can be omitted. */
-+ case R_LARCH_TLS_IE_PC_HI20:
-+ case R_LARCH_TLS_IE_HI20:
-+ case R_LARCH_TLS_LD_PC_HI20:
-+ case R_LARCH_TLS_LD_HI20:
-+ case R_LARCH_TLS_GD_PC_HI20:
-+ case R_LARCH_TLS_GD_HI20:
-+ BFD_ASSERT (rel->r_addend == 0);
-+ unresolved_reloc = FALSE;
-+
-+ if (r_type == R_LARCH_TLS_IE_PC_HI20
-+ || r_type == R_LARCH_TLS_IE_HI20)
-+ is_ie = TRUE;
-+
-+ bfd_vma got_off = 0;
-+ if (h != NULL)
-+ {
-+ got_off = h->got.offset;
-+ h->got.offset |= 1;
-+ }
-+ else
-+ {
-+ got_off = local_got_offsets[r_symndx];
-+ local_got_offsets[r_symndx] |= 1;
-+ }
-+
-+ 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))
-+ ie_off = 2 * GOT_ENTRY_SIZE;
-+
-+ if ((got_off & 1) == 0)
-+ {
-+ Elf_Internal_Rela rela;
-+ asection *relgot = htab->elf.srelgot;
-+ bfd_vma tls_block_off = 0;
-+
-+ if (SYMBOL_REFERENCES_LOCAL (info, h))
-+ {
-+ BFD_ASSERT (elf_hash_table (info)->tls_sec);
-+ tls_block_off = relocation
-+ - elf_hash_table (info)->tls_sec->vma;
-+ }
-+
-+ if (tls_type & GOT_TLS_GD)
-+ {
-+ rela.r_offset = sec_addr (got) + got_off;
-+ rela.r_addend = 0;
-+ if (SYMBOL_REFERENCES_LOCAL (info, h))
-+ {
-+ /* Local sym, used in exec, set module id 1. */
-+ if (bfd_link_executable (info))
-+ bfd_put_NN (output_bfd, 1, got->contents + got_off);
-+ else
-+ {
-+ rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN);
-+ loongarch_elf_append_rela (output_bfd, relgot, &rela);
-+ }
-+
-+ bfd_put_NN (output_bfd, tls_block_off,
-+ got->contents + got_off + GOT_ENTRY_SIZE);
-+ }
-+ /* Dynamic resolved. */
-+ else
-+ {
-+ /* Dynamic relocate module id. */
-+ rela.r_info = ELFNN_R_INFO (h->dynindx,
-+ R_LARCH_TLS_DTPMODNN);
-+ loongarch_elf_append_rela (output_bfd, relgot, &rela);
-+
-+ /* Dynamic relocate offset of block. */
-+ rela.r_offset += GOT_ENTRY_SIZE;
-+ rela.r_info = ELFNN_R_INFO (h->dynindx,
-+ R_LARCH_TLS_DTPRELNN);
-+ loongarch_elf_append_rela (output_bfd, relgot, &rela);
-+ }
-+ }
-+ if (tls_type & GOT_TLS_IE)
-+ {
-+ rela.r_offset = sec_addr (got) + got_off + ie_off;
-+ if (SYMBOL_REFERENCES_LOCAL (info, h))
-+ {
-+ /* Local sym, used in exec, set module id 1. */
-+ if (!bfd_link_executable (info))
-+ {
-+ rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN);
-+ rela.r_addend = tls_block_off;
-+ loongarch_elf_append_rela (output_bfd, relgot, &rela);
-+ }
-+
-+ bfd_put_NN (output_bfd, tls_block_off,
-+ got->contents + got_off + ie_off);
-+ }
-+ /* Dynamic resolved. */
-+ else
-+ {
-+ /* Dynamic relocate offset of block. */
-+ rela.r_info = ELFNN_R_INFO (h->dynindx,
-+ R_LARCH_TLS_TPRELNN);
-+ rela.r_addend = 0;
-+ loongarch_elf_append_rela (output_bfd, relgot, &rela);
-+ }
-+ }
-+ }
-+ relocation = (got_off & (~(bfd_vma)1)) + sec_addr (got)
-+ + (is_ie ? ie_off : 0);
-+
-+ 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)
-+ RELOCATE_CALC_PC32_HI20 (relocation, pc);
-+
-+ break;
-+
-+ case R_LARCH_TLS_IE_PC_LO12:
-+ case R_LARCH_TLS_IE64_PC_LO20:
-+ case R_LARCH_TLS_IE64_PC_HI12:
-+ case R_LARCH_TLS_IE_LO12:
-+ case R_LARCH_TLS_IE64_LO20:
-+ case R_LARCH_TLS_IE64_HI12:
-+ unresolved_reloc = FALSE;
-+
-+ if (h)
-+ relocation = sec_addr (got) + (h->got.offset & (~(bfd_vma)3));
-+ else
-+ relocation = sec_addr (got)
-+ + (local_got_offsets[r_symndx] & (~(bfd_vma)3));
-+
-+ 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))
-+ relocation += 2 * GOT_ENTRY_SIZE;
-+
-+ if (r_type == R_LARCH_TLS_IE_PC_LO12)
-+ relocation &= (bfd_vma)0xfff;
-+ else if (r_type == R_LARCH_TLS_IE64_PC_LO20
-+ || r_type == R_LARCH_TLS_IE64_PC_HI12)
-+ RELOCATE_CALC_PC64_HI32 (relocation, pc);
-+
-+ break;
-+
-+ case R_LARCH_RELAX:
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ if (fatal)
-+ break;
-+
-+ do
-+ {
-+ /* 'unresolved_reloc' means we haven't done it yet.
-+ We need help of dynamic linker to fix this memory location up. */
-+ if (!unresolved_reloc)
-+ break;
-+
-+ if (_bfd_elf_section_offset (output_bfd, info, input_section,
-+ rel->r_offset) == MINUS_ONE)
-+ /* WHY? May because it's invalid so skip checking.
-+ But why dynamic reloc a invalid section? */
-+ break;
-+
-+ if (input_section->output_section->flags & SEC_DEBUGGING)
-+ {
-+ fatal = (loongarch_reloc_is_fatal
-+ (info, input_bfd, input_section, rel, howto,
-+ bfd_reloc_dangerous, is_undefweak, name,
-+ "Seems dynamic linker not process "
-+ "sections 'SEC_DEBUGGING'."));
-+ }
-+ if (!is_dyn)
-+ break;
-+
-+ if ((info->flags & DF_TEXTREL) == 0)
-+ if (input_section->output_section->flags & SEC_READONLY)
-+ info->flags |= DF_TEXTREL;
-+ }
-+ while (0);
-+
-+ if (fatal)
-+ break;
-+
-+ loongarch_record_one_reloc (input_bfd, input_section, r_type,
-+ rel->r_offset, sym, h, rel->r_addend);
-+
-+ if (r != bfd_reloc_continue)
-+ r = perform_relocation (rel, input_section, howto, relocation,
-+ input_bfd, contents);
-+
-+ switch (r)
-+ {
-+ case bfd_reloc_dangerous:
-+ case bfd_reloc_continue:
-+ case bfd_reloc_ok:
-+ continue;
-+
-+ case bfd_reloc_overflow:
-+ /* Overflow value can't be filled in. */
-+ loongarch_dump_reloc_record (info->callbacks->info);
-+ info->callbacks->reloc_overflow
-+ (info, h ? &h->root : NULL, name, howto->name, rel->r_addend,
-+ input_bfd, input_section, rel->r_offset);
-+ break;
-+
-+ case bfd_reloc_outofrange:
-+ /* Stack state incorrect. */
-+ loongarch_dump_reloc_record (info->callbacks->info);
-+ info->callbacks->info
-+ ("%X%H: Internal stack state is incorrect.\n"
-+ "Want to push to full stack or pop from empty stack?\n",
-+ input_bfd, input_section, rel->r_offset);
-+ break;
-+
-+ case bfd_reloc_notsupported:
-+ info->callbacks->info ("%X%H: Unknown relocation type.\n",
input_bfd,
-+ input_section, rel->r_offset);
-+ break;
-+
-+ default:
-+ info->callbacks->info ("%X%H: Internal: unknown error.\n",
input_bfd,
-+ input_section, rel->r_offset);
-+ break;
-+ }
-+
-+ fatal = TRUE;
-+ }
-+
-+ return !fatal;
-+}
-+
-+/* Finish up dynamic symbol handling. We set the contents of various
-+ dynamic sections here. */
-+
-+static bfd_boolean
-+loongarch_elf_finish_dynamic_symbol (bfd *output_bfd,
-+ struct bfd_link_info *info,
-+ struct elf_link_hash_entry *h,
-+ Elf_Internal_Sym *sym)
-+{
-+ struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
-+ const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
-+
-+ if (h->plt.offset != MINUS_ONE)
-+ {
-+ size_t i, plt_idx;
-+ asection *plt, *gotplt, *relplt;
-+ bfd_vma got_address;
-+ uint32_t plt_entry[PLT_ENTRY_INSNS];
-+ bfd_byte *loc;
-+ Elf_Internal_Rela rela;
-+
-+ if (htab->elf.splt)
-+ {
-+ BFD_ASSERT ((h->type == STT_GNU_IFUNC
-+ && SYMBOL_REFERENCES_LOCAL (info, h))
-+ || h->dynindx != -1);
-+
-+ plt = htab->elf.splt;
-+ gotplt = htab->elf.sgotplt;
-+ if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h))
-+ relplt = htab->elf.srelgot;
-+ else
-+ relplt = htab->elf.srelplt;
-+ plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
-+ got_address =
-+ sec_addr (gotplt) + GOTPLT_HEADER_SIZE + plt_idx * GOT_ENTRY_SIZE;
-+ }
-+ else /* if (htab->elf.iplt) */
-+ {
-+ BFD_ASSERT (h->type == STT_GNU_IFUNC
-+ && SYMBOL_REFERENCES_LOCAL (info, h));
-+
-+ plt = htab->elf.iplt;
-+ gotplt = htab->elf.igotplt;
-+ relplt = htab->elf.irelplt;
-+ plt_idx = h->plt.offset / PLT_ENTRY_SIZE;
-+ got_address = sec_addr (gotplt) + plt_idx * GOT_ENTRY_SIZE;
-+ }
-+
-+ /* Find out where the .plt entry should go. */
-+ loc = plt->contents + h->plt.offset;
-+
-+ /* Fill in the PLT entry itself. */
-+ if (!loongarch_make_plt_entry (got_address,
-+ sec_addr (plt) + h->plt.offset,
-+ plt_entry))
-+ return FALSE;
-+
-+ for (i = 0; i < PLT_ENTRY_INSNS; i++)
-+ bfd_put_32 (output_bfd, plt_entry[i], loc + 4 * i);
-+
-+ /* Fill in the initial value of the got.plt entry. */
-+ loc = gotplt->contents + (got_address - sec_addr (gotplt));
-+ bfd_put_NN (output_bfd, sec_addr (plt), loc);
-+
-+ rela.r_offset = got_address;
-+
-+ /* TRUE if this is a PLT reference to a local IFUNC. */
-+ if (PLT_LOCAL_IFUNC_P (info, h)
-+ && (relplt == htab->elf.srelgot
-+ || relplt == htab->elf.irelplt))
-+ {
-+ {
-+ rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
-+ rela.r_addend = (h->root.u.def.value
-+ + h->root.u.def.section->output_section->vma
-+ + h->root.u.def.section->output_offset);
-+ }
-+
-+ /* Find the space after dyn sort. */
-+ {
-+ Elf_Internal_Rela *dyn = (Elf_Internal_Rela *)relplt->contents;
-+ bfd_boolean fill = FALSE;
-+ for (;dyn < dyn + relplt->size / sizeof (*dyn); dyn++)
-+ {
-+ if (0 == dyn->r_offset)
-+ {
-+ bed->s->swap_reloca_out (output_bfd, &rela,
-+ (bfd_byte *)dyn);
-+ relplt->reloc_count++;
-+ fill = TRUE;
-+ break;
-+ }
-+ }
-+ BFD_ASSERT (fill);
-+ }
-+
-+ }
-+ else
-+ {
-+ /* Fill in the entry in the rela.plt section. */
-+ rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_JUMP_SLOT);
-+ rela.r_addend = 0;
-+ loc = relplt->contents + plt_idx * sizeof (ElfNN_External_Rela);
-+ bed->s->swap_reloca_out (output_bfd, &rela, loc);
-+ }
-+
-+ if (!h->def_regular)
-+ {
-+ /* Mark the symbol as undefined, rather than as defined in
-+ the .plt section. Leave the value alone. */
-+ sym->st_shndx = SHN_UNDEF;
-+ /* If the symbol is weak, we do need to clear the value.
-+ Otherwise, the PLT entry would provide a definition for
-+ the symbol even if the symbol wasn't defined anywhere,
-+ and so the symbol would never be NULL. */
-+ if (!h->ref_regular_nonweak)
-+ sym->st_value = 0;
-+ }
-+ }
-+
-+ 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))
-+ /* Have allocated got entry but not allocated rela before. */
-+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
-+ {
-+ asection *sgot, *srela;
-+ Elf_Internal_Rela rela;
-+ bfd_vma off = h->got.offset & ~(bfd_vma)1;
-+
-+ /* This symbol has an entry in the GOT. Set it up. */
-+ sgot = htab->elf.sgot;
-+ srela = htab->elf.srelgot;
-+ BFD_ASSERT (sgot && srela);
-+
-+ rela.r_offset = sec_addr (sgot) + off;
-+
-+ if (h->def_regular
-+ && h->type == STT_GNU_IFUNC)
-+ {
-+ if(h->plt.offset == MINUS_ONE)
-+ {
-+ if (htab->elf.splt == NULL)
-+ srela = htab->elf.irelplt;
-+
-+ if (SYMBOL_REFERENCES_LOCAL (info, h))
-+ {
-+ asection *sec = h->root.u.def.section;
-+ rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE);
-+ rela.r_addend = h->root.u.def.value + sec->output_section->vma
-+ + sec->output_offset;
-+ bfd_put_NN (output_bfd, 0, sgot->contents + off);
-+ }
-+ else
-+ {
-+ BFD_ASSERT (h->dynindx != -1);
-+ rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
-+ rela.r_addend = 0;
-+ bfd_put_NN (output_bfd, (bfd_vma) 0, sgot->contents + off);
-+ }
-+ }
-+ else if(bfd_link_pic (info))
-+ {
-+ rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
-+ rela.r_addend = 0;
-+ bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off);
-+ }
-+ else
-+ {
-+ asection *plt;
-+ /* For non-shared object, we can't use .got.plt, which
-+ contains the real function address if we need pointer
-+ equality. We load the GOT entry with the PLT entry. */
-+ plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt;
-+ bfd_put_NN (output_bfd,
-+ (plt->output_section->vma
-+ + plt->output_offset
-+ + h->plt.offset),
-+ sgot->contents + off);
-+ return TRUE;
-+ }
-+ }
-+ else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h))
-+ {
-+ asection *sec = h->root.u.def.section;
-+ rela.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE);
-+ rela.r_addend = (h->root.u.def.value + sec->output_section->vma
-+ + sec->output_offset);
-+ }
-+ else
-+ {
-+ BFD_ASSERT (h->dynindx != -1);
-+ rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN);
-+ rela.r_addend = 0;
-+ }
-+
-+ loongarch_elf_append_rela (output_bfd, srela, &rela);
-+ }
-+
-+ /* Mark some specially defined symbols as absolute. */
-+ if (h == htab->elf.hdynamic || h == htab->elf.hgot || h == htab->elf.hplt)
-+ sym->st_shndx = SHN_ABS;
-+
-+ return TRUE;
-+}
-+
-+/* Finish up the dynamic sections. */
-+
-+static bfd_boolean
-+loongarch_finish_dyn (bfd *output_bfd, struct bfd_link_info *info, bfd *dynobj,
-+ asection *sdyn)
-+{
-+ struct loongarch_elf_link_hash_table *htab = loongarch_elf_hash_table (info);
-+ const struct elf_backend_data *bed = get_elf_backend_data (output_bfd);
-+ size_t dynsize = bed->s->sizeof_dyn, skipped_size = 0;
-+ bfd_byte *dyncon, *dynconend;
-+
-+ dynconend = sdyn->contents + sdyn->size;
-+ for (dyncon = sdyn->contents; dyncon < dynconend; dyncon += dynsize)
-+ {
-+ Elf_Internal_Dyn dyn;
-+ asection *s;
-+ int skipped = 0;
-+
-+ bed->s->swap_dyn_in (dynobj, dyncon, &dyn);
-+
-+ switch (dyn.d_tag)
-+ {
-+ case DT_PLTGOT:
-+ s = htab->elf.sgotplt;
-+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
-+ break;
-+ case DT_JMPREL:
-+ s = htab->elf.srelplt;
-+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
-+ break;
-+ case DT_PLTRELSZ:
-+ s = htab->elf.srelplt;
-+ dyn.d_un.d_val = s->size;
-+ break;
-+ case DT_TEXTREL:
-+ if ((info->flags & DF_TEXTREL) == 0)
-+ skipped = 1;
-+ break;
-+ case DT_FLAGS:
-+ if ((info->flags & DF_TEXTREL) == 0)
-+ dyn.d_un.d_val &= ~DF_TEXTREL;
-+ break;
-+ }
-+ if (skipped)
-+ skipped_size += dynsize;
-+ else
-+ bed->s->swap_dyn_out (output_bfd, &dyn, dyncon - skipped_size);
-+ }
-+ /* Wipe out any trailing entries if we shifted down a dynamic tag. */
-+ memset (dyncon - skipped_size, 0, skipped_size);
-+ return TRUE;
-+}
-+
-+/* Finish up local dynamic symbol handling. We set the contents of
-+ various dynamic sections here. */
-+
-+static bfd_boolean
-+elfNN_loongarch_finish_local_dynamic_symbol (void **slot, void *inf)
-+{
-+ struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot;
-+ struct bfd_link_info *info = (struct bfd_link_info *) inf;
-+
-+ return loongarch_elf_finish_dynamic_symbol (info->output_bfd, info, h, NULL);
-+}
-+
-+static bfd_boolean
-+loongarch_elf_finish_dynamic_sections (bfd *output_bfd,
-+ struct bfd_link_info *info)
-+{
-+ bfd *dynobj;
-+ asection *sdyn, *plt, *gotplt = NULL;
-+ struct loongarch_elf_link_hash_table *htab;
-+
-+ htab = loongarch_elf_hash_table (info);
-+ BFD_ASSERT (htab);
-+ dynobj = htab->elf.dynobj;
-+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
-+
-+ if (elf_hash_table (info)->dynamic_sections_created)
-+ {
-+ BFD_ASSERT (htab->elf.splt && sdyn);
-+
-+ if (!loongarch_finish_dyn (output_bfd, info, dynobj, sdyn))
-+ return FALSE;
-+ }
-+
-+ plt = htab->elf.splt;
-+ gotplt = htab->elf.sgotplt;
-+
-+ if (plt && 0 < plt->size)
-+ {
-+ size_t i;
-+ uint32_t plt_header[PLT_HEADER_INSNS];
-+ if (!loongarch_make_plt_header (sec_addr (gotplt), sec_addr (plt),
-+ plt_header))
-+ return FALSE;
-+
-+ for (i = 0; i < PLT_HEADER_INSNS; i++)
-+ bfd_put_32 (output_bfd, plt_header[i], plt->contents + 4 * i);
-+
-+ elf_section_data (plt->output_section)->this_hdr.sh_entsize =
-+ PLT_ENTRY_SIZE;
-+ }
-+
-+ if (htab->elf.sgotplt)
-+ {
-+ asection *output_section = htab->elf.sgotplt->output_section;
-+
-+ if (bfd_is_abs_section (output_section))
-+ {
-+ _bfd_error_handler (_("discarded output section: `%pA'"),
-+ htab->elf.sgotplt);
-+ return FALSE;
-+ }
-+
-+ if (0 < htab->elf.sgotplt->size)
-+ {
-+ /* Write the first two entries in .got.plt, needed for the dynamic
-+ linker. */
-+ bfd_put_NN (output_bfd, MINUS_ONE, htab->elf.sgotplt->contents);
-+
-+ bfd_put_NN (output_bfd, (bfd_vma) 0,
-+ htab->elf.sgotplt->contents + GOT_ENTRY_SIZE);
-+ }
-+
-+ elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
-+ }
-+
-+ if (htab->elf.sgot)
-+ {
-+ asection *output_section = htab->elf.sgot->output_section;
-+
-+ if (0 < htab->elf.sgot->size)
-+ {
-+ /* Set the first entry in the global offset table to the address of
-+ the dynamic section. */
-+ bfd_vma val = sdyn ? sec_addr (sdyn) : 0;
-+ bfd_put_NN (output_bfd, val, htab->elf.sgot->contents);
-+ }
-+
-+ elf_section_data (output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE;
-+ }
-+
-+ /* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
-+ htab_traverse (htab->loc_hash_table,
-+ (void *) elfNN_loongarch_finish_local_dynamic_symbol, info);
-+
-+ return TRUE;
-+}
-+
-+/* Return address for Ith PLT stub in section PLT, for relocation REL
-+ or (bfd_vma) -1 if it should not be included. */
-+
-+static bfd_vma
-+loongarch_elf_plt_sym_val (bfd_vma i, const asection *plt,
-+ const arelent *rel ATTRIBUTE_UNUSED)
-+{
-+ return plt->vma + PLT_HEADER_SIZE + i * PLT_ENTRY_SIZE;
-+}
-+
-+static enum elf_reloc_type_class
-+loongarch_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED,
-+ const asection *rel_sec ATTRIBUTE_UNUSED,
-+ const Elf_Internal_Rela *rela)
-+{
-+ struct loongarch_elf_link_hash_table *htab;
-+ htab = loongarch_elf_hash_table (info);
-+
-+ if (htab->elf.dynsym != NULL && htab->elf.dynsym->contents != NULL)
-+ {
-+ /* Check relocation against STT_GNU_IFUNC symbol if there are
-+ dynamic symbols. */
-+ bfd *abfd = info->output_bfd;
-+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
-+ unsigned long r_symndx = ELFNN_R_SYM (rela->r_info);
-+ if (r_symndx != STN_UNDEF)
-+ {
-+ Elf_Internal_Sym sym;
-+ if (!bed->s->swap_symbol_in (abfd,
-+ htab->elf.dynsym->contents
-+ + r_symndx * bed->s->sizeof_sym,
-+ 0, &sym))
-+ {
-+ /* xgettext:c-format */
-+ _bfd_error_handler (_("%pB symbol number %lu references"
-+ " nonexistent SHT_SYMTAB_SHNDX section"),
-+ abfd, r_symndx);
-+ /* Ideally an error class should be returned here. */
-+ }
-+ else if (ELF_ST_TYPE (sym.st_info) == STT_GNU_IFUNC)
-+ return reloc_class_ifunc;
-+ }
-+ }
-+
-+ switch (ELFNN_R_TYPE (rela->r_info))
-+ {
-+ case R_LARCH_IRELATIVE:
-+ return reloc_class_ifunc;
-+ case R_LARCH_RELATIVE:
-+ return reloc_class_relative;
-+ case R_LARCH_JUMP_SLOT:
-+ return reloc_class_plt;
-+ case R_LARCH_COPY:
-+ return reloc_class_copy;
-+ default:
-+ return reloc_class_normal;
-+ }
-+}
-+
-+/* Copy the extra info we tack onto an elf_link_hash_entry. */
-+
-+static void
-+loongarch_elf_copy_indirect_symbol (struct bfd_link_info *info,
-+ struct elf_link_hash_entry *dir,
-+ struct elf_link_hash_entry *ind)
-+{
-+ struct elf_link_hash_entry *edir, *eind;
-+
-+ edir = dir;
-+ eind = ind;
-+
-+ if (eind->dyn_relocs != NULL)
-+ {
-+ if (edir->dyn_relocs != NULL)
-+ {
-+ struct elf_dyn_relocs **pp;
-+ struct elf_dyn_relocs *p;
-+
-+ /* Add reloc counts against the indirect sym to the direct sym
-+ list. Merge any entries against the same section. */
-+ for (pp = &eind->dyn_relocs; (p = *pp) != NULL;)
-+ {
-+ struct elf_dyn_relocs *q;
-+
-+ for (q = edir->dyn_relocs; q != NULL; q = q->next)
-+ if (q->sec == p->sec)
-+ {
-+ q->pc_count += p->pc_count;
-+ q->count += p->count;
-+ *pp = p->next;
-+ break;
-+ }
-+ if (q == NULL)
-+ pp = &p->next;
-+ }
-+ *pp = edir->dyn_relocs;
-+ }
-+
-+ edir->dyn_relocs = eind->dyn_relocs;
-+ eind->dyn_relocs = NULL;
-+ }
-+
-+ if (ind->root.type == bfd_link_hash_indirect && dir->got.refcount <
0)
-+ {
-+ loongarch_elf_hash_entry(edir)->tls_type
-+ = loongarch_elf_hash_entry(eind)->tls_type;
-+ loongarch_elf_hash_entry(eind)->tls_type = GOT_UNKNOWN;
-+ }
-+ _bfd_elf_link_hash_copy_indirect (info, dir, ind);
-+}
-+
-+#define PRSTATUS_SIZE 0x1d8
-+#define PRSTATUS_OFFSET_PR_CURSIG 0xc
-+#define PRSTATUS_OFFSET_PR_PID 0x20
-+#define ELF_GREGSET_T_SIZE 0x168
-+#define PRSTATUS_OFFSET_PR_REG 0x70
-+
-+/* Support for core dump NOTE sections. */
-+
-+static bfd_boolean
-+loongarch_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
-+{
-+ switch (note->descsz)
-+ {
-+ default:
-+ return FALSE;
-+
-+ /* The sizeof (struct elf_prstatus) on Linux/LoongArch. */
-+ case PRSTATUS_SIZE:
-+ /* pr_cursig */
-+ elf_tdata (abfd)->core->signal =
-+ bfd_get_16 (abfd, note->descdata + PRSTATUS_OFFSET_PR_CURSIG);
-+
-+ /* pr_pid */
-+ elf_tdata (abfd)->core->lwpid =
-+ bfd_get_32 (abfd, note->descdata + PRSTATUS_OFFSET_PR_PID);
-+ break;
-+ }
-+
-+ /* Make a ".reg/999" section. */
-+ return _bfd_elfcore_make_pseudosection (abfd, ".reg", ELF_GREGSET_T_SIZE,
-+ note->descpos
-+ + PRSTATUS_OFFSET_PR_REG);
-+}
-+
-+#define PRPSINFO_SIZE 0x88
-+#define PRPSINFO_OFFSET_PR_PID 0x18
-+#define PRPSINFO_OFFSET_PR_FNAME 0x28
-+#define PRPSINFO_SIZEOF_PR_FNAME 0x10
-+#define PRPSINFO_OFFSET_PR_PS_ARGS 0x38
-+#define PRPSINFO_SIZEOF_PR_PS_ARGS 0x50
-+
-+static bfd_boolean
-+loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
-+{
-+ switch (note->descsz)
-+ {
-+ default:
-+ return FALSE;
-+
-+ /* The sizeof (prpsinfo_t) on Linux/LoongArch. */
-+ case PRPSINFO_SIZE:
-+ /* pr_pid */
-+ elf_tdata (abfd)->core->pid =
-+ bfd_get_32 (abfd, note->descdata + PRPSINFO_OFFSET_PR_PID);
-+
-+ /* pr_fname */
-+ elf_tdata (abfd)->core->program =
-+ _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_FNAME,
-+ PRPSINFO_SIZEOF_PR_FNAME);
-+
-+ /* pr_psargs */
-+ elf_tdata (abfd)->core->command =
-+ _bfd_elfcore_strndup (abfd, note->descdata + PRPSINFO_OFFSET_PR_PS_ARGS,
-+ PRPSINFO_SIZEOF_PR_PS_ARGS);
-+ break;
-+ }
-+
-+ /* Note that for some reason, a spurious space is tacked
-+ onto the end of the args in some (at least one anyway)
-+ implementations, so strip it off if it exists. */
-+
-+ {
-+ char *command = elf_tdata (abfd)->core->command;
-+ int n = strlen (command);
-+
-+ if (0 < n && command[n - 1] == ' ')
-+ command[n - 1] = '\0';
-+ }
-+
-+ return TRUE;
-+}
-+
-+/* Set the right mach type. */
-+static bfd_boolean
-+loongarch_elf_object_p (bfd *abfd)
-+{
-+ /* There are only two mach types in LoongArch currently. */
-+ if (strcmp (abfd->xvec->name, "elf64-loongarch") == 0)
-+ bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch64);
-+ else
-+ bfd_default_set_arch_mach (abfd, bfd_arch_loongarch, bfd_mach_loongarch32);
-+ return TRUE;
-+}
-+
-+static asection *
-+loongarch_elf_gc_mark_hook (asection *sec, struct bfd_link_info *info,
-+ Elf_Internal_Rela *rel,
-+ struct elf_link_hash_entry *h,
-+ Elf_Internal_Sym *sym)
-+{
-+ if (h != NULL)
-+ switch (ELFNN_R_TYPE (rel->r_info))
-+ {
-+ case R_LARCH_GNU_VTINHERIT:
-+ case R_LARCH_GNU_VTENTRY:
-+ return NULL;
-+ }
-+
-+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
-+}
-+
-+/* Return TRUE if symbol H should be hashed in the `.gnu.hash' section. For
-+ executable PLT slots where the executable never takes the address of those
-+ functions, the function symbols are not added to the hash table. */
-+
-+static bfd_boolean
-+elf_loongarch64_hash_symbol (struct elf_link_hash_entry *h)
-+{
-+ if (h->plt.offset != (bfd_vma) -1
-+ && !h->def_regular
-+ && !h->pointer_equality_needed)
-+ return FALSE;
-+
-+ return _bfd_elf_hash_symbol (h);
-+}
-+
-+#define TARGET_LITTLE_SYM loongarch_elfNN_vec
-+#define TARGET_LITTLE_NAME "elfNN-loongarch"
-+#define ELF_ARCH bfd_arch_loongarch
-+#define ELF_TARGET_ID LARCH_ELF_DATA
-+#define ELF_MACHINE_CODE EM_LOONGARCH
-+#define ELF_MAXPAGESIZE 0x4000
-+#define bfd_elfNN_bfd_reloc_type_lookup loongarch_reloc_type_lookup
-+#define bfd_elfNN_bfd_link_hash_table_create \
-+ loongarch_elf_link_hash_table_create
-+#define bfd_elfNN_bfd_reloc_name_lookup loongarch_reloc_name_lookup
-+#define elf_info_to_howto_rel NULL /* Fall through to elf_info_to_howto. */
-+#define elf_info_to_howto loongarch_info_to_howto_rela
-+#define bfd_elfNN_bfd_merge_private_bfd_data \
-+ elfNN_loongarch_merge_private_bfd_data
-+
-+#define elf_backend_reloc_type_class loongarch_reloc_type_class
-+#define elf_backend_copy_indirect_symbol loongarch_elf_copy_indirect_symbol
-+#define elf_backend_create_dynamic_sections \
-+ loongarch_elf_create_dynamic_sections
-+#define elf_backend_check_relocs loongarch_elf_check_relocs
-+#define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
-+#define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
-+#define elf_backend_relocate_section loongarch_elf_relocate_section
-+#define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
-+#define elf_backend_finish_dynamic_sections \
-+ loongarch_elf_finish_dynamic_sections
-+#define elf_backend_object_p loongarch_elf_object_p
-+#define elf_backend_gc_mark_hook loongarch_elf_gc_mark_hook
-+#define elf_backend_plt_sym_val loongarch_elf_plt_sym_val
-+#define elf_backend_grok_prstatus loongarch_elf_grok_prstatus
-+#define elf_backend_grok_psinfo loongarch_elf_grok_psinfo
-+#define elf_backend_hash_symbol elf_loongarch64_hash_symbol
-+
-+#include "elfNN-target.h"
---- /dev/null
-+++ gdb-10.2/bfd/elfxx-loongarch.c
-@@ -0,0 +1,1618 @@
-+/* LoongArch-specific support for ELF.
-+ Copyright (C) 2021-2022 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ Based on LoongArch target.
-+
-+ This file is part of BFD, the Binary File Descriptor library.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING3. If not,
-+ see <
http://www.gnu.org/licenses/>. */
-+
-+#include "sysdep.h"
-+#include "bfd.h"
-+#include "libbfd.h"
-+#include "elf-bfd.h"
-+#include "elf/loongarch.h"
-+#include "elfxx-loongarch.h"
-+
-+#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;
-+ bfd_boolean (*adjust_reloc_bits)(reloc_howto_type *, bfd_vma *);
-+ const char *larch_reloc_type_name;
-+} 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, NULL }
-+
-+#define LOONGARCH_HOWTO(type, right, size, bits, pcrel, left, ovf, func, \
-+ name, inplace, src_mask, dst_mask, pcrel_off, btype, afunc,lname) \
-+ { HOWTO(type, right, size, bits, pcrel, left, ovf, func, name, \
-+ inplace, src_mask, dst_mask, pcrel_off), btype, afunc, lname }
-+
-+#define LOONGARCH_EMPTY_HOWTO(C) \
-+ { EMPTY_HOWTO (C), BFD_RELOC_NONE, NULL, NULL }
-+
-+static bfd_boolean
-+reloc_bits (reloc_howto_type *howto, bfd_vma *val);
-+static bfd_boolean
-+reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val);
-+static bfd_boolean
-+reloc_bits_b21 (reloc_howto_type *howto, bfd_vma *fix_val);
-+static bfd_boolean
-+reloc_bits_b26 (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 loongarch_reloc_howto_type loongarch_howto_table[] =
-+{
-+ /* No relocation. */
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ /* 32 bit relocation. */
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ /* 64 bit relocation. */
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_COPY, /* type (4). */
-+ 0, /* rightshift */
-+ 3, /* 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ /* Dynamic TLS relocations. */
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_MARK_LA", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask. */
-+ 0, /* dst_mask. */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_MARK_LA, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_MARK_PCREL, /* type (21). */
-+ 0, /* rightshift. */
-+ 3, /* size. */
-+ 0, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_MARK_PCREL", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask. */
-+ 0, /* dst_mask. */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_MARK_PCREL, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type (22). */
-+ 2, /* rightshift. */
-+ 2, /* size. */
-+ 32, /* bitsize. */
-+ TRUE /* FIXME: somewhat use this. */, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_SOP_PUSH_PCREL", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0x03ffffff, /* src_mask. */
-+ 0x03ffffff, /* dst_mask. */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_SOP_PUSH_PCREL, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ /* type 23-37. */
-+ 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 */
-+ reloc_bits, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ reloc_bits, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ reloc_bits, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ reloc_bits, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ reloc_bits_b16, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ reloc_bits, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ 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 */
-+ reloc_bits_b21, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, /* type (45). */
-+ 2, /* rightshift. */
-+ 2, /* size. */
-+ 26, /* 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_10_10_16_S2", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x03ffffff, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2,
-+ /* bfd_reloc_code_real_type */
-+ reloc_bits_b26, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_SOP_POP_32_U, /* type (46). */
-+ 0, /* rightshift. */
-+ 2, /* size. */
-+ 32, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_unsigned, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_SOP_POP_32_S_U", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0xffffffff00000000, /* src_mask */
-+ 0x00000000ffffffff, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_SOP_POP_32_U, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_ADD8, /* type (47). */
-+ 0, /* rightshift. */
-+ 2, /* size. */
-+ 8, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_ADD8", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ ALL_ONES, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_ADD8, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_ADD16, /* type (48). */
-+ 0, /* rightshift. */
-+ 2, /* size. */
-+ 16, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_ADD16", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ ALL_ONES, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_ADD16, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_ADD24, /* type (49). */
-+ 0, /* rightshift. */
-+ 2, /* size. */
-+ 24, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_ADD24", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ ALL_ONES, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_ADD24, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_ADD32, /* type (50). */
-+ 0, /* rightshift. */
-+ 2, /* size. */
-+ 32, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_ADD32", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ ALL_ONES, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_ADD32, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_ADD64, /* type (51). */
-+ 0, /* rightshift. */
-+ 4, /* size. */
-+ 64, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_ADD64", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ ALL_ONES, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_ADD64, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_SUB8, /* type (52). */
-+ 0, /* rightshift. */
-+ 2, /* size. */
-+ 8, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_SUB8", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ ALL_ONES, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_SUB8, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_SUB16, /* type (53). */
-+ 0, /* rightshift. */
-+ 2, /* size. */
-+ 16, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_SUB16", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ ALL_ONES, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_SUB16, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_SUB24, /* type (54). */
-+ 0, /* rightshift. */
-+ 2, /* size. */
-+ 24, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_SUB24", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ ALL_ONES, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_SUB24, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_SUB32, /* type (55). */
-+ 0, /* rightshift. */
-+ 2, /* size. */
-+ 32, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_SUB32", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ ALL_ONES, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_SUB32, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_SUB64, /* type (56). */
-+ 0, /* rightshift. */
-+ 4, /* size. */
-+ 64, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_SUB64", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ ALL_ONES, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_SUB64, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_GNU_VTINHERIT, /* type (57). */
-+ 0, /* rightshift. */
-+ 3, /* 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_GNU_VTENTRY, /* type (58). */
-+ 0, /* rightshift. */
-+ 3, /* 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 */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_EMPTY_HOWTO (59),
-+ LOONGARCH_EMPTY_HOWTO (60),
-+ LOONGARCH_EMPTY_HOWTO (61),
-+ LOONGARCH_EMPTY_HOWTO (62),
-+ LOONGARCH_EMPTY_HOWTO (63),
-+
-+ /* New reloc types. */
-+ LOONGARCH_HOWTO (R_LARCH_B16, /* type (64). */
-+ 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_B16", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0x3fffc00, /* src_mask */
-+ 0x3fffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_B16, /* bfd_reloc_code_real_type */
-+ reloc_bits_b16, /* adjust_reloc_bits */
-+ "b16"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_B21, /* type (65). */
-+ 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_B21", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0xfc0003e0, /* src_mask */
-+ 0xfc0003e0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_B21, /* bfd_reloc_code_real_type */
-+ reloc_bits_b21, /* adjust_reloc_bits */
-+ "b21"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_B26, /* type (66). */
-+ 2, /* rightshift. */
-+ 2, /* size. */
-+ 26, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_B26", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x03ffffff, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_B26, /* bfd_reloc_code_real_type */
-+ reloc_bits_b26, /* adjust_reloc_bits */
-+ "b26"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_ABS_HI20, /* type (67). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_ABS_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_ABS_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "abs_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_ABS_LO12, /* type (68). */
-+ 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_ABS_LO12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_ABS_LO12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "abs_lo12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_ABS64_LO20, /* type (69). */
-+ 32, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_ABS64_LO20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_ABS64_LO20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "abs64_lo20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_ABS64_HI12, /* type (70). */
-+ 52, /* rightshift. */
-+ 2, /* size. */
-+ 12, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 10, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_ABS64_HI12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_ABS64_HI12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "abs64_hi12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_PCALA_HI20, /* type (71). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_PCALA_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_PCALA_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "pc_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_PCALA_LO12, /* type (72). */
-+ 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_PCALA_LO12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_PCALA_LO12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "pc_lo12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_PCALA64_LO20, /* type (73). */
-+ 32, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_PCALA64_LO20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_PCALA64_LO20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "pc64_lo20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_PCALA64_HI12, /* type (74). */
-+ 52, /* rightshift. */
-+ 2, /* size. */
-+ 12, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 10, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_PCALA64_HI12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_PCALA64_HI12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "pc64_hi12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_GOT_PC_HI20, /* type (75). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_GOT_PC_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_GOT_PC_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "got_pc_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_GOT_PC_LO12, /* type (76). */
-+ 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_GOT_PC_LO12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_GOT_PC_LO12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "got_pc_lo12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_GOT64_PC_LO20, /* type (77). */
-+ 32, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_GOT64_PC_LO20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_GOT64_PC_LO20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "got64_pc_lo20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_GOT64_PC_HI12, /* type (78). */
-+ 52, /* rightshift. */
-+ 2, /* size. */
-+ 12, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 10, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_GOT64_PC_HI12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_GOT64_PC_HI12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "got64_pc_hi12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_GOT_HI20, /* type (79). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_GOT_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_GOT_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "got_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_GOT_LO12, /* type (80). */
-+ 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_GOT_LO12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_GOT_LO12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "got_lo12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_GOT64_LO20, /* type (81). */
-+ 32, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_GOT64_LO20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_GOT64_LO20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "got64_lo20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_GOT64_HI12, /* type (82). */
-+ 52, /* rightshift. */
-+ 2, /* size. */
-+ 12, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 10, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_GOT64_HI12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_GOT64_HI12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "got64_hi12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_LE_HI20, /* type (83). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_LE_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_LE_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "le_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_LE_LO12, /* type (84). */
-+ 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_TLS_LE_LO12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_LE_LO12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "le_lo12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_LE64_LO20, /* type (85). */
-+ 32, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_LE64_LO20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_LE64_LO20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "le64_lo20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_LE64_HI12, /* type (86). */
-+ 52, /* rightshift. */
-+ 2, /* size. */
-+ 12, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 10, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_LE64_HI12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_LE64_HI12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "le64_hi12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_HI20, /* type (87). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_IE_PC_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_IE_PC_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "ie_pc_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_IE_PC_LO12, /* type (88). */
-+ 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_TLS_IE_PC_LO12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_IE_PC_LO12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "ie_pc_lo12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_LO20, /* type (89). */
-+ 32, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_IE64_PC_LO20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_IE64_PC_LO20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "ie64_pc_lo20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_PC_HI12, /* type (90). */
-+ 52, /* rightshift. */
-+ 2, /* size. */
-+ 12, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 10, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_IE64_PC_HI12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_IE64_PC_HI12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "ie64_pc_hi12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_IE_HI20, /* type (91). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_IE_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_IE_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "ie_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_IE_LO12, /* type (92). */
-+ 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_TLS_IE_LO12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_IE_LO12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "ie_lo12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_LO20, /* type (93). */
-+ 32, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_IE64_LO20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_IE64_LO20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "ie64_lo20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_IE64_HI12, /* type (94). */
-+ 52, /* rightshift. */
-+ 2, /* size. */
-+ 12, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 10, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_IE64_HI12", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x3ffc00, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_IE64_HI12, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "ie64_hi12"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_LD_PC_HI20, /* type (95). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_LD_PC_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_LD_PC_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "ld_pc_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_LD_HI20, /* type (96). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_LD_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_LD_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "ld_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_GD_PC_HI20, /* type (97). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_GD_PC_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_GD_PC_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "gd_pc_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_TLS_GD_HI20, /* type (98). */
-+ 12, /* rightshift. */
-+ 2, /* size. */
-+ 20, /* bitsize. */
-+ FALSE, /* pc_relative. */
-+ 5, /* bitpos. */
-+ complain_overflow_signed, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_TLS_GD_HI20", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0x1ffffe0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_TLS_GD_HI20, /* bfd_reloc_code_real_type */
-+ reloc_bits, /* adjust_reloc_bits */
-+ "gd_hi20"), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_32_PCREL, /* type (99). */
-+ 0, /* rightshift. */
-+ 2, /* size. */
-+ 32, /* bitsize. */
-+ TRUE, /* pc_relative. */
-+ 0, /* bitpos. */
-+ complain_overflow_dont, /* complain_on_overflow. */
-+ bfd_elf_generic_reloc, /* special_function. */
-+ "R_LARCH_32_PCREL", /* name. */
-+ FALSE, /* partial_inplace. */
-+ 0, /* src_mask */
-+ 0xffffffff, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_32_PCREL, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+ LOONGARCH_HOWTO (R_LARCH_RELAX, /* type (100). */
-+ 0, /* rightshift */
-+ 0, /* size */
-+ 0, /* bitsize */
-+ FALSE, /* pc_relative */
-+ 0, /* bitpos */
-+ complain_overflow_dont, /* complain_on_overflow */
-+ bfd_elf_generic_reloc, /* special_function */
-+ "R_LARCH_RELAX", /* name */
-+ FALSE, /* partial_inplace */
-+ 0, /* src_mask */
-+ 0, /* dst_mask */
-+ FALSE, /* pcrel_offset */
-+ BFD_RELOC_LARCH_RELAX, /* bfd_reloc_code_real_type */
-+ NULL, /* adjust_reloc_bits */
-+ NULL), /* larch_reloc_type_name */
-+
-+};
-+
-+reloc_howto_type *
-+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];
-+
-+ 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);
-+ bfd_set_error (bfd_error_bad_value);
-+ return NULL;
-+}
-+
-+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
-+ && 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_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)
-+ {
-+ BFD_ASSERT (BFD_RELOC_LARCH_RELAX - BFD_RELOC_LARCH_B16
-+ == R_LARCH_RELAX - R_LARCH_B16);
-+ loongarch_reloc_howto_type *ht = NULL;
-+ ht = &loongarch_howto_table[code - BFD_RELOC_LARCH_B16 + R_LARCH_B16];
-+ BFD_ASSERT (ht->bfd_type == code);
-+ return (reloc_howto_type *)ht;
-+ }
-+
-+ 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;
-+}
-+
-+bfd_reloc_code_real_type
-+loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
-+ const char *l_r_name)
-+{
-+ for (size_t i = 0; i < ARRAY_SIZE (loongarch_howto_table); i++)
-+ {
-+ loongarch_reloc_howto_type *lht = &loongarch_howto_table[i];
-+ if ((NULL != lht->larch_reloc_type_name)
-+ && (0 == strcmp (lht->larch_reloc_type_name, l_r_name)))
-+ return lht->bfd_type;
-+ }
-+
-+ (*_bfd_error_handler) (_("%pB: unsupported relocation type name %s"),
-+ abfd, l_r_name);
-+ bfd_set_error (bfd_error_bad_value);
-+ return BFD_RELOC_NONE;
-+}
-+
-+
-+/* Functions for reloc bits field.
-+ 1. Signed extend *fix_val.
-+ 2. Return FALSE if overflow. */
-+
-+#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_5_20
-+ BFD_RELOC_LARCH_SOP_POP_32_U. */
-+static bfd_boolean
-+reloc_bits (reloc_howto_type *howto, bfd_vma *fix_val)
-+{
-+ bfd_signed_vma val = ((bfd_signed_vma)(*fix_val)) >> howto->rightshift;
-+
-+ /* Perform insn bits field. */
-+ val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
-+ val <<= howto->bitpos;
-+
-+ *fix_val = (bfd_vma)val;
-+
-+ return TRUE;
-+}
-+
-+/* Adjust val to perform insn
-+ R_LARCH_SOP_POP_32_S_10_16_S2
-+ R_LARCH_B16. */
-+static bfd_boolean
-+reloc_bits_b16 (reloc_howto_type *howto, bfd_vma *fix_val)
-+{
-+ if (howto->complain_on_overflow != complain_overflow_signed)
-+ return FALSE;
-+
-+ bfd_signed_vma val = *fix_val;
-+
-+ /* Judge whether 4 bytes align. */
-+ if (val & ((0x1UL << howto->rightshift) - 1))
-+ return FALSE;
-+
-+ int bitsize = howto->bitsize + howto->rightshift;
-+ bfd_signed_vma sig_bit = (val >> (bitsize - 1)) & 0x1;
-+
-+ /* If val < 0, sign bit is 1. */
-+ if (sig_bit)
-+ {
-+ /* Signed bits is 1. */
-+ if ((LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1) & val)
-+ != LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize - 1))
-+ return FALSE;
-+ }
-+ else
-+ {
-+ /* Signed bits is 0. */
-+ if (LARCH_RELOC_BFD_VMA_BIT_MASK (bitsize) & val)
-+ return FALSE;
-+ }
-+
-+ /* Perform insn bits field. */
-+ val >>= howto->rightshift;
-+ val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
-+ val <<= howto->bitpos;
-+
-+ *fix_val = val;
-+
-+ return TRUE;
-+}
-+
-+/* Reloc type :
-+ R_LARCH_SOP_POP_32_S_0_5_10_16_S2
-+ R_LARCH_B21. */
-+static bfd_boolean
-+reloc_bits_b21 (reloc_howto_type *howto,
-+ bfd_vma *fix_val)
-+{
-+ if (howto->complain_on_overflow != complain_overflow_signed)
-+ return FALSE;
-+
-+ bfd_signed_vma val = *fix_val;
-+
-+ if (val & ((0x1UL << howto->rightshift) - 1))
-+ return FALSE;
-+
-+ int bitsize = howto->bitsize + howto->rightshift;
-+ bfd_signed_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) & val)
-+ return FALSE;
-+ }
-+
-+ /* Perform insn bits field. */
-+ val >>= howto->rightshift;
-+ val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
-+
-+ /* Perform insn bits field. 15:0<<10, 20:16>>16. */
-+ 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
-+ R_LARCH_B26. */
-+static bfd_boolean
-+reloc_bits_b26 (reloc_howto_type *howto,
-+ bfd_vma *fix_val)
-+{
-+ /* Return FALSE if overflow. */
-+ if (howto->complain_on_overflow != complain_overflow_signed)
-+ return FALSE;
-+
-+ bfd_signed_vma val = *fix_val;
-+
-+ if (val & ((0x1UL << howto->rightshift) - 1))
-+ return FALSE;
-+
-+ int bitsize = howto->bitsize + howto->rightshift;
-+ bfd_signed_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) & val)
-+ return FALSE;
-+ }
-+
-+ /* Perform insn bits field. */
-+ val >>= howto->rightshift;
-+ val = val & (((bfd_vma)0x1 << howto->bitsize) - 1);
-+
-+ /* Perform insn bits field. 25:16>>16, 15:0<<10. */
-+ val = ((val & 0xffff) << 10) | ((val >> 16) & 0x3ff);
-+
-+ *fix_val = val;
-+
-+ return TRUE;
-+}
-+
-+bfd_boolean
-+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);
-+}
---- /dev/null
-+++ gdb-10.2/bfd/elfxx-loongarch.h
-@@ -0,0 +1,45 @@
-+/* LoongArch-specific backend routines.
-+ Copyright (C) 2021-2022 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of BFD, the Binary File Descriptor library.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING3. If not,
-+ see <
http://www.gnu.org/licenses/>. */
-+
-+#include "elf/common.h"
-+#include "elf/internal.h"
-+
-+extern reloc_howto_type *
-+loongarch_elf_rtype_to_howto (bfd *abfd, unsigned int r_type);
-+
-+extern reloc_howto_type *
-+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);
-+
-+extern bfd_reloc_code_real_type
-+loongarch_larch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
-+ const char *l_r_name);
-+
-+bfd_boolean loongarch_adjust_reloc_bitsfield (reloc_howto_type *howto, bfd_vma
*fix_val);
-+
-+/* TRUE if this is a PLT reference to a local IFUNC. */
-+#define PLT_LOCAL_IFUNC_P(INFO, H) \
-+ ((H)->dynindx == -1 \
-+ || ((bfd_link_executable (INFO) \
-+ || ELF_ST_VISIBILITY ((H)->other) != STV_DEFAULT) \
-+ && (H)->def_regular \
-+ && (H)->type == STT_GNU_IFUNC))
---- gdb-10.2/bfd/libbfd.h.orig
-+++ gdb-10.2/bfd/libbfd.h
-@@ -3396,6 +3396,86 @@ static const char *const bfd_reloc_code_real_names[] = {
"@@uninitialized@@",
- "BFD_RELOC_CKCORE_PCREL_BLOOP_IMM4BY4",
- "BFD_RELOC_CKCORE_PCREL_BLOOP_IMM12BY4",
- "BFD_RELOC_S12Z_OPR",
-+ "BFD_RELOC_LARCH_TLS_DTPMOD32",
-+ "BFD_RELOC_LARCH_TLS_DTPREL32",
-+ "BFD_RELOC_LARCH_TLS_DTPMOD64",
-+ "BFD_RELOC_LARCH_TLS_DTPREL64",
-+ "BFD_RELOC_LARCH_TLS_TPREL32",
-+ "BFD_RELOC_LARCH_TLS_TPREL64",
-+ "BFD_RELOC_LARCH_MARK_LA",
-+ "BFD_RELOC_LARCH_MARK_PCREL",
-+ "BFD_RELOC_LARCH_SOP_PUSH_PCREL",
-+ "BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE",
-+ "BFD_RELOC_LARCH_SOP_PUSH_DUP",
-+ "BFD_RELOC_LARCH_SOP_PUSH_GPREL",
-+ "BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL",
-+ "BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT",
-+ "BFD_RELOC_LARCH_SOP_PUSH_TLS_GD",
-+ "BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL",
-+ "BFD_RELOC_LARCH_SOP_ASSERT",
-+ "BFD_RELOC_LARCH_SOP_NOT",
-+ "BFD_RELOC_LARCH_SOP_SUB",
-+ "BFD_RELOC_LARCH_SOP_SL",
-+ "BFD_RELOC_LARCH_SOP_SR",
-+ "BFD_RELOC_LARCH_SOP_ADD",
-+ "BFD_RELOC_LARCH_SOP_AND",
-+ "BFD_RELOC_LARCH_SOP_IF_ELSE",
-+ "BFD_RELOC_LARCH_SOP_POP_32_S_10_5",
-+ "BFD_RELOC_LARCH_SOP_POP_32_U_10_12",
-+ "BFD_RELOC_LARCH_SOP_POP_32_S_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_S_0_5_10_16_S2",
-+ "BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2",
-+ "BFD_RELOC_LARCH_SOP_POP_32_U",
-+ "BFD_RELOC_LARCH_ADD8",
-+ "BFD_RELOC_LARCH_ADD16",
-+ "BFD_RELOC_LARCH_ADD24",
-+ "BFD_RELOC_LARCH_ADD32",
-+ "BFD_RELOC_LARCH_ADD64",
-+ "BFD_RELOC_LARCH_SUB8",
-+ "BFD_RELOC_LARCH_SUB16",
-+ "BFD_RELOC_LARCH_SUB24",
-+ "BFD_RELOC_LARCH_SUB32",
-+ "BFD_RELOC_LARCH_SUB64",
-+ "BFD_RELOC_LARCH_B16",
-+ "BFD_RELOC_LARCH_B21",
-+ "BFD_RELOC_LARCH_B26",
-+ "BFD_RELOC_LARCH_ABS_HI20",
-+ "BFD_RELOC_LARCH_ABS_LO12",
-+ "BFD_RELOC_LARCH_ABS64_LO20",
-+ "BFD_RELOC_LARCH_ABS64_HI12",
-+ "BFD_RELOC_LARCH_PCALA_HI20",
-+ "BFD_RELOC_LARCH_PCALA_LO12",
-+ "BFD_RELOC_LARCH_PCALA64_LO20",
-+ "BFD_RELOC_LARCH_PCALA64_HI12",
-+ "BFD_RELOC_LARCH_GOT_PC_HI20",
-+ "BFD_RELOC_LARCH_GOT_PC_LO12",
-+ "BFD_RELOC_LARCH_GOT64_PC_LO20",
-+ "BFD_RELOC_LARCH_GOT64_PC_HI12",
-+ "BFD_RELOC_LARCH_GOT_HI20",
-+ "BFD_RELOC_LARCH_GOT_LO12",
-+ "BFD_RELOC_LARCH_GOT64_LO20",
-+ "BFD_RELOC_LARCH_GOT64_HI12",
-+ "BFD_RELOC_LARCH_TLS_LE_HI20",
-+ "BFD_RELOC_LARCH_TLS_LE_LO12",
-+ "BFD_RELOC_LARCH_TLS_LE64_LO20",
-+ "BFD_RELOC_LARCH_TLS_LE64_HI12",
-+ "BFD_RELOC_LARCH_TLS_IE_PC_HI20",
-+ "BFD_RELOC_LARCH_TLS_IE_PC_LO12",
-+ "BFD_RELOC_LARCH_TLS_IE64_PC_LO20",
-+ "BFD_RELOC_LARCH_TLS_IE64_PC_HI12",
-+ "BFD_RELOC_LARCH_TLS_IE_HI20",
-+ "BFD_RELOC_LARCH_TLS_IE_LO12",
-+ "BFD_RELOC_LARCH_TLS_IE64_LO20",
-+ "BFD_RELOC_LARCH_TLS_IE64_HI12",
-+ "BFD_RELOC_LARCH_TLS_LD_PC_HI20",
-+ "BFD_RELOC_LARCH_TLS_LD_HI20",
-+ "BFD_RELOC_LARCH_TLS_GD_PC_HI20",
-+ "BFD_RELOC_LARCH_TLS_GD_HI20",
-+ "BFD_RELOC_LARCH_32_PCREL",
-+ "BFD_RELOC_LARCH_RELAX",
- "@@overflow: BFD_RELOC_UNUSED@@",
- };
- #endif
---- gdb-10.2/bfd/po/BLD-POTFILES.in.orig
-+++ gdb-10.2/bfd/po/BLD-POTFILES.in
-@@ -2,10 +2,12 @@ bfd_stdint.h
- bfdver.h
- elf32-aarch64.c
- elf32-ia64.c
-+elf32-loongarch.c
- elf32-riscv.c
- elf32-target.h
- elf64-aarch64.c
- elf64-ia64.c
-+elf64-loongarch.c
- elf64-riscv.c
- elf64-target.h
- peigen.c
---- gdb-10.2/bfd/po/SRC-POTFILES.in.orig
-+++ gdb-10.2/bfd/po/SRC-POTFILES.in
-@@ -72,6 +72,7 @@ cpu-iq2000.c
- cpu-k1om.c
- cpu-l1om.c
- cpu-lm32.c
-+cpu-loongarch.c
- cpu-m10200.c
- cpu-m10300.c
- cpu-m32c.c
---- gdb-10.2/bfd/targets.c.orig
-+++ gdb-10.2/bfd/targets.c
-@@ -759,6 +759,8 @@ extern const bfd_target l1om_elf64_vec;
- extern const bfd_target l1om_elf64_fbsd_vec;
- extern const bfd_target lm32_elf32_vec;
- extern const bfd_target lm32_elf32_fdpic_vec;
-+extern const bfd_target loongarch_elf64_vec;
-+extern const bfd_target loongarch_elf32_vec;
- extern const bfd_target m32c_elf32_vec;
- extern const bfd_target m32r_elf32_vec;
- extern const bfd_target m32r_elf32_le_vec;
-@@ -1346,6 +1348,12 @@ static const bfd_target * const _bfd_target_vector[] =
- &z80_elf32_vec,
-
- &z8k_coff_vec,
-+
-+#ifdef BFD64
-+ &loongarch_elf32_vec,
-+ &loongarch_elf64_vec,
-+#endif
-+
- #endif /* not SELECT_VECS */
-
- /* Always support S-records, for convenience. */
---- gdb-10.2/config.guess.orig
-+++ gdb-10.2/config.guess
-@@ -985,6 +985,9 @@ EOF
- k1om:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
-+ loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
-+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-+ exit ;;
- m32r*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
- exit ;;
---- gdb-10.2/config.sub.orig
-+++ gdb-10.2/config.sub
-@@ -1183,6 +1183,7 @@ case $cpu-$vendor in
- | k1om \
- | le32 | le64 \
- | lm32 \
-+ | loongarch32 | loongarch64 | loongarchx32 \
- | m32c | m32r | m32rle \
- | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
- | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
---- gdb-10.2/gdb/Makefile.in.orig
-+++ gdb-10.2/gdb/Makefile.in
-@@ -712,6 +712,7 @@ ALL_TARGET_OBS = \
- arch/i386.o \
- arch/ppc-linux-common.o \
- arch/riscv.o \
-+ arch/loongarch.o \
- arm-bsd-tdep.o \
- arm-fbsd-tdep.o \
- arm-linux-tdep.o \
-@@ -760,6 +761,8 @@ ALL_TARGET_OBS = \
- linux-record.o \
- linux-tdep.o \
- lm32-tdep.o \
-+ loongarch-tdep.o \
-+ loongarch-linux-tdep.o \
- m32c-tdep.o \
- m32r-linux-tdep.o \
- m32r-tdep.o \
-@@ -1325,6 +1328,8 @@ HFILES_NO_SRCDIR = \
- linux-record.h \
- linux-tdep.h \
- location.h \
-+ loongarch-tdep.h \
-+ loongarch-linux-tdep.h \
- m2-lang.h \
- m32r-tdep.h \
- m68k-tdep.h \
-@@ -1457,6 +1462,7 @@ HFILES_NO_SRCDIR = \
- arch/arc.h \
- arch/arm.h \
- arch/i386.h \
-+ arch/loongarch.h \
- arch/ppc-linux-common.h \
- arch/ppc-linux-tdesc.h \
- arch/riscv.h \
-@@ -2207,6 +2214,8 @@ ALLDEPFILES = \
- linux-record.c \
- linux-tdep.c \
- lm32-tdep.c \
-+ loongarch-tdep.c \
-+ loongarch-linux-tdep.c \
- m32r-linux-nat.c \
- m32r-linux-tdep.c \
- m32r-tdep.c \
---- /dev/null
-+++ gdb-10.2/gdb/arch/loongarch.c
-@@ -0,0 +1,75 @@
-+/* Copyright (C) 2021 Free Software Foundation, Inc.
-+
-+ This file is part of GDB.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <
http://www.gnu.org/licenses/>. */
-+
-+#include "gdbsupport/common-defs.h"
-+#include "gdbsupport/common-regcache.h"
-+#include "arch/loongarch.h"
-+
-+unsigned int loongarch_debug = 0;
-+
-+#include <../features/loongarch/base32.c>
-+#include <../features/loongarch/base64.c>
-+#include <../features/loongarch/fpu32.c>
-+#include <../features/loongarch/fpu64.c>
-+#include <../features/loongarch/lbt32.c>
-+#include <../features/loongarch/lbt64.c>
-+#include <../features/loongarch/lsx.c>
-+#include <../features/loongarch/lasx.c>
-+
-+target_desc *
-+loongarch_create_target_description (int rlen, int flen, int lbt,
-+ int lsx, int lasx)
-+{
-+ gdb_assert (rlen == 32 || rlen == 64);
-+
-+ target_desc *tdesc = allocate_target_description ();
-+
-+ set_tdesc_architecture (tdesc, rlen == 64 ? "loongarch64" :
"loongarch32");
-+
-+ int regnum = 0;
-+
-+ if (rlen == 64)
-+ regnum = create_feature_loongarch_base64 (tdesc, regnum);
-+ else if (rlen == 32)
-+ regnum = create_feature_loongarch_base32 (tdesc, regnum);
-+ else
-+ gdb_assert_not_reached ("rlen unknown");
-+
-+ if (flen == 64)
-+ regnum = create_feature_loongarch_fpu64 (tdesc, regnum);
-+ else if (flen == 32)
-+ regnum = create_feature_loongarch_fpu32 (tdesc, regnum);
-+
-+ if (lbt && rlen == 32)
-+ regnum = create_feature_loongarch_lbt32 (tdesc, regnum);
-+ else if (lbt && rlen == 64)
-+ regnum = create_feature_loongarch_lbt64 (tdesc, regnum);
-+
-+ if (lsx)
-+ regnum = create_feature_loongarch_lsx (tdesc, regnum);
-+
-+ if (lasx)
-+ regnum = create_feature_loongarch_lasx (tdesc, regnum);
-+
-+ return tdesc;
-+}
-+
-+target_desc *
-+loongarch_get_base_target_description (int rlen, int flen)
-+{
-+ return loongarch_create_target_description (rlen, flen, 0, 0, 0);
-+}
---- /dev/null
-+++ gdb-10.2/gdb/arch/loongarch.h
-@@ -0,0 +1,35 @@
-+/*
-+ Copyright (C) 2021 Free Software Foundation, Inc.
-+
-+ This file is part of GDB.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <
http://www.gnu.org/licenses/>. */
-+
-+#ifndef ARCH_LOONGARCH_H
-+#define ARCH_LOONGARCH_H
-+
-+#include "elf/loongarch.h"
-+#include "opcode/loongarch.h"
-+
-+extern unsigned int loongarch_debug;
-+
-+struct target_desc;
-+
-+extern struct target_desc *loongarch_get_base_target_description (int rlen, int flen);
-+
-+extern struct target_desc *
-+loongarch_create_target_description (int rlen, int flen, int lbt,
-+ int lsx, int lasx);
-+
-+#endif
---- gdb-10.2/gdb/configure.host.orig
-+++ gdb-10.2/gdb/configure.host
-@@ -63,6 +63,7 @@ alpha*) gdb_host_cpu=alpha ;;
- arm*) gdb_host_cpu=arm ;;
- hppa*) gdb_host_cpu=pa ;;
- i[34567]86*) gdb_host_cpu=i386 ;;
-+loongarch*) gdb_host_cpu=loongarch ;;
- m68*) gdb_host_cpu=m68k ;;
- mips*) gdb_host_cpu=mips ;;
- powerpc* | rs6000) gdb_host_cpu=powerpc ;;
-@@ -120,6 +121,8 @@ i[34567]86-*-cygwin*) gdb_host=cygwin ;;
-
- ia64-*-linux*) gdb_host=linux ;;
-
-+loongarch*-linux*) gdb_host=linux ;;
-+
- m68*-*-linux*) gdb_host=linux ;;
- m68*-*-netbsdelf* | m68*-*-knetbsd*-gnu)
- gdb_host=nbsdelf ;;
---- gdb-10.2/gdb/configure.tgt.orig
-+++ gdb-10.2/gdb/configure.tgt
-@@ -95,6 +95,9 @@ xtensa*)
- cpu_obs="xtensa-tdep.o xtensa-config.o solib-svr4.o"
- ;;
-
-+loongarch*)
-+ cpu_obs="arch/loongarch.o";;
-+
- esac
-
- # 2. Get the objects per os in $TARG.
-@@ -346,6 +349,11 @@ lm32-*-*)
- gdb_sim=../sim/lm32/libsim.a
- ;;
-
-+loongarch*-linux*)
-+ gdb_target_obs="loongarch-tdep.o loongarch-linux-tdep.o glibc-tdep.o linux-tdep.o
solib-svr4.o symfile-mem.o"
-+ build_gdbserver=yes
-+ ;;
-+
- m32c-*-*)
- # Target: Renesas M32C family
- gdb_target_obs="m32c-tdep.o"
---- gdb-10.2/gdb/doc/gdb.texinfo.orig
-+++ gdb-10.2/gdb/doc/gdb.texinfo
-@@ -45227,6 +45227,7 @@ registers using the capitalization used in the description.
- * ARC Features::
- * ARM Features::
- * i386 Features::
-+* LoongArch Features::
- * MicroBlaze Features::
- * MIPS Features::
- * M68K Features::
-@@ -45444,6 +45445,15 @@ The @samp{org.gnu.gdb.i386.pkeys} feature is optional. It
should
- describe a single register, @samp{pkru}. It is a 32-bit register
- valid for i386 and amd64.
-
-+@node LoongArch Features
-+@subsection LoongArch Features
-+@cindex target descriptions, LoongArch Features
-+
-+The @samp{org.gnu.gdb.loongarch.base} feature is required for LoongArch
-+targets. It should contain the registers @samp{r0} through @samp{r31},
-+@samp{pc}, and @samp{badvaddr}. Either the architectural names (@samp{r0},
-+@samp{r1}, etc) can be used, or the ABI names (@samp{zero}, @samp{ra}, etc).
-+
- @node MicroBlaze Features
- @subsection MicroBlaze Features
- @cindex target descriptions, MicroBlaze features
---- gdb-10.2/gdb/features/Makefile.orig
-+++ gdb-10.2/gdb/features/Makefile
-@@ -74,6 +74,7 @@ arm-expedite = r11,sp,pc
- i386-expedite = ebp,esp,eip
- amd64-expedite = rbp,rsp,rip
- x32-expedite = rbp,rsp,rip
-+loongarch-expedite = r3,pc
- mips-expedite = r29,pc
- mips-dsp-expedite = r29,pc
- mips64-expedite = r29,pc
-@@ -178,6 +179,7 @@ GDB = false
- aarch64-feature = 1
- arm-feature = 1
- i386-feature = 1
-+loongarch-feature = 1
- riscv-feature = 1
- tic6x-feature = 1
-
-@@ -228,6 +230,14 @@ FEATURE_XMLFILES = aarch64-core.xml \
- i386/64bit-pkeys.xml \
- i386/64bit-sse.xml \
- i386/x32-core.xml \
-+ loongarch/base32.xml \
-+ loongarch/base64.xml \
-+ loongarch/fpu32.xml \
-+ loongarch/fpu64.xml \
-+ loongarch/lbt32.xml \
-+ loongarch/lbt64.xml \
-+ loongarch/lsx.xml \
-+ loongarch/lasx.xml \
- riscv/32bit-cpu.xml \
- riscv/32bit-fpu.xml \
- riscv/64bit-cpu.xml \
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/base32.c
-@@ -0,0 +1,48 @@
-+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
-+ Original: base32.xml */
-+
-+#include "gdbsupport/tdesc.h"
-+
-+static int
-+create_feature_loongarch_base32 (struct target_desc *result, long regnum)
-+{
-+ struct tdesc_feature *feature;
-+
-+ feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.base");
-+ tdesc_create_reg (feature, "r0", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r1", regnum++, 1, "general", 32,
"code_ptr");
-+ tdesc_create_reg (feature, "r2", regnum++, 1, "general", 32,
"data_ptr");
-+ tdesc_create_reg (feature, "r3", regnum++, 1, "general", 32,
"data_ptr");
-+ tdesc_create_reg (feature, "r4", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r5", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r6", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r7", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r8", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r9", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r10", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r11", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r12", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r13", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r14", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r15", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r16", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r17", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r18", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r19", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r20", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r21", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r22", regnum++, 1, "general", 32,
"data_ptr");
-+ tdesc_create_reg (feature, "r23", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r24", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r25", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r26", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r27", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r28", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r29", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r30", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "r31", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "orig_a0", regnum++, 1, "general", 32,
"uint32");
-+ tdesc_create_reg (feature, "pc", regnum++, 1, "general", 32,
"code_ptr");
-+ tdesc_create_reg (feature, "badv", regnum++, 1, "general", 32,
"code_ptr");
-+ return regnum;
-+}
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/base32.xml
-@@ -0,0 +1,46 @@
-+<?xml version="1.0"?>
-+<!-- Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ Copying and distribution of this file, with or without modification,
-+ are permitted in any medium without royalty provided the copyright
-+ notice and this notice are preserved. -->
-+
-+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-+<feature name="org.gnu.gdb.loongarch.base">
-+ <reg name="r0" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r1" bitsize="32" type="code_ptr"
group="general"/>
-+ <reg name="r2" bitsize="32" type="data_ptr"
group="general"/>
-+ <reg name="r3" bitsize="32" type="data_ptr"
group="general"/>
-+ <reg name="r4" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r5" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r6" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r7" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r8" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r9" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r10" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r11" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r12" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r13" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r14" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r15" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r16" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r17" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r18" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r19" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r20" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r21" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r22" bitsize="32" type="data_ptr"
group="general"/>
-+ <reg name="r23" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r24" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r25" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r26" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r27" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r28" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r29" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r30" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="r31" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="orig_a0" bitsize="32" type="uint32"
group="general"/>
-+ <reg name="pc" bitsize="32" type="code_ptr"
group="general"/>
-+ <reg name="badv" bitsize="32" type="code_ptr"
group="general"/>
-+</feature>
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/base64.c
-@@ -0,0 +1,48 @@
-+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
-+ Original: base64.xml */
-+
-+#include "gdbsupport/tdesc.h"
-+
-+static int
-+create_feature_loongarch_base64 (struct target_desc *result, long regnum)
-+{
-+ struct tdesc_feature *feature;
-+
-+ feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.base");
-+ tdesc_create_reg (feature, "r0", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r1", regnum++, 1, "general", 64,
"code_ptr");
-+ tdesc_create_reg (feature, "r2", regnum++, 1, "general", 64,
"data_ptr");
-+ tdesc_create_reg (feature, "r3", regnum++, 1, "general", 64,
"data_ptr");
-+ tdesc_create_reg (feature, "r4", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r5", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r6", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r7", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r8", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r9", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r10", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r11", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r12", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r13", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r14", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r15", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r16", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r17", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r18", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r19", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r20", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r21", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r22", regnum++, 1, "general", 64,
"data_ptr");
-+ tdesc_create_reg (feature, "r23", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r24", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r25", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r26", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r27", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r28", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r29", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r30", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "r31", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "orig_a0", regnum++, 1, "general", 64,
"uint64");
-+ tdesc_create_reg (feature, "pc", regnum++, 1, "general", 64,
"code_ptr");
-+ tdesc_create_reg (feature, "badv", regnum++, 1, "general", 64,
"code_ptr");
-+ return regnum;
-+}
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/base64.xml
-@@ -0,0 +1,46 @@
-+<?xml version="1.0"?>
-+<!-- Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ Copying and distribution of this file, with or without modification,
-+ are permitted in any medium without royalty provided the copyright
-+ notice and this notice are preserved. -->
-+
-+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-+<feature name="org.gnu.gdb.loongarch.base">
-+ <reg name="r0" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r1" bitsize="64" type="code_ptr"
group="general"/>
-+ <reg name="r2" bitsize="64" type="data_ptr"
group="general"/>
-+ <reg name="r3" bitsize="64" type="data_ptr"
group="general"/>
-+ <reg name="r4" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r5" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r6" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r7" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r8" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r9" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r10" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r11" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r12" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r13" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r14" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r15" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r16" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r17" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r18" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r19" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r20" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r21" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r22" bitsize="64" type="data_ptr"
group="general"/>
-+ <reg name="r23" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r24" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r25" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r26" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r27" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r28" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r29" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r30" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="r31" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="orig_a0" bitsize="64" type="uint64"
group="general"/>
-+ <reg name="pc" bitsize="64" type="code_ptr"
group="general"/>
-+ <reg name="badv" bitsize="64" type="code_ptr"
group="general"/>
-+</feature>
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/fpu32.c
-@@ -0,0 +1,54 @@
-+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
-+ Original: fpu32.xml */
-+
-+#include "gdbsupport/tdesc.h"
-+
-+static int
-+create_feature_loongarch_fpu32 (struct target_desc *result, long regnum)
-+{
-+ struct tdesc_feature *feature;
-+
-+ feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.fpu");
-+ tdesc_create_reg (feature, "f0", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f1", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f2", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f3", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f4", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f5", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f6", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f7", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f8", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f9", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f10", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f11", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f12", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f13", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f14", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f15", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f16", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f17", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f18", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f19", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f20", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f21", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f22", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f23", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f24", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f25", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f26", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f27", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f28", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f29", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f30", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "f31", regnum++, 1, "float", 32,
"ieee_single");
-+ tdesc_create_reg (feature, "fcc0", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc1", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc2", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc3", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc4", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc5", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc6", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc7", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcsr", regnum++, 1, "float", 32,
"uint32");
-+ return regnum;
-+}
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/fpu32.xml
-@@ -0,0 +1,53 @@
-+<?xml version="1.0"?>
-+<!-- Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ Copying and distribution of this file, with or without modification,
-+ are permitted in any medium without royalty provided the copyright
-+ notice and this notice are preserved. -->
-+
-+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-+<feature name="org.gnu.gdb.loongarch.fpu">
-+
-+ <reg name="f0" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f1" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f2" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f3" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f4" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f5" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f6" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f7" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f8" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f9" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f10" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f11" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f12" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f13" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f14" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f15" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f16" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f17" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f18" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f19" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f20" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f21" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f22" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f23" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f24" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f25" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f26" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f27" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f28" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f29" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f30" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="f31" bitsize="32" type="ieee_single"
group="float"/>
-+ <reg name="fcc0" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc1" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc2" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc3" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc4" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc5" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc6" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc7" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcsr" bitsize="32" type="uint32"
group="float"/>
-+</feature>
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/fpu64.c
-@@ -0,0 +1,62 @@
-+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
-+ Original: fpu64.xml */
-+
-+#include "gdbsupport/tdesc.h"
-+
-+static int
-+create_feature_loongarch_fpu64 (struct target_desc *result, long regnum)
-+{
-+ struct tdesc_feature *feature;
-+
-+ feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.fpu");
-+ tdesc_type_with_fields *type_with_fields;
-+ type_with_fields = tdesc_create_union (feature, "fpu64type");
-+ tdesc_type *field_type;
-+ field_type = tdesc_named_type (feature, "ieee_single");
-+ tdesc_add_field (type_with_fields, "f", field_type);
-+ field_type = tdesc_named_type (feature, "ieee_double");
-+ tdesc_add_field (type_with_fields, "d", field_type);
-+
-+ tdesc_create_reg (feature, "f0", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f1", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f2", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f3", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f4", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f5", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f6", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f7", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f8", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f9", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f10", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f11", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f12", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f13", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f14", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f15", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f16", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f17", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f18", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f19", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f20", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f21", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f22", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f23", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f24", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f25", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f26", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f27", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f28", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f29", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f30", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "f31", regnum++, 1, "float", 64,
"fpu64type");
-+ tdesc_create_reg (feature, "fcc0", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc1", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc2", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc3", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc4", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc5", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc6", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcc7", regnum++, 1, "float", 8,
"uint8");
-+ tdesc_create_reg (feature, "fcsr", regnum++, 1, "float", 32,
"uint32");
-+ return regnum;
-+}
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/fpu64.xml
-@@ -0,0 +1,58 @@
-+<?xml version="1.0"?>
-+<!-- Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ Copying and distribution of this file, with or without modification,
-+ are permitted in any medium without royalty provided the copyright
-+ notice and this notice are preserved. -->
-+
-+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-+<feature name="org.gnu.gdb.loongarch.fpu">
-+
-+ <union id="fpu64type">
-+ <field name="f" type="ieee_single"/>
-+ <field name="d" type="ieee_double"/>
-+ </union>
-+
-+ <reg name="f0" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f1" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f2" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f3" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f4" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f5" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f6" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f7" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f8" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f9" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f10" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f11" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f12" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f13" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f14" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f15" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f16" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f17" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f18" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f19" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f20" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f21" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f22" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f23" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f24" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f25" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f26" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f27" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f28" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f29" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f30" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="f31" bitsize="64" type="fpu64type"
group="float"/>
-+ <reg name="fcc0" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc1" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc2" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc3" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc4" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc5" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc6" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcc7" bitsize="8" type="uint8"
group="float"/>
-+ <reg name="fcsr" bitsize="32" type="uint32"
group="float"/>
-+</feature>
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/lasx.c
-@@ -0,0 +1,80 @@
-+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
-+ Original: lasx.xml */
-+
-+#include "gdbsupport/tdesc.h"
-+
-+static int
-+create_feature_loongarch_lasx (struct target_desc *result, long regnum)
-+{
-+ struct tdesc_feature *feature;
-+
-+ feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.lasx");
-+ tdesc_type *element_type;
-+ element_type = tdesc_named_type (feature, "int8");
-+ tdesc_create_vector (feature, "v32i8", element_type, 32);
-+
-+ element_type = tdesc_named_type (feature, "int16");
-+ tdesc_create_vector (feature, "v16i16", element_type, 16);
-+
-+ element_type = tdesc_named_type (feature, "int32");
-+ tdesc_create_vector (feature, "v8i32", element_type, 8);
-+
-+ element_type = tdesc_named_type (feature, "int64");
-+ tdesc_create_vector (feature, "v4i64", element_type, 4);
-+
-+ element_type = tdesc_named_type (feature, "ieee_single");
-+ tdesc_create_vector (feature, "v8f32", element_type, 8);
-+
-+ element_type = tdesc_named_type (feature, "ieee_double");
-+ tdesc_create_vector (feature, "v4f64", element_type, 4);
-+
-+ tdesc_type_with_fields *type_with_fields;
-+ type_with_fields = tdesc_create_union (feature, "lasxv");
-+ tdesc_type *field_type;
-+ field_type = tdesc_named_type (feature, "v32i8");
-+ tdesc_add_field (type_with_fields, "v32i8", field_type);
-+ field_type = tdesc_named_type (feature, "v16i16");
-+ tdesc_add_field (type_with_fields, "v16i16", field_type);
-+ field_type = tdesc_named_type (feature, "v8i32");
-+ tdesc_add_field (type_with_fields, "v8i32", field_type);
-+ field_type = tdesc_named_type (feature, "v4i64");
-+ tdesc_add_field (type_with_fields, "v4i64", field_type);
-+ field_type = tdesc_named_type (feature, "v8f32");
-+ tdesc_add_field (type_with_fields, "v8f32", field_type);
-+ field_type = tdesc_named_type (feature, "v4f64");
-+ tdesc_add_field (type_with_fields, "v4f64", field_type);
-+
-+ tdesc_create_reg (feature, "xr0", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr1", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr2", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr3", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr4", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr5", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr6", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr7", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr8", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr9", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr10", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr11", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr12", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr13", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr14", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr15", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr16", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr17", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr18", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr19", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr20", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr21", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr22", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr23", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr24", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr25", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr26", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr27", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr28", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr29", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr30", regnum++, 1, "lasx", 256,
"lasxv");
-+ tdesc_create_reg (feature, "xr31", regnum++, 1, "lasx", 256,
"lasxv");
-+ return regnum;
-+}
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/lasx.xml
-@@ -0,0 +1,59 @@
-+<?xml version="1.0"?>
-+<!-- Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ Copying and distribution of this file, with or without modification,
-+ are permitted in any medium without royalty provided the copyright
-+ notice and this notice are preserved. -->
-+
-+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-+<feature name="org.gnu.gdb.loongarch.lasx">
-+ <vector id="v32i8" type="int8" count="32"/>
-+ <vector id="v16i16" type="int16" count="16"/>
-+ <vector id="v8i32" type="int32" count="8"/>
-+ <vector id="v4i64" type="int64" count="4"/>
-+ <vector id="v8f32" type="ieee_single" count="8"/>
-+ <vector id="v4f64" type="ieee_double" count="4"/>
-+
-+ <union id="lasxv">
-+ <field name="v32i8" type="v32i8"/>
-+ <field name="v16i16" type="v16i16"/>
-+ <field name="v8i32" type="v8i32"/>
-+ <field name="v4i64" type="v4i64"/>
-+ <field name="v8f32" type="v8f32"/>
-+ <field name="v4f64" type="v4f64"/>
-+ </union>
-+
-+ <reg name="xr0" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr1" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr2" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr3" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr4" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr5" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr6" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr7" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr8" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr9" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr10" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr11" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr12" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr13" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr14" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr15" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr16" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr17" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr18" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr19" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr20" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr21" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr22" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr23" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr24" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr25" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr26" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr27" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr28" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr29" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr30" bitsize="256" type="lasxv"
group="lasx"/>
-+ <reg name="xr31" bitsize="256" type="lasxv"
group="lasx"/>
-+</feature>
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/lbt32.c
-@@ -0,0 +1,19 @@
-+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
-+ Original: lbt32.xml */
-+
-+#include "gdbsupport/tdesc.h"
-+
-+static int
-+create_feature_loongarch_lbt32 (struct target_desc *result, long regnum)
-+{
-+ struct tdesc_feature *feature;
-+
-+ feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.lbt");
-+ tdesc_create_reg (feature, "scr0", regnum++, 1, "lbt", 32,
"uint32");
-+ tdesc_create_reg (feature, "scr1", regnum++, 1, "lbt", 32,
"uint32");
-+ tdesc_create_reg (feature, "scr2", regnum++, 1, "lbt", 32,
"uint32");
-+ tdesc_create_reg (feature, "scr3", regnum++, 1, "lbt", 32,
"uint32");
-+ tdesc_create_reg (feature, "EFLAG", regnum++, 1, "lbt", 32,
"uint32");
-+ tdesc_create_reg (feature, "x86_top", regnum++, 1, "lbt", 8,
"uint8");
-+ return regnum;
-+}
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/lbt32.xml
-@@ -0,0 +1,17 @@
-+<?xml version="1.0"?>
-+<!-- Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ Copying and distribution of this file, with or without modification,
-+ are permitted in any medium without royalty provided the copyright
-+ notice and this notice are preserved. -->
-+
-+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-+<feature name="org.gnu.gdb.loongarch.lbt">
-+ <reg name="scr0" bitsize="32" type="uint32"
group="lbt"/>
-+ <reg name="scr1" bitsize="32" type="uint32"
group="lbt"/>
-+ <reg name="scr2" bitsize="32" type="uint32"
group="lbt"/>
-+ <reg name="scr3" bitsize="32" type="uint32"
group="lbt"/>
-+ <reg name="EFLAG" bitsize="32" type="uint32"
group="lbt"/>
-+ <reg name="x86_top" bitsize="8" type="uint8"
group="lbt"/>
-+</feature>
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/lbt64.c
-@@ -0,0 +1,19 @@
-+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
-+ Original: lbt64.xml */
-+
-+#include "gdbsupport/tdesc.h"
-+
-+static int
-+create_feature_loongarch_lbt64 (struct target_desc *result, long regnum)
-+{
-+ struct tdesc_feature *feature;
-+
-+ feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.lbt");
-+ tdesc_create_reg (feature, "scr0", regnum++, 1, "lbt", 64,
"uint64");
-+ tdesc_create_reg (feature, "scr1", regnum++, 1, "lbt", 64,
"uint64");
-+ tdesc_create_reg (feature, "scr2", regnum++, 1, "lbt", 64,
"uint64");
-+ tdesc_create_reg (feature, "scr3", regnum++, 1, "lbt", 64,
"uint64");
-+ tdesc_create_reg (feature, "EFLAG", regnum++, 1, "lbt", 32,
"uint32");
-+ tdesc_create_reg (feature, "x86_top", regnum++, 1, "lbt", 8,
"uint8");
-+ return regnum;
-+}
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/lbt64.xml
-@@ -0,0 +1,17 @@
-+<?xml version="1.0"?>
-+<!-- Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ Copying and distribution of this file, with or without modification,
-+ are permitted in any medium without royalty provided the copyright
-+ notice and this notice are preserved. -->
-+
-+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-+<feature name="org.gnu.gdb.loongarch.lbt">
-+ <reg name="scr0" bitsize="64" type="uint64"
group="lbt"/>
-+ <reg name="scr1" bitsize="64" type="uint64"
group="lbt"/>
-+ <reg name="scr2" bitsize="64" type="uint64"
group="lbt"/>
-+ <reg name="scr3" bitsize="64" type="uint64"
group="lbt"/>
-+ <reg name="EFLAG" bitsize="32" type="uint32"
group="lbt"/>
-+ <reg name="x86_top" bitsize="8" type="uint8"
group="lbt"/>
-+</feature>
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/lsx.c
-@@ -0,0 +1,80 @@
-+/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro:
-+ Original: lsx.xml */
-+
-+#include "gdbsupport/tdesc.h"
-+
-+static int
-+create_feature_loongarch_lsx (struct target_desc *result, long regnum)
-+{
-+ struct tdesc_feature *feature;
-+
-+ feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.lsx");
-+ tdesc_type *element_type;
-+ element_type = tdesc_named_type (feature, "int8");
-+ tdesc_create_vector (feature, "v16i8", element_type, 16);
-+
-+ element_type = tdesc_named_type (feature, "int16");
-+ tdesc_create_vector (feature, "v8i16", element_type, 8);
-+
-+ element_type = tdesc_named_type (feature, "int32");
-+ tdesc_create_vector (feature, "v4i32", element_type, 4);
-+
-+ element_type = tdesc_named_type (feature, "int64");
-+ tdesc_create_vector (feature, "v2i64", element_type, 2);
-+
-+ element_type = tdesc_named_type (feature, "ieee_single");
-+ tdesc_create_vector (feature, "v4f32", element_type, 4);
-+
-+ element_type = tdesc_named_type (feature, "ieee_double");
-+ tdesc_create_vector (feature, "v2f64", element_type, 2);
-+
-+ tdesc_type_with_fields *type_with_fields;
-+ type_with_fields = tdesc_create_union (feature, "lsxv");
-+ tdesc_type *field_type;
-+ field_type = tdesc_named_type (feature, "v16i8");
-+ tdesc_add_field (type_with_fields, "v16i8", field_type);
-+ field_type = tdesc_named_type (feature, "v8i16");
-+ tdesc_add_field (type_with_fields, "v8i16", field_type);
-+ field_type = tdesc_named_type (feature, "v4i32");
-+ tdesc_add_field (type_with_fields, "v4i32", field_type);
-+ field_type = tdesc_named_type (feature, "v2i64");
-+ tdesc_add_field (type_with_fields, "v2i64", field_type);
-+ field_type = tdesc_named_type (feature, "v4f32");
-+ tdesc_add_field (type_with_fields, "v4f32", field_type);
-+ field_type = tdesc_named_type (feature, "v2f64");
-+ tdesc_add_field (type_with_fields, "v2f64", field_type);
-+
-+ tdesc_create_reg (feature, "vr0", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr1", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr2", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr3", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr4", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr5", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr6", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr7", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr8", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr9", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr10", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr11", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr12", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr13", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr14", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr15", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr16", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr17", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr18", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr19", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr20", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr21", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr22", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr23", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr24", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr25", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr26", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr27", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr28", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr29", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr30", regnum++, 1, "lsx", 128,
"lsxv");
-+ tdesc_create_reg (feature, "vr31", regnum++, 1, "lsx", 128,
"lsxv");
-+ return regnum;
-+}
---- /dev/null
-+++ gdb-10.2/gdb/features/loongarch/lsx.xml
-@@ -0,0 +1,59 @@
-+<?xml version="1.0"?>
-+<!-- Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ Copying and distribution of this file, with or without modification,
-+ are permitted in any medium without royalty provided the copyright
-+ notice and this notice are preserved. -->
-+
-+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-+<feature name="org.gnu.gdb.loongarch.lsx">
-+ <vector id="v16i8" type="int8" count="16"/>
-+ <vector id="v8i16" type="int16" count="8"/>
-+ <vector id="v4i32" type="int32" count="4"/>
-+ <vector id="v2i64" type="int64" count="2"/>
-+ <vector id="v4f32" type="ieee_single" count="4"/>
-+ <vector id="v2f64" type="ieee_double" count="2"/>
-+
-+ <union id="lsxv">
-+ <field name="v16i8" type="v16i8"/>
-+ <field name="v8i16" type="v8i16"/>
-+ <field name="v4i32" type="v4i32"/>
-+ <field name="v2i64" type="v2i64"/>
-+ <field name="v4f32" type="v4f32"/>
-+ <field name="v2f64" type="v2f64"/>
-+ </union>
-+
-+ <reg name="vr0" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr1" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr2" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr3" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr4" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr5" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr6" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr7" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr8" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr9" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr10" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr11" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr12" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr13" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr14" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr15" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr16" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr17" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr18" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr19" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr20" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr21" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr22" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr23" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr24" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr25" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr26" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr27" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr28" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr29" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr30" bitsize="128" type="lsxv"
group="lsx"/>
-+ <reg name="vr31" bitsize="128" type="lsxv"
group="lsx"/>
-+</feature>
---- /dev/null
-+++ gdb-10.2/gdb/loongarch-linux-tdep.c
-@@ -0,0 +1,709 @@
-+/* Target-dependent code for GNU/Linux LoongArch.
-+
-+ Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of GDB.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <
http://www.gnu.org/licenses/>. */
-+
-+#include "defs.h"
-+#include "inferior.h"
-+#include "gdbcore.h"
-+#include "target.h"
-+#include "solib-svr4.h"
-+#include "osabi.h"
-+#include "loongarch-tdep.h"
-+#include "frame.h"
-+#include "regcache.h"
-+#include "trad-frame.h"
-+#include "tramp-frame.h"
-+#include "gdbtypes.h"
-+#include "objfiles.h"
-+#include "solib.h"
-+#include "solist.h"
-+#include "symtab.h"
-+#include "target-descriptions.h"
-+#include "loongarch-linux-tdep.h"
-+#include "glibc-tdep.h"
-+#include "linux-tdep.h"
-+#include "xml-syscall.h"
-+#include "gdbsupport/gdb_signals.h"
-+
-+static void
-+loongarch_supply_elf_gregset (const struct regset *r,
-+ struct regcache *regcache, int regno,
-+ const void *gprs, size_t len)
-+{
-+ auto regs = &gdbarch_tdep (regcache->arch ())->regs;
-+ gdb_assert (0 <= regs->r && sizeof (loongarch_elf_gregset_t) <=
len);
-+
-+ int regsize = register_size (regcache->arch (), regs->r);
-+ const gdb_byte *buf = NULL;
-+
-+ if (regno == -1)
-+ {
-+ /* Set $r0 = 0. */
-+ regcache->raw_supply_zeroed (regs->r);
-+
-+ for (int i = 1; i < 32; i++)
-+ {
-+ buf = (const gdb_byte*)gprs + regsize * i;
-+ regcache->raw_supply (regs->r + i, (const void *)buf);
-+ }
-+
-+ /* Size base (orig_a0) = regsize * regs->orig_a0. */
-+ buf = (const gdb_byte*)gprs + regsize * regs->orig_a0;
-+ regcache->raw_supply (regs->orig_a0, (const void *)buf);
-+
-+ /* Size base (pc) = regsize * regs->pc. */
-+ buf = (const gdb_byte*)gprs + regsize * regs->pc;
-+ regcache->raw_supply (regs->pc, (const void *)buf);
-+
-+ /* Size base (badv) = regsize * regs->badv. */
-+ buf = (const gdb_byte*)gprs + regsize * regs->badv;
-+ regcache->raw_supply (regs->badv, (const void *)buf);
-+ }
-+ else if (regs->r == regno)
-+ regcache->raw_supply_zeroed (regno);
-+ else if ((regs->r < regno && regno < regs->r + 32)
-+ || (regs->orig_a0 == regno)
-+ || (regs->pc == regno)
-+ || (regs->badv == regno))
-+ {
-+ /* Offset offset (regno) = regsize * (regno - regs->r). */
-+ buf = (const gdb_byte*)gprs + regsize * (regno - regs->r);
-+ regcache->raw_supply (regno, (const void *)buf);
-+ }
-+}
-+
-+static void
-+loongarch_fill_elf_gregset (const struct regset *r,
-+ const struct regcache *regcache, int regno,
-+ void *gprs, size_t len)
-+{
-+ auto regs = &gdbarch_tdep (regcache->arch ())->regs;
-+ gdb_assert (0 <= regs->r && sizeof (loongarch_elf_gregset_t) <=
len);
-+ int regsize = register_size (regcache->arch (), regs->r);
-+ gdb_byte *buf = NULL;
-+
-+ if (regno == -1)
-+ {
-+ for (int i = 0; i < 32; i++)
-+ {
-+ buf = (gdb_byte *)gprs + regsize * i;
-+ regcache->raw_collect (regs->r + i, (void *)buf);
-+ }
-+
-+ /* Size base (orig_a0) = regsize * regs->orig_a0. */
-+ buf = (gdb_byte *)gprs + regsize * regs->orig_a0;
-+ regcache->raw_collect (regs->orig_a0, (void *)buf);
-+
-+ /* Size base (pc) = regsize * regs->pc. */
-+ buf = (gdb_byte *)gprs + regsize * regs->pc;
-+ regcache->raw_collect (regs->pc, (void *)buf);
-+
-+ /* Size base (badv) = regsize * regs->badv. */
-+ buf = (gdb_byte *)gprs + regsize * regs->badv;
-+ regcache->raw_collect (regs->badv, (void *)buf);
-+ }
-+ else if ((regs->r <= regno && regno < regs->r + 32)
-+ ||(regs->orig_a0 == regno)
-+ ||(regs->pc == regno)
-+ ||(regs->badv == regno))
-+ {
-+ /* Offset offset (regno) = regsize * (regno - regs->r). */
-+ buf = (gdb_byte *)gprs + regsize * (regno - regs->r);
-+ regcache->raw_collect (regno, (void *)buf);
-+ }
-+}
-+
-+const struct regset loongarch_elf_gregset =
-+{
-+ NULL,
-+ loongarch_supply_elf_gregset,
-+ loongarch_fill_elf_gregset,
-+};
-+
-+static void
-+loongarch_supply_elf_fpregset (const struct regset *r,
-+ struct regcache *regcache, int regno,
-+ const void *fprs, size_t len)
-+{
-+ auto regs = &gdbarch_tdep (regcache->arch ())->regs;
-+ gdb_assert (0 <= regs->f && sizeof (loongarch_elf_fpregset_t) <=
len);
-+
-+ const gdb_byte *buf = NULL;
-+ int fprsize = register_size (regcache->arch (), regs->f);
-+ int fccsize = register_size (regcache->arch (), regs->fcc);
-+
-+ if (regno == -1)
-+ {
-+ /* 32 fprs. */
-+ for (int i = 0; i < 32; i++)
-+ {
-+ buf = (const gdb_byte *)fprs + fprsize * i;
-+ regcache->raw_supply (regs->f + i, (const void *)buf);
-+ }
-+
-+ /* 8 fccs , base (fcc) = 32 * sizeof (fpr). */
-+ buf = (const gdb_byte *)fprs + fprsize * 32;
-+ for (int i = 0; i < 8; i++)
-+ {
-+ regcache->raw_supply (regs->fcc + i, (const void *)buf);
-+ buf += fccsize;
-+ }
-+
-+ /* Size base (fcsr) = 32 * sizeof (fpr) + 8 * sizeof (fcc). */
-+ buf = (const gdb_byte *)fprs + 32 * fprsize + 8 * fccsize;
-+ regno = regs->fcsr;
-+ }
-+ else if (regs->f <= regno && regno < regs->f + 32)
-+ {
-+ /* Offset offset (regno - f) = (regno - regs->f) * sizeof (fpr). */
-+ buf = (const gdb_byte *)fprs + fprsize * (regno - regs->f);
-+ }
-+ else if (regs->fcc <= regno && regno < regs->fcc + 8)
-+ {
-+ /* Size base (fcc) + offset (regno - fcc)
-+ = 32 * sizeof (fpr) + (regno - regs->fcc) * sizeof (fcc). */
-+ buf = (const gdb_byte *)fprs + 32 * fprsize
-+ + (regno - regs->fcc) * fccsize;
-+ }
-+ else if (regs->fcsr == regno)
-+ {
-+ /* Size base (fcsr) = 32 * sizeof (fpr) + 8 * sizeof (fcc). */
-+ buf = (const gdb_byte *)fprs + 32 * fprsize + 8 * fccsize;
-+ }
-+ else
-+ {
-+ return;
-+ }
-+
-+ /* Supply register. */
-+ regcache->raw_supply (regno, (const void *)buf);
-+}
-+
-+static void
-+loongarch_fill_elf_fpregset (const struct regset *r,
-+ const struct regcache *regcache, int regno,
-+ void *fprs, size_t len)
-+{
-+ auto regs = &gdbarch_tdep (regcache->arch ())->regs;
-+ gdb_assert (0 <= regs->f && sizeof (loongarch_elf_fpregset_t) <=
len);
-+ gdb_byte *buf = NULL;
-+ int fprsize = register_size (regcache->arch (), regs->f);
-+ int fccsize = register_size (regcache->arch (), regs->fcc);
-+
-+ if (regno == -1)
-+ {
-+ /* 32 fprs. */
-+ for (int i = 0; i < 32; i++)
-+ {
-+ buf = (gdb_byte *)fprs + fprsize * i;
-+ regcache->raw_collect (regs->f + i, (void *)buf);
-+ }
-+
-+ /* 8 fccs , base (fcc) = 32 * sizeof (fpr). */
-+ buf = (gdb_byte *)fprs + fprsize * 32;
-+ for (int i = 0; i < 8; i++)
-+ {
-+ regcache->raw_collect (regs->fcc + i, (void *)buf);
-+ buf += fccsize;
-+ }
-+
-+ /* Size base (fcsr) = 32 * sizeof (fpr) + 8 * sizeof (fcc). */
-+ buf = (gdb_byte *)fprs + fprsize * 32 + fccsize * 8;
-+ regno = regs->fcsr;
-+ }
-+ else if (regs->f <= regno && regno < regs->f + 32)
-+ {
-+ /* Offset offset (regno - f) = (regno - regs->f) * sizeof (fpr). */
-+ buf = (gdb_byte *)fprs + fprsize * (regno - regs->f);
-+ }
-+ else if (regs->fcc <= regno && regno < regs->fcc + 8)
-+ {
-+ /* Size base (fcc) + offset (regno - fcc)
-+ = 32 * sizeof (fpr) + (regno - regs->fcc) * sizeof (fcc). */
-+ buf = (gdb_byte *)fprs + 32 * fprsize + (regno - regs->fcc) * fccsize;
-+ }
-+ else if (regs->fcsr == regno)
-+ {
-+ /* Size base (fcsr) = 32 * sizeof (fpr) + 8 * sizeof (fcc). */
-+ buf = (gdb_byte *)fprs + 32 * fprsize + 8 * fccsize;
-+ }
-+ else
-+ {
-+ return;
-+ }
-+
-+ /* Supply register. */
-+ regcache->raw_collect (regno, (void *)buf);
-+}
-+
-+const struct regset loongarch_elf_fpregset =
-+{
-+ NULL,
-+ loongarch_supply_elf_fpregset,
-+ loongarch_fill_elf_fpregset,
-+};
-+
-+static void
-+loongarch_supply_elf_cpucfgregset (const struct regset *r,
-+ struct regcache *regcache, int regno,
-+ const void *cpucfgs, size_t len)
-+{
-+}
-+
-+static void
-+loongarch_fill_elf_cpucfgregset (const struct regset *r,
-+ const struct regcache *regcache, int regno,
-+ void *cpucfgs, size_t len)
-+{
-+ ULONGEST xfered_len;
-+ target_xfer_partial (current_inferior ()->top_target (),
-+ /* current_top_target (),*/ TARGET_OBJECT_LARCH,
-+ "cpucfg", (gdb_byte *) cpucfgs, NULL, 0, len,
-+ &xfered_len);
-+ memset ((gdb_byte *) cpucfgs + xfered_len, 0, len - xfered_len);
-+}
-+
-+const struct regset loongarch_elf_cpucfgregset =
-+{
-+ NULL,
-+ loongarch_supply_elf_cpucfgregset,
-+ loongarch_fill_elf_cpucfgregset,
-+};
-+
-+static void
-+loongarch_supply_elf_lbtregset (const struct regset *r,
-+ struct regcache *regcache, int regno,
-+ const void *lbtrs, size_t len)
-+{
-+ auto regs = &gdbarch_tdep (regcache->arch ())->regs;
-+ gdb_assert (0 <= regs->scr && sizeof (loongarch_elf_lbtregset_t) <=
len);
-+
-+ const gdb_byte *buf = NULL;
-+ int scrsize = register_size (regcache->arch (), regs->scr);
-+ int efsize = register_size (regcache->arch (), regs->EFLAG);
-+
-+ if (regno == -1)
-+ {
-+ /* 4 scrs. */
-+ for (int i = 0; i < 4; i++)
-+ {
-+ buf = (const gdb_byte *)lbtrs + scrsize * i;
-+ regcache->raw_supply (regs->scr + i, (const void *)buf);
-+ }
-+
-+ /* Size base (EFLAG) = 4 * sizeof (scr). */
-+ buf = (const gdb_byte *)lbtrs + scrsize * 4;
-+ regcache->raw_supply (regs->EFLAG, (const void *)buf);
-+
-+ /* Size base (x86_top) = 4 * sizeof (scr) + sizeof (EFLAG). */
-+ buf = (const gdb_byte *)lbtrs + scrsize * 4 + efsize;
-+ regno = regs->x86_top;
-+ }
-+ else if (regs->scr <= regno && regno < regs->scr + 4)
-+ /* Offset offset (EFLAG) = sizeof (scr) * (regno - regs->scr). */
-+ buf = (const gdb_byte *)lbtrs + scrsize * (regno - regs->scr);
-+ else if (regs->EFLAG == regno)
-+ /* Size base (EFLAG) = 4 * sizeof (scr). */
-+ buf = (const gdb_byte *)lbtrs + scrsize * 4;
-+ else if (regs->x86_top == regno)
-+ {
-+ /* Size base (x86_top) = 4 * sizeof (scr) + sizeof (EFLAG). */
-+ buf = (const gdb_byte *)lbtrs + scrsize * 4 + efsize;
-+ }
-+ else
-+ {
-+ return;
-+ }
-+
-+ regcache->raw_supply (regno, (const void *)buf);
-+}
-+
-+static void
-+loongarch_fill_elf_lbtregset (const struct regset *r,
-+ const struct regcache *regcache, int regno,
-+ void *lbtrs, size_t len)
-+{
-+ auto regs = &gdbarch_tdep (regcache->arch ())->regs;
-+ gdb_assert (0 <= regs->scr && sizeof (loongarch_elf_lbtregset_t) <=
len);
-+
-+ gdb_byte *buf = NULL;
-+ int scrsize = register_size (regcache->arch (), regs->scr);
-+ int efsize = register_size (regcache->arch (), regs->EFLAG);
-+
-+ if (regno == -1)
-+ {
-+
-+ /* 4 scrs. */
-+ for (int i = 0; i < 4; i++)
-+ {
-+ buf = (gdb_byte *)lbtrs + scrsize * i;
-+ regcache->raw_collect (regs->scr + i, (void *)buf);
-+ }
-+
-+ /* Size base (EFLAG) = 4 * sizeof (scr). */
-+ buf = (gdb_byte *)lbtrs + scrsize * 4;
-+ regcache->raw_collect (regs->EFLAG, (void *)buf);
-+
-+ /* Size base (x86_top) = 4 * sizeof (scr) + sizeof (EFLAG). */
-+ buf = (gdb_byte *)lbtrs + scrsize * 4 + efsize;
-+ regno = regs->x86_top;
-+ }
-+ else if (regs->scr <= regno && regno < regs->scr + 4)
-+ /* Offset offset (EFLAG) = sizeof (scr) * (regno - regs->scr). */
-+ buf = (gdb_byte *)lbtrs + scrsize * (regno - regs->scr);
-+ else if (regs->EFLAG == regno)
-+ /* Size base (EFLAG) = 4 * sizeof (scr). */
-+ buf = (gdb_byte *)lbtrs + scrsize * 4;
-+ else if (regs->x86_top == regno)
-+ /* Size base (x86_top) = 4 * sizeof (scr) + sizeof (EFLAG). */
-+ buf = (gdb_byte *)lbtrs + scrsize * 4 + efsize;
-+ else
-+ {
-+ return;
-+ }
-+
-+ regcache->raw_collect (regno, (void *)buf);
-+}
-+
-+const struct regset loongarch_elf_lbtregset =
-+{
-+ NULL,
-+ loongarch_supply_elf_lbtregset,
-+ loongarch_fill_elf_lbtregset,
-+};
-+
-+static void
-+loongarch_supply_elf_lsxregset (const struct regset *r,
-+ struct regcache *regcache, int regno,
-+ const void *lsxrs, size_t len)
-+{
-+ auto regs = &gdbarch_tdep (regcache->arch ())->regs;
-+ gdb_assert (0 <= regs->vr && sizeof (loongarch_elf_lsxregset_t) <=
len);
-+
-+ const gdb_byte *buf = NULL;
-+ int regsize = register_size (regcache->arch (), regs->vr);
-+
-+ if (regno == -1)
-+ {
-+ for (int i = 0; i < 32; i++)
-+ {
-+ buf = (const gdb_byte *)lsxrs + regsize * i;
-+ regcache->raw_supply (regs->vr + i, (const void *)buf);
-+ }
-+ }
-+ else if (regs->vr <= regno && regno < regs->vr + 32)
-+ {
-+ buf = (const gdb_byte *)lsxrs + regsize * (regno - regs->vr);
-+ regcache->raw_supply (regno, (const void *)buf);
-+ }
-+}
-+
-+static void
-+loongarch_fill_elf_lsxregset (const struct regset *r,
-+ const struct regcache *regcache, int regno,
-+ void *lsxrs, size_t len)
-+{
-+ auto regs = &gdbarch_tdep (regcache->arch ())->regs;
-+ gdb_assert (0 <= regs->vr && sizeof (loongarch_elf_lsxregset_t) <=
len);
-+
-+ gdb_byte *buf = NULL;
-+ int regsize = register_size (regcache->arch (), regs->vr);
-+
-+ if (regno == -1)
-+ {
-+ for (int i = 0; i < 32; i++)
-+ {
-+ buf = (gdb_byte *)lsxrs + regsize * i;
-+ regcache->raw_collect (regs->vr + i, (void *)buf);
-+ }
-+ }
-+ else if (regs->vr <= regno && regno < regs->vr + 32)
-+ {
-+ buf = (gdb_byte *)lsxrs + regsize * (regno - regs->vr);
-+ regcache->raw_collect (regno, (void *)buf);
-+ }
-+}
-+
-+const struct regset loongarch_elf_lsxregset =
-+{
-+ NULL,
-+ loongarch_supply_elf_lsxregset,
-+ loongarch_fill_elf_lsxregset,
-+};
-+
-+static void
-+loongarch_supply_elf_lasxregset (const struct regset *r,
-+ struct regcache *regcache, int regno,
-+ const void *lasxrs, size_t len)
-+{
-+ auto regs = &gdbarch_tdep (regcache->arch ())->regs;
-+ gdb_assert (0 <= regs->xr && sizeof (loongarch_elf_lasxregset_t) <=
len);
-+
-+ const gdb_byte *buf = NULL;
-+ int regsize = register_size (regcache->arch (), regs->xr);
-+
-+ if (regno == -1)
-+ {
-+ for (int i = 0; i < 32; i++)
-+ {
-+ buf = (const gdb_byte *)lasxrs + regsize * i;
-+ regcache->raw_supply (regs->xr + i, (const void *)buf);
-+ }
-+ }
-+ else if (regs->xr <= regno && regno < regs->xr + 32)
-+ {
-+ buf = (const gdb_byte *)lasxrs + regsize * (regno - regs->xr);
-+ regcache->raw_supply (regno, (const void *)buf);
-+ }
-+}
-+
-+static void
-+loongarch_fill_elf_lasxregset (const struct regset *r,
-+ const struct regcache *regcache, int regno,
-+ void *lasxrs, size_t len)
-+{
-+ auto regs = &gdbarch_tdep (regcache->arch ())->regs;
-+ gdb_assert (0 <= regs->xr && sizeof (loongarch_elf_lasxregset_t) <=
len);
-+
-+ gdb_byte *buf = NULL;
-+ int regsize = register_size (regcache->arch (), regs->xr);
-+
-+ if (regno == -1)
-+ {
-+ for (int i = 0; i < 32; i++)
-+ {
-+ buf = (gdb_byte *)lasxrs + regsize * i;
-+ regcache->raw_collect (regs->xr + i, (void *)buf);
-+ }
-+ }
-+ else if (regs->xr <= regno && regno < regs->xr + 32)
-+ {
-+ buf = (gdb_byte *)lasxrs + regsize * (regno - regs->xr);
-+ regcache->raw_collect (regno, (void *)buf);
-+ }
-+}
-+
-+const struct regset loongarch_elf_lasxregset =
-+{
-+ NULL,
-+ loongarch_supply_elf_lasxregset,
-+ loongarch_fill_elf_lasxregset,
-+};
-+
-+static void
-+loongarch_linux_iterate_over_regset_sections (
-+ struct gdbarch *gdbarch, iterate_over_regset_sections_cb *cb, void *cb_data,
-+ const struct regcache *regcache)
-+{
-+ auto regs = &gdbarch_tdep (gdbarch)->regs;
-+ if (0 <= regs->r)
-+ cb (".reg", sizeof (loongarch_elf_gregset_t),
-+ sizeof (loongarch_elf_gregset_t), &loongarch_elf_gregset, NULL,
-+ cb_data);
-+ if (0 <= regs->f)
-+ cb (".reg2", sizeof (loongarch_elf_fpregset_t),
-+ sizeof (loongarch_elf_fpregset_t), &loongarch_elf_fpregset, NULL,
-+ cb_data);
-+ do
-+ {
-+ uint32_t t;
-+ ULONGEST xfered_len;
-+ if (target_xfer_partial (current_inferior ()->top_target (),
-+ /* current_top_target (),*/ TARGET_OBJECT_LARCH,
-+ "cpucfg", (gdb_byte *) &t, NULL, 0, sizeof (t),
-+ &xfered_len) != TARGET_XFER_OK)
-+ break;
-+ cb (".reg-loongarch-cpucfg", 64 * 4, 64 * 4,
&loongarch_elf_cpucfgregset,
-+ "LoongArch CPU config", cb_data);
-+ }
-+ while (0);
-+ if (0 <= regs->scr)
-+ cb (".reg-loongarch-lbt", sizeof (loongarch_elf_lbtregset_t),
-+ sizeof (loongarch_elf_lbtregset_t), &loongarch_elf_lbtregset,
-+ "LoongArch Binary Translation", cb_data);
-+ if (0 <= regs->vr)
-+ cb (".reg-loongarch-lsx", sizeof (loongarch_elf_lsxregset_t),
-+ sizeof (loongarch_elf_lsxregset_t), &loongarch_elf_lsxregset,
-+ "LoongArch SIMD Extension", cb_data);
-+ if (0 <= regs->xr)
-+ cb (".reg-loongarch-lasx", sizeof (loongarch_elf_lasxregset_t),
-+ sizeof (loongarch_elf_lasxregset_t), &loongarch_elf_lasxregset,
-+ "LoongArch Advanced SIMD Extension", cb_data);
-+}
-+
-+static const struct target_desc *
-+loongarch_linux_core_read_description (struct gdbarch *gdbarch,
-+ struct target_ops *target, bfd *abfd)
-+{
-+ int rlen, flen, fpu64, lbt, lsx, lasx;
-+
-+ rlen = 64;
-+
-+ fpu64 = !!bfd_get_section_by_name (abfd, ".reg2");
-+ lbt = !!bfd_get_section_by_name (abfd, ".reg-loongarch-lbt");
-+ lsx = !!bfd_get_section_by_name (abfd, ".reg-loongarch-lsx");
-+ lasx = !!bfd_get_section_by_name (abfd, ".reg-loongarch-lasx");
-+
-+ if (fpu64)
-+ flen = 64;
-+ else
-+ flen = 0;
-+
-+ return loongarch_create_target_description (rlen, flen, lbt, lsx, lasx);
-+}
-+
-+/* The RT signal frames look like this:
-+ struct rt_sigframe {
-+ struct siginfo rs_info;
-+ struct ucontext rs_uctx;
-+ };
-+
-+ struct ucontext {
-+ unsigned long uc_flags;
-+ struct ucontext *uc_link;
-+ stack_t uc_stack;
-+ sigset_t uc_sigmask;
-+ _u8 __unused[1024 / 8 - sizeof(sigset_t)];
-+ struct sigcontext uc_mcontext;
-+ };
-+}; */
-+
-+#define RTSIGFRAME_SIGINFO_SIZE 128
-+#define UCONTEXT_SIGCONTEXT_OFFSET 176
-+#define RTSIGFRAME_SIGCONTEXT_OFFSET (RTSIGFRAME_SIGINFO_SIZE \
-+ + UCONTEXT_SIGCONTEXT_OFFSET)
-+
-+static void
-+loongarch_linux_lp64_sigframe_init (const struct tramp_frame *self,
-+ struct frame_info *this_frame,
-+ struct trad_frame_cache *this_cache,
-+ CORE_ADDR func)
-+{
-+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
-+ auto regs = &gdbarch_tdep (gdbarch)->regs;
-+ CORE_ADDR frame_sp = get_frame_sp (this_frame);
-+
-+ CORE_ADDR sigcontext_base = frame_sp + RTSIGFRAME_SIGCONTEXT_OFFSET;
-+ int i;
-+
-+ trad_frame_set_reg_addr (this_cache, regs->pc, sigcontext_base);
-+ for (i = 0; i < 32; i++)
-+ trad_frame_set_reg_addr (this_cache, regs->r + i,
-+ sigcontext_base + 8 + i * 8);
-+
-+ trad_frame_set_id (this_cache, frame_id_build (frame_sp, func));
-+}
-+
-+static const struct tramp_frame loongarch_linux_lp64_rt_sigframe =
-+{
-+ SIGTRAMP_FRAME,
-+ 4,
-+ { /* From $kernel/arch/loongarch/vdso/sigreturn.S. */
-+ /* ori $r11, $r0, 0x8b(__NR_rt_sigreturn) */
-+ { 0x03822c0b, ULONGEST_MAX },
-+ { 0x002b0000, ULONGEST_MAX }, /* syscall 0 */
-+ { TRAMP_SENTINEL_INSN, ULONGEST_MAX } },
-+ loongarch_linux_lp64_sigframe_init,
-+ NULL
-+};
-+
-+/* Return the current system call's number present in the
-+ a7 register. When the function fails, it returns -1. */
-+
-+static LONGEST
-+loongarch_linux_get_syscall_number (struct gdbarch *gdbarch,
-+ thread_info *thread)
-+{
-+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-+ auto regs = &tdep->regs;
-+ struct regcache *regcache = get_thread_regcache (thread);
-+ LONGEST ret;
-+
-+ if ((EF_LOONGARCH_IS_LP64 (tdep->ef_abi))
-+ && (REG_VALID == regcache_cooked_read_signed (regcache, regs->r + 11,
&ret)))
-+ return ret;
-+
-+ return -1;
-+}
-+
-+static CORE_ADDR
-+loongarch_linux_syscall_next_pc (struct frame_info *frame)
-+{
-+ struct gdbarch *gdbarch = get_frame_arch (frame);
-+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-+ auto regs = &tdep->regs;
-+ ULONGEST a7 = get_frame_register_unsigned (frame, regs->r + 11);
-+
-+ /* If we are about to make a sigreturn syscall, use the unwinder to
-+ decode the signal frame. */
-+ if ((EF_LOONGARCH_IS_LP64 (tdep->ef_abi))
-+ && (a7 == 0x8b /* LP64: __NR_rt_sigreturn. */))
-+ return frame_unwind_caller_pc (get_current_frame ());
-+
-+ return -1;
-+}
-+
-+static void
-+loongarch_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
-+{
-+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-+
-+ linux_init_abi (info, gdbarch); /* FIXME displaced step support. */
-+
-+ if (EF_LOONGARCH_IS_ILP32 (tdep->ef_abi))
-+ set_solib_svr4_fetch_link_map_offsets (
-+ gdbarch, svr4_ilp32_fetch_link_map_offsets);
-+
-+ else if (EF_LOONGARCH_IS_LP64 (tdep->ef_abi))
-+ {
-+ set_solib_svr4_fetch_link_map_offsets (gdbarch,
-+ svr4_lp64_fetch_link_map_offsets);
-+ tramp_frame_prepend_unwinder (gdbarch,
-+ &loongarch_linux_lp64_rt_sigframe);
-+ tdep->syscall_next_pc = loongarch_linux_syscall_next_pc;
-+
-+ set_gdbarch_get_syscall_number (gdbarch,
-+ loongarch_linux_get_syscall_number);
-+ }
-+
-+ /* GNU/Linux uses the dynamic linker included in the GNU C Library. */
-+ set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
-+
-+ /* Enable TLS support. */
-+ set_gdbarch_fetch_tls_load_module_address (gdbarch,
-+ svr4_fetch_objfile_link_map);
-+
-+ set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
-+
-+ /* Core file support. */
-+ set_gdbarch_iterate_over_regset_sections (
-+ gdbarch, loongarch_linux_iterate_over_regset_sections);
-+ set_gdbarch_core_read_description (gdbarch,
-+ loongarch_linux_core_read_description);
-+}
-+
-+void _initialize_loongarch_linux_tdep ();
-+void
-+_initialize_loongarch_linux_tdep ()
-+{
-+ gdbarch_register_osabi (bfd_arch_loongarch, bfd_mach_loongarch32,
-+ GDB_OSABI_LINUX, loongarch_linux_init_abi);
-+ gdbarch_register_osabi (bfd_arch_loongarch, bfd_mach_loongarch64,
-+ GDB_OSABI_LINUX, loongarch_linux_init_abi);
-+}
---- /dev/null
-+++ gdb-10.2/gdb/loongarch-linux-tdep.h
-@@ -0,0 +1,48 @@
-+/* GNU/Linux on LoongArch target support, prototypes.
-+
-+ Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of GDB.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <
http://www.gnu.org/licenses/>. */
-+
-+#ifndef LOONGARCH_LINUX_TDEP_H
-+#define LOONGARCH_LINUX_TDEP_H
-+
-+#include <regset.h>
-+
-+#define ELF_NGREG 45
-+#define ELF_NFPREG 34
-+
-+typedef unsigned long loongarch_elf_gregset_t[ELF_NGREG];
-+extern const struct regset loongarch_elf_gregset;
-+
-+typedef double loongarch_elf_fpregset_t[ELF_NFPREG];
-+extern const struct regset loongarch_elf_fpregset;
-+
-+/* Regset variable size. */
-+extern const struct regset loongarch_elf_cpucfg;
-+
-+/* 4 SCRs + 4-byte EFLAG + 1-byte x86_top. */
-+typedef uint64_t loongarch_elf_lbtregset_t[5];
-+extern const struct regset loongarch_elf_lbtregset;
-+
-+typedef uint64_t loongarch_elf_lsxregset_t[32 * 2];
-+extern const struct regset loongarch_elf_lsxregset;
-+
-+typedef uint64_t loongarch_elf_lasxregset_t[32 * 4];
-+extern const struct regset loongarch_elf_lasxregset;
-+
-+#endif
---- /dev/null
-+++ gdb-10.2/gdb/loongarch-tdep.c
-@@ -0,0 +1,1926 @@
-+/* Target-dependent code for GNU/Linux LoongArch.
-+
-+ Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of GDB.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <
http://www.gnu.org/licenses/>. */
-+
-+#include "defs.h"
-+#include "frame.h"
-+#include "inferior.h"
-+#include "symtab.h"
-+#include "value.h"
-+#include "gdbcmd.h"
-+#include "language.h"
-+#include "gdbcore.h"
-+#include "symfile.h"
-+#include "objfiles.h"
-+#include "gdbtypes.h"
-+#include "target.h"
-+#include "arch-utils.h"
-+#include "regcache.h"
-+#include "osabi.h"
-+#include "block.h"
-+#include "reggroups.h"
-+#include "elf-bfd.h"
-+#include "symcat.h"
-+#include "dis-asm.h"
-+#include "frame-unwind.h"
-+#include "frame-base.h"
-+#include "trad-frame.h"
-+#include "infcall.h"
-+#include "floatformat.h"
-+#include "remote.h"
-+#include "target-descriptions.h"
-+#include "dwarf2/frame.h"
-+#include "user-regs.h"
-+#include "valprint.h"
-+#include "gdbsupport/common-defs.h"
-+#include "cli/cli-decode.h"
-+#include "observable.h"
-+#include "loongarch-tdep.h"
-+#include "arch/loongarch.h"
-+
-+#include <algorithm>
-+
-+/* Figure out where the longjmp will land.
-+ We expect the first arg to be a pointer to the jmp_buf structure
-+ from which we extract the pc (LOONGARCH_JB_PC) that we will land
-+ at. The pc is copied into PC. This routine returns 1 on
-+ success. */
-+#define LOONGARCH_JB_PC 0
-+
-+static int
-+loongarch_rlen (struct gdbarch *gdbarch)
-+{
-+ if (EF_LOONGARCH_IS_LP64 (gdbarch_tdep (gdbarch)->ef_abi))
-+ return 64;
-+ else if (EF_LOONGARCH_IS_ILP32 (gdbarch_tdep (gdbarch)->ef_abi))
-+ return 32;
-+ else
-+ gdb_assert_not_reached ("unknown ABI");
-+ return 0;
-+}
-+
-+static insn_t
-+loongarch_fetch_instruction (CORE_ADDR addr, int *errp)
-+{
-+ size_t insnlen = loongarch_insn_length (0);
-+ gdb_byte buf[insnlen];
-+ int err;
-+ ULONGEST ret;
-+
-+ err = target_read_memory (addr, buf, insnlen);
-+ if (errp != NULL)
-+ *errp = err;
-+ if (err != 0)
-+ {
-+ if (errp == NULL)
-+ memory_error (TARGET_XFER_E_IO, addr);
-+ return 0;
-+ }
-+ ret = extract_unsigned_integer (buf, insnlen, BFD_ENDIAN_LITTLE);
-+ return ret;
-+}
-+
-+static int
-+loongarch_insn_is_branch_and_must_branch (insn_t insn)
-+{
-+ if ((insn & 0xfc000000) == 0x4c000000 /* jirl r0:5,r5:5,s10:16<<2 */
-+ || (insn & 0xfc000000) == 0x50000000 /* b sb0:10|10:16<<2 */
-+ || (insn & 0xfc000000) == 0x54000000) /* bl sb0:10|10:16<<2 */
-+ return 1;
-+ return 0;
-+}
-+
-+static int
-+loongarch_insn_is_branch (insn_t insn)
-+{
-+ if (loongarch_insn_is_branch_and_must_branch (insn)
-+ || (insn & 0xfc000000) == 0x40000000 /* beqz r5:5,sb0:5|10:16<<2 */
-+ || (insn & 0xfc000000) == 0x44000000 /* bnez r5:5,sb0:5|10:16<<2 */
-+ || (insn & 0xfc000300) == 0x48000000 /* bceqz c5:3,sb0:5|10:16<<2 */
-+ || (insn & 0xfc000300) == 0x48000100 /* bcnez c5:3,sb0:5|10:16<<2 */
-+ || (insn & 0xfc000000) == 0x58000000 /* beq r5:5,r0:5,sb10:16<<2 */
-+ || (insn & 0xfc000000) == 0x5c000000 /* bne r5:5,r0:5,sb10:16<<2 */
-+ || (insn & 0xfc000000) == 0x60000000 /* blt r5:5,r0:5,sb10:16<<2 */
-+ || (insn & 0xfc000000) == 0x64000000 /* bge r5:5,r0:5,sb10:16<<2 */
-+ || (insn & 0xfc000000) == 0x68000000 /* bltu r5:5,r0:5,sb10:16<<2 */
-+ || (insn & 0xfc000000) == 0x6c000000) /* bgeu r5:5,r0:5,sb10:16<<2 */
-+ return 1;
-+ return 0;
-+}
-+
-+static CORE_ADDR
-+loongarch_next_pc_if_branch (struct regcache *regcache, CORE_ADDR cur_pc,
-+ insn_t insn)
-+{
-+ struct gdbarch *gdbarch = regcache->arch ();
-+ auto regs = &gdbarch_tdep (gdbarch)->regs;
-+ CORE_ADDR next_pc;
-+
-+ if ((insn & 0xfc000000) == 0x40000000 /* beqz r5:5,sb0:5|10:16<<2 */
-+ || (insn & 0xfc000000) == 0x44000000 /* bnez r5:5,sb0:5|10:16<<2 */
-+ || (insn & 0xfc000300) == 0x48000000 /* bceqz c5:3,sb0:5|10:16<<2 */
-+ || (insn & 0xfc000300) == 0x48000100) /* bcnez c5:3,sb0:5|10:16<<2 */
-+ next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
-+ else if ((insn & 0xfc000000) == 0x4c000000) /* jirl r0:5,r5:5,s10:16<<2 */
-+ next_pc = regcache_raw_get_signed (
-+ regcache, regs->r + loongarch_decode_imm ("5:5", insn, 0))
-+ + loongarch_decode_imm ("10:16<<2", insn, 1);
-+ else if ((insn & 0xfc000000) == 0x50000000 /* b sb0:10|10:16<<2 */
-+ || (insn & 0xfc000000) == 0x54000000) /* bl sb0:10|10:16<<2 */
-+ next_pc = cur_pc + loongarch_decode_imm ("0:10|10:16<<2", insn, 1);
-+ else if ((insn & 0xfc000000) == 0x58000000 /* beq r5:5,r0:5,sb10:16<<2 */
-+ || (insn & 0xfc000000) == 0x5c000000 /* bne r5:5,r0:5,sb10:16<<2 */
-+ || (insn & 0xfc000000) == 0x60000000 /* blt r5:5,r0:5,sb10:16<<2 */
-+ || (insn & 0xfc000000) == 0x64000000 /* bge r5:5,r0:5,sb10:16<<2 */
-+ || (insn & 0xfc000000) == 0x68000000 /* bltu r5:5,r0:5,sb10:16<<2 */
-+ || (insn & 0xfc000000)
-+ == 0x6c000000) /* bgeu r5:5,r0:5,sb10:16<<2 */
-+ next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
-+ else
-+ gdb_assert_not_reached ("I don't know what branch is this");
-+
-+ return next_pc;
-+}
-+
-+/* Checks for an atomic sequence of instructions beginning with a LL/LLD
-+ instruction and ending with a SC/SCD instruction. If such a sequence
-+ is found, attempt to step through it. A breakpoint is placed at the end of
-+ the sequence. */
-+
-+static std::vector<CORE_ADDR>
-+loongarch_deal_with_atomic_sequence (struct regcache *regcache, CORE_ADDR pc)
-+{
-+ struct gdbarch *gdbarch = regcache->arch ();
-+ CORE_ADDR next_pc;
-+ std::vector<CORE_ADDR> next_pcs;
-+ insn_t insn = loongarch_fetch_instruction (pc, NULL);
-+ size_t insnlen = loongarch_insn_length (insn);
-+ int i, atomic_sequence_length, found_atomic_sequence_endpoint;
-+
-+ if ((insn & 0xff000000) != 0x20000000 /* ll.w */
-+ && (insn & 0xff000000) != 0x22000000) /* ll.d */
-+ return {};
-+
-+ if (loongarch_debug)
-+ fprintf_unfiltered (gdb_stdlog,
-+ "Single step: PC: %s OK, I found ll\\.[wd] here. It's "
-+ "atomic sequence?\n",
-+ paddress (gdbarch, pc));
-+
-+ atomic_sequence_length = 30; /* Magic. */
-+ found_atomic_sequence_endpoint = 0;
-+ for (pc += insnlen, i = 0; i < atomic_sequence_length; pc += insnlen, i++)
-+ {
-+ insn = loongarch_fetch_instruction (pc, NULL);
-+ insnlen = loongarch_insn_length (insn);
-+
-+ if (loongarch_insn_is_branch_and_must_branch (insn))
-+ {
-+ if (loongarch_debug)
-+ fprintf_unfiltered (
-+ gdb_stdlog,
-+ "Single step: PC: %s Must branch here. Treat it normally.\n",
-+ paddress (gdbarch, pc));
-+ break;
-+ }
-+ else if (loongarch_insn_is_branch (insn))
-+ {
-+ next_pc = loongarch_next_pc_if_branch (regcache, pc, insn);
-+
-+ if (loongarch_debug)
-+ fprintf_unfiltered (gdb_stdlog,
-+ "Single step: PC: %s May branch inside and "
-+ "target is %s. Breakpoint there.\n",
-+ paddress (gdbarch, pc),
-+ paddress (gdbarch, next_pc));
-+
-+ next_pcs.push_back (next_pc);
-+ }
-+ else if ((insn & 0xff000000) == 0x21000000 /* sc.w */
-+ || (insn & 0xff000000) == 0x23000000) /* sc.d */
-+ {
-+ found_atomic_sequence_endpoint = 1;
-+ next_pc = pc + insnlen;
-+
-+ if (loongarch_debug)
-+ fprintf_unfiltered (gdb_stdlog,
-+ "Single step: PC: %s I found sc\\.[wd] and "
-+ "atomic sequence ends at here.\n"
-+ "Breakpoint next pc: %s.\n",
-+ paddress (gdbarch, pc),
-+ paddress (gdbarch, next_pc));
-+
-+ next_pcs.push_back (next_pc);
-+ break;
-+ }
-+ }
-+
-+ if (!found_atomic_sequence_endpoint)
-+ {
-+ if (loongarch_debug)
-+ fprintf_unfiltered (
-+ gdb_stdlog,
-+ "Single step: PC: %s Not ends with sc\\.[wd] in %d insns?\n"
-+ "Treat it as not atomic sequence.\n",
-+ paddress (gdbarch, pc), atomic_sequence_length);
-+
-+ return {};
-+ }
-+
-+ return next_pcs;
-+}
-+
-+/* Implement LoongArch software single step. */
-+
-+std::vector<CORE_ADDR>
-+loongarch_software_single_step (struct regcache *regcache);
-+std::vector<CORE_ADDR>
-+loongarch_software_single_step (struct regcache *regcache)
-+{
-+ struct gdbarch *gdbarch = regcache->arch ();
-+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-+ CORE_ADDR pc = regcache_read_pc (regcache);
-+ std::vector<CORE_ADDR> next_pcs
-+ = loongarch_deal_with_atomic_sequence (regcache, pc);
-+
-+ if (!next_pcs.empty ())
-+ return next_pcs;
-+
-+ insn_t insn = loongarch_fetch_instruction (pc, NULL);
-+ size_t insnlen = loongarch_insn_length (insn);
-+ CORE_ADDR next = pc + insnlen;
-+
-+ if ((insn & 0xffff8000) == 0x002b0000 && tdep->syscall_next_pc)
-+ {
-+ CORE_ADDR syscall_next = tdep->syscall_next_pc (get_current_frame ());
-+ if (syscall_next != -1)
-+ {
-+ if (loongarch_debug)
-+ fprintf_unfiltered (gdb_stdlog,
-+ "PC: %s Syscall found. Next pc is %s.\n",
-+ paddress (gdbarch, pc),
-+ paddress (gdbarch, syscall_next));
-+ return {syscall_next};
-+ }
-+ }
-+
-+ if (loongarch_insn_is_branch (insn))
-+ {
-+ CORE_ADDR branch_tgt = loongarch_next_pc_if_branch (regcache, pc, insn);
-+ if (loongarch_debug)
-+ fprintf_unfiltered (
-+ gdb_stdlog, "PC: %s Next pc is %s if branch, %s for non-branch.\n",
-+ paddress (gdbarch, pc), paddress (gdbarch, branch_tgt),
-+ paddress (gdbarch, next));
-+ return {next, branch_tgt};
-+ }
-+ else
-+ {
-+ if (loongarch_debug)
-+ fprintf_unfiltered (gdb_stdlog, "PC: %s Next pc is %s.\n",
-+ paddress (gdbarch, pc), paddress (gdbarch, next));
-+ return {next};
-+ }
-+}
-+
-+/* Callback function for user_reg_add. */
-+
-+static struct value *
-+value_of_loongarch_user_reg (struct frame_info *frame, const void *baton)
-+{
-+ return value_of_register ((long long) baton, frame);
-+}
-+
-+/* Implement the register_name gdbarch method. */
-+
-+static const char *
-+loongarch_register_name (struct gdbarch *gdbarch, int regnum)
-+{
-+ auto regs = &gdbarch_tdep (gdbarch)->regs;
-+
-+ if ((0 <= regs->r && regs->r <= regnum && regnum <
regs->r + 32)
-+ && (EF_LOONGARCH_IS_LP64 (gdbarch_tdep (gdbarch)->ef_abi)))
-+ return loongarch_r_lp64_name[regnum - regs->r] + 1;
-+
-+ else if ((0 <= regs->f && regs->f <= regnum && regnum <
regs->f + 32)
-+ && (EF_LOONGARCH_IS_LP64 (gdbarch_tdep (gdbarch)->ef_abi)))
-+ return loongarch_f_lp64_name[regnum - regs->f] + 1;
-+
-+ return tdesc_register_name (gdbarch, regnum);
-+}
-+
-+/* Analyze the function prologue from START_PC to LIMIT_PC. Builds
-+ the associated FRAME_CACHE if not null.
-+ Return the address of the first instruction past the prologue. */
-+
-+static CORE_ADDR
-+loongarch_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
-+ CORE_ADDR limit_pc, struct frame_info *this_frame,
-+ struct trad_frame_cache *this_cache)
-+{
-+ auto regs = &gdbarch_tdep (gdbarch)->regs;
-+ int rlen_is_64b = (loongarch_rlen (gdbarch) == 64);
-+
-+ CORE_ADDR cur_pc, prologue_end = 0;
-+ insn_t insn;
-+ size_t insnlen;
-+
-+ int sp = regs->sp - regs->r;
-+
-+ long frame_offset = 0;
-+ int non_prologue_insns = 0;
-+ int cfa_unknown = 0;
-+
-+ /* Try to trace li. */
-+ int64_t r_value[32] = {0};
-+ int r_value_known[32] = {1, 0};
-+
-+ long r_cfa_offset[32] = {0};
-+ int r_cfa_offset_p[32] = {0};
-+
-+ long f_cfa_offset[32] = {0};
-+ int f_cfa_offset_p[32] = {0};
-+
-+ if (start_pc + 80 < limit_pc)
-+ limit_pc = start_pc + 80;
-+
-+ for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += insnlen)
-+ {
-+ int rd, rj, rk;
-+ int64_t si12, si20, si14;
-+
-+ insn = loongarch_fetch_instruction (cur_pc, NULL);
-+ insnlen = loongarch_insn_length (insn);
-+
-+ rd = loongarch_decode_imm ("0:5", insn, 0);
-+ rj = loongarch_decode_imm ("5:5", insn, 0);
-+ rk = loongarch_decode_imm ("10:5", insn, 0);
-+ si12 = loongarch_decode_imm ("10:12", insn, 1);
-+ si20 = loongarch_decode_imm ("5:20", insn, 1);
-+ si14 = loongarch_decode_imm ("10:14<<2", insn, 1);
-+
-+ if ((((insn & 0xffc00000) == 0x02800000 /* addi.w sp,sp,si12 */
-+ && !rlen_is_64b)
-+ || ((insn & 0xffc00000) == 0x02c00000 /* addi.d sp,sp,si12 */
-+ && rlen_is_64b))
-+ && rd == sp && rj == sp)
-+ {
-+ if (si12 < 0)
-+ frame_offset -= si12;
-+ else
-+ /* Exit loop if a positive stack adjustment is found, which
-+ usually means that the stack cleanup code in the function
-+ epilogue is reached. */
-+ break;
-+ prologue_end = cur_pc + insnlen;
-+ }
-+ else if ((((insn & 0xffc00000) == 0x29800000 /* st.w rd,sp,si12 */
-+ && !rlen_is_64b)
-+ || ((insn & 0xffc00000) == 0x29c00000 /* st.d rd,sp,si12 */
-+ && rlen_is_64b))
-+ && rj == sp)
-+ {
-+ if (!r_cfa_offset_p[rd] && !r_value_known[rd])
-+ r_cfa_offset[rd] = si12 - frame_offset, r_cfa_offset_p[rd] = 1;
-+ prologue_end = cur_pc + insnlen;
-+ }
-+ else if ((((insn & 0xff000000) == 0x25000000 /* stptr.w rd,sp,si14 */
-+ && !rlen_is_64b)
-+ || ((insn & 0xff000000) == 0x27000000 /* stptr.d rd,sp,si14 */
-+ && rlen_is_64b))
-+ && rj == sp)
-+ {
-+ if (!r_cfa_offset_p[rd] && !r_value_known[rd])
-+ r_cfa_offset[rd] = si14 - frame_offset, r_cfa_offset_p[rd] = 1;
-+ prologue_end = cur_pc + insnlen;
-+ }
-+ else if (((insn & 0xffc00000) == 0x2b400000 /* fst.s fd,sp,si12 */
-+ || (insn & 0xffc00000) == 0x2bc00000) /* fst.d fd,sp,si12 */
-+ && rj == sp)
-+ {
-+ if (!f_cfa_offset_p[rd])
-+ f_cfa_offset[rd] = si12 - frame_offset, f_cfa_offset_p[rd] = 1;
-+ }
-+ else if ((((insn & 0xffff8000) == 0x00110000 /* sub.w sp,sp,rk */
-+ && !rlen_is_64b)
-+ || ((insn & 0xffff8000) == 0x00118000 /* sub.d sp,sp,rk */
-+ && rlen_is_64b))
-+ && rd == sp && rj == sp)
-+ {
-+ if (r_value_known[rk])
-+ {
-+ frame_offset += r_value[rk];
-+ prologue_end = cur_pc + insnlen;
-+ }
-+ else
-+ cfa_unknown = 1;
-+ }
-+ else if ((((insn & 0xffff8000) == 0x00100000 /* add.w sp,sp,rk */
-+ && !rlen_is_64b)
-+ || ((insn & 0xffff8000) == 0x00108000 /* add.d sp,sp,rk */
-+ && rlen_is_64b))
-+ && rd == sp && rj == sp)
-+ {
-+ if (r_value_known[rk] && r_value[rk] < 0)
-+ {
-+ frame_offset -= r_value[rk];
-+ prologue_end = cur_pc + insnlen;
-+ }
-+ else
-+ cfa_unknown = 1;
-+ }
-+ else if ((insn & 0xffff8000) == 0x00150000 /* or rd,sp,$r0 */
-+ && rj == sp && rk == 0)
-+ {
-+ sp = rd;
-+ prologue_end = cur_pc + insnlen;
-+ }
-+ else if ((insn & 0xffc00000) == 0x02800000) /* addi.w rd,rj,si12 */
-+ {
-+ if (r_value_known[rj] && rd != 0)
-+ r_value[rd] = (int32_t) (r_value[rj] + si12),
-+ r_value_known[rd] = 1;
-+ }
-+ else if ((insn & 0xffc00000) == 0x03800000) /* ori rd,rj,si12 */
-+ {
-+ if (r_value_known[rj] && rd != 0)
-+ r_value[rd] = r_value[rj] | (si12 & 0xfff), r_value_known[rd] = 1;
-+ }
-+ else if ((insn & 0xfe000000) == 0x14000000) /* lu12i.w rd,si20 */
-+ {
-+ if (rd != 0)
-+ r_value[rd] = si20 << 12, r_value_known[rd] = 1;
-+ }
-+ else if ((insn & 0xfe000000) == 0x16000000) /* lu32i.d rd,si20 */
-+ {
-+ if (r_value_known[rd] && rd != 0)
-+ r_value[rd] = (r_value[rd] & 0xffffffff) | (si20 << 32),
-+ r_value_known[rd] = 1;
-+ }
-+ else if ((insn & 0xffc00000) == 0x03000000) /* lu52i.d rd,rj,si12 */
-+ {
-+ if (r_value_known[rj] && rd != 0)
-+ r_value[rd] = (r_value[rj] & 0xfffffffffffff) | (si12 << 52),
-+ r_value_known[rd] = 1;
-+ }
-+ else if (loongarch_insn_is_branch (insn))
-+ break; /* Shrink-wrap or end of prologue in a basic block. */
-+ else
-+ non_prologue_insns++;
-+
-+ /* 4 INSNs for 'la' and one for some other. */
-+ if (5 < non_prologue_insns)
-+ break;
-+ }
-+
-+ if (loongarch_debug)
-+ {
-+ const char *fun_name;
-+ find_pc_partial_function (start_pc, &fun_name, NULL, NULL);
-+ fprintf_unfiltered (gdb_stdlog,
-+ "Prologue Analyze: -- Start -- Callee [%s] %s\n",
-+ fun_name ? fun_name : "<unknown>",
-+ paddress (gdbarch, start_pc));
-+ }
-+
-+ do
-+ {
-+ int i;
-+ CORE_ADDR cfa = -1;
-+
-+ if (!(this_frame && this_cache))
-+ break;
-+
-+ if (!cfa_unknown)
-+ {
-+ try
-+ {
-+ cfa = get_frame_register_signed (this_frame, regs->r + sp)
-+ + frame_offset;
-+ }
-+ catch (const gdb_exception_error &ex)
-+ {
-+ cfa_unknown = 1;
-+ if (ex.error != NOT_AVAILABLE_ERROR)
-+ throw;
-+ }
-+
-+ if (loongarch_debug)
-+ fprintf_unfiltered (
-+ gdb_stdlog,
-+ "Prologue Analyze: CFA is (frame pointer $%s + 0x%lx) = %s\n",
-+ gdbarch_register_name (gdbarch, regs->r + sp),
-+ (long) frame_offset,
-+ cfa_unknown ? "<unknown>" : paddress (gdbarch, cfa));
-+ }
-+ else if (loongarch_debug)
-+ fprintf_unfiltered (gdb_stdlog,
-+ "Prologue Analyze: Unknown stack frame size, so "
-+ "can't get known CFA\n");
-+
-+ if (r_cfa_offset_p[1] && !cfa_unknown)
-+ {
-+ CORE_ADDR ret_saved = cfa + r_cfa_offset[1];
-+ trad_frame_set_reg_addr (this_cache, gdbarch_pc_regnum (gdbarch),
-+ ret_saved);
-+ if (loongarch_debug)
-+ fprintf_unfiltered (
-+ gdb_stdlog,
-+ "Prologue Analyze: Return addr saved in (CFA - 0x%lx) = %s\n",
-+ -r_cfa_offset[1], paddress (gdbarch, ret_saved));
-+ }
-+ else if (r_cfa_offset_p[1] /* && cfa_unknown */)
-+ {
-+ if (loongarch_debug)
-+ fprintf_unfiltered (gdb_stdlog,
-+ "Prologue Analyze: Return addr saved in (CFA "
-+ "- 0x%lx), but CFA is unknown\n",
-+ -r_cfa_offset[1]);
-+ }
-+ else
-+ {
-+ trad_frame_set_reg_realreg (this_cache, gdbarch_pc_regnum (gdbarch),
-+ regs->r + 1);
-+ if (loongarch_debug)
-+ fprintf_unfiltered (gdb_stdlog,
-+ "Prologue Analyze: No found $r1 pushed in "
-+ "stack. Return addr saved in $r1\n");
-+ }
-+
-+ if (cfa_unknown)
-+ {
-+ trad_frame_set_this_base (this_cache, -1);
-+ break;
-+ }
-+
-+ trad_frame_set_reg_value (this_cache, gdbarch_sp_regnum (gdbarch),
-+ (LONGEST) cfa);
-+ trad_frame_set_this_base (this_cache, cfa);
-+
-+ if (loongarch_debug)
-+ fprintf_unfiltered (
-+ gdb_stdlog,
-+ "Prologue Analyze: Where caller's registers saved as follow:\n");
-+
-+ for (i = 0; i < 32; i++)
-+ if (r_cfa_offset_p[i] && i != 1)
-+ {
-+ trad_frame_set_reg_addr (this_cache, regs->r + i,
-+ cfa + r_cfa_offset[i]);
-+ if (loongarch_debug)
-+ fprintf_unfiltered (
-+ gdb_stdlog,
-+ "Prologue Analyze: $%s: saved in (CFA - 0x%lx) = %s\n",
-+ gdbarch_register_name (gdbarch, regs->r + i), -r_cfa_offset[i],
-+ paddress (gdbarch, cfa + r_cfa_offset[i]));
-+ }
-+
-+ if (regs->f <= 0)
-+ for (i = 0; i < 32; i++)
-+ {
-+ if (f_cfa_offset_p[i])
-+ trad_frame_set_reg_addr (this_cache, regs->f + i,
-+ cfa + f_cfa_offset[i]);
-+ if (loongarch_debug)
-+ fprintf_unfiltered (
-+ gdb_stdlog,
-+ "Prologue Analyze: $%s: saved in (CFA - 0x%lx) = %s\n",
-+ gdbarch_register_name (gdbarch, regs->f + i), -f_cfa_offset[i],
-+ paddress (gdbarch, cfa + f_cfa_offset[i]));
-+ }
-+ }
-+ while (0);
-+
-+ if (loongarch_debug)
-+ fprintf_unfiltered (gdb_stdlog, "Prologue Analyze: -- End -- %s\n",
-+ paddress (gdbarch, cur_pc));
-+
-+ return prologue_end ? prologue_end : cur_pc;
-+}
-+
-+/* Implement the loongarch_skip_prologue gdbarch method. */
-+
-+/* To skip prologues, I use this predicate. Returns either PC itself
-+ if the code at PC does not look like a function prologue; otherwise
-+ returns an address that (if we're lucky) follows the prologue. If
-+ LENIENT, then we must skip everything which is involved in setting
-+ up the frame (it's OK to skip more, just so long as we don't skip
-+ anything which might clobber the registers which are being saved.
-+ We must skip more in the case where part of the prologue is in the
-+ delay slot of a non-prologue instruction). */
-+
-+static CORE_ADDR
-+loongarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
-+{
-+ CORE_ADDR limit_pc;
-+ CORE_ADDR func_addr;
-+
-+ /* See if we can determine the end of the prologue via the symbol table.
-+ If so, then return either PC, or the PC after the prologue, whichever
-+ is greater. */
-+ if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
-+ {
-+ CORE_ADDR post_prologue_pc
-+ = skip_prologue_using_sal (gdbarch, func_addr);
-+ if (post_prologue_pc != 0)
-+ return std::max (pc, post_prologue_pc);
-+ }
-+
-+ /* Can't determine prologue from the symbol table, need to examine
-+ instructions. */
-+
-+ /* Find an upper limit on the function prologue using the debug
-+ information. If the debug information could not be used to provide
-+ that bound, then use an arbitrary large number as the upper bound. */
-+ limit_pc = skip_prologue_using_sal (gdbarch, pc);
-+ if (limit_pc == 0)
-+ limit_pc = pc + 100; /* Magic. */
-+
-+ return loongarch_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL);
-+}
-+
-+/* Adjust the address downward (direction of stack growth) so that it
-+ is correctly aligned for a new stack frame. */
-+static CORE_ADDR
-+loongarch_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
-+{
-+ return align_down (addr, 16);
-+}
-+
-+/* Implement the unwind_pc gdbarch method. */
-+
-+static CORE_ADDR
-+loongarch_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-+{
-+ return frame_unwind_register_signed (next_frame,
-+ gdbarch_pc_regnum (gdbarch));
-+}
-+
-+/* Implement the unwind_sp gdbarch method. */
-+
-+static CORE_ADDR
-+loongarch_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
-+{
-+ return frame_unwind_register_signed (next_frame,
-+ gdbarch_sp_regnum (gdbarch));
-+}
-+
-+/* Implement the dummy_id gdbarch method. */
-+
-+static struct frame_id
-+loongarch_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-+{
-+ return frame_id_build (
-+ get_frame_register_signed (this_frame, gdbarch_sp_regnum (gdbarch)),
-+ get_frame_pc (this_frame));
-+}
-+
-+/* Generate, or return the cached frame cache for the loongarch frame
-+ unwinder. */
-+
-+static struct trad_frame_cache *
-+loongarch_frame_cache (struct frame_info *this_frame, void **this_cache)
-+{
-+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
-+ struct trad_frame_cache *cache;
-+ CORE_ADDR pc, start_addr, stack_addr;
-+
-+ if (*this_cache != NULL)
-+ return (struct trad_frame_cache *) *this_cache;
-+ cache = trad_frame_cache_zalloc (this_frame);
-+ *this_cache = cache;
-+
-+ pc = get_frame_address_in_block (this_frame);
-+ if (find_pc_partial_function (pc, NULL, &start_addr, NULL))
-+ {
-+ loongarch_scan_prologue (gdbarch, start_addr, pc, this_frame, cache);
-+ stack_addr = trad_frame_get_this_base (cache);
-+ trad_frame_set_id (cache,
-+ stack_addr == -1
-+ ? frame_id_build_unavailable_stack (start_addr)
-+ : frame_id_build (stack_addr, start_addr));
-+ }
-+ else
-+ {
-+ auto regs = &gdbarch_tdep (gdbarch)->regs;
-+ trad_frame_set_reg_realreg (cache, regs->ra, -2 /* TF_REG_UNKNOWN */);
-+ trad_frame_set_reg_realreg (cache, gdbarch_pc_regnum (gdbarch),
-+ regs->ra);
-+
-+ trad_frame_set_id (cache, frame_id_build_unavailable_stack (pc));
-+ }
-+ return cache;
-+}
-+
-+/* Implement the this_id callback for loongarch frame unwinder. */
-+
-+static void
-+loongarch_frame_this_id (struct frame_info *this_frame, void **prologue_cache,
-+ struct frame_id *this_id)
-+{
-+ struct trad_frame_cache *info;
-+
-+ info = loongarch_frame_cache (this_frame, prologue_cache);
-+ trad_frame_get_id (info, this_id);
-+}
-+
-+/* Implement the prev_register callback for loongarch frame unwinder. */
-+
-+static struct value *
-+loongarch_frame_prev_register (struct frame_info *this_frame,
-+ void **prologue_cache, int regnum)
-+{
-+ struct trad_frame_cache *info;
-+
-+ info = loongarch_frame_cache (this_frame, prologue_cache);
-+ return trad_frame_get_register (info, this_frame, regnum);
-+}
-+
-+static const struct frame_unwind loongarch_frame_unwind = {
-+ /*.type =*/NORMAL_FRAME,
-+ /*.stop_reason =*/default_frame_unwind_stop_reason,
-+ /*.this_id =*/loongarch_frame_this_id,
-+ /*.prev_register =*/loongarch_frame_prev_register,
-+ /*.unwind_data =*/NULL,
-+ /*.sniffer =*/default_frame_sniffer,
-+};
-+
-+typedef struct stack_data_t
-+{
-+ const gdb_byte *addr = NULL;
-+ int len = 0;
-+ bool ref = false;
-+} stack_data_t;
-+
-+static void
-+pass_on_stack (std::vector<stack_data_t> &stack, const gdb_byte *val, int
len,
-+ int align, bool ref = false)
-+{
-+ stack_data_t buf;
-+ buf.addr = val;
-+ buf.len = align_up (len, align);
-+ buf.ref = ref;
-+
-+ stack.push_back (buf);
-+}
-+
-+static void
-+pass_on_reg (struct regcache *regcache, int regno, const gdb_byte *val,
-+ int len)
-+{
-+ gdb_byte reg[32];
-+ memset (reg, 0, sizeof (reg));
-+ memcpy (reg, val, len);
-+ regcache->cooked_write (regno, reg);
-+}
-+
-+static void
-+compute_type_num(struct type *tp, int &complex_num, int &float_num,
-+ int &other_num, int &counter, int &float_seq,
-+ int &other_seq)
-+{
-+ if (tp->code () == TYPE_CODE_COMPLEX)
-+ complex_num++;
-+ else if (tp->code () == TYPE_CODE_FLT)
-+ float_num++;
-+ else if (tp->code () != TYPE_CODE_STRUCT)
-+ other_num++;
-+
-+ /* When the function parameter or return value type is a structure,
-+ traverse each member in the structure and make relevant marks. */
-+ for (int i = 0; i < tp->num_fields (); i++)
-+ {
-+ field fd = tp->field (i);
-+ struct type *t = fd.type ();
-+
-+ /* Call check_typedef(TYPE_TARGET_TYPE (TYPE)) on our type to make
-+ sure that, if TYPE is a TYPE_CODE_TYPEDEF, its TYPE is set to
-+ the target type instead of TYPE_CODE_TYPEDEF. */
-+ if (t->code () == TYPE_CODE_TYPEDEF)
-+ t = check_typedef (TYPE_TARGET_TYPE (t));
-+
-+ switch (t->code ())
-+ {
-+ case TYPE_CODE_STRUCT:
-+ compute_type_num(t, complex_num, float_num, other_num,
-+ counter, float_seq, other_seq);
-+ break;
-+ case TYPE_CODE_COMPLEX:
-+ complex_num++;
-+ break;
-+ case TYPE_CODE_FLT:
-+ float_num++;
-+ float_seq = ++counter;
-+ break;
-+ default:
-+ other_num++;
-+ other_seq = ++counter;
-+ break;
-+ }
-+ }
-+}
-+
-+static void
-+pass_small_struct_on_reg (struct gdbarch *gdbarch, struct type *tp,
-+ const gdb_byte *data, std::vector<stack_data_t>
&gp,
-+ std::vector<stack_data_t> &fp)
-+{
-+ const int rlen = loongarch_rlen (gdbarch) / 8;
-+ int len = TYPE_LENGTH (tp);
-+ int complex_num = 0, float_num = 0, other_num = 0;
-+ int counter = 0, float_seq = 0, other_seq = 0;
-+ stack_data_t elm;
-+
-+ gdb_assert (len <= 2 * rlen);
-+
-+ /* Compute the relevant members and types in the function parameters
-+ and mark them. */
-+ compute_type_num(tp, complex_num, float_num, other_num,
-+ counter, float_seq, other_seq);
-+
-+ if (other_num > 0 && float_num == 0 && len <= rlen)
-+ {
-+ /* For the small structure has only other types (like char/short/int/long
-+ etc.), and the size does not exceed rlen, pass on one gp or stack. */
-+ elm.addr = data;
-+ elm.len = rlen;
-+ gp.push_back (elm);
-+ }
-+ else if (float_num == 1 && complex_num == 0 && other_num == 0
&& len <= rlen)
-+ {
-+ /* For the small structure has only floating-point (like float/double),
-+ and the size does not exceed rlen, pass on one fp or stack. */
-+ elm.addr = data;
-+ elm.len = rlen;
-+ fp.push_back (elm);
-+ }
-+ else if (float_num == 1 && other_num == 1)
-+ {
-+ /* For the small structure has only one floating-point type and
-+ one other type(like float and int, char and double etc.), the
-+ floating-point type passes through one fp or stack, and the
-+ other types pass on one gp or stack. */
-+ if (float_seq < other_seq)
-+ {
-+ /* Floating point first, first pass on fp, then gp. */
-+ elm.addr = data;
-+ if (len == rlen)
-+ elm.len = rlen / 2;
-+ else
-+ elm.len = rlen;
-+ fp.push_back (elm);
-+ elm.addr += elm.len;
-+ gp.push_back (elm);
-+ }
-+ else
-+ {
-+ /* Floating point after, first pass on gp, then fp. */
-+ elm.addr = data;
-+ if (len == rlen)
-+ elm.len = rlen / 2;
-+ else
-+ elm.len = rlen;
-+ gp.push_back (elm);
-+ elm.addr += elm.len;
-+ fp.push_back (elm);
-+ }
-+ }
-+ else if ((complex_num == 1 && float_num == 0 && other_num == 0) ||
-+ (float_num ==2 && other_num == 0))
-+ {
-+ /* For the small structure has only two floating-point types or
-+ * one complex number type, pass on two fp or stack. */
-+ elm.addr = data;
-+ /* 2 float or 1 'float _Complex'. */
-+ if (len == rlen)
-+ elm.len = rlen / 2;
-+ /* 2 double or 1 'double _Complex'. */
-+ else
-+ elm.len = rlen;
-+ fp.push_back (elm);
-+ elm.addr += elm.len;
-+ fp.push_back (elm);
-+ }
-+ else
-+ {
-+ /* For other cases, pass on two gp or stack. */
-+ /* For example, the small structure is of the following type,
-+ 1. with more than 2 other types and the size is greater than rlen
-+ (like struct{int; int; int;}; struct{long; int; short; char;}; etc.).
-+ 2. with 'long double' on fpu64 or 'double' on fpu32
-+ (like struct{long double;}; or struct{double;}; etc.).
-+ 3. with more than 2 floating-point types
-+ (like struct{float; float; float;}; struct{float; float; double;};
-+ struct{float; float; float; float;}; etc.)
-+ 4. with 2 'float _Complex'
-+ (like struct{float _Complex; float _Complex;} etc.). */
-+ elm.addr = data;
-+ elm.len = rlen;
-+ gp.push_back (elm);
-+ elm.addr += elm.len;
-+ gp.push_back (elm);
-+ }
-+}
-+
-+static bool
-+try_pass_small_struct_on_reg (struct gdbarch *gdbarch,
-+ struct regcache *regcache, struct value *arg,
-+ int &gp, int &fp, int gp_max, int fp_max)
-+{
-+ const int rlen = loongarch_rlen (gdbarch) / 8;
-+ struct type *a_type = check_typedef (value_type (arg));
-+ int len = TYPE_LENGTH (a_type);
-+ const gdb_byte *val = value_contents (arg);
-+
-+ std::vector<stack_data_t> gpreg;
-+ std::vector<stack_data_t> fpreg;
-+
-+ gdb_assert (len <= 2 * rlen);
-+ // gdb_assert (a_type->code () == TYPE_CODE_STRUCT);
-+
-+ pass_small_struct_on_reg (gdbarch, a_type, val, gpreg, fpreg);
-+
-+ if (gp + gpreg.size () - 1 < gp_max && fp + fpreg.size () - 1 < fp_max)
-+ {
-+ for (auto it : gpreg)
-+ {
-+ pass_on_reg (regcache, gp, it.addr, it.len);
-+ gp++;
-+ }
-+ for (auto it : fpreg)
-+ {
-+ pass_on_reg (regcache, fp, it.addr, it.len);
-+ fp++;
-+ }
-+ return true;
-+ }
-+ return false;
-+}
-+
-+/* Implement the push dummy call gdbarch callback. */
-+
-+static CORE_ADDR
-+loongarch_lp32lp64_push_dummy_call (
-+ struct gdbarch *gdbarch, struct value *function, struct regcache *regcache,
-+ CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp,
-+ function_call_return_method return_method, CORE_ADDR struct_addr)
-+{
-+ const int rlen = loongarch_rlen (gdbarch) / 8;
-+ auto regs = &gdbarch_tdep (gdbarch)->regs;
-+ int gp = regs->r + 4; /* $a0 = $r4 = regs->r + 4 */
-+ int fp = regs->f; /* $fa0 */
-+ const int gp_max = gp + 8; /* gpr $a0 ~ $a7 ($r4 ~ $r11) */
-+ const int fp_max = fp + 8; /* fpr $fa0 ~ $fa7 */
-+ std::vector<stack_data_t> stack;
-+ int vec_insn = 0;
-+
-+ {
-+ if (return_method != return_method_normal)
-+ {
-+ regcache_cooked_write_unsigned (regcache, gp++, struct_addr);
-+ }
-+
-+ if (return_method == return_method_hidden_param)
-+ {
-+ args++;
-+ nargs--;
-+ }
-+ }
-+ regcache_cooked_write_signed (regcache, regs->ra, bp_addr);
-+
-+ struct type *f_type = check_typedef (value_type (function));
-+
-+ for (int i = 0; i < nargs; i++)
-+ {
-+ struct value *arg = args[i];
-+ struct type *a_type = check_typedef (value_type (arg));
-+ int len = TYPE_LENGTH (a_type);
-+ const gdb_byte *val = value_contents (arg);
-+
-+ switch (a_type->code ())
-+ {
-+ case TYPE_CODE_INT:
-+ case TYPE_CODE_BOOL:
-+ case TYPE_CODE_CHAR:
-+ case TYPE_CODE_RANGE:
-+ case TYPE_CODE_ENUM:
-+ case TYPE_CODE_PTR:
-+ if (gp < gp_max)
-+ {
-+ if (TYPE_UNSIGNED (a_type))
-+ {
-+ ULONGEST data
-+ = extract_unsigned_integer (val, len, BFD_ENDIAN_LITTLE);
-+ regcache_cooked_write_unsigned (regcache, gp++, data);
-+ }
-+ else
-+ {
-+ LONGEST data
-+ = extract_signed_integer (val, len, BFD_ENDIAN_LITTLE);
-+ regcache_cooked_write_signed (regcache, gp++, data);
-+ }
-+ }
-+ else
-+ {
-+ pass_on_stack (stack, val, len, rlen);
-+ }
-+ break;
-+ case TYPE_CODE_FLT:
-+ if (len <= rlen)
-+ {
-+ if (!TYPE_VARARGS (f_type) && (fp < fp_max))
-+ pass_on_reg (regcache, fp++, val, len);
-+ else if (gp < gp_max)
-+ pass_on_reg (regcache, gp++, val, len);
-+ else
-+ pass_on_stack (stack, val, len, rlen);
-+ }
-+ /* Long double like struct. */
-+ else
-+ {
-+ if (gp < gp_max - 1)
-+ {
-+ pass_on_reg (regcache, gp++, val, rlen);
-+ pass_on_reg (regcache, gp++, val + rlen, len - rlen);
-+ }
-+ else
-+ pass_on_stack (stack, val, len, rlen);
-+ }
-+ break;
-+ case TYPE_CODE_ARRAY:
-+ /* lsx */
-+ if (TYPE_VECTOR (a_type) && len == vec_insn && vec_insn == 16
-+ && fp < fp_max)
-+ {
-+ pass_on_reg (regcache, regs->vr + (fp++ - regs->f), val, len);
-+ }
-+ /* lasx */
-+ else if (TYPE_VECTOR (a_type) && len == vec_insn && vec_insn == 32
-+ && fp < fp_max)
-+ {
-+ pass_on_reg (regcache, regs->xr + (fp++ - regs->f), val, len);
-+ }
-+ /* scalar */
-+ else
-+ {
-+ if (len > rlen * 2)
-+ {
-+ /* Address on register, data on stack. */
-+ sp = align_down (sp - len, rlen);
-+ write_memory (sp, val, len);
-+ if (gp < gp_max)
-+ pass_on_reg (regcache, gp++, (const gdb_byte *) &sp, rlen);
-+ else
-+ pass_on_stack (stack, (const gdb_byte *) sp, rlen, rlen,
-+ true);
-+ }
-+ else
-+ {
-+ if (len <= rlen && gp < gp_max)
-+ {
-+ pass_on_reg (regcache, gp++, val, len);
-+ }
-+ else if (gp + 1 < gp_max)
-+ {
-+ pass_on_reg (regcache, gp++, val, rlen);
-+ pass_on_reg (regcache, gp++, val + rlen, rlen);
-+ }
-+ else
-+ {
-+ pass_on_stack (stack, val, len, rlen);
-+ }
-+ }
-+ }
-+ break;
-+ case TYPE_CODE_STRUCT:
-+ case TYPE_CODE_UNION:
-+ if (len > rlen * 2)
-+ {
-+ /* Address on register, data on stack. */
-+ sp = align_down (sp - len, rlen);
-+ write_memory (sp, val, len);
-+ if (gp < gp_max)
-+ pass_on_reg (regcache, gp++, (const gdb_byte *) &sp, rlen);
-+ else
-+ pass_on_stack (stack, (const gdb_byte *) sp, rlen, rlen, true);
-+ }
-+ else
-+ {
-+ if (!try_pass_small_struct_on_reg (gdbarch, regcache, arg, gp,
-+ fp, gp_max, fp_max))
-+ {
-+ pass_on_stack (stack, val, len, rlen);
-+ }
-+ }
-+ break;
-+ case TYPE_CODE_COMPLEX:
-+ {
-+ /* Two fpr or mem. */
-+ struct type *t_type = check_typedef (TYPE_TARGET_TYPE (a_type));
-+ int tlen = TYPE_LENGTH (t_type);
-+
-+ if (tlen < rlen)
-+ {
-+ if (!TYPE_VARARGS (f_type) && fp + 1 < fp_max)
-+ {
-+ pass_on_reg (regcache, fp++, (const gdb_byte *) val, tlen);
-+ pass_on_reg (regcache, fp++, (const gdb_byte *) val + tlen,
-+ tlen);
-+ }
-+ else if (gp < gp_max)
-+ {
-+ pass_on_reg (regcache, gp++, (const gdb_byte *) val, rlen);
-+ }
-+ else
-+ {
-+ pass_on_stack (stack, val, len, rlen);
-+ }
-+ }
-+ else if (tlen == rlen)
-+ {
-+ if (!TYPE_VARARGS (f_type) && fp + 1 < fp_max)
-+ {
-+ pass_on_reg (regcache, fp++, (const gdb_byte *) val, tlen);
-+ pass_on_reg (regcache, fp++, (const gdb_byte *) val + tlen,
-+ tlen);
-+ }
-+ else if (gp + 1 < gp_max)
-+ {
-+ pass_on_reg (regcache, gp++, (const gdb_byte *) val, rlen);
-+ pass_on_reg (regcache, gp++, (const gdb_byte *) val + rlen,
-+ rlen);
-+ }
-+ else if (gp + 1 == gp_max)
-+ {
-+ pass_on_reg (regcache, gp++, (const gdb_byte *) val, rlen);
-+ pass_on_stack (stack, val, tlen, rlen);
-+ }
-+ else
-+ {
-+ pass_on_stack (stack, val, len, rlen);
-+ }
-+ }
-+ else
-+ {
-+ sp = align_down (sp - len, rlen);
-+ write_memory (sp, val, len);
-+ if (gp < gp_max)
-+ pass_on_reg (regcache, gp++, (const gdb_byte *) &sp, rlen);
-+ else
-+ {
-+ pass_on_stack (stack, (const gdb_byte *) sp, rlen, rlen,
-+ true);
-+ }
-+ }
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ }
-+
-+ for (auto it : stack)
-+ sp = align_down (sp - it.len, rlen);
-+
-+ sp = align_down (sp, 16);
-+ CORE_ADDR tsp = sp;
-+ for (auto it : stack)
-+ {
-+ if (it.ref)
-+ write_memory (tsp, (const gdb_byte *) &it.addr, it.len);
-+ else
-+ write_memory (tsp, it.addr, it.len);
-+ tsp += it.len;
-+ stack.pop_back ();
-+ }
-+ regcache_cooked_write_unsigned (regcache, regs->sp, sp);
-+ return sp;
-+}
-+
-+static void
-+loongarch_xfer_reg_part (struct regcache *regcache, int reg_num, int len,
-+ gdb_byte *readbuf, size_t readbuf_off,
-+ const gdb_byte *writebuf, size_t writebuf_off)
-+{
-+ if (readbuf)
-+ regcache->cooked_read_part (reg_num, 0, len, readbuf + readbuf_off);
-+ if (writebuf)
-+ regcache->cooked_write_part (reg_num, 0, len, writebuf + writebuf_off);
-+}
-+
-+static enum return_value_convention
-+loongarch_lp64_return_value (struct gdbarch *gdbarch, struct value *function,
-+ struct type *type, struct regcache *regcache,
-+ gdb_byte *readbuf, const gdb_byte *writebuf)
-+{
-+ const size_t rlen = loongarch_rlen (gdbarch) / 8;
-+ auto regs = &gdbarch_tdep (gdbarch)->regs;
-+ size_t len = TYPE_LENGTH (type);
-+ enum type_code typecode = type->code ();
-+ int fpu_exist = 0 <= regs->f;
-+ int fv = fpu_exist ? regs->f : regs->r + 4;
-+
-+ gdb_assert (8 <= sizeof (LONGEST));
-+
-+ gdb_assert (!fpu_exist || register_size (gdbarch, regs->f) == rlen);
-+
-+ if (2 * rlen < len)
-+ return RETURN_VALUE_STRUCT_CONVENTION;
-+
-+ if (((typecode == TYPE_CODE_INT && TYPE_UNSIGNED (type))
-+ || typecode == TYPE_CODE_ENUM)
-+ && len <= rlen)
-+ /* For unsigned scalar type, we have zero-extended one in $v0. */
-+ if (writebuf)
-+ {
-+ gdb_byte buf[rlen];
-+ store_signed_integer (buf, rlen, BFD_ENDIAN_LITTLE,
-+ extract_unsigned_integer (writebuf, len,
-+ BFD_ENDIAN_LITTLE));
-+ loongarch_xfer_reg_part (regcache, regs->r + 4, rlen, NULL, 0,
-+ writebuf, 0);
-+ }
-+ else
-+ loongarch_xfer_reg_part (regcache, regs->r + 4, len, readbuf, 0, NULL,
-+ 0);
-+ else if (((typecode == TYPE_CODE_INT && !TYPE_UNSIGNED (type))
-+ || typecode == TYPE_CODE_PTR)
-+ && len <= rlen)
-+ /* For signed scalar type, we have sign-extended one in $v0. */
-+ if (writebuf)
-+ {
-+ gdb_byte buf[rlen];
-+ store_signed_integer (buf, rlen, BFD_ENDIAN_LITTLE,
-+ extract_signed_integer (writebuf, len,
-+ BFD_ENDIAN_LITTLE));
-+ loongarch_xfer_reg_part (regcache, regs->r + 4, rlen, NULL, 0,
-+ writebuf, 0);
-+ }
-+ else
-+ loongarch_xfer_reg_part (regcache, regs->r + 4, len, readbuf, 0, NULL,
-+ 0);
-+ else
-+ {
-+ int complex_num = 0, float_num = 0, other_num = 0;
-+ int counter = 0, float_seq = 0, other_seq = 0, tlen;
-+ /* Calculate the relevant members and types in the return value
-+ and mark them. */
-+ compute_type_num(type, complex_num, float_num, other_num,
-+ counter, float_seq, other_seq);
-+
-+ if (len == rlen)
-+ tlen = rlen / 2;
-+ else
-+ tlen = rlen;
-+
-+ /* For the small structure has only other types members (like char/short/int/long
-+ etc.), and the size does not exceed rlen, pass on $v0. */
-+ /* For 'char/short/int/long' etc. pass on $v0. */
-+ if (other_num > 0 && float_num == 0 && len <= rlen)
-+ loongarch_xfer_reg_part (regcache, regs->r + 4, len, readbuf, 0,
-+ writebuf, 0);
-+ /* For small structure with only one floating-point member, (like float/double)
pass on $fv0. */
-+ /* For float/double pass on $fv0. */
-+ else if (float_num == 1 && complex_num == 0 && other_num == 0
&& len <= rlen)
-+ loongarch_xfer_reg_part (regcache, fv, len, readbuf, 0, writebuf, 0);
-+ /* For small structure with one float/double member and one other member
-+ (char/short/int/long etc.). If the float/dobule member is in the front
-+ position, the float/dobule member pass on $fv0, the other member pass
-+ on $v0, otherwise the opposite . */
-+ else if (float_num == 1 && other_num == 1)
-+ if (float_seq < other_seq)
-+ loongarch_xfer_reg_part (regcache, fv, rlen, readbuf, 0,
-+ writebuf, 0),
-+ loongarch_xfer_reg_part (regcache, regs->r + 4, tlen, readbuf,
-+ tlen, writebuf, rlen);
-+ else
-+ loongarch_xfer_reg_part (regcache, regs->r + 4, rlen, readbuf, 0,
-+ writebuf, 0),
-+ loongarch_xfer_reg_part (regcache, fv, tlen, readbuf,
-+ tlen, writebuf, rlen);
-+ /* For small structure with one 'float/double _Complex' member,
-+ $fv0 is real and $fv1 is img. */
-+ /* For small structure with only one float and double member or
-+ or two float member , or two dobule member, $fv0 is the 1st
-+ member and $fv1 is the 2nd member. */
-+ /* For 'float/double _Complex', $fv0 is real and $fv1 is img. */
-+ else if ((complex_num == 1 && float_num == 0 && other_num == 0)
||
-+ (float_num ==2 && other_num == 0))
-+ loongarch_xfer_reg_part (regcache, fv, rlen, readbuf, 0,
-+ writebuf, 0),
-+ loongarch_xfer_reg_part (regcache, fv + 1, tlen, readbuf,
-+ tlen, writebuf, rlen);
-+ /* For small structure with 'long double' member,
-+ or when the small structure has more than two vaild members
-+ and the size is greater than rlen, pass on $v0 and $v1. */
-+ /* For small structure with two 'float _Complex' member,
-+ $v0 is the 1st member and $v1 is the 2nd member. */
-+ /* For 'long double' on fpu64 or 'double' on fpu32 pass on $v0 and
$v1. */
-+ else
-+ loongarch_xfer_reg_part (regcache, regs->r + 4, rlen, readbuf, 0,
-+ writebuf, 0),
-+ loongarch_xfer_reg_part (regcache, regs->r + 5, len - rlen, readbuf,
-+ rlen, writebuf, rlen);
-+ }
-+
-+ return RETURN_VALUE_REGISTER_CONVENTION;
-+}
-+
-+static int
-+loongarch_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num)
-+{
-+ auto regs = &gdbarch_tdep (gdbarch)->regs;
-+ if (0 <= num && num < 32)
-+ return regs->r + num;
-+ else if (32 <= num && num < 64 && 0 <= regs->f)
-+ return regs->f + num - 32;
-+ else if (64 <= num && num < 72 && 0 <= regs->fcc)
-+ return regs->fcc + num - 64;
-+ else
-+ return -1;
-+}
-+
-+static std::string
-+loongarch_gcc_target_options (struct gdbarch *gdbarch)
-+{
-+ return "";
-+}
-+
-+static int
-+loongarch_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
-+ struct reggroup *group)
-+{
-+ auto regs = &gdbarch_tdep (gdbarch)->regs;
-+
-+ if (gdbarch_register_name (gdbarch, regnum) == NULL
-+ || *gdbarch_register_name (gdbarch, regnum) == '\0')
-+ return 0;
-+
-+ int raw_p = regnum < gdbarch_num_regs (gdbarch);
-+
-+ if (group == save_reggroup || group == restore_reggroup)
-+ return raw_p;
-+ if (group == all_reggroup)
-+ return 1;
-+
-+ if (group == general_reggroup
-+ && (regs->orig_a0 == regnum || regs->pc == regnum
-+ || regs->badv == regnum
-+ || (regs->r <= regnum && regnum < regs->r + 32)))
-+ return 1;
-+
-+ /* Only $rx and $pc in general_reggroup. */
-+ if (group == general_reggroup)
-+ return 0;
-+
-+ if (0 <= regs->f
-+ && (regs->fcsr == regnum || (regs->f <= regnum && regnum
< regs->f + 32)
-+ || (regs->fcc <= regnum && regnum < regs->fcc + 8)))
-+ return group == float_reggroup;
-+
-+ /* Only $fx / $fccx / $fcsr in float_reggroup. */
-+ if (group == float_reggroup)
-+ return 0;
-+
-+ if (0 <= regs->vr && regs->vr <= regnum && regnum <
regs->vr + 32)
-+ if (group == vector_reggroup)
-+ return 1;
-+
-+ if (0 <= regs->xr && regs->xr <= regnum && regnum <
regs->xr + 32)
-+ if (group == vector_reggroup)
-+ return 1;
-+
-+ int ret = tdesc_register_in_reggroup_p (gdbarch, regnum, group);
-+ if (ret != -1)
-+ return ret;
-+
-+ return default_register_reggroup_p (gdbarch, regnum, group);
-+}
-+
-+constexpr gdb_byte loongarch_default_breakpoint[] = {0x05, 0x00, 0x2a, 0x00};
-+typedef BP_MANIPULATION (loongarch_default_breakpoint) loongarch_breakpoint;
-+
-+/* Initialize the current architecture based on INFO. If possible,
-+ re-use an architecture from ARCHES, which is a list of
-+ architectures already created during this debugging session.
-+
-+ Called e.g. at program startup, when reading a core file, and when
-+ reading a binary file. */
-+
-+/* This predicate tests whether we need to read lsx/lasx registers
-+ (instead of fp registers with the same DWARF2 code
-+ (thus the same internal code, though lasx/lsx/fp reg internal
-+ codes are different)) according to the byte-size of requested type. */
-+
-+static int
-+loongarch_fp_regnum_refers_to_lsx_lasx_p (struct gdbarch *gdbarch, int regnum,
-+ struct type *type)
-+{
-+ /* Conditions:
-+ 1) regnum is in "disputed" zone (fp/lsx/lasx, translated
-+ from dwarf regnum).
-+ 2) type is larger than 8 bytes.
-+
-+ (if specified type is larger than 8 bytes,
-+ then regnum refers to lsx / lasx register instead of fp register).
-+ */
-+ return regnum >= gdbarch_tdep (gdbarch)->regs.f
-+ && regnum < gdbarch_tdep (gdbarch)->regs.f + 32
-+ && TYPE_LENGTH (type) > 8;
-+}
-+
-+static int
-+loongarch_convert_register_p (struct gdbarch *gdbarch, int regnum,
-+ struct type *type)
-+{
-+ return loongarch_fp_regnum_refers_to_lsx_lasx_p (gdbarch, regnum, type);
-+}
-+
-+static int
-+loongarch_register_to_value (struct frame_info *frame, int regnum,
-+ struct type *type, gdb_byte *to, int *optimizedp,
-+ int *unavailablep)
-+{
-+ struct gdbarch *gdbarch = get_frame_arch (frame);
-+
-+ if (loongarch_fp_regnum_refers_to_lsx_lasx_p (gdbarch, regnum, type))
-+ {
-+ /* Add a displacement to regnum. */
-+ switch (TYPE_LENGTH (type))
-+ {
-+ case 16: /* 16-byte types, access vr. */
-+ if (!get_frame_register_bytes (frame,
-+ regnum
-+ + gdbarch_tdep (gdbarch)->regs.vr
-+ - gdbarch_tdep (gdbarch)->regs.f,
-+ 0, 16, to + 0, optimizedp,
-+ unavailablep))
-+ return 0;
-+ break;
-+
-+ case 32: /* 32-byte types, access xr. */
-+ if (!get_frame_register_bytes (frame,
-+ regnum
-+ + gdbarch_tdep (gdbarch)->regs.xr
-+ - gdbarch_tdep (gdbarch)->regs.f,
-+ 0, 32, to + 0, optimizedp,
-+ unavailablep))
-+ return 0;
-+ break;
-+
-+ default:
-+ goto fail;
-+ }
-+
-+ *optimizedp = *unavailablep = 0;
-+ return 1; /* 1 for success, 0 for fail. */
-+ }
-+
-+fail:
-+ internal_error (__FILE__, __LINE__,
-+ _ ("loongarch_register_to_value: unrecognized case"));
-+}
-+
-+static void
-+loongarch_value_to_register (struct frame_info *frame, int regnum,
-+ struct type *type, const gdb_byte *from)
-+{
-+ struct gdbarch *gdbarch = get_frame_arch (frame);
-+ if (loongarch_fp_regnum_refers_to_lsx_lasx_p (gdbarch, regnum, type))
-+ {
-+ switch (TYPE_LENGTH (type))
-+ {
-+ case 16: /* 16-byte types, access vr. */
-+ put_frame_register (frame,
-+ regnum + gdbarch_tdep (gdbarch)->regs.vr
-+ - gdbarch_tdep (gdbarch)->regs.f,
-+ from);
-+ return;
-+
-+ case 32: /* 32-byte types, access xr. */
-+ put_frame_register (frame,
-+ regnum + gdbarch_tdep (gdbarch)->regs.xr
-+ - gdbarch_tdep (gdbarch)->regs.f,
-+ from);
-+ return;
-+ }
-+ }
-+
-+ internal_error (__FILE__, __LINE__,
-+ _ ("loongarch_value_to_register: unrecognized case"));
-+}
-+
-+static int
-+loongarch_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
-+{
-+ CORE_ADDR jb_addr;
-+ struct gdbarch *gdbarch = get_frame_arch (frame);
-+ uint32_t ptr_size = gdbarch_ptr_bit (gdbarch) / TARGET_CHAR_BIT;
-+ gdb_byte buf[ptr_size];
-+
-+ jb_addr = get_frame_register_unsigned (frame, LOONGARCH_A0_REGNUM);
-+
-+ if (target_read_memory ((jb_addr + LOONGARCH_JB_PC * ptr_size),
-+ buf, ptr_size))
-+ return 0;
-+
-+ *pc = extract_unsigned_integer (buf, ptr_size, BFD_ENDIAN_LITTLE);
-+
-+ return 1;
-+}
-+
-+static struct gdbarch *
-+loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
-+{
-+ struct gdbarch *gdbarch;
-+ struct gdbarch_tdep tdep_instant, *tdep;
-+ struct tdesc_arch_data *tdesc_data = NULL;
-+ const struct target_desc *tdesc = info.target_desc;
-+ int i;
-+ size_t regnum;
-+
-+ tdep = &tdep_instant;
-+ memset (tdep, 0, sizeof (*tdep));
-+ memset (&tdep->regs, -1, sizeof (tdep->regs));
-+
-+ /* If abfd is nullptr then a EF_LOONGARCH_ABI_LP64 | EF_LOONGARCH_FLOAT_ABI_DOUBLE
-+ is returned in its default state. */
-+ if (info.abfd != NULL
-+ && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
-+ {
-+ int eflags = elf_elfheader (info.abfd)->e_flags;
-+ unsigned char eclass = elf_elfheader (info.abfd)->e_ident[EI_CLASS];
-+
-+ if (eflags) /* Executable file */
-+ {
-+ tdep->ef_abi = (EF_LOONGARCH_ABI(eflags) & EF_LOONGARCH_ABI_MASK);
-+ }
-+ else /* Core file */
-+ {
-+ if (eclass == ELFCLASS64)
-+ tdep->ef_abi = EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT;
-+ else
-+ tdep->ef_abi = EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT;
-+ }
-+ }
-+ else
-+ tdep->ef_abi = EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT;
-+
-+ /* Check any target description for validity. */
-+ if (!tdesc_has_registers (tdesc))
-+ tdesc = loongarch_get_base_target_description (
-+ EF_LOONGARCH_IS_ILP32 (tdep->ef_abi) ? 32 : 64,
-+ EF_LOONGARCH_IS_SINGLE_FLOAT (tdep->ef_abi) ? 32 : 64);
-+
-+ int valid_p = 1;
-+ const struct tdesc_feature *feature;
-+
-+ feature = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.base");
-+ if (feature == NULL)
-+ return NULL;
-+ regnum = 0;
-+ tdesc_data = tdesc_data_alloc ();
-+
-+ tdep->regs.r = regnum;
-+ for (i = 0; i < 32; i++)
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ loongarch_r_normal_name[i] + 1);
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
-+ tdep->regs.orig_a0 = regnum++, "orig_a0");
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
-+ tdep->regs.pc = regnum++, "pc");
-+ valid_p
-+ &= tdesc_numbered_register (feature, tdesc_data,
-+ tdep->regs.badv = regnum++, "badv");
-+
-+ if ((feature = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.fpu")))
-+ {
-+ tdep->regs.f = regnum;
-+ for (i = 0; i < 32; i++)
-+ valid_p
-+ &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ loongarch_f_normal_name[i] + 1);
-+ tdep->regs.fcc = regnum;
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ "fcc0");
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ "fcc1");
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ "fcc2");
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ "fcc3");
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ "fcc4");
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ "fcc5");
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ "fcc6");
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ "fcc7");
-+ valid_p &= tdesc_numbered_register (feature, tdesc_data,
-+ tdep->regs.fcsr = regnum++, "fcsr");
-+ }
-+
-+ if ((feature = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.lbt")))
-+ {
-+ tdep->regs.scr = regnum;
-+ for (i = 0; i < 4; i++)
-+ valid_p
-+ &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ loongarch_cr_normal_name[i] + 1);
-+ valid_p
-+ &= tdesc_numbered_register (feature, tdesc_data,
-+ tdep->regs.EFLAG = regnum++, "EFLAG");
-+ valid_p
-+ &= tdesc_numbered_register (feature, tdesc_data,
-+ tdep->regs.x86_top = regnum++, "x86_top");
-+ }
-+
-+ if ((feature = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.lsx")))
-+ {
-+ tdep->regs.vr = regnum;
-+ for (i = 0; i < 32; i++)
-+ valid_p
-+ &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ loongarch_v_normal_name[i] + 1);
-+ }
-+
-+ if ((feature = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.lasx")))
-+ {
-+ tdep->regs.xr = regnum;
-+ for (i = 0; i < 32; i++)
-+ valid_p
-+ &= tdesc_numbered_register (feature, tdesc_data, regnum++,
-+ loongarch_x_normal_name[i] + 1);
-+ }
-+
-+ if (!valid_p)
-+ {
-+ return NULL;
-+ }
-+
-+ info.byte_order_for_code = BFD_ENDIAN_LITTLE;
-+
-+ /* Find a candidate among the list of pre-declared architectures. */
-+ for (arches = gdbarch_list_lookup_by_info (arches, &info); arches != NULL;
-+ arches = gdbarch_list_lookup_by_info (arches->next, &info))
-+ {
-+ if (gdbarch_tdep (arches->gdbarch)->ef_abi != tdep->ef_abi)
-+ continue;
-+
-+ return arches->gdbarch;
-+ }
-+
-+ /* None found, so create a new architecture from the information provided. */
-+ tdep = (struct gdbarch_tdep *) xmalloc (sizeof (tdep_instant));
-+ memcpy (tdep, &tdep_instant, sizeof (tdep_instant));
-+ gdbarch = gdbarch_alloc (&info, tdep);
-+
-+ /* Target data types. */
-+ if (EF_LOONGARCH_IS_ILP32 (tdep->ef_abi))
-+ {
-+ set_gdbarch_short_bit (gdbarch, 16);
-+ set_gdbarch_int_bit (gdbarch, 32);
-+ set_gdbarch_long_bit (gdbarch, 32);
-+ set_gdbarch_long_long_bit (gdbarch, 32);
-+ set_gdbarch_float_bit (gdbarch, 32);
-+ set_gdbarch_double_bit (gdbarch, 64);
-+ set_gdbarch_long_double_bit (gdbarch, 128);
-+ set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
-+ set_gdbarch_ptr_bit (gdbarch, 32);
-+ set_gdbarch_char_signed (gdbarch, 0);
-+ }
-+ else if (EF_LOONGARCH_IS_LP64 (tdep->ef_abi))
-+ {
-+ set_gdbarch_short_bit (gdbarch, 16);
-+ set_gdbarch_int_bit (gdbarch, 32);
-+ set_gdbarch_long_bit (gdbarch, 64);
-+ set_gdbarch_long_long_bit (gdbarch, 64);
-+ set_gdbarch_float_bit (gdbarch, 32);
-+ set_gdbarch_double_bit (gdbarch, 64);
-+ set_gdbarch_long_double_bit (gdbarch, 128);
-+ set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
-+ set_gdbarch_ptr_bit (gdbarch, 64);
-+ set_gdbarch_char_signed (gdbarch, 0);
-+
-+ tdep->regs.ra = tdep->regs.r + 1;
-+ tdep->regs.sp = tdep->regs.r + 3;
-+
-+ for (i = 0; i < ARRAY_SIZE (loongarch_r_normal_name); ++i)
-+ if (loongarch_r_normal_name[i][0] != '\0')
-+ user_reg_add (gdbarch, loongarch_r_normal_name[i] + 1,
-+ value_of_loongarch_user_reg,
-+ (void *) (size_t) (tdep->regs.r + i));
-+
-+ for (i = 0; i < ARRAY_SIZE (loongarch_r_lp64_name); ++i)
-+ if (loongarch_r_lp64_name[i][0] != '\0')
-+ user_reg_add (gdbarch, loongarch_r_lp64_name[i] + 1,
-+ value_of_loongarch_user_reg,
-+ (void *) (size_t) (tdep->regs.r + i));
-+
-+ for (i = 0; i < ARRAY_SIZE (loongarch_r_lp64_name1); ++i)
-+ if (loongarch_r_lp64_name[i][0] != '\0')
-+ user_reg_add (gdbarch, loongarch_r_lp64_name1[i] + 1,
-+ value_of_loongarch_user_reg,
-+ (void *) (size_t) (tdep->regs.r + i));
-+
-+ /* Functions handling dummy frames. */
-+ set_gdbarch_push_dummy_call (gdbarch,
-+ loongarch_lp32lp64_push_dummy_call);
-+ set_gdbarch_return_value (gdbarch, loongarch_lp64_return_value);
-+
-+ }
-+ else
-+ gdb_assert_not_reached ("unknown ABI");
-+
-+ /* Hook in OS ABI-specific overrides, if they have been registered. */
-+ info.target_desc = tdesc;
-+ info.tdesc_data = tdesc_data;
-+
-+ /* Register architecture. */
-+ set_gdbarch_num_regs (gdbarch, regnum);
-+ set_gdbarch_sp_regnum (gdbarch, tdep->regs.sp);
-+ set_gdbarch_pc_regnum (gdbarch, tdep->regs.pc);
-+
-+ tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
-+
-+ /* Functions to supply register information. */
-+ set_gdbarch_register_name (gdbarch, loongarch_register_name);
-+
-+ /* Handle overlapping dwarf2 register code for fp/lsx/lasx. */
-+ set_gdbarch_convert_register_p (gdbarch, loongarch_convert_register_p);
-+ set_gdbarch_register_to_value (gdbarch, loongarch_register_to_value);
-+ set_gdbarch_value_to_register (gdbarch, loongarch_value_to_register);
-+
-+ /* Functions to analyze frames. */
-+ set_gdbarch_skip_prologue (gdbarch, loongarch_skip_prologue);
-+ set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-+ set_gdbarch_frame_align (gdbarch, loongarch_frame_align);
-+
-+ /* Functions to access frame data. */
-+ set_gdbarch_unwind_pc (gdbarch, loongarch_unwind_pc);
-+ set_gdbarch_unwind_sp (gdbarch, loongarch_unwind_sp);
-+
-+ set_gdbarch_dummy_id (gdbarch, loongarch_dummy_id);
-+
-+ set_gdbarch_software_single_step (gdbarch, loongarch_software_single_step);
-+
-+ set_gdbarch_breakpoint_kind_from_pc (gdbarch,
-+ loongarch_breakpoint::kind_from_pc);
-+ set_gdbarch_sw_breakpoint_from_kind (gdbarch,
-+ loongarch_breakpoint::bp_from_kind);
-+
-+ set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
-+
-+ /* Virtual tables. */
-+ set_gdbarch_vbit_in_delta (gdbarch, 1);
-+
-+ set_gdbarch_gcc_target_options (gdbarch, loongarch_gcc_target_options);
-+
-+ gdbarch_init_osabi (info, gdbarch);
-+ set_gdbarch_register_reggroup_p (gdbarch, loongarch_register_reggroup_p);
-+ set_gdbarch_register_name (gdbarch, loongarch_register_name);
-+
-+ set_gdbarch_get_longjmp_target (gdbarch, loongarch_get_longjmp_target);
-+
-+ /* Frame unwinders. Use DWARF debug info if available, otherwise use our own
-+ unwinder. */
-+ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, loongarch_dwarf2_reg_to_regnum);
-+ dwarf2_append_unwinders (gdbarch);
-+ frame_unwind_append_unwinder (gdbarch, &loongarch_frame_unwind);
-+
-+ return gdbarch;
-+}
-+
-+static void
-+info_loongarch (const char *addr_exp, int from_tty)
-+{
-+ char *buf, *t;
-+ int set;
-+ char *item;
-+ unsigned long addr;
-+ unsigned long long value;
-+
-+ if (addr_exp)
-+ {
-+ addr_exp = skip_spaces (addr_exp);
-+ buf = (char *) alloca (strlen (addr_exp) + 1);
-+ strcpy (buf, addr_exp);
-+ loongarch_eliminate_adjacent_repeat_char (buf, ' ');
-+ }
-+ else
-+ goto Empty;
-+
-+ if (!(t = strtok (buf, " ")))
-+ goto Empty;
-+ if (strcmp (t, "set") == 0)
-+ {
-+ t = strtok (NULL, " ");
-+ set = 1;
-+ }
-+ else
-+ {
-+ if (strcmp (t, "get") == 0)
-+ t = strtok (NULL, " ");
-+ set = 0;
-+ }
-+ if (!(item = t))
-+ goto Empty;
-+ if (!(t = strtok (NULL, " ")))
-+ goto Empty;
-+ addr = strtoul (t, NULL, 0);
-+ if (set && (t = strtok (NULL, " ")) == NULL)
-+ goto Empty;
-+ value = strtoll (t, NULL, 0);
-+
-+ if (set)
-+ if (strcmp (item, "cpucfg") == 0)
-+ {
-+ uint32_t val32 = value;
-+ ULONGEST xfered_len;
-+ target_xfer_partial (current_inferior ()->top_target (),
-+ TARGET_OBJECT_LARCH, "cpucfg", NULL,
-+ (const gdb_byte *) &val32, addr * 4,
-+ sizeof (val32), &xfered_len);
-+ if (0 < xfered_len)
-+ fprintf_unfiltered (gdb_stdout, "ok\n");
-+ else
-+ error ("Set failed");
-+ }
-+ else
-+ {
-+ uint64_t val64 = value;
-+ ULONGEST xfered_len;
-+ target_xfer_partial (current_inferior ()->top_target (),
-+ TARGET_OBJECT_LARCH, item, NULL,
-+ (const gdb_byte *) &val64, addr * 8,
-+ sizeof (val64), &xfered_len);
-+ if (0 < xfered_len)
-+ fprintf_unfiltered (gdb_stdout, "ok\n");
-+ else
-+ error ("Set failed");
-+ }
-+ else if (strcmp (item, "cpucfg") == 0)
-+ {
-+ uint32_t val32;
-+ ULONGEST xfered_len;
-+ target_xfer_partial (current_inferior ()->top_target (),
-+ TARGET_OBJECT_LARCH, "cpucfg", (gdb_byte *) &val32,
-+ NULL, addr * 4, sizeof (val32), &xfered_len);
-+ if (0 < xfered_len)
-+ fprintf_unfiltered (gdb_stdout, "return is %x\n", val32);
-+ else
-+ error ("Get failed");
-+ }
-+ else
-+ {
-+ uint64_t val64;
-+ ULONGEST xfered_len;
-+ target_xfer_partial (current_inferior ()->top_target (),
-+ TARGET_OBJECT_LARCH, item, (gdb_byte *) &val64,
-+ NULL, addr * 8, sizeof (val64), &xfered_len);
-+ if (0 < xfered_len)
-+ fprintf_unfiltered (gdb_stdout, "return is %llx\n", (long long) val64);
-+ else
-+ error ("Get failed");
-+ }
-+
-+ return;
-+Empty:
-+ error ("Empty. Should be 'info loongarch ([get]|set) item addr
[value]'");
-+}
-+
-+void _initialize_loongarch_tdep ();
-+void
-+_initialize_loongarch_tdep ()
-+{
-+ gdbarch_register (bfd_arch_loongarch, loongarch_gdbarch_init, NULL);
-+
-+ add_info ("loongarch", info_loongarch, _ ("Loongarch extra"));
-+
-+ /* Debug this files internals. */
-+ add_setshow_zuinteger_cmd ("loongarch", class_maintenance,
&loongarch_debug,
-+ _ ("\
-+Set loongarch debugging."),
-+ _ ("\
-+Show loongarch debugging."),
-+ _ ("\
-+When non-zero, loongarch specific debugging is enabled."),
-+ NULL, NULL, &setdebuglist, &showdebuglist);
-+}
---- /dev/null
-+++ gdb-10.2/gdb/loongarch-tdep.h
-@@ -0,0 +1,61 @@
-+/* Target-dependent code for GNU/Linux LoongArch.
-+
-+ Copyright (C) 2021 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of GDB.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the License, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program. If not, see <
http://www.gnu.org/licenses/>. */
-+
-+#ifndef LOONGARCH_TDEP_H
-+#define LOONGARCH_TDEP_H
-+
-+#include "arch/loongarch.h"
-+
-+/* Register numbers of important registers. Note that most of
-+ these values are "real" register numbers, and correspond to the
-+ general registers of the machine. */
-+#define LOONGARCH_A0_REGNUM 4 /* Loc of first arg */
-+
-+struct gdbarch_tdep
-+{
-+ int ef_abi; /* EF_LOONGARCH_ABI */
-+
-+ struct
-+ {
-+ int r;
-+ int ra;
-+ int sp;
-+ int orig_a0;
-+ int pc;
-+ int badv;
-+
-+ int f;
-+ int fcc;
-+ int fcsr;
-+ int vr;
-+ int xr;
-+
-+ int scr;
-+ int EFLAG;
-+ int x86_top;
-+
-+ } regs;
-+
-+ /* Return the expected next PC if FRAME is stopped at a syscall
-+ instruction. */
-+ CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
-+};
-+
-+#endif /* LOONGARCH_TDEP_H */
---- gdb-10.2/gdb/remote.c.orig
-+++ gdb-10.2/gdb/remote.c
-@@ -1983,6 +1983,8 @@ enum {
- PACKET_qXfer_statictrace_read,
- PACKET_qXfer_traceframe_info,
- PACKET_qXfer_uib,
-+ PACKET_qXfer_loongarch_read,
-+ PACKET_qXfer_loongarch_write,
- PACKET_qGetTIBAddr,
- PACKET_qGetTLSAddr,
- PACKET_qSupported,
-@@ -5154,6 +5156,10 @@ static const struct protocol_feature remote_protocol_features[] =
{
- PACKET_qXfer_threads },
- { "qXfer:traceframe-info:read", PACKET_DISABLE, remote_supported_packet,
- PACKET_qXfer_traceframe_info },
-+ { "qXfer:loongarch:read", PACKET_DISABLE, remote_supported_packet,
-+ PACKET_qXfer_loongarch_read },
-+ { "qXfer:loongarch:write", PACKET_DISABLE, remote_supported_packet,
-+ PACKET_qXfer_loongarch_write },
- { "QPassSignals", PACKET_DISABLE, remote_supported_packet,
- PACKET_QPassSignals },
- { "QCatchSyscalls", PACKET_DISABLE, remote_supported_packet,
-@@ -11013,6 +11019,18 @@ remote_target::xfer_partial (enum target_object object,
- return TARGET_XFER_E_IO;
- }
-
-+ if (object == TARGET_OBJECT_LARCH)
-+ {
-+ if (readbuf)
-+ return remote_read_qxfer ("loongarch", annex, readbuf, offset, len,
-+ xfered_len, &remote_protocol_packets
-+ [PACKET_qXfer_loongarch_read]);
-+ else
-+ return remote_write_qxfer ("loongarch", annex, writebuf, offset, len,
-+ xfered_len, &remote_protocol_packets
-+ [PACKET_qXfer_loongarch_write]);
-+ }
-+
- /* Only handle flash writes. */
- if (writebuf != NULL)
- {
-@@ -14626,6 +14644,13 @@ Show the maximum size of the address (in bits) in a memory
packet."), NULL,
- add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_uib],
- "qXfer:uib:read", "unwind-info-block", 0);
-
-+ add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_loongarch_read],
-+ "qXfer:loongarch:read", "read-loongarch-object", 0);
-+
-+ add_packet_config_cmd
-+ (&remote_protocol_packets[PACKET_qXfer_loongarch_write],
-+ "qXfer:loongarch:write", "write-loongarch-object", 0);
-+
- add_packet_config_cmd (&remote_protocol_packets[PACKET_qGetTLSAddr],
- "qGetTLSAddr", "get-thread-local-storage-address",
- 0);
---- gdb-10.2/gdb/target.h.orig
-+++ gdb-10.2/gdb/target.h
-@@ -135,6 +135,9 @@ enum inferior_event_type
-
- enum target_object
- {
-+ /* LARCH target specific transfer. See "loongarch-nat.c"
"corelow.c"
-+ and "remote.c". */
-+ TARGET_OBJECT_LARCH,
- /* AVR target specific transfer. See "avr-tdep.c" and "remote.c".
*/
- TARGET_OBJECT_AVR,
- /* Transfer up-to LEN bytes of memory starting at OFFSET. */
---- gdb-10.2/include/dis-asm.h.orig
-+++ gdb-10.2/include/dis-asm.h
-@@ -303,6 +303,7 @@ extern void print_arm_disassembler_options (FILE *);
- extern void print_arc_disassembler_options (FILE *);
- extern void print_s390_disassembler_options (FILE *);
- extern void print_wasm32_disassembler_options (FILE *);
-+extern void print_loongarch_disassembler_options (FILE *);
- extern bfd_boolean aarch64_symbol_is_valid (asymbol *, struct disassemble_info *);
- extern bfd_boolean arm_symbol_is_valid (asymbol *, struct disassemble_info *);
- extern bfd_boolean csky_symbol_is_valid (asymbol *, struct disassemble_info *);
---- gdb-10.2/include/elf/common.h.orig
-+++ gdb-10.2/include/elf/common.h
-@@ -342,6 +342,7 @@
- #define EM_BPF 247 /* Linux BPF – in-kernel virtual machine. */
- #define EM_NFP 250 /* Netronome Flow Processor. */
- #define EM_CSKY 252 /* C-SKY processor family. */
-+#define EM_LOONGARCH 258 /* LoongArch */
-
- /* If it is necessary to assign new unofficial EM_* values, please pick large
- random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision
-@@ -662,6 +663,19 @@
- /* note name must be "LINUX". */
- #define NT_ARC_V2 0x600 /* ARC HS accumulator/extra registers. */
- /* note name must be "LINUX". */
-+#define NT_LARCH_CPUCFG 0xa00 /* LoongArch CPU config registers */
-+ /* note name must be "LINUX". */
-+#define NT_LARCH_CSR 0xa01 /* LoongArch Control State Registers */
-+ /* note name must be "LINUX". */
-+#define NT_LARCH_LSX 0xa02 /* LoongArch SIMD eXtension registers */
-+ /* note name must be "LINUX". */
-+#define NT_LARCH_LASX 0xa03 /* LoongArch Advanced SIMD eXtension registers */
-+ /* note name must be "LINUX". */
-+#define NT_LARCH_LBT 0xa04 /* LoongArch Binary Translation registers */
-+ /* note name must be "CORE". */
-+#define NT_RISCV_CSR 0x900 /* RISC-V Control and Status Registers */
-+ /* note name must be "LINUX". */
-+
- #define NT_SIGINFO 0x53494749 /* Fields of siginfo_t. */
- #define NT_FILE 0x46494c45 /* Description of mapped files. */
-
---- /dev/null
-+++ gdb-10.2/include/elf/loongarch.h
-@@ -0,0 +1,267 @@
-+/* Copyright (C) 2021-2022 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of GNU Binutils.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the license, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING3. If not,
-+ see <
http://www.gnu.org/licenses/>. */
-+
-+#ifndef _ELF_LOONGARCH_H
-+#define _ELF_LOONGARCH_H
-+
-+#include "elf/reloc-macros.h"
-+#include "libiberty.h"
-+
-+START_RELOC_NUMBERS (elf_loongarch_reloc_type)
-+/* Used by the dynamic linker. */
-+RELOC_NUMBER (R_LARCH_NONE, 0)
-+RELOC_NUMBER (R_LARCH_32, 1)
-+RELOC_NUMBER (R_LARCH_64, 2)
-+RELOC_NUMBER (R_LARCH_RELATIVE, 3)
-+RELOC_NUMBER (R_LARCH_COPY, 4)
-+RELOC_NUMBER (R_LARCH_JUMP_SLOT, 5)
-+RELOC_NUMBER (R_LARCH_TLS_DTPMOD32, 6)
-+RELOC_NUMBER (R_LARCH_TLS_DTPMOD64, 7)
-+RELOC_NUMBER (R_LARCH_TLS_DTPREL32, 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)
-+
-+/* Reserved for future relocs that the dynamic linker must understand. */
-+
-+/* Used by the static linker for relocating .text. */
-+RELOC_NUMBER (R_LARCH_MARK_LA, 20)
-+RELOC_NUMBER (R_LARCH_MARK_PCREL, 21)
-+
-+RELOC_NUMBER (R_LARCH_SOP_PUSH_PCREL, 22)
-+
-+RELOC_NUMBER (R_LARCH_SOP_PUSH_ABSOLUTE, 23)
-+
-+RELOC_NUMBER (R_LARCH_SOP_PUSH_DUP, 24)
-+RELOC_NUMBER (R_LARCH_SOP_PUSH_GPREL, 25)
-+RELOC_NUMBER (R_LARCH_SOP_PUSH_TLS_TPREL, 26)
-+RELOC_NUMBER (R_LARCH_SOP_PUSH_TLS_GOT, 27)
-+RELOC_NUMBER (R_LARCH_SOP_PUSH_TLS_GD, 28)
-+RELOC_NUMBER (R_LARCH_SOP_PUSH_PLT_PCREL, 29)
-+
-+RELOC_NUMBER (R_LARCH_SOP_ASSERT, 30)
-+RELOC_NUMBER (R_LARCH_SOP_NOT, 31)
-+RELOC_NUMBER (R_LARCH_SOP_SUB, 32)
-+RELOC_NUMBER (R_LARCH_SOP_SL, 33)
-+RELOC_NUMBER (R_LARCH_SOP_SR, 34)
-+RELOC_NUMBER (R_LARCH_SOP_ADD, 35)
-+RELOC_NUMBER (R_LARCH_SOP_AND, 36)
-+RELOC_NUMBER (R_LARCH_SOP_IF_ELSE, 37)
-+RELOC_NUMBER (R_LARCH_SOP_POP_32_S_10_5, 38)
-+RELOC_NUMBER (R_LARCH_SOP_POP_32_U_10_12, 39)
-+RELOC_NUMBER (R_LARCH_SOP_POP_32_S_10_12, 40)
-+RELOC_NUMBER (R_LARCH_SOP_POP_32_S_10_16, 41)
-+RELOC_NUMBER (R_LARCH_SOP_POP_32_S_10_16_S2, 42)
-+RELOC_NUMBER (R_LARCH_SOP_POP_32_S_5_20, 43)
-+RELOC_NUMBER (R_LARCH_SOP_POP_32_S_0_5_10_16_S2, 44)
-+RELOC_NUMBER (R_LARCH_SOP_POP_32_S_0_10_10_16_S2, 45)
-+RELOC_NUMBER (R_LARCH_SOP_POP_32_U, 46)
-+
-+/* Used by the static linker for relocating non .text. */
-+RELOC_NUMBER (R_LARCH_ADD8, 47)
-+RELOC_NUMBER (R_LARCH_ADD16, 48)
-+RELOC_NUMBER (R_LARCH_ADD24, 49)
-+RELOC_NUMBER (R_LARCH_ADD32, 50)
-+RELOC_NUMBER (R_LARCH_ADD64, 51)
-+RELOC_NUMBER (R_LARCH_SUB8, 52)
-+RELOC_NUMBER (R_LARCH_SUB16, 53)
-+RELOC_NUMBER (R_LARCH_SUB24, 54)
-+RELOC_NUMBER (R_LARCH_SUB32, 55)
-+RELOC_NUMBER (R_LARCH_SUB64, 56)
-+
-+/* I don't know what it is. Existing in almost all other arch. */
-+RELOC_NUMBER (R_LARCH_GNU_VTINHERIT, 57)
-+RELOC_NUMBER (R_LARCH_GNU_VTENTRY, 58)
-+
-+
-+/* B16:
-+ beq/bne/blt/bge/bltu/bgeu/jirl
-+ %b16 (sym). */
-+RELOC_NUMBER (R_LARCH_B16, 64)
-+/* B21:
-+ beqz/bnez
-+ %b16 (sym). */
-+RELOC_NUMBER (R_LARCH_B21, 65)
-+/* B26:
-+ b/bl
-+ %b26 (sym) or %plt (sym). */
-+RELOC_NUMBER (R_LARCH_B26, 66)
-+
-+/* ABS: 32/64
-+ lu12i.w
-+ %abs_hi20 (sym). */
-+RELOC_NUMBER (R_LARCH_ABS_HI20, 67)
-+/* ABS: 32/64
-+ ori
-+ %abs_lo12 (sym). */
-+RELOC_NUMBER (R_LARCH_ABS_LO12, 68)
-+
-+/* ABS: 64
-+ lu32i.d
-+ %abs64_lo20 (sym). */
-+RELOC_NUMBER (R_LARCH_ABS64_LO20, 69)
-+/* ABS: 64
-+ lu52i.d
-+ %abs64_hi12 (sym). */
-+RELOC_NUMBER (R_LARCH_ABS64_HI12, 70)
-+
-+/* PCREL: 32/64
-+ pcalau12i
-+ %pc_hi20 (sym). */
-+RELOC_NUMBER (R_LARCH_PCALA_HI20, 71)
-+/* PCREL: 32/64
-+ addi.w/addi.d
-+ %pc_lo12 (sym). */
-+RELOC_NUMBER (R_LARCH_PCALA_LO12, 72)
-+/* PCREL: 64
-+ lu32i.d
-+ %pc64_lo20 (sym). */
-+RELOC_NUMBER (R_LARCH_PCALA64_LO20, 73)
-+/* PCREL: 64
-+ lu52i.d
-+ %pc64_hi12 (sym). */
-+RELOC_NUMBER (R_LARCH_PCALA64_HI12, 74)
-+
-+/* GOT: 32/64
-+ pcalau12i
-+ %got_pc_hi20 (got). */
-+RELOC_NUMBER (R_LARCH_GOT_PC_HI20, 75)
-+/* GOT: 32/64
-+ ld.w/ld.d
-+ %got_pc_lo12 (got). */
-+RELOC_NUMBER (R_LARCH_GOT_PC_LO12, 76)
-+/* GOT: 32/64
-+ lu32i.d
-+ %got_pc_lo12 (got). */
-+RELOC_NUMBER (R_LARCH_GOT64_PC_LO20, 77)
-+/* GOT64: PCREL
-+ lu52i.d
-+ %got64_pc_hi12 (got). */
-+RELOC_NUMBER (R_LARCH_GOT64_PC_HI12, 78)
-+/* GOT32/64: ABS
-+ lu12i.w
-+ %got_hi20 (got). */
-+RELOC_NUMBER (R_LARCH_GOT_HI20, 79)
-+/* GOT: 32/64: ABS
-+ ori
-+ %got_lo12 (got). */
-+RELOC_NUMBER (R_LARCH_GOT_LO12, 80)
-+/* GOT64: ABS
-+ lu32i.d
-+ %got64_lo20 (got). */
-+RELOC_NUMBER (R_LARCH_GOT64_LO20, 81)
-+/* GOT64: ABS
-+ lu52i.d
-+ %got64_hi12 (got). */
-+RELOC_NUMBER (R_LARCH_GOT64_HI12, 82)
-+
-+/* TLS-LE: 32/64
-+ lu12i.w
-+ %le_hi20 (sym). */
-+RELOC_NUMBER (R_LARCH_TLS_LE_HI20, 83)
-+/* TLS-LE: 32/64
-+ ori
-+ %le_lo12 (sym). */
-+RELOC_NUMBER (R_LARCH_TLS_LE_LO12, 84)
-+/* TLS-LE: 64
-+ lu32i.d
-+ %le64_lo20 (sym). */
-+RELOC_NUMBER (R_LARCH_TLS_LE64_LO20, 85)
-+/* TLS-LE: 64
-+ lu52i.d
-+ %le64_hi12 (sym). */
-+RELOC_NUMBER (R_LARCH_TLS_LE64_HI12, 86)
-+
-+/* TLS-IE: 32/64
-+ pcalau12i
-+ %ie_pc_hi20 (sym). */
-+RELOC_NUMBER (R_LARCH_TLS_IE_PC_HI20, 87)
-+RELOC_NUMBER (R_LARCH_TLS_IE_PC_LO12, 88)
-+RELOC_NUMBER (R_LARCH_TLS_IE64_PC_LO20, 89)
-+RELOC_NUMBER (R_LARCH_TLS_IE64_PC_HI12, 90)
-+
-+/* TLS-IE: 32/64: ABS
-+ lu12i.w
-+ %ie_hi20 (sym). */
-+RELOC_NUMBER (R_LARCH_TLS_IE_HI20, 91)
-+RELOC_NUMBER (R_LARCH_TLS_IE_LO12, 92)
-+RELOC_NUMBER (R_LARCH_TLS_IE64_LO20, 93)
-+RELOC_NUMBER (R_LARCH_TLS_IE64_HI12, 94)
-+
-+/* TLS-LD: 32/64
-+ pcalau12i
-+ %ld_pc_hi20 (sym). */
-+RELOC_NUMBER (R_LARCH_TLS_LD_PC_HI20, 95)
-+/* TLS-LD: 32/64: ABS
-+ lu12i.w
-+ %ld_hi20 (sym). */
-+RELOC_NUMBER (R_LARCH_TLS_LD_HI20, 96)
-+
-+/* TLS-GD: 32/64
-+ pcalau12i
-+ %gd_pc_hi20 (sym). */
-+RELOC_NUMBER (R_LARCH_TLS_GD_PC_HI20, 97)
-+/* TLS-GD: 32/64: ABS
-+ lu12i.w
-+ %gd_hi20 (sym). */
-+RELOC_NUMBER (R_LARCH_TLS_GD_HI20, 98)
-+
-+/* For eh_frame and debug info. */
-+RELOC_NUMBER (R_LARCH_32_PCREL, 99)
-+
-+/* RELAX. */
-+RELOC_NUMBER (R_LARCH_RELAX, 100)
-+
-+END_RELOC_NUMBERS (R_LARCH_count)
-+
-+/* Processor specific flags for the ELF header e_flags field. */
-+/*The flag lp64s/lp64f/lp64d/ilp32s/ilp32f/ilp32d 3bits. */
-+#define EF_LOONGARCH_ABI_LP64_SOFT_FLOAT 0x1
-+#define EF_LOONGARCH_ABI_LP64_SINGLE_FLOAT 0x2
-+#define EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT 0x3
-+
-+#define EF_LOONGARCH_ABI_ILP32_SOFT_FLOAT 0x5
-+#define EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT 0x6
-+#define EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT 0x7
-+
-+#define EF_LOONGARCH_ABI_MASK 0x7
-+#define EF_LOONGARCH_ABI_ILP32_MASK 0x4
-+#define EF_LOONGARCH_ABI_FLOAT_MASK 0x3
-+#define EF_LOONGARCH_ABI_SOFT_FLOAT_MASK 0x1
-+#define EF_LOONGARCH_ABI_SINGLE_FLOAT_MASK 0x2
-+#define EF_LOONGARCH_ABI_DOUBLE_FLOAT_MASK 0x3
-+
-+#define EF_LOONGARCH_ABI(abi) (EF_LOONGARCH_ABI_MASK & (abi))
-+
-+#define EF_LOONGARCH_IS_LP64(abi) \
-+ (EF_LOONGARCH_ABI(abi) && (!(EF_LOONGARCH_ABI(abi) &
EF_LOONGARCH_ABI_ILP32_MASK)))
-+#define EF_LOONGARCH_IS_ILP32(abi) \
-+ (EF_LOONGARCH_ABI(abi) && (EF_LOONGARCH_ABI(abi) &
EF_LOONGARCH_ABI_ILP32_MASK))
-+
-+#define EF_LOONGARCH_IS_SOFT_FLOAT(abi) \
-+ (!((EF_LOONGARCH_ABI(abi) & EF_LOONGARCH_ABI_FLOAT_MASK) ^
EF_LOONGARCH_ABI_SOFT_FLOAT_MASK))
-+
-+#define EF_LOONGARCH_IS_SINGLE_FLOAT(abi) \
-+ (!((EF_LOONGARCH_ABI(abi) & EF_LOONGARCH_ABI_FLOAT_MASK) ^
EF_LOONGARCH_ABI_SINGLE_FLOAT_MASK))
-+
-+#define EF_LOONGARCH_IS_DOUBLE_FLOAT(abi) \
-+ (!((EF_LOONGARCH_ABI(abi) & EF_LOONGARCH_ABI_FLOAT_MASK) ^
EF_LOONGARCH_ABI_DOUBLE_FLOAT_MASK))
-+
-+#endif /* _ELF_LOONGARCH_H */
---- /dev/null
-+++ gdb-10.2/include/opcode/loongarch.h
-@@ -0,0 +1,239 @@
-+/* LoongArch assembler/disassembler support.
-+
-+ Copyright (C) 2021-2022 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of GNU Binutils.
-+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3 of the license, or
-+ (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING3. If not,
-+ see <
http://www.gnu.org/licenses/>. */
-+
-+#ifndef _LOONGARCH_H_
-+#define _LOONGARCH_H_
-+#include <stdint.h>
-+
-+#ifdef __cplusplus
-+extern "C"
-+{
-+#endif
-+
-+ typedef uint32_t insn_t;
-+
-+ struct loongarch_opcode
-+ {
-+ const insn_t match;
-+ const insn_t mask; /* High 1 byte is main opcode and it must be 0xf. */
-+#define LARCH_INSN_OPC(insn) ((insn & 0xf0000000) >> 28)
-+ const char *const name;
-+
-+ /* ACTUAL PARAMETER:
-+
-+ // BNF with regular expression.
-+args : token* end
-+
-+ // just few char separate 'iden'
-+token : ','
-+| '('
-+| ')'
-+| iden // maybe a label (include at least one alphabet),
-+ maybe a number, maybe a expr
-+| regname
-+
-+regname : '$' iden
-+
-+iden : [a-zA-Z0-9\.\+\-]+
-+
-+end : '\0'
-+
-+
-+FORMAT: A string to describe the format of actual parameter including
-+bit field infomation. For example, "r5:5,r0:5,sr10:16<<2" matches
-+"$12,$13,12345" and "$4,$7,a_label". That 'sr' means the
instruction
-+may need relocate. '10:16' means bit field of instruction.
-+In a 'format', every 'escape's can be replaced to 'iden' or
'regname'
-+acrroding to its meaning. We fill all information needed by
-+disassembing and assembing to 'format'.
-+
-+ // BNF with regular expression.
-+format : escape (literal+ escape)* literal* end
-+| (literal+ escape)* literal* end
-+
-+end : '\0' // Get here means parse end.
-+
-+ // The intersection between any two among FIRST (end), FIRST
-+ // (literal) and FIRST (escape) must be empty.
-+ // So we can build a simple parser.
-+literal : ','
-+| '('
-+| ')'
-+
-+ // Double '<'s means the real number is the immediate after shifting left.
-+escape : esc_ch bit_field '<' '<' dec2
-+| esc_ch bit_field
-+| esc_ch // for MACRO. non-macro format must indicate 'bit_field'
-+
-+ // '|' means to concatenate nonadjacent bit fields
-+ // For example, "10:16|0:4" means
-+ // "16 bits starting from the 10th bit concatenating with 4 bits
-+ // starting from the 0th bit".
-+ // This is to say "[25..10]||[3..0]" (little endian).
-+b_field : dec2 ':' dec2
-+| dec2 ':' dec2 '|' bit_field
-+
-+esc_ch : 's' 'r' // signed immediate or label need relocate
-+| 's' // signed immediate no need relocate
-+| 'u' // unsigned immediate
-+| 'l' // label needed relocate
-+| 'r' // general purpose registers
-+| 'f' // FPU registers
-+| 'v' // 128 bit SIMD register
-+| 'x' // 256 bit SIMD register
-+
-+dec2 : [1-9][0-9]?
-+| 0
-+
-+*/
-+ const char *const format;
-+
-+ /* MACRO: Indicate how a macro instruction expand for assembling.
-+ The main is to replace the '%num'(means the 'num'th
'escape' in
-+ 'format') in 'macro' string to get the real instruction.
-+
-+ Maybe need
-+ */
-+ const char *const macro;
-+ const int *include;
-+ const int *exclude;
-+
-+ const unsigned long pinfo;
-+#define USELESS 0x0l
-+ };
-+
-+ struct hash_control;
-+
-+ struct loongarch_ase
-+ {
-+ const int *enabled;
-+ struct loongarch_opcode *const opcodes;
-+ const int *include;
-+ const int *exclude;
-+
-+ /* For disassemble to create main opcode hash table. */
-+ const struct loongarch_opcode *opc_htab[16];
-+ unsigned char opc_htab_inited;
-+
-+ /* For GAS to create hash table. */
-+ struct htab *name_hash_entry;
-+ };
-+
-+ extern int is_unsigned (const char *);
-+ extern int is_signed (const char *);
-+ extern int is_branch_label (const char *);
-+
-+ extern int loongarch_get_bit_field_width (const char *bit_field, char **end);
-+ extern int32_t loongarch_decode_imm (const char *bit_field, insn_t insn,
-+ int si);
-+
-+#define MAX_ARG_NUM_PLUS_2 9
-+
-+ extern size_t loongarch_split_args_by_comma (char *args,
-+ const char *arg_strs[]);
-+ extern char *loongarch_cat_splited_strs (const char *arg_strs[]);
-+ extern insn_t loongarch_foreach_args (
-+ const char *format, const char *arg_strs[],
-+ int32_t (*helper) (char esc1, char esc2, const char *bit_field,
-+ const char *arg, void *context),
-+ void *context);
-+
-+ extern int loongarch_check_format (const char *format);
-+ extern int loongarch_check_macro (const char *format, const char *macro);
-+
-+ extern char *loongarch_expand_macro_with_format_map (
-+ const char *format, const char *macro, const char *const arg_strs[],
-+ const char *(*map) (char esc1, char esc2, const char *arg),
-+ char *(*helper) (const char *const arg_strs[], void *context),
-+ void *context, size_t len_str);
-+ extern char *loongarch_expand_macro (
-+ const char *macro, const char *const arg_strs[],
-+ char *(*helper) (const char *const arg_strs[], void *context),
-+ void *context, size_t len_str);
-+ extern size_t loongarch_bits_imm_needed (int64_t imm, int si);
-+
-+ extern void loongarch_eliminate_adjacent_repeat_char (char *dest, char c);
-+
-+ extern int loongarch_parse_dis_options (const char *opts_in);
-+ extern void loongarch_disassemble_one (
-+ int64_t pc, insn_t insn,
-+ int (*fprintf_func) (void *stream, const char *format, ...), void *stream);
-+
-+ extern const char *const loongarch_r_normal_name[32];
-+ extern const char *const loongarch_r_lp64_name[32];
-+ extern const char *const loongarch_r_lp64_name1[32];
-+ extern const char *const loongarch_f_normal_name[32];
-+ extern const char *const loongarch_f_lp64_name[32];
-+ extern const char *const loongarch_f_lp64_name1[32];
-+ extern const char *const loongarch_c_normal_name[8];
-+ extern const char *const loongarch_cr_normal_name[4];
-+ extern const char *const loongarch_v_normal_name[32];
-+ extern const char *const loongarch_x_normal_name[32];
-+
-+ extern struct loongarch_ase loongarch_ASEs[];
-+
-+ extern struct loongarch_ASEs_option
-+ {
-+ struct opt_abi
-+ {
-+ int elf_abi;
-+ } abi;
-+#define ase_abi abi.elf_abi
-+
-+ struct opt_isa
-+ {
-+ int use_ilp32;
-+ int use_lp64;
-+
-+ int use_soft_float;
-+ int use_single_float;
-+ int use_double_float;
-+
-+ int use_lsx;
-+ int use_lasx;
-+
-+ int use_la_local_with_abs;
-+ int use_la_global_with_pcrel;
-+ int use_la_global_with_abs;
-+ } isa;
-+#define ase_ilp32 isa.use_ilp32
-+#define ase_lp64 isa.use_lp64
-+
-+#define ase_nf isa.use_soft_float
-+#define ase_sf isa.use_single_float
-+#define ase_df isa.use_double_float
-+
-+#define ase_lsx isa.use_lsx
-+#define ase_lasx isa.use_lasx
-+
-+#define ase_labs isa.use_la_local_with_abs
-+#define ase_gpcr isa.use_la_global_with_pcrel
-+#define ase_gabs isa.use_la_global_with_abs
-+
-+ } LARCH_opts;
-+
-+ extern size_t loongarch_insn_length (insn_t insn);
-+
-+#ifdef __cplusplus
-+}
-+#endif
-+
-+#endif /* _LOONGARCH_H_ */
---- gdb-10.2/opcodes/Makefile.am.orig
-+++ gdb-10.2/opcodes/Makefile.am
-@@ -162,6 +162,9 @@ TARGET_LIBOPCODES_CFILES = \
- lm32-ibld.c \
- lm32-opc.c \
- lm32-opinst.c \
-+ loongarch-opc.c \
-+ loongarch-dis.c \
-+ loongarch-coder.c \
- m10200-dis.c \
- m10200-opc.c \
- m10300-dis.c \
---- gdb-10.2/opcodes/Makefile.in.orig
-+++ gdb-10.2/opcodes/Makefile.in
-@@ -552,6 +552,9 @@ TARGET_LIBOPCODES_CFILES = \
- lm32-ibld.c \
- lm32-opc.c \
- lm32-opinst.c \
-+ loongarch-opc.c \
-+ loongarch-dis.c \
-+ loongarch-coder.c \
- m10200-dis.c \
- m10200-opc.c \
- m10300-dis.c \
-@@ -966,6 +969,9 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lm32-ibld.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lm32-opc.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lm32-opinst.Plo(a)am__quote@
-+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loongarch-coder.Plo(a)am__quote@
-+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loongarch-dis.Plo(a)am__quote@
-+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loongarch-opc.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m10200-dis.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m10200-opc.Plo(a)am__quote@
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m10300-dis.Plo(a)am__quote@
---- gdb-10.2/opcodes/configure.orig
-+++ gdb-10.2/opcodes/configure
-@@ -12949,6 +12949,7 @@ if test x${all_targets} = xfalse ; then
- bfd_z80_arch) ta="$ta z80-dis.lo" ;;
- bfd_z8k_arch) ta="$ta z8k-dis.lo" ;;
- bfd_bpf_arch) ta="$ta bpf-asm.lo bpf-desc.lo bpf-dis.lo bpf-ibld.lo
bpf-opc.lo" using_cgen=yes ;;
-+ bfd_loongarch_arch) ta="$ta loongarch-dis.lo loongarch-opc.lo
loongarch-coder.lo" ;;
-
- "") ;;
- *) as_fn_error $? "*** unknown target architecture $arch"
"$LINENO" 5 ;;
---- gdb-10.2/opcodes/configure.ac.orig
-+++ gdb-10.2/opcodes/configure.ac
-@@ -340,6 +340,7 @@ if test x${all_targets} = xfalse ; then
- bfd_z80_arch) ta="$ta z80-dis.lo" ;;
- bfd_z8k_arch) ta="$ta z8k-dis.lo" ;;
- bfd_bpf_arch) ta="$ta bpf-asm.lo bpf-desc.lo bpf-dis.lo bpf-ibld.lo
bpf-opc.lo" using_cgen=yes ;;
-+ bfd_loongarch_arch) ta="$ta loongarch-dis.lo loongarch-opc.lo
loongarch-coder.lo" ;;
-
- "") ;;
- *) AC_MSG_ERROR(*** unknown target architecture $arch) ;;
---- gdb-10.2/opcodes/disassemble.c.orig
-+++ gdb-10.2/opcodes/disassemble.c
-@@ -49,6 +49,7 @@
- #define ARCH_ip2k
- #define ARCH_iq2000
- #define ARCH_lm32
-+#define ARCH_loongarch
- #define ARCH_m32c
- #define ARCH_m32r
- #define ARCH_m68hc11
-@@ -551,6 +552,11 @@ disassembler (enum bfd_architecture a,
- case bfd_arch_tilepro:
- disassemble = print_insn_tilepro;
- break;
-+#endif
-+#ifdef ARCH_loongarch
-+ case bfd_arch_loongarch:
-+ disassemble = print_insn_loongarch;
-+ break;
- #endif
- default:
- return 0;
-@@ -591,6 +597,9 @@ disassembler_usage (FILE *stream ATTRIBUTE_UNUSED)
- #ifdef ARCH_wasm32
- print_wasm32_disassembler_options (stream);
- #endif
-+#ifdef ARCH_loongarch
-+ print_loongarch_disassembler_options (stream);
-+#endif
-
- return;
- }
---- gdb-10.2/opcodes/disassemble.h.orig
-+++ gdb-10.2/opcodes/disassemble.h
-@@ -100,6 +100,7 @@ extern int print_insn_xtensa (bfd_vma, disassemble_info *);
- extern int print_insn_z80 (bfd_vma, disassemble_info *);
- extern int print_insn_z8001 (bfd_vma, disassemble_info *);
- extern int print_insn_z8002 (bfd_vma, disassemble_info *);
-+extern int print_insn_loongarch (bfd_vma, disassemble_info *);
-
- extern disassembler_ftype csky_get_disassembler (bfd *);
- extern disassembler_ftype rl78_get_disassembler (bfd *);
---- /dev/null
-+++ gdb-10.2/opcodes/loongarch-coder.c
-@@ -0,0 +1,481 @@
-+/* LoongArch opcode support.
-+ Copyright (C) 2021-2022 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of the GNU opcodes library.
-+
-+ This library is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3, or (at your option)
-+ any later version.
-+
-+ It is distributed in the hope that it will be useful, but WITHOUT
-+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-+ License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING3. If not,
-+ see <
http://www.gnu.org/licenses/>. */
-+#include "sysdep.h"
-+#include "opcode/loongarch.h"
-+
-+int
-+is_unsigned (const char *c_str)
-+{
-+ if (c_str[0] == '0' && (c_str[1] == 'x' || c_str[1] ==
'X'))
-+ {
-+ c_str += 2;
-+ while (('a' <= *c_str && *c_str <= 'f')
-+ || ('A' <= *c_str && *c_str <= 'F')
-+ || ('0' <= *c_str && *c_str <= '9'))
-+ c_str++;
-+ }
-+ else if (*c_str == '\0')
-+ return 0;
-+ else
-+ while ('0' <= *c_str && *c_str <= '9')
-+ c_str++;
-+ return *c_str == '\0';
-+}
-+
-+int
-+is_signed (const char *c_str)
-+{
-+ return *c_str == '-' ? is_unsigned (c_str + 1) : is_unsigned (c_str);
-+}
-+
-+int
-+loongarch_get_bit_field_width (const char *bit_field, char **end)
-+{
-+ int width = 0;
-+ char has_specify = 0, *bit_field_1 = (char *) bit_field;
-+ if (bit_field_1 && *bit_field_1 != '\0')
-+ while (1)
-+ {
-+ strtol (bit_field_1, &bit_field_1, 10);
-+
-+ if (*bit_field_1 != ':')
-+ break;
-+ bit_field_1++;
-+
-+ width += strtol (bit_field_1, &bit_field_1, 10);
-+ has_specify = 1;
-+
-+ if (*bit_field_1 != '|')
-+ break;
-+ bit_field_1++;
-+ }
-+ if (end)
-+ *end = bit_field_1;
-+ return has_specify ? width : -1;
-+}
-+
-+int32_t
-+loongarch_decode_imm (const char *bit_field, insn_t insn, int si)
-+{
-+ int32_t ret = 0;
-+ uint32_t t;
-+ int len = 0, width, b_start;
-+ char *bit_field_1 = (char *) bit_field;
-+ while (1)
-+ {
-+ b_start = strtol (bit_field_1, &bit_field_1, 10);
-+ if (*bit_field_1 != ':')
-+ break;
-+ width = strtol (bit_field_1 + 1, &bit_field_1, 10);
-+ len += width;
-+
-+ t = insn;
-+ t <<= sizeof (t) * 8 - width - b_start;
-+ t >>= sizeof (t) * 8 - width;
-+ ret <<= width;
-+ ret |= t;
-+
-+ if (*bit_field_1 != '|')
-+ break;
-+ bit_field_1++;
-+ }
-+
-+ if (*bit_field_1 == '<' && *(++bit_field_1) == '<')
-+ {
-+ width = atoi (bit_field_1 + 1);
-+ ret <<= width;
-+ len += width;
-+ }
-+ else if (*bit_field_1 == '+')
-+ ret += atoi (bit_field_1 + 1);
-+
-+ /* Extend signed bit. */
-+ if (si)
-+ {
-+ uint32_t sign = 1u << (len - 1);
-+ ret = (ret ^ sign) - sign;
-+ }
-+
-+ return ret;
-+}
-+
-+static insn_t
-+loongarch_encode_imm (const char *bit_field, int32_t imm)
-+{
-+ char *bit_field_1 = (char *) bit_field;
-+ char *t = bit_field_1;
-+ int width, b_start;
-+ insn_t ret = 0;
-+ uint32_t i;
-+ uint32_t uimm = (uint32_t)imm;
-+
-+ width = loongarch_get_bit_field_width (t, &t);
-+ if (width == -1)
-+ return ret;
-+
-+ if (*t == '<' && *(++t) == '<')
-+ width += atoi (t + 1);
-+ else if (*t == '+')
-+ uimm -= atoi (t + 1);
-+
-+ uimm = width ? (uimm << (sizeof (uimm) * 8 - width)) : 0;
-+
-+ while (1)
-+ {
-+ b_start = strtol (bit_field_1, &bit_field_1, 10);
-+ if (*bit_field_1 != ':')
-+ break;
-+ width = strtol (bit_field_1 + 1, &bit_field_1, 10);
-+ i = uimm;
-+ i = width ? (i >> (sizeof (i) * 8 - width)) : 0;
-+ i = (b_start == 32) ? 0 : (i << b_start);
-+ ret |= i;
-+ uimm = (width == 32) ? 0 : (uimm << width);
-+
-+ if (*bit_field_1 != '|')
-+ break;
-+ bit_field_1++;
-+ }
-+ return ret;
-+}
-+
-+/* Parse such FORMAT
-+ ""
-+ "u"
-+ "v0:5,r5:5,s10:10<<2"
-+ "r0:5,r5:5,r10:5,u15:2+1"
-+ "r,r,u0:5+32,u0:5+1"
-+*/
-+static int
-+loongarch_parse_format (const char *format, char *esc1s, char *esc2s,
-+ const char **bit_fields)
-+{
-+ size_t arg_num = 0;
-+
-+ if (*format == '\0')
-+ goto end;
-+
-+ while (1)
-+ {
-+ /* esc1 esc2
-+ for "[a-zA-Z][a-zA-Z]?" */
-+ if (('a' <= *format && *format <= 'z')
-+ || ('A' <= *format && *format <= 'Z'))
-+ {
-+ *esc1s++ = *format++;
-+ if (('a' <= *format && *format <= 'z')
-+ || ('A' <= *format && *format <= 'Z'))
-+ *esc2s++ = *format++;
-+ else
-+ *esc2s++ = '\0';
-+ }
-+ else
-+ return -1;
-+
-+ arg_num++;
-+ if (MAX_ARG_NUM_PLUS_2 - 2 < arg_num)
-+ /* Need larger MAX_ARG_NUM_PLUS_2. */
-+ return -1;
-+
-+ *bit_fields++ = format;
-+
-+ if ('0' <= *format && *format <= '9')
-+ {
-+ /* For "[0-9]+:[0-9]+(\|[0-9]+:[0-9]+)*". */
-+ while (1)
-+ {
-+ while ('0' <= *format && *format <= '9')
-+ format++;
-+
-+ if (*format != ':')
-+ return -1;
-+ format++;
-+
-+ if (!('0' <= *format && *format <= '9'))
-+ return -1;
-+ while ('0' <= *format && *format <= '9')
-+ format++;
-+
-+ if (*format != '|')
-+ break;
-+ format++;
-+ }
-+
-+ /* For "((\+|<<)[1-9][0-9]*)?". */
-+ do
-+ {
-+ if (*format == '+')
-+ format++;
-+ else if (format[0] == '<' && format[1] == '<')
-+ format += 2;
-+ else
-+ break;
-+
-+ if (!('1' <= *format && *format <= '9'))
-+ return -1;
-+ while ('0' <= *format && *format <= '9')
-+ format++;
-+ }
-+ while (0);
-+ }
-+
-+ if (*format == ',')
-+ format++;
-+ else if (*format == '\0')
-+ break;
-+ else
-+ return -1;
-+ }
-+
-+ end:
-+ *esc1s = '\0';
-+ return 0;
-+}
-+
-+size_t
-+loongarch_split_args_by_comma (char *args, const char *arg_strs[])
-+{
-+ size_t num = 0;
-+
-+ if (*args)
-+ arg_strs[num++] = args;
-+ for (; *args; args++)
-+ if (*args == ',')
-+ {
-+ if (MAX_ARG_NUM_PLUS_2 - 1 == num)
-+ break;
-+ else
-+ *args = '\0', arg_strs[num++] = args + 1;
-+ }
-+ arg_strs[num] = NULL;
-+ return num;
-+}
-+
-+char *
-+loongarch_cat_splited_strs (const char *arg_strs[])
-+{
-+ char *ret;
-+ size_t n, l;
-+
-+ for (l = 0, n = 0; arg_strs[n]; n++)
-+ l += strlen (arg_strs[n]);
-+ ret = malloc (l + n + 1);
-+ if (!ret)
-+ return ret;
-+
-+ ret[0] = '\0';
-+ if (0 < n)
-+ strcat (ret, arg_strs[0]);
-+ for (l = 1; l < n; l++)
-+ strcat (ret, ","), strcat (ret, arg_strs[l]);
-+ return ret;
-+}
-+
-+insn_t
-+loongarch_foreach_args (const char *format, const char *arg_strs[],
-+ int32_t (*helper) (char esc1, char esc2,
-+ const char *bit_field,
-+ const char *arg, void *context),
-+ void *context)
-+{
-+ char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
-+ const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
-+ size_t i;
-+ insn_t ret = 0;
-+ int ok;
-+
-+ ok = loongarch_parse_format (format, esc1s, esc2s, bit_fields) == 0;
-+
-+ /* Make sure the num of actual args is equal to the num of escape. */
-+ for (i = 0; esc1s[i] && arg_strs[i]; i++)
-+ ;
-+ ok = ok && !esc1s[i] && !arg_strs[i];
-+
-+ if (ok && helper)
-+ {
-+ for (i = 0; arg_strs[i]; i++)
-+ ret |= loongarch_encode_imm (bit_fields[i],
-+ helper (esc1s[i], esc2s[i],
-+ bit_fields[i], arg_strs[i],
-+ context));
-+ ret |= helper ('\0', '\0', NULL, NULL, context);
-+ }
-+
-+ return ret;
-+}
-+
-+int
-+loongarch_check_format (const char *format)
-+{
-+ char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
-+ const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
-+
-+ if (!format)
-+ return -1;
-+
-+ return loongarch_parse_format (format, esc1s, esc2s, bit_fields);
-+}
-+
-+int
-+loongarch_check_macro (const char *format, const char *macro)
-+{
-+ int num_of_args;
-+ char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
-+ const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
-+
-+ if (!format || !macro
-+ || loongarch_parse_format (format, esc1s, esc2s, bit_fields) != 0)
-+ return -1;
-+
-+ for (num_of_args = 0; esc1s[num_of_args]; num_of_args++)
-+ ;
-+
-+ for (; macro[0]; macro++)
-+ if (macro[0] == '%')
-+ {
-+ macro++;
-+ if ('1' <= macro[0] && macro[0] <= '9')
-+ {
-+ if (num_of_args < macro[0] - '0')
-+ /* Out of args num. */
-+ return -1;
-+ }
-+ else if (macro[0] == 'f')
-+ ;
-+ else if (macro[0] == '%')
-+ ;
-+ else
-+ return -1;
-+ }
-+ return 0;
-+}
-+
-+static const char *
-+I (char esc_ch1 ATTRIBUTE_UNUSED, char esc_ch2 ATTRIBUTE_UNUSED,
-+ const char *c_str)
-+{
-+ return c_str;
-+}
-+
-+char *
-+loongarch_expand_macro_with_format_map (
-+ const char *format, const char *macro, const char *const arg_strs[],
-+ const char *(*map) (char esc1, char esc2, const char *arg),
-+ char *(*helper) (const char *const arg_strs[], void *context), void *context,
-+ size_t len_str)
-+{
-+ char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1];
-+ const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1];
-+ const char *src;
-+ char *dest;
-+
-+ /* The expanded macro character length does not exceed 1000, and number of
-+ label is 6 at most in the expanded macro. The len_str is the length of
-+ str. */
-+ char *buffer =(char *) malloc(1024 + 6 * len_str);
-+
-+ if (format)
-+ loongarch_parse_format (format, esc1s, esc2s, bit_fields);
-+
-+ src = macro;
-+ dest = buffer;
-+
-+ while (*src)
-+ if (*src == '%')
-+ {
-+ src++;
-+ if ('1' <= *src && *src <= '9')
-+ {
-+ size_t i = *src - '1';
-+ const char *t = map (esc1s[i], esc2s[i], arg_strs[i]);
-+ while (*t)
-+ *dest++ = *t++;
-+ }
-+ else if (*src == '%')
-+ *dest++ = '%';
-+ else if (*src == 'f' && helper)
-+ {
-+ char *b, *t;
-+ t = b = (*helper) (arg_strs, context);
-+ if (b)
-+ {
-+ while (*t)
-+ *dest++ = *t++;
-+ free (b);
-+ }
-+ }
-+ src++;
-+ }
-+ else
-+ *dest++ = *src++;
-+
-+ *dest = '\0';
-+ return buffer;
-+}
-+
-+char *
-+loongarch_expand_macro (const char *macro, const char *const arg_strs[],
-+ char *(*helper) (const char *const arg_strs[],
-+ void *context),
-+ void *context, size_t len_str)
-+{
-+ return loongarch_expand_macro_with_format_map (NULL, macro, arg_strs, I,
-+ helper, context, len_str);
-+}
-+
-+size_t
-+loongarch_bits_imm_needed (int64_t imm, int si)
-+{
-+ size_t ret;
-+ if (si)
-+ {
-+ if (imm < 0)
-+ {
-+ uint64_t uimm = (uint64_t) imm;
-+ uint64_t uimax = UINT64_C (1) << 63;
-+ for (ret = 0; (uimm & uimax) != 0; uimm <<= 1, ret++)
-+ ;
-+ ret = 64 - ret + 1;
-+ }
-+ else
-+ ret = loongarch_bits_imm_needed (imm, 0) + 1;
-+ }
-+ else
-+ {
-+ uint64_t t = imm;
-+ for (ret = 0; t; t >>= 1, ret++)
-+ ;
-+ }
-+ return ret;
-+}
-+
-+void
-+loongarch_eliminate_adjacent_repeat_char (char *dest, char c)
-+{
-+ if (c == '\0')
-+ return;
-+ char *src = dest;
-+ while (*dest)
-+ {
-+ while (src[0] == c && src[0] == src[1])
-+ src++;
-+ *dest++ = *src++;
-+ }
-+}
---- /dev/null
-+++ gdb-10.2/opcodes/loongarch-dis.c
-@@ -0,0 +1,342 @@
-+/* LoongArch opcode support.
-+ Copyright (C) 2021-2022 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of the GNU opcodes library.
-+
-+ This library is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3, or (at your option)
-+ any later version.
-+
-+ It is distributed in the hope that it will be useful, but WITHOUT
-+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-+ License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING3. If not,
-+ see <
http://www.gnu.org/licenses/>. */
-+
-+#include "sysdep.h"
-+#include "disassemble.h"
-+#include "opintl.h"
-+#include "opcode/loongarch.h"
-+#include "libiberty.h"
-+#include <stdlib.h>
-+
-+static const struct loongarch_opcode *
-+get_loongarch_opcode_by_binfmt (insn_t insn)
-+{
-+ const struct loongarch_opcode *it;
-+ struct loongarch_ase *ase;
-+ size_t i;
-+ for (ase = loongarch_ASEs; ase->enabled; ase++)
-+ {
-+ if (!*ase->enabled || (ase->include && !*ase->include)
-+ || (ase->exclude && *ase->exclude))
-+ continue;
-+
-+ if (!ase->opc_htab_inited)
-+ {
-+ for (it = ase->opcodes; it->mask; it++)
-+ if (!ase->opc_htab[LARCH_INSN_OPC (it->match)]
-+ && it->macro == NULL)
-+ ase->opc_htab[LARCH_INSN_OPC (it->match)] = it;
-+ for (i = 0; i < 16; i++)
-+ if (!ase->opc_htab[i])
-+ ase->opc_htab[i] = it;
-+ ase->opc_htab_inited = 1;
-+ }
-+
-+ it = ase->opc_htab[LARCH_INSN_OPC (insn)];
-+ for (; it->name; it++)
-+ if ((insn & it->mask) == it->match && it->mask
-+ && !(it->include && !*it->include)
-+ && !(it->exclude && *it->exclude))
-+ return it;
-+ }
-+ return NULL;
-+}
-+
-+static const char *const *loongarch_r_disname = NULL;
-+static const char *const *loongarch_f_disname = NULL;
-+static const char *const *loongarch_c_disname = NULL;
-+static const char *const *loongarch_cr_disname = NULL;
-+static const char *const *loongarch_v_disname = NULL;
-+static const char *const *loongarch_x_disname = NULL;
-+
-+static void
-+set_default_loongarch_dis_options (void)
-+{
-+ LARCH_opts.ase_ilp32 = 1;
-+ LARCH_opts.ase_lp64 = 1;
-+ LARCH_opts.ase_sf = 1;
-+ LARCH_opts.ase_df = 1;
-+ LARCH_opts.ase_lsx = 1;
-+ LARCH_opts.ase_lasx = 1;
-+
-+ loongarch_r_disname = loongarch_r_lp64_name;
-+ loongarch_f_disname = loongarch_f_lp64_name;
-+ loongarch_c_disname = loongarch_c_normal_name;
-+ loongarch_cr_disname = loongarch_cr_normal_name;
-+ loongarch_v_disname = loongarch_v_normal_name;
-+ loongarch_x_disname = loongarch_x_normal_name;
-+}
-+
-+static int
-+parse_loongarch_dis_option (const char *option)
-+{
-+ if (strcmp (option, "numeric") == 0)
-+ {
-+ loongarch_r_disname = loongarch_r_normal_name;
-+ loongarch_f_disname = loongarch_f_normal_name;
-+ }
-+ return -1;
-+}
-+
-+static int
-+parse_loongarch_dis_options (const char *opts_in)
-+{
-+ set_default_loongarch_dis_options ();
-+
-+ if (opts_in == NULL)
-+ return 0;
-+
-+ char *opts, *opt, *opt_end;
-+ opts = xmalloc (strlen (opts_in) + 1);
-+ strcpy (opts, opts_in);
-+
-+ for (opt = opt_end = opts; opt_end != NULL; opt = opt_end + 1)
-+ {
-+ if ((opt_end = strchr (opt, ',')) != NULL)
-+ *opt_end = 0;
-+ if (parse_loongarch_dis_option (opt) != 0)
-+ return -1;
-+ }
-+ free (opts);
-+ return 0;
-+}
-+
-+static int32_t
-+dis_one_arg (char esc1, char esc2, const char *bit_field,
-+ const char *arg ATTRIBUTE_UNUSED, void *context)
-+{
-+ static int need_comma = 0;
-+ struct disassemble_info *info = context;
-+ insn_t insn = *(insn_t *) info->private_data;
-+ int32_t imm, u_imm;
-+
-+ if (esc1)
-+ {
-+ if (need_comma)
-+ info->fprintf_func (info->stream, ", ");
-+ need_comma = 1;
-+ imm = loongarch_decode_imm (bit_field, insn, 1);
-+ u_imm = loongarch_decode_imm (bit_field, insn, 0);
-+ }
-+
-+ switch (esc1)
-+ {
-+ case 'r':
-+ info->fprintf_func (info->stream, "%s",
loongarch_r_disname[u_imm]);
-+ break;
-+ case 'f':
-+ info->fprintf_func (info->stream, "%s",
loongarch_f_disname[u_imm]);
-+ break;
-+ case 'c':
-+ switch (esc2)
-+ {
-+ case 'r':
-+ info->fprintf_func (info->stream, "%s",
loongarch_cr_disname[u_imm]);
-+ break;
-+ default:
-+ info->fprintf_func (info->stream, "%s", loongarch_c_disname[u_imm]);
-+ }
-+ break;
-+ case 'v':
-+ info->fprintf_func (info->stream, "%s",
loongarch_v_disname[u_imm]);
-+ break;
-+ case 'x':
-+ info->fprintf_func (info->stream, "%s",
loongarch_x_disname[u_imm]);
-+ break;
-+ case 'u':
-+ info->fprintf_func (info->stream, "0x%x", u_imm);
-+ break;
-+ case 's':
-+ if (imm == 0)
-+ info->fprintf_func (info->stream, "%d", imm);
-+ else
-+ info->fprintf_func (info->stream, "%d(0x%x)", imm, u_imm);
-+ switch (esc2)
-+ {
-+ case 'b':
-+ info->insn_type = dis_branch;
-+ info->target += imm;
-+ }
-+ break;
-+ case '\0':
-+ need_comma = 0;
-+ }
-+ return 0;
-+}
-+
-+static void
-+disassemble_one (insn_t insn, struct disassemble_info *info)
-+{
-+ const struct loongarch_opcode *opc = get_loongarch_opcode_by_binfmt (insn);
-+
-+#ifdef LOONGARCH_DEBUG
-+ char have_space[32] = { 0 };
-+ insn_t t;
-+ int i;
-+ const char *t_f = opc ? opc->format : NULL;
-+ if (t_f)
-+ while (*t_f)
-+ {
-+ while (('a' <= t_f[0] && t_f[0] <= 'z')
-+ || ('A' <= t_f[0] && t_f[0] <= 'Z')
-+ || t_f[0] == ',')
-+ t_f++;
-+ while (1)
-+ {
-+ i = strtol (t_f, &t_f, 10);
-+ have_space[i] = 1;
-+ t_f++; /* ':' */
-+ i += strtol (t_f, &t_f, 10);
-+ have_space[i] = 1;
-+ if (t_f[0] == '|')
-+ t_f++;
-+ else
-+ break;
-+ }
-+ if (t_f[0] == '<')
-+ t_f += 2; /* '<' '<' */
-+ strtol (t_f, &t_f, 10);
-+ }
-+
-+ have_space[28] = 1;
-+ have_space[0] = 0;
-+ t = ~((insn_t) -1 >> 1);
-+ for (i = 31; 0 <= i; i--)
-+ {
-+ if (t & insn)
-+ info->fprintf_func (info->stream, "1");
-+ else
-+ info->fprintf_func (info->stream, "0");
-+ if (have_space[i])
-+ info->fprintf_func (info->stream, " ");
-+ t = t >> 1;
-+ }
-+ info->fprintf_func (info->stream, "\t");
-+#endif
-+
-+ if (!opc)
-+ {
-+ info->insn_type = dis_noninsn;
-+ info->fprintf_func (info->stream, "0x%08x", insn);
-+ return;
-+ }
-+
-+ info->insn_type = dis_nonbranch;
-+ info->fprintf_func (info->stream, "%-12s", opc->name);
-+
-+ {
-+ char *fake_args = xmalloc (strlen (opc->format) + 1);
-+ const char *fake_arg_strs[MAX_ARG_NUM_PLUS_2];
-+ strcpy (fake_args, opc->format);
-+ if (0 < loongarch_split_args_by_comma (fake_args, fake_arg_strs))
-+ info->fprintf_func (info->stream, "\t");
-+ info->private_data = &insn;
-+ loongarch_foreach_args (opc->format, fake_arg_strs, dis_one_arg, info);
-+ free (fake_args);
-+ }
-+
-+ if (info->insn_type == dis_branch || info->insn_type == dis_condbranch
-+ /* Someother if we have extra info to print. */)
-+ info->fprintf_func (info->stream, "\t#");
-+
-+ if (info->insn_type == dis_branch || info->insn_type == dis_condbranch)
-+ {
-+ info->fprintf_func (info->stream, " ");
-+ info->print_address_func (info->target, info);
-+ }
-+}
-+
-+int
-+print_insn_loongarch (bfd_vma memaddr, struct disassemble_info *info)
-+{
-+ insn_t insn;
-+ int status;
-+
-+ static int not_init_yet = 1;
-+ if (not_init_yet)
-+ {
-+ parse_loongarch_dis_options (info->disassembler_options);
-+ not_init_yet = 0;
-+ }
-+
-+ info->bytes_per_chunk = 4;
-+ info->bytes_per_line = 4;
-+ info->display_endian = BFD_ENDIAN_LITTLE;
-+ info->insn_info_valid = 1;
-+ info->target = memaddr;
-+
-+ if ((status = info->read_memory_func (memaddr, (bfd_byte *) &insn,
-+ sizeof (insn), info)) != 0)
-+ {
-+ info->memory_error_func (status, memaddr, info);
-+ return -1; /* loongarch_insn_length (0); */
-+ }
-+
-+ disassemble_one (insn, info);
-+
-+ return loongarch_insn_length (insn);
-+}
-+
-+void
-+print_loongarch_disassembler_options (FILE *stream)
-+{
-+ fprintf (stream, _("\n\
-+The following LoongArch disassembler options are supported for use\n\
-+with the -M switch (multiple options should be separated by commas):\n"));
-+
-+ fprintf (stream, _("\n\
-+ numeric Print numeric register names, rather than ABI names.\n"));
-+ fprintf (stream, _("\n"));
-+}
-+
-+int
-+loongarch_parse_dis_options (const char *opts_in)
-+{
-+ return parse_loongarch_dis_options (opts_in);
-+}
-+
-+static void
-+my_print_address_func (bfd_vma addr, struct disassemble_info *dinfo)
-+{
-+ dinfo->fprintf_func (dinfo->stream, "0x%llx", (long long) addr);
-+}
-+
-+void
-+loongarch_disassemble_one (int64_t pc, insn_t insn,
-+ int (*fprintf_func) (void *stream,
-+ const char *format, ...),
-+ void *stream)
-+{
-+ static struct disassemble_info my_disinfo =
-+ {
-+ .print_address_func = my_print_address_func,
-+ };
-+ static int not_init_yet = 1;
-+ if (not_init_yet)
-+ {
-+ loongarch_parse_dis_options (NULL);
-+ not_init_yet = 0;
-+ }
-+
-+ my_disinfo.fprintf_func = fprintf_func;
-+ my_disinfo.stream = stream;
-+ my_disinfo.target = pc;
-+ disassemble_one (insn, &my_disinfo);
-+}
---- /dev/null
-+++ gdb-10.2/opcodes/loongarch-opc.c
-@@ -0,0 +1,870 @@
-+/* LoongArch opcode support.
-+ Copyright (C) 2021-2022 Free Software Foundation, Inc.
-+ Contributed by Loongson Ltd.
-+
-+ This file is part of the GNU opcodes library.
-+
-+ This library is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 3, or (at your option)
-+ any later version.
-+
-+ It is distributed in the hope that it will be useful, but WITHOUT
-+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
-+ License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; see the file COPYING3. If not,
-+ see <
http://www.gnu.org/licenses/>. */
-+
-+#include <stddef.h>
-+#include "opcode/loongarch.h"
-+#include "libiberty.h"
-+
-+struct loongarch_ASEs_option LARCH_opts;
-+
-+size_t
-+loongarch_insn_length (insn_t insn ATTRIBUTE_UNUSED)
-+{
-+ return 4;
-+}
-+
-+const char *const loongarch_r_normal_name[32] =
-+{
-+ "$r0", "$r1", "$r2", "$r3",
"$r4", "$r5", "$r6", "$r7",
-+ "$r8", "$r9", "$r10", "$r11",
"$r12", "$r13", "$r14", "$r15",
-+ "$r16", "$r17", "$r18", "$r19",
"$r20", "$r21", "$r22", "$r23",
-+ "$r24", "$r25", "$r26", "$r27",
"$r28", "$r29", "$r30", "$r31",
-+};
-+
-+const char *const loongarch_r_lp64_name[32] =
-+{
-+ "$zero", "$ra", "$tp", "$sp", "$a0",
"$a1", "$a2", "$a3",
-+ "$a4", "$a5", "$a6", "$a7", "$t0",
"$t1", "$t2", "$t3",
-+ "$t4", "$t5", "$t6", "$t7", "$t8",
"$x", "$fp", "$s0",
-+ "$s1", "$s2", "$s3", "$s4", "$s5",
"$s6", "$s7", "$s8",
-+};
-+
-+const char *const loongarch_r_lp64_name1[32] =
-+{
-+ "", "", "", "", "$v0",
"$v1", "", "", "", "", "",
"", "", "", "", "",
-+ "", "", "", "", "", "",
"", "", "", "", "", "",
"", "", "", "",
-+};
-+
-+const char *const loongarch_f_normal_name[32] =
-+{
-+ "$f0", "$f1", "$f2", "$f3",
"$f4", "$f5", "$f6", "$f7",
-+ "$f8", "$f9", "$f10", "$f11",
"$f12", "$f13", "$f14", "$f15",
-+ "$f16", "$f17", "$f18", "$f19",
"$f20", "$f21", "$f22", "$f23",
-+ "$f24", "$f25", "$f26", "$f27",
"$f28", "$f29", "$f30", "$f31",
-+};
-+
-+const char *const loongarch_f_lp64_name[32] =
-+{
-+ "$fa0", "$fa1", "$fa2", "$fa3",
"$fa4", "$fa5", "$fa6", "$fa7",
-+ "$ft0", "$ft1", "$ft2", "$ft3",
"$ft4", "$ft5", "$ft6", "$ft7",
-+ "$ft8", "$ft9", "$ft10", "$ft11",
"$ft12", "$ft13", "$ft14", "$ft15",
-+ "$fs0", "$fs1", "$fs2", "$fs3",
"$fs4", "$fs5", "$fs6", "$fs7",
-+};
-+
-+const char *const loongarch_f_lp64_name1[32] =
-+{
-+ "$fv0", "$fv1", "", "", "",
"", "", "", "", "", "",
"", "", "", "", "",
-+ "", "", "", "", "",
"", "", "", "", "", "",
"", "", "", "", "",
-+};
-+
-+const char *const loongarch_c_normal_name[8] =
-+{
-+ "$fcc0", "$fcc1", "$fcc2", "$fcc3",
"$fcc4", "$fcc5", "$fcc6", "$fcc7",
-+};
-+
-+const char *const loongarch_cr_normal_name[4] =
-+{
-+ "$scr0",
-+ "$scr1",
-+ "$scr2",
-+ "$scr3",
-+};
-+
-+const char *const loongarch_v_normal_name[32] =
-+{
-+ "$vr0", "$vr1", "$vr2", "$vr3",
"$vr4", "$vr5", "$vr6", "$vr7",
-+ "$vr8", "$vr9", "$vr10", "$vr11",
"$vr12", "$vr13", "$vr14", "$vr15",
-+ "$vr16", "$vr17", "$vr18", "$vr19",
"$vr20", "$vr21", "$vr22", "$vr23",
-+ "$vr24", "$vr25", "$vr26", "$vr27",
"$vr28", "$vr29", "$vr30", "$vr31",
-+};
-+
-+const char *const loongarch_x_normal_name[32] =
-+{
-+ "$xr0", "$xr1", "$xr2", "$xr3",
"$xr4", "$xr5", "$xr6", "$xr7",
-+ "$xr8", "$xr9", "$xr10", "$xr11",
"$xr12", "$xr13", "$xr14", "$xr15",
-+ "$xr16", "$xr17", "$xr18", "$xr19",
"$xr20", "$xr21", "$xr22", "$xr23",
-+ "$xr24", "$xr25", "$xr26", "$xr27",
"$xr28", "$xr29", "$xr30", "$xr31",
-+};
-+
-+/* Can not use xx_pa for abs. */
-+
-+/* For LoongArch32 abs. */
-+#define INSN_LA_ABS32 \
-+ "lu12i.w %1,%%abs_hi20(%2);" \
-+ "ori %1,%1,%%abs_lo12(%2);", \
-+ &LARCH_opts.ase_ilp32, \
-+ &LARCH_opts.ase_lp64
-+#define INSN_LA_ABS64 \
-+ "lu12i.w %1,%%abs_hi20(%2);" \
-+ "ori %1,%1,%%abs_lo12(%2);" \
-+ "lu32i.d %1,%%abs64_lo20(%2);" \
-+ "lu52i.d %1,%1,%%abs64_hi12(%2);", \
-+ &LARCH_opts.ase_lp64, 0
-+
-+#define INSN_LA_PCREL32 \
-+ "pcalau12i %1,%%pc_hi20(%2);" \
-+ "addi.w %1,%1,%%pc_lo12(%2);", \
-+ &LARCH_opts.ase_ilp32, \
-+ &LARCH_opts.ase_lp64
-+#define INSN_LA_PCREL64 \
-+ "pcalau12i %1,%%pc_hi20(%2);" \
-+ "addi.d %1,%1,%%pc_lo12(%2);", \
-+ &LARCH_opts.ase_lp64, 0
-+#define INSN_LA_PCREL64_LARGE \
-+ "pcalau12i %1,%%pc_hi20(%3);" \
-+ "addi.d %2,$r0,%%pc_lo12(%3);" \
-+ "lu32i.d %2,%%pc64_lo20(%3);" \
-+ "lu52i.d %2,%2,%%pc64_hi12(%3);" \
-+ "add.d %1,%1,%2;", \
-+ &LARCH_opts.ase_lp64, 0
-+
-+#define INSN_LA_GOT32 \
-+ "pcalau12i %1,%%got_pc_hi20(%2);" \
-+ "ld.w %1,%1,%%got_pc_lo12(%2);", \
-+ &LARCH_opts.ase_ilp32, \
-+ &LARCH_opts.ase_lp64
-+/* got32 abs. */
-+#define INSN_LA_GOT32_ABS \
-+ "lu12i.w %1,%%got_hi20(%2);" \
-+ "ori %1,%1,%%got_lo12(%2);" \
-+ "ld.w %1,%1,0;", \
-+ &LARCH_opts.ase_gabs, \
-+ &LARCH_opts.ase_lp64
-+#define INSN_LA_GOT64 \
-+ "pcalau12i %1,%%got_pc_hi20(%2);" \
-+ "ld.d %1,%1,%%got_pc_lo12(%2);", \
-+ &LARCH_opts.ase_lp64, 0
-+/* got64 abs. */
-+#define INSN_LA_GOT64_LARGE_ABS \
-+ "lu12i.w %1,%%got_hi20(%2);" \
-+ "ori %1,%1,%%got_lo12(%2);" \
-+ "lu32i.d %1,%%got64_lo20(%2);" \
-+ "lu52i.d %1,%1,%%got64_hi12(%2);" \
-+ "ld.d %1,%1,0", \
-+ &LARCH_opts.ase_lp64, \
-+ &LARCH_opts.ase_gpcr
-+/* got64 pic. */
-+#define INSN_LA_GOT64_LARGE_PCREL \
-+ "pcalau12i %1,%%got_pc_hi20(%3);" \
-+ "addi.d %2,$r0,%%got_pc_lo12(%3);" \
-+ "lu32i.d %2,%%got64_pc_lo20(%3);" \
-+ "lu52i.d %2,%2,%%got64_pc_hi12(%3);"\
-+ "ldx.d %1,%1,%2;", \
-+ &LARCH_opts.ase_lp64, \
-+ &LARCH_opts.ase_gabs
-+
-+/* For LoongArch32/64 cmode=normal. */
-+#define INSN_LA_TLS_LE \
-+ "lu12i.w %1,%%le_hi20(%2);" \
-+ "ori %1,%1,%%le_lo12(%2);", \
-+ &LARCH_opts.ase_ilp32, 0
-+
-+/* For LoongArch64 cmode=large. */
-+#define INSN_LA_TLS_LE64_LARGE \
-+ "lu12i.w %1,%%le_hi20(%2);" \
-+ "ori %1,%1,%%le_lo12(%2);" \
-+ "lu32i.d %1,%%le64_lo20(%2);" \
-+ "lu52i.d %1,%1,%%le64_hi12(%2);", \
-+ &LARCH_opts.ase_lp64, 0
-+
-+#define INSN_LA_TLS_IE32 \
-+ "pcalau12i %1,%%ie_pc_hi20(%2);" \
-+ "ld.w %1,%1,%%ie_pc_lo12(%2);", \
-+ &LARCH_opts.ase_ilp32, \
-+ &LARCH_opts.ase_lp64
-+/* For ie32 abs. */
-+#define INSN_LA_TLS_IE32_ABS \
-+ "lu12i.w %1,%%ie_hi20(%2);" \
-+ "ori %1,%1,%%ie_lo12(%2);" \
-+ "ld.w %1,%1,0", \
-+ &LARCH_opts.ase_gabs, \
-+ &LARCH_opts.ase_lp64
-+#define INSN_LA_TLS_IE64 \
-+ "pcalau12i %1,%%ie_pc_hi20(%2);" \
-+ "ld.d %1,%1,%%ie_pc_lo12(%2);", \
-+ &LARCH_opts.ase_lp64, 0
-+/* For ie64 pic. */
-+#define INSN_LA_TLS_IE64_LARGE_PCREL \
-+ "pcalau12i %1,%%ie_pc_hi20(%3);" \
-+ "addi.d %2,$r0,%%ie_pc_lo12(%3);" \
-+ "lu32i.d %2,%%ie64_pc_lo20(%3);" \
-+ "lu52i.d %2,%2,%%ie64_pc_hi12(%3);"\
-+ "ldx.d %1,%1,%2;", \
-+ &LARCH_opts.ase_lp64, \
-+ &LARCH_opts.ase_gabs
-+/* For ie64 abs. */
-+#define INSN_LA_TLS_IE64_LARGE_ABS \
-+ "lu12i.w %1,%%ie_hi20(%2);" \
-+ "ori %1,%1,%%ie_lo12(%2);" \
-+ "lu32i.d %1,%%ie64_lo20(%2);" \
-+ "lu52i.d %1,%1,%%ie64_hi12(%2);" \
-+ "ld.d %1,%1,0", \
-+ &LARCH_opts.ase_lp64, \
-+ &LARCH_opts.ase_gpcr
-+
-+/* For LoongArch32/64 cmode=normal. */
-+#define INSN_LA_TLS_LD32 \
-+ "pcalau12i %1,%%ld_pc_hi20(%2);" \
-+ "addi.w %1,%1,%%got_pc_lo12(%2);", \
-+ &LARCH_opts.ase_ilp32, \
-+ &LARCH_opts.ase_lp64
-+#define INSN_LA_TLS_LD32_ABS \
-+ "lu12i.w %1,%%ld_hi20(%2);" \
-+ "ori %1,%1,%%got_lo12(%2);", \
-+ &LARCH_opts.ase_gabs, \
-+ &LARCH_opts.ase_lp64
-+#define INSN_LA_TLS_LD64 \
-+ "pcalau12i %1,%%ld_pc_hi20(%2);" \
-+ "addi.d %1,%1,%%got_pc_lo12(%2);", \
-+ &LARCH_opts.ase_lp64, 0
-+#define INSN_LA_TLS_LD64_LARGE_PCREL \
-+ "pcalau12i %1,%%ld_pc_hi20(%3);" \
-+ "addi.d %2,$r0,%%got_pc_lo12(%3);" \
-+ "lu32i.d %2,%%got64_pc_lo20(%3);" \
-+ "lu52i.d %2,%2,%%got64_pc_hi12(%3);"\
-+ "add.d %1,%1,%2;", \
-+ &LARCH_opts.ase_lp64, \
-+ &LARCH_opts.ase_gabs
-+#define INSN_LA_TLS_LD64_LARGE_ABS \
-+ "lu12i.w %1,%%ld_hi20(%2);" \
-+ "ori %1,%1,%%got_lo12(%2);" \
-+ "lu32i.d %1,%%got64_lo20(%2);" \
-+ "lu52i.d %1,%1,%%got64_hi12(%2);", \
-+ &LARCH_opts.ase_lp64, \
-+ &LARCH_opts.ase_gpcr
-+
-+#define INSN_LA_TLS_GD32 \
-+ "pcalau12i %1,%%gd_pc_hi20(%2);" \
-+ "addi.w %1,%1,%%got_pc_lo12(%2);", \
-+ &LARCH_opts.ase_ilp32, \
-+ &LARCH_opts.ase_lp64
-+#define INSN_LA_TLS_GD32_ABS \
-+ "lu12i.w %1,%%gd_hi20(%2);" \
-+ "ori %1,%1,%%got_lo12(%2);", \
-+ &LARCH_opts.ase_gabs, \
-+ &LARCH_opts.ase_lp64
-+#define INSN_LA_TLS_GD64 \
-+ "pcalau12i %1,%%gd_pc_hi20(%2);" \
-+ "addi.d %1,%1,%%got_pc_lo12(%2);", \
-+ &LARCH_opts.ase_lp64, 0
-+#define INSN_LA_TLS_GD64_LARGE_PCREL \
-+ "pcalau12i %1,%%gd_pc_hi20(%3);" \
-+ "addi.d %2,$r0,%%got_pc_lo12(%3);" \
-+ "lu32i.d %2,%%got64_pc_lo20(%3);" \
-+ "lu52i.d %2,%2,%%got64_pc_hi12(%3);"\
-+ "add.d %1,%1,%2;", \
-+ &LARCH_opts.ase_lp64, \
-+ &LARCH_opts.ase_gabs
-+#define INSN_LA_TLS_GD64_LARGE_ABS \
-+ "lu12i.w %1,%%gd_hi20(%2);" \
-+ "ori %1,%1,%%got_lo12(%2);" \
-+ "lu32i.d %1,%%got64_lo20(%2);" \
-+ "lu52i.d %1,%1,%%got64_hi12(%2);", \
-+ &LARCH_opts.ase_lp64, \
-+ &LARCH_opts.ase_gpcr
-+
-+
-+static struct loongarch_opcode loongarch_macro_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0, 0, "li.w", "r,sc", "%f", 0, 0, 0 },
-+ { 0, 0, "li.d", "r,sc", "%f", 0, 0, 0 },
-+
-+ { 0, 0, "la", "r,la", "la.global %1,%2", 0, 0, 0
},
-+ { 0, 0, "la.global", "r,la", "la.pcrel
%1,%2", &LARCH_opts.ase_gpcr, 0, 0 },
-+ { 0, 0, "la.global", "r,r,la", "la.pcrel
%1,%2,%3", &LARCH_opts.ase_gpcr, 0, 0 },
-+ { 0, 0, "la.global", "r,la", "la.abs
%1,%2", &LARCH_opts.ase_gabs, 0, 0 },
-+ { 0, 0, "la.global", "r,r,la", "la.abs
%1,%3", &LARCH_opts.ase_gabs, 0, 0 },
-+ { 0, 0, "la.global", "r,la", "la.got %1,%2", 0, 0, 0
},
-+ { 0, 0, "la.global", "r,r,la", "la.got
%1,%2,%3", &LARCH_opts.ase_lp64, 0, 0 },
-+
-+ { 0, 0, "la.local", "r,la", "la.abs
%1,%2", &LARCH_opts.ase_labs, 0, 0 },
-+ { 0, 0, "la.local", "r,r,la", "la.abs
%1,%3", &LARCH_opts.ase_labs, 0, 0 },
-+ { 0, 0, "la.local", "r,la", "la.pcrel %1,%2", 0, 0,
0 },
-+ { 0, 0, "la.local", "r,r,la", "la.pcrel
%1,%2,%3", &LARCH_opts.ase_lp64, 0, 0 },
-+
-+ { 0, 0, "la.abs", "r,la", INSN_LA_ABS32, 0 },
-+ { 0, 0, "la.abs", "r,la", INSN_LA_ABS64, 0 },
-+ { 0, 0, "la.pcrel", "r,la", INSN_LA_PCREL32, 0 },
-+ { 0, 0, "la.pcrel", "r,la", INSN_LA_PCREL64, 0 },
-+ { 0, 0, "la.pcrel", "r,r,la", INSN_LA_PCREL64_LARGE, 0 },
-+ { 0, 0, "la.got", "r,la", INSN_LA_GOT32, 0 },
-+ { 0, 0, "la.got", "r,la", INSN_LA_GOT32_ABS, 0 },
-+ { 0, 0, "la.got", "r,la", INSN_LA_GOT64, 0 },
-+ { 0, 0, "la.got", "r,la", INSN_LA_GOT64_LARGE_ABS, 0 },
-+ { 0, 0, "la.got", "r,r,la", INSN_LA_GOT64_LARGE_PCREL, 0 },
-+ { 0, 0, "la.tls.le", "r,l", INSN_LA_TLS_LE, 0 },
-+ { 0, 0, "la.tls.le", "r,l", INSN_LA_TLS_LE64_LARGE, 0 },
-+ { 0, 0, "la.tls.ie", "r,l", INSN_LA_TLS_IE32, 0 },
-+ { 0, 0, "la.tls.ie", "r,l", INSN_LA_TLS_IE32_ABS, 0 },
-+ { 0, 0, "la.tls.ie", "r,l", INSN_LA_TLS_IE64, 0 },
-+ { 0, 0, "la.tls.ie", "r,l", INSN_LA_TLS_IE64_LARGE_ABS, 0 },
-+ { 0, 0, "la.tls.ie", "r,r,l", INSN_LA_TLS_IE64_LARGE_PCREL, 0 },
-+ { 0, 0, "la.tls.ld", "r,l", INSN_LA_TLS_LD32, 0 },
-+ { 0, 0, "la.tls.ld", "r,l", INSN_LA_TLS_LD32_ABS, 0 },
-+ { 0, 0, "la.tls.ld", "r,l", INSN_LA_TLS_LD64, 0 },
-+ { 0, 0, "la.tls.ld", "r,l", INSN_LA_TLS_LD64_LARGE_ABS, 0 },
-+ { 0, 0, "la.tls.ld", "r,r,l", INSN_LA_TLS_LD64_LARGE_PCREL, 0 },
-+ { 0, 0, "la.tls.gd", "r,l", INSN_LA_TLS_GD32, 0 },
-+ { 0, 0, "la.tls.gd", "r,l", INSN_LA_TLS_GD32_ABS, 0 },
-+ { 0, 0, "la.tls.gd", "r,l", INSN_LA_TLS_GD64, 0 },
-+ { 0, 0, "la.tls.gd", "r,l", INSN_LA_TLS_GD64_LARGE_ABS, 0 },
-+ { 0, 0, "la.tls.gd", "r,r,l", INSN_LA_TLS_GD64_LARGE_PCREL, 0 },
-+
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_fix_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x00001000, 0xfffffc00, "clo.w", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x00001400, 0xfffffc00, "clz.w", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x00001800, 0xfffffc00, "cto.w", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x00001c00, 0xfffffc00, "ctz.w", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x00002000, 0xfffffc00, "clo.d", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x00002400, 0xfffffc00, "clz.d", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x00002800, 0xfffffc00, "cto.d", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x00002c00, 0xfffffc00, "ctz.d", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x00003000, 0xfffffc00, "revb.2h", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00003400, 0xfffffc00, "revb.4h", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00003800, 0xfffffc00, "revb.2w", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00003c00, 0xfffffc00, "revb.d", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00004000, 0xfffffc00, "revh.2w", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00004400, 0xfffffc00, "revh.d", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00004800, 0xfffffc00, "bitrev.4b", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00004c00, 0xfffffc00, "bitrev.8b", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00005000, 0xfffffc00, "bitrev.w", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00005400, 0xfffffc00, "bitrev.d", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00005800, 0xfffffc00, "ext.w.h", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00005c00, 0xfffffc00, "ext.w.b", "r0:5,r5:5", 0, 0, 0, 0
},
-+ /* or %1,%2,$r0 */
-+ { 0x00150000, 0xfffffc00, "move", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x00006000, 0xfffffc00, "rdtimel.w", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00006400, 0xfffffc00, "rdtimeh.w", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00006800, 0xfffffc00, "rdtime.d", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00006c00, 0xfffffc00, "cpucfg", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x00010000, 0xffff801f, "asrtle.d", "r5:5,r10:5", 0, 0, 0, 0
},
-+ { 0x00018000, 0xffff801f, "asrtgt.d", "r5:5,r10:5", 0, 0, 0, 0
},
-+ { 0x00040000,
0xfffe0000, "alsl.w", "r0:5,r5:5,r10:5,u15:2+1", 0, 0, 0, 0 },
-+ { 0x00060000,
0xfffe0000, "alsl.wu", "r0:5,r5:5,r10:5,u15:2+1", 0, 0, 0, 0 },
-+ { 0x00080000,
0xfffe0000, "bytepick.w", "r0:5,r5:5,r10:5,u15:2", 0, 0, 0, 0 },
-+ { 0x000c0000,
0xfffc0000, "bytepick.d", "r0:5,r5:5,r10:5,u15:3", 0, 0, 0, 0 },
-+ { 0x00100000,
0xffff8000, "add.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00108000,
0xffff8000, "add.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00110000,
0xffff8000, "sub.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00118000,
0xffff8000, "sub.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00120000, 0xffff8000, "slt", "r0:5,r5:5,r10:5", 0, 0, 0, 0
},
-+ { 0x00128000,
0xffff8000, "sltu", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00130000,
0xffff8000, "maskeqz", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00138000,
0xffff8000, "masknez", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00140000, 0xffff8000, "nor", "r0:5,r5:5,r10:5", 0, 0, 0, 0
},
-+ { 0x00148000, 0xffff8000, "and", "r0:5,r5:5,r10:5", 0, 0, 0, 0
},
-+ { 0x00150000, 0xffff8000, "or", "r0:5,r5:5,r10:5", 0, 0, 0, 0
},
-+ { 0x00158000, 0xffff8000, "xor", "r0:5,r5:5,r10:5", 0, 0, 0, 0
},
-+ { 0x00160000, 0xffff8000, "orn", "r0:5,r5:5,r10:5", 0, 0, 0, 0
},
-+ { 0x00168000,
0xffff8000, "andn", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00170000,
0xffff8000, "sll.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00178000,
0xffff8000, "srl.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00180000,
0xffff8000, "sra.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00188000,
0xffff8000, "sll.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00190000,
0xffff8000, "srl.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00198000,
0xffff8000, "sra.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x001b0000,
0xffff8000, "rotr.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x001b8000,
0xffff8000, "rotr.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x001c0000,
0xffff8000, "mul.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x001c8000,
0xffff8000, "mulh.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x001d0000,
0xffff8000, "mulh.wu", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x001d8000,
0xffff8000, "mul.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x001e0000,
0xffff8000, "mulh.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x001e8000,
0xffff8000, "mulh.du", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x001f0000,
0xffff8000, "mulw.d.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x001f8000,
0xffff8000, "mulw.d.wu", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00200000,
0xffff8000, "div.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00208000,
0xffff8000, "mod.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00210000,
0xffff8000, "div.wu", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00218000,
0xffff8000, "mod.wu", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00220000,
0xffff8000, "div.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00228000,
0xffff8000, "mod.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00230000,
0xffff8000, "div.du", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00238000,
0xffff8000, "mod.du", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00240000,
0xffff8000, "crc.w.b.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00248000,
0xffff8000, "crc.w.h.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00250000,
0xffff8000, "crc.w.w.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00258000,
0xffff8000, "crc.w.d.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00260000,
0xffff8000, "crcc.w.b.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00268000,
0xffff8000, "crcc.w.h.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00270000,
0xffff8000, "crcc.w.w.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x00278000,
0xffff8000, "crcc.w.d.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x002a0000, 0xffff8000, "break", "u0:15", 0, 0, 0, 0 },
-+ { 0x002a8000, 0xffff8000, "dbcl", "u0:15", 0, 0, 0, 0 },
-+ { 0x002b0000, 0xffff8000, "syscall", "u0:15", 0, 0, 0, 0 },
-+ { 0x002c0000,
0xfffe0000, "alsl.d", "r0:5,r5:5,r10:5,u15:2+1", 0, 0, 0, 0 },
-+ { 0x00408000,
0xffff8000, "slli.w", "r0:5,r5:5,u10:5", 0, 0, 0, 0 },
-+ { 0x00410000,
0xffff0000, "slli.d", "r0:5,r5:5,u10:6", 0, 0, 0, 0 },
-+ { 0x00448000,
0xffff8000, "srli.w", "r0:5,r5:5,u10:5", 0, 0, 0, 0 },
-+ { 0x00450000,
0xffff0000, "srli.d", "r0:5,r5:5,u10:6", 0, 0, 0, 0 },
-+ { 0x00488000,
0xffff8000, "srai.w", "r0:5,r5:5,u10:5", 0, 0, 0, 0 },
-+ { 0x00490000,
0xffff0000, "srai.d", "r0:5,r5:5,u10:6", 0, 0, 0, 0 },
-+ { 0x004c8000,
0xffff8000, "rotri.w", "r0:5,r5:5,u10:5", 0, 0, 0, 0 },
-+ { 0x004d0000,
0xffff0000, "rotri.d", "r0:5,r5:5,u10:6", 0, 0, 0, 0 },
-+ { 0x00600000,
0xffe08000, "bstrins.w", "r0:5,r5:5,u16:5,u10:5", 0, 0, 0, 0 },
-+ { 0x00608000,
0xffe08000, "bstrpick.w", "r0:5,r5:5,u16:5,u10:5", 0, 0, 0, 0 },
-+ { 0x00800000,
0xffc00000, "bstrins.d", "r0:5,r5:5,u16:6,u10:6", 0, 0, 0, 0 },
-+ { 0x00c00000,
0xffc00000, "bstrpick.d", "r0:5,r5:5,u16:6,u10:6", 0, 0, 0, 0 },
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_single_float_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x01008000,
0xffff8000, "fadd.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01028000,
0xffff8000, "fsub.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01048000,
0xffff8000, "fmul.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01068000,
0xffff8000, "fdiv.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01088000,
0xffff8000, "fmax.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x010a8000,
0xffff8000, "fmin.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x010c8000,
0xffff8000, "fmaxa.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x010e8000,
0xffff8000, "fmina.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01108000,
0xffff8000, "fscaleb.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01128000,
0xffff8000, "fcopysign.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01140400, 0xfffffc00, "fabs.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01141400, 0xfffffc00, "fneg.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01142400, 0xfffffc00, "flogb.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01143400, 0xfffffc00, "fclass.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01144400, 0xfffffc00, "fsqrt.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01145400, 0xfffffc00, "frecip.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01146400, 0xfffffc00, "frsqrt.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01149400, 0xfffffc00, "fmov.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x0114a400,
0xfffffc00, "movgr2fr.w", "f0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0114ac00,
0xfffffc00, "movgr2frh.w", "f0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0114b400,
0xfffffc00, "movfr2gr.s", "r0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x0114bc00,
0xfffffc00, "movfrh2gr.s", "r0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x0114c000,
0xfffffc00, "movgr2fcsr", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0114c800,
0xfffffc00, "movfcsr2gr", "r0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0114d000, 0xfffffc18, "movfr2cf", "c0:3,f5:5", 0, 0, 0, 0
},
-+ { 0x0114d400, 0xffffff00, "movcf2fr", "f0:5,c5:3", 0, 0, 0, 0
},
-+ { 0x0114d800, 0xfffffc18, "movgr2cf", "c0:3,r5:5", 0, 0, 0, 0
},
-+ { 0x0114dc00, 0xffffff00, "movcf2gr", "r0:5,c5:3", 0, 0, 0, 0
},
-+ { 0x011a0400,
0xfffffc00, "ftintrm.w.s", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011a2400,
0xfffffc00, "ftintrm.l.s", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011a4400,
0xfffffc00, "ftintrp.w.s", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011a6400,
0xfffffc00, "ftintrp.l.s", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011a8400,
0xfffffc00, "ftintrz.w.s", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011aa400,
0xfffffc00, "ftintrz.l.s", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011ac400,
0xfffffc00, "ftintrne.w.s", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011ae400,
0xfffffc00, "ftintrne.l.s", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011b0400, 0xfffffc00, "ftint.w.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x011b2400, 0xfffffc00, "ftint.l.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x011d1000, 0xfffffc00, "ffint.s.w", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x011d1800, 0xfffffc00, "ffint.s.l", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x011e4400, 0xfffffc00, "frint.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0 } /* Terminate the list. */
-+};
-+static struct loongarch_opcode loongarch_double_float_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x01010000,
0xffff8000, "fadd.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01030000,
0xffff8000, "fsub.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01050000,
0xffff8000, "fmul.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01070000,
0xffff8000, "fdiv.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01090000,
0xffff8000, "fmax.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x010b0000,
0xffff8000, "fmin.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x010d0000,
0xffff8000, "fmaxa.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x010f0000,
0xffff8000, "fmina.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01110000,
0xffff8000, "fscaleb.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01130000,
0xffff8000, "fcopysign.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x01140800, 0xfffffc00, "fabs.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01141800, 0xfffffc00, "fneg.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01142800, 0xfffffc00, "flogb.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01143800, 0xfffffc00, "fclass.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01144800, 0xfffffc00, "fsqrt.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01145800, 0xfffffc00, "frecip.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01146800, 0xfffffc00, "frsqrt.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01149800, 0xfffffc00, "fmov.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x0114a800,
0xfffffc00, "movgr2fr.d", "f0:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0114b800,
0xfffffc00, "movfr2gr.d", "r0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x01191800, 0xfffffc00, "fcvt.s.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x01192400, 0xfffffc00, "fcvt.d.s", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x011a0800,
0xfffffc00, "ftintrm.w.d", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011a2800,
0xfffffc00, "ftintrm.l.d", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011a4800,
0xfffffc00, "ftintrp.w.d", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011a6800,
0xfffffc00, "ftintrp.l.d", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011a8800,
0xfffffc00, "ftintrz.w.d", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011aa800,
0xfffffc00, "ftintrz.l.d", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011ac800,
0xfffffc00, "ftintrne.w.d", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011ae800,
0xfffffc00, "ftintrne.l.d", "f0:5,f5:5", 0, 0, 0, 0 },
-+ { 0x011b0800, 0xfffffc00, "ftint.w.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x011b2800, 0xfffffc00, "ftint.l.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x011d2000, 0xfffffc00, "ffint.d.w", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x011d2800, 0xfffffc00, "ffint.d.l", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0x011e4800, 0xfffffc00, "frint.d", "f0:5,f5:5", 0, 0, 0, 0
},
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_imm_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x02000000,
0xffc00000, "slti", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x02400000,
0xffc00000, "sltui", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x02800000,
0xffc00000, "addi.w", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x02c00000,
0xffc00000, "addi.d", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x03000000,
0xffc00000, "lu52i.d", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "nop", "", "andi $r0,$r0,0", 0, 0, 0
},
-+ { 0x03400000,
0xffc00000, "andi", "r0:5,r5:5,u10:12", 0, 0, 0, 0 },
-+ { 0x03800000,
0xffc00000, "ori", "r0:5,r5:5,u10:12", 0, 0, 0, 0 },
-+ { 0x03c00000,
0xffc00000, "xori", "r0:5,r5:5,u10:12", 0, 0, 0, 0 },
-+ { 0x10000000,
0xfc000000, "addu16i.d", "r0:5,r5:5,s10:16", 0, 0, 0, 0 },
-+ { 0x14000000, 0xfe000000, "lu12i.w", "r0:5,s5:20", 0, 0, 0, 0
},
-+ { 0x16000000, 0xfe000000, "lu32i.d", "r0:5,s5:20", 0, 0, 0, 0
},
-+ { 0x18000000, 0xfe000000, "pcaddi", "r0:5,s5:20", 0, 0, 0, 0
},
-+ { 0x1a000000,
0xfe000000, "pcalau12i", "r0:5,s5:20", 0, 0, 0, 0 },
-+ { 0x1c000000,
0xfe000000, "pcaddu12i", "r0:5,s5:20", 0, 0, 0, 0 },
-+ { 0x1e000000,
0xfe000000, "pcaddu18i", "r0:5,s5:20", 0, 0, 0, 0 },
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_privilege_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x04000000, 0xff0003e0, "csrrd", "r0:5,u10:14", 0, 0, 0, 0
},
-+ { 0x04000020, 0xff0003e0, "csrwr", "r0:5,u10:14", 0, 0, 0, 0
},
-+ { 0x04000000,
0xff000000, "csrxchg", "r0:5,r5:5,u10:14", 0, 0, 0, 0 },
-+ { 0x06000000,
0xffc00000, "cacop", "u0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x06400000,
0xfffc0000, "lddir", "r0:5,r5:5,u10:8", 0, 0, 0, 0 },
-+ { 0x06440000, 0xfffc001f, "ldpte", "r5:5,u10:8", 0, 0, 0, 0
},
-+ { 0x06480000, 0xfffffc00, "iocsrrd.b", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x06480400, 0xfffffc00, "iocsrrd.h", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x06480800, 0xfffffc00, "iocsrrd.w", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x06480c00, 0xfffffc00, "iocsrrd.d", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x06481000, 0xfffffc00, "iocsrwr.b", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x06481400, 0xfffffc00, "iocsrwr.h", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x06481800, 0xfffffc00, "iocsrwr.w", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x06481c00, 0xfffffc00, "iocsrwr.d", "r0:5,r5:5", 0, 0, 0, 0
},
-+ { 0x06482000, 0xffffffff, "tlbclr", "", 0, 0, 0, 0 },
-+ { 0x06482400, 0xffffffff, "tlbflush", "", 0, 0, 0, 0 },
-+ { 0x06482800, 0xffffffff, "tlbsrch", "", 0, 0, 0, 0 },
-+ { 0x06482c00, 0xffffffff, "tlbrd", "", 0, 0, 0, 0 },
-+ { 0x06483000, 0xffffffff, "tlbwr", "", 0, 0, 0, 0 },
-+ { 0x06483400, 0xffffffff, "tlbfill", "", 0, 0, 0, 0 },
-+ { 0x06483800, 0xffffffff, "ertn", "", 0, 0, 0, 0 },
-+ { 0x06488000, 0xffff8000, "idle", "u0:15", 0, 0, 0, 0 },
-+ { 0x06498000,
0xffff8000, "invtlb", "u0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_4opt_single_float_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x08100000,
0xfff00000, "fmadd.s", "f0:5,f5:5,f10:5,f15:5", 0, 0, 0, 0 },
-+ { 0x08500000,
0xfff00000, "fmsub.s", "f0:5,f5:5,f10:5,f15:5", 0, 0, 0, 0 },
-+ { 0x08900000,
0xfff00000, "fnmadd.s", "f0:5,f5:5,f10:5,f15:5", 0, 0, 0, 0 },
-+ { 0x08d00000,
0xfff00000, "fnmsub.s", "f0:5,f5:5,f10:5,f15:5", 0, 0, 0, 0 },
-+ { 0x0c100000,
0xffff8018, "fcmp.caf.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c108000,
0xffff8018, "fcmp.saf.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c110000,
0xffff8018, "fcmp.clt.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c118000,
0xffff8018, "fcmp.slt.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c118000,
0xffff8018, "fcmp.sgt.s", "c0:3,f10:5,f5:5", 0, 0, 0, 0 },
-+ { 0x0c120000,
0xffff8018, "fcmp.ceq.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c128000,
0xffff8018, "fcmp.seq.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c130000,
0xffff8018, "fcmp.cle.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c138000,
0xffff8018, "fcmp.sle.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c138000,
0xffff8018, "fcmp.sge.s", "c0:3,f10:5,f5:5", 0, 0, 0, 0 },
-+ { 0x0c140000,
0xffff8018, "fcmp.cun.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c148000,
0xffff8018, "fcmp.sun.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c150000,
0xffff8018, "fcmp.cult.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c150000,
0xffff8018, "fcmp.cugt.s", "c0:3,f10:5,f5:5", 0, 0, 0, 0 },
-+ { 0x0c158000,
0xffff8018, "fcmp.sult.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c160000,
0xffff8018, "fcmp.cueq.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c168000,
0xffff8018, "fcmp.sueq.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c170000,
0xffff8018, "fcmp.cule.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c170000,
0xffff8018, "fcmp.cuge.s", "c0:3,f10:5,f5:5", 0, 0, 0, 0 },
-+ { 0x0c178000,
0xffff8018, "fcmp.sule.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c180000,
0xffff8018, "fcmp.cne.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c188000,
0xffff8018, "fcmp.sne.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c1a0000,
0xffff8018, "fcmp.cor.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c1a8000,
0xffff8018, "fcmp.sor.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c1c0000,
0xffff8018, "fcmp.cune.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c1c8000,
0xffff8018, "fcmp.sune.s", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0d000000,
0xfffc0000, "fsel", "f0:5,f5:5,f10:5,c15:3", 0, 0, 0, 0 },
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_4opt_double_float_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x08200000,
0xfff00000, "fmadd.d", "f0:5,f5:5,f10:5,f15:5", 0, 0, 0, 0 },
-+ { 0x08600000,
0xfff00000, "fmsub.d", "f0:5,f5:5,f10:5,f15:5", 0, 0, 0, 0 },
-+ { 0x08a00000,
0xfff00000, "fnmadd.d", "f0:5,f5:5,f10:5,f15:5", 0, 0, 0, 0 },
-+ { 0x08e00000,
0xfff00000, "fnmsub.d", "f0:5,f5:5,f10:5,f15:5", 0, 0, 0, 0 },
-+ { 0x0c200000,
0xffff8018, "fcmp.caf.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c208000,
0xffff8018, "fcmp.saf.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c210000,
0xffff8018, "fcmp.clt.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c218000,
0xffff8018, "fcmp.slt.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c218000,
0xffff8018, "fcmp.sgt.d", "c0:3,f10:5,f5:5", 0, 0, 0, 0 },
-+ { 0x0c220000,
0xffff8018, "fcmp.ceq.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c228000,
0xffff8018, "fcmp.seq.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c230000,
0xffff8018, "fcmp.cle.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c238000,
0xffff8018, "fcmp.sle.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c238000,
0xffff8018, "fcmp.sge.d", "c0:3,f10:5,f5:5", 0, 0, 0, 0 },
-+ { 0x0c240000,
0xffff8018, "fcmp.cun.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c248000,
0xffff8018, "fcmp.sun.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c250000,
0xffff8018, "fcmp.cult.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c250000,
0xffff8018, "fcmp.cugt.d", "c0:3,f10:5,f5:5", 0, 0, 0, 0 },
-+ { 0x0c258000,
0xffff8018, "fcmp.sult.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c260000,
0xffff8018, "fcmp.cueq.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c268000,
0xffff8018, "fcmp.sueq.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c270000,
0xffff8018, "fcmp.cule.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c270000,
0xffff8018, "fcmp.cuge.d", "c0:3,f10:5,f5:5", 0, 0, 0, 0 },
-+ { 0x0c278000,
0xffff8018, "fcmp.sule.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c280000,
0xffff8018, "fcmp.cne.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c288000,
0xffff8018, "fcmp.sne.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c2a0000,
0xffff8018, "fcmp.cor.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c2a8000,
0xffff8018, "fcmp.sor.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c2c0000,
0xffff8018, "fcmp.cune.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0x0c2c8000,
0xffff8018, "fcmp.sune.d", "c0:3,f5:5,f10:5", 0, 0, 0, 0 },
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_load_store_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x20000000,
0xff000000, "ll.w", "r0:5,r5:5,s10:14<<2", 0, 0, 0, 0 },
-+ { 0x21000000,
0xff000000, "sc.w", "r0:5,r5:5,s10:14<<2", 0, 0, 0, 0 },
-+ { 0x22000000,
0xff000000, "ll.d", "r0:5,r5:5,s10:14<<2", 0, 0, 0, 0 },
-+ { 0x23000000,
0xff000000, "sc.d", "r0:5,r5:5,s10:14<<2", 0, 0, 0, 0 },
-+ { 0x24000000,
0xff000000, "ldptr.w", "r0:5,r5:5,s10:14<<2", 0, 0, 0, 0 },
-+ { 0x25000000,
0xff000000, "stptr.w", "r0:5,r5:5,s10:14<<2", 0, 0, 0, 0 },
-+ { 0x26000000,
0xff000000, "ldptr.d", "r0:5,r5:5,s10:14<<2", 0, 0, 0, 0 },
-+ { 0x27000000,
0xff000000, "stptr.d", "r0:5,r5:5,s10:14<<2", 0, 0, 0, 0 },
-+ { 0x28000000,
0xffc00000, "ld.b", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x28400000,
0xffc00000, "ld.h", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x28800000,
0xffc00000, "ld.w", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x28c00000,
0xffc00000, "ld.d", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x29000000,
0xffc00000, "st.b", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x29400000,
0xffc00000, "st.h", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x29800000,
0xffc00000, "st.w", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x29c00000,
0xffc00000, "st.d", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x2a000000,
0xffc00000, "ld.bu", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x2a400000,
0xffc00000, "ld.hu", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x2a800000,
0xffc00000, "ld.wu", "r0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x2ac00000,
0xffc00000, "preld", "u0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x38000000,
0xffff8000, "ldx.b", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38040000,
0xffff8000, "ldx.h", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38080000,
0xffff8000, "ldx.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x380c0000,
0xffff8000, "ldx.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38100000,
0xffff8000, "stx.b", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38140000,
0xffff8000, "stx.h", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38180000,
0xffff8000, "stx.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x381c0000,
0xffff8000, "stx.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38200000,
0xffff8000, "ldx.bu", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38240000,
0xffff8000, "ldx.hu", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38280000,
0xffff8000, "ldx.wu", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x382c0000,
0xffff8000, "preldx", "u0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amswap.w", "r,r,r,u0:0", "amswap.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x38600000,
0xffff8000, "amswap.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amswap.d", "r,r,r,u0:0", "amswap.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x38608000,
0xffff8000, "amswap.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amadd.w", "r,r,r,u0:0", "amadd.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x38610000,
0xffff8000, "amadd.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amadd.d", "r,r,r,u0:0", "amadd.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x38618000,
0xffff8000, "amadd.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amand.w", "r,r,r,u0:0", "amand.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x38620000,
0xffff8000, "amand.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amand.d", "r,r,r,u0:0", "amand.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x38628000,
0xffff8000, "amand.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amor.w", "r,r,r,u0:0", "amor.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x38630000,
0xffff8000, "amor.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amor.d", "r,r,r,u0:0", "amor.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x38638000,
0xffff8000, "amor.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amxor.w", "r,r,r,u0:0", "amxor.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x38640000,
0xffff8000, "amxor.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amxor.d", "r,r,r,u0:0", "amxor.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x38648000,
0xffff8000, "amxor.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammax.w", "r,r,r,u0:0", "ammax.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x38650000,
0xffff8000, "ammax.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammax.d", "r,r,r,u0:0", "ammax.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x38658000,
0xffff8000, "ammax.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammin.w", "r,r,r,u0:0", "ammin.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x38660000,
0xffff8000, "ammin.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammin.d", "r,r,r,u0:0", "ammin.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x38668000,
0xffff8000, "ammin.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammax.wu", "r,r,r,u0:0", "ammax.wu
%1,%2,%3", 0, 0, 0 },
-+ { 0x38670000,
0xffff8000, "ammax.wu", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammax.du", "r,r,r,u0:0", "ammax.du
%1,%2,%3", 0, 0, 0 },
-+ { 0x38678000,
0xffff8000, "ammax.du", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammin.wu", "r,r,r,u0:0", "ammin.wu
%1,%2,%3", 0, 0, 0 },
-+ { 0x38680000,
0xffff8000, "ammin.wu", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammin.du", "r,r,r,u0:0", "ammin.du
%1,%2,%3", 0, 0, 0 },
-+ { 0x38688000,
0xffff8000, "ammin.du", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amswap_db.w", "r,r,r,u0:0", "amswap_db.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x38690000,
0xffff8000, "amswap_db.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amswap_db.d", "r,r,r,u0:0", "amswap_db.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x38698000,
0xffff8000, "amswap_db.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amadd_db.w", "r,r,r,u0:0", "amadd_db.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x386a0000,
0xffff8000, "amadd_db.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amadd_db.d", "r,r,r,u0:0", "amadd_db.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x386a8000,
0xffff8000, "amadd_db.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amand_db.w", "r,r,r,u0:0", "amand_db.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x386b0000,
0xffff8000, "amand_db.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amand_db.d", "r,r,r,u0:0", "amand_db.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x386b8000,
0xffff8000, "amand_db.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amor_db.w", "r,r,r,u0:0", "amor_db.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x386c0000,
0xffff8000, "amor_db.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amor_db.d", "r,r,r,u0:0", "amor_db.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x386c8000,
0xffff8000, "amor_db.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amxor_db.w", "r,r,r,u0:0", "amxor_db.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x386d0000,
0xffff8000, "amxor_db.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "amxor_db.d", "r,r,r,u0:0", "amxor_db.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x386d8000,
0xffff8000, "amxor_db.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammax_db.w", "r,r,r,u0:0", "ammax_db.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x386e0000,
0xffff8000, "ammax_db.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammax_db.d", "r,r,r,u0:0", "ammax_db.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x386e8000,
0xffff8000, "ammax_db.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammin_db.w", "r,r,r,u0:0", "ammin_db.w
%1,%2,%3", 0, 0, 0 },
-+ { 0x386f0000,
0xffff8000, "ammin_db.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammin_db.d", "r,r,r,u0:0", "ammin_db.d
%1,%2,%3", 0, 0, 0 },
-+ { 0x386f8000,
0xffff8000, "ammin_db.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammax_db.wu", "r,r,r,u0:0", "ammax_db.wu
%1,%2,%3", 0, 0, 0 },
-+ { 0x38700000,
0xffff8000, "ammax_db.wu", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammax_db.du", "r,r,r,u0:0", "ammax_db.du
%1,%2,%3", 0, 0, 0 },
-+ { 0x38708000,
0xffff8000, "ammax_db.du", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammin_db.wu", "r,r,r,u0:0", "ammin_db.wu
%1,%2,%3", 0, 0, 0 },
-+ { 0x38710000,
0xffff8000, "ammin_db.wu", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ammin_db.du", "r,r,r,u0:0", "ammin_db.du
%1,%2,%3", 0, 0, 0 },
-+ { 0x38718000,
0xffff8000, "ammin_db.du", "r0:5,r10:5,r5:5", 0, 0, 0, 0 },
-+ { 0x38720000, 0xffff8000, "dbar", "u0:15", 0, 0, 0, 0 },
-+ { 0x38728000, 0xffff8000, "ibar", "u0:15", 0, 0, 0, 0 },
-+ { 0x38780000,
0xffff8000, "ldgt.b", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38788000,
0xffff8000, "ldgt.h", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38790000,
0xffff8000, "ldgt.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x38798000,
0xffff8000, "ldgt.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387a0000,
0xffff8000, "ldle.b", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387a8000,
0xffff8000, "ldle.h", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387b0000,
0xffff8000, "ldle.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387b8000,
0xffff8000, "ldle.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387c0000,
0xffff8000, "stgt.b", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387c8000,
0xffff8000, "stgt.h", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387d0000,
0xffff8000, "stgt.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387d8000,
0xffff8000, "stgt.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387e0000,
0xffff8000, "stle.b", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387e8000,
0xffff8000, "stle.h", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387f0000,
0xffff8000, "stle.w", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0x387f8000,
0xffff8000, "stle.d", "r0:5,r5:5,r10:5", 0, 0, 0, 0 },
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_single_float_load_store_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x2b000000,
0xffc00000, "fld.s", "f0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x2b400000,
0xffc00000, "fst.s", "f0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x38300000,
0xffff8000, "fldx.s", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0x38380000,
0xffff8000, "fstx.s", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0x38740000,
0xffff8000, "fldgt.s", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0x38750000,
0xffff8000, "fldle.s", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0x38760000,
0xffff8000, "fstgt.s", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0x38770000,
0xffff8000, "fstle.s", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_double_float_load_store_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x2b800000,
0xffc00000, "fld.d", "f0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x2bc00000,
0xffc00000, "fst.d", "f0:5,r5:5,s10:12", 0, 0, 0, 0 },
-+ { 0x38340000,
0xffff8000, "fldx.d", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0x383c0000,
0xffff8000, "fstx.d", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0x38748000,
0xffff8000, "fldgt.d", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0x38758000,
0xffff8000, "fldle.d", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0x38768000,
0xffff8000, "fstgt.d", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0x38778000,
0xffff8000, "fstle.d", "f0:5,r5:5,r10:5", 0, &LARCH_opts.ase_lp64, 0, 0
},
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_float_jmp_opcodes[] =
-+{
-+ { 0x0, 0x0, "bceqz", "c,la", "bceqz
%1,%%b21(%2)", 0, 0, 0 },
-+ { 0x48000000,
0xfc000300, "bceqz", "c5:3,sb0:5|10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bcnez", "c,la", "bcnez
%1,%%b21(%2)", 0, 0, 0 },
-+ { 0x48000100,
0xfc000300, "bcnez", "c5:3,sb0:5|10:16<<2", 0, 0, 0, 0 },
-+ { 0 } /* Terminate the list. */
-+};
-+
-+static struct loongarch_opcode loongarch_jmp_opcodes[] =
-+{
-+ /* match, mask, name, format, macro, include, exclude, pinfo. */
-+ { 0x0, 0x0, "bltz", "r,la", "bltz
%1,%%b16(%2)", 0, 0, 0 },
-+ { 0x60000000,
0xfc00001f, "bltz", "r5:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bgtz", "r,la", "bgtz
%1,%%b16(%2)", 0, 0, 0 },
-+ { 0x60000000,
0xfc0003e0, "bgtz", "r0:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bgez", "r,la", "bgez
%1,%%b16(%2)", 0, 0, 0 },
-+ { 0x64000000,
0xfc00001f, "bgez", "r5:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "blez", "r,la", "blez
%1,%%b16(%2)", 0, 0, 0 },
-+ { 0x64000000,
0xfc0003e0, "blez", "r0:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "beqz", "r,la", "beqz
%1,%%b21(%2)", 0, 0, 0 },
-+ { 0x40000000,
0xfc000000, "beqz", "r5:5,sb0:5|10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bnez", "r,la", "bnez
%1,%%b21(%2)", 0, 0, 0 },
-+ { 0x44000000,
0xfc000000, "bnez", "r5:5,sb0:5|10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "jr", "r", "jirl $r0,%1,0", 0, 0, 0
},
-+ { 0x50000000, 0xfc000000, "b", "sb0:10|10:16<<2", 0, 0,
0, 0 },
-+ { 0x0, 0x0, "b", "la", "b %%b26(%1)", 0, 0, 0 },
-+ { 0x4c000000,
0xfc000000, "jirl", "r0:5,r5:5,s10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bl", "la", "bl %%b26(%1)", 0, 0, 0
},
-+ { 0x54000000,
0xfc000000, "bl", "sb0:10|10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "beq", "r,r,la", "beq
%1,%2,%%b16(%3)", 0, 0, 0 },
-+ { 0x58000000,
0xfc000000, "beq", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bne", "r,r,la", "bne
%1,%2,%%b16(%3)", 0, 0, 0 },
-+ { 0x5c000000,
0xfc000000, "bne", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "blt", "r,r,la", "blt
%1,%2,%%b16(%3)", 0, 0, 0 },
-+ { 0x60000000,
0xfc000000, "blt", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bgt", "r,r,la", "bgt
%1,%2,%%b16(%3)", 0, 0, 0 },
-+ { 0x60000000,
0xfc000000, "bgt", "r0:5,r5:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bge", "r,r,la", "bge
%1,%2,%%b16(%3)", 0, 0, 0 },
-+ { 0x64000000,
0xfc000000, "bge", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "ble", "r,r,la", "ble
%1,%2,%%b16(%3)", 0, 0, 0 },
-+ { 0x64000000,
0xfc000000, "ble", "r0:5,r5:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bltu", "r,r,la", "bltu
%1,%2,%%b16(%3)", 0, 0, 0 },
-+ { 0x68000000,
0xfc000000, "bltu", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bgtu", "r,r,la", "bgtu
%1,%2,%%b16(%3)", 0, 0, 0 },
-+ { 0x68000000,
0xfc000000, "bgtu", "r0:5,r5:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bgeu", "r,r,la", "bgeu
%1,%2,%%b16(%3)", 0, 0, 0 },
-+ { 0x6c000000,
0xfc000000, "bgeu", "r5:5,r0:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0x0, 0x0, "bleu", "r,r,la", "bleu
%1,%2,%%b16(%3)", 0, 0, 0 },
-+ { 0x6c000000,
0xfc000000, "bleu", "r0:5,r5:5,sb10:16<<2", 0, 0, 0, 0 },
-+ { 0 } /* Terminate the list. */
-+};
-+
-+struct loongarch_ase loongarch_ASEs[] =
-+{
-+ { &LARCH_opts.ase_ilp32, loongarch_macro_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_ilp32, loongarch_imm_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_ilp32, loongarch_privilege_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_ilp32, loongarch_load_store_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_ilp32, loongarch_fix_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_ilp32, loongarch_jmp_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_sf, loongarch_float_jmp_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_sf, loongarch_single_float_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_df, loongarch_double_float_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_sf, loongarch_4opt_single_float_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_df, loongarch_4opt_double_float_opcodes, 0, 0, { 0 }, 0, 0 },
-+ { &LARCH_opts.ase_sf, loongarch_single_float_load_store_opcodes, 0, 0, { 0 }, 0, 0
},
-+ { &LARCH_opts.ase_df, loongarch_double_float_load_store_opcodes, 0, 0, { 0 }, 0, 0
},
-+ { 0 },
-+};
---- gdb-10.2/opcodes/po/POTFILES.in.orig
-+++ gdb-10.2/opcodes/po/POTFILES.in
-@@ -108,6 +108,9 @@ lm32-ibld.c
- lm32-opc.c
- lm32-opc.h
- lm32-opinst.c
-+loongarch-coder.c
-+loongarch-dis.c
-+loongarch-opc.c
- m10200-dis.c
- m10200-opc.c
- m10300-dis.c
---- gdb-10.2/gdb/loongarch-linux-tdep.c.orig
-+++ gdb-10.2/gdb/loongarch-linux-tdep.c
-@@ -707,3 +707,30 @@ _initialize_loongarch_linux_tdep ()
- gdbarch_register_osabi (bfd_arch_loongarch, bfd_mach_loongarch64,
- GDB_OSABI_LINUX, loongarch_linux_init_abi);
- }
-+
-+/* Wrapper functions. These are only used by libthread_db. */
-+#include <sys/procfs.h>
-+extern void supply_gregset (struct regcache *regcache,const prgregset_t *gregset);
-+extern void fill_gregset (const struct regcache *regcache, prgregset_t *gregset, int
regno);
-+extern void supply_fpregset (struct regcache *regcache, const prfpregset_t *fpregset);
-+extern void fill_fpregset (const struct regcache *regcache, prfpregset_t *fpregset, int
regno);
-+
-+void supply_gregset (struct regcache *regcache, const prgregset_t *gregset)
-+{
-+ loongarch_elf_gregset.supply_regset (NULL, regcache, -1, gregset, sizeof
(prgregset_t));
-+}
-+
-+void fill_gregset (const struct regcache *regcache, prgregset_t *gregset, int regno)
-+{
-+ loongarch_elf_gregset.collect_regset (NULL, regcache, regno, gregset, sizeof
(prgregset_t));
-+}
-+
-+void supply_fpregset (struct regcache *regcache, const prfpregset_t *fpregset)
-+{
-+ loongarch_elf_fpregset.supply_regset (NULL, regcache, -1, fpregset, sizeof
(prfpregset_t));
-+}
-+
-+void fill_fpregset (const struct regcache *regcache, prfpregset_t *fpregset, int regno)
-+{
-+ loongarch_elf_fpregset.collect_regset (NULL, regcache, regno, fpregset, sizeof
(prfpregset_t));
-+}
--- gdb-10.2/gdb/minsyms.c.orig
+++ gdb-10.2/gdb/minsyms.c
@@ -535,7 +535,9 @@ lookup_minimal_symbol_linkage (const char *name, struct objfile
*objf)
--
2.47.0