From 1e41fa1f5615510b14fe8bccb8a2786d0034080c Mon Sep 17 00:00:00 2001 From: Bo Ren Date: Tue, 27 Dec 2022 13:23:57 +0800 Subject: [PATCH 1/5] update to binutils-2.30-117.el8 Signed-off-by: Bo Ren --- 0001-binutils-anolis-rebrand.patch | 241 - binutils-aarch64-rng.patch | 82 + binutils-coffgen-buffer-overrun.patch | 14 + binutils-loongarch-support.patch | 10198 ------------------------ binutils-s390-z16.patch | 53 + binutils-verdef.patch | 12 + binutils.spec | 57 +- dist | 1 + 8 files changed, 194 insertions(+), 10464 deletions(-) delete mode 100644 0001-binutils-anolis-rebrand.patch create mode 100644 binutils-aarch64-rng.patch create mode 100644 binutils-coffgen-buffer-overrun.patch delete mode 100644 binutils-loongarch-support.patch create mode 100644 binutils-s390-z16.patch create mode 100644 binutils-verdef.patch create mode 100644 dist diff --git a/0001-binutils-anolis-rebrand.patch b/0001-binutils-anolis-rebrand.patch deleted file mode 100644 index 0b71807..0000000 --- a/0001-binutils-anolis-rebrand.patch +++ /dev/null @@ -1,241 +0,0 @@ -From e784eaaa48e00d5ba8da5c74a57459c662c078f6 Mon Sep 17 00:00:00 2001 -From: xuehaolin -Date: Sun, 24 Jan 2021 10:55:25 +0800 -Subject: [PATCH] rebrand - ---- - bfd/elf32-rx.c | 2 +- - bfd/po/da.po | 4 ++-- - bfd/po/es.po | 4 ++-- - bfd/po/fi.po | 4 ++-- - bfd/po/fr.po | 4 ++-- - bfd/po/hr.po | 2 +- - bfd/po/id.po | 4 ++-- - bfd/po/ja.po | 4 ++-- - bfd/po/ru.po | 4 ++-- - bfd/po/sr.po | 2 +- - bfd/po/sv.po | 4 ++-- - bfd/po/uk.po | 4 ++-- - bfd/po/vi.po | 4 ++-- - bfd/po/zh_CN.po | 2 +- - zlib/contrib/minizip/configure.ac | 2 +- - 15 files changed, 25 insertions(+), 25 deletions(-) - -diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c -index a0e1f782..559a9d2a 100644 ---- a/bfd/elf32-rx.c -+++ b/bfd/elf32-rx.c -@@ -665,7 +665,7 @@ rx_elf_relocate_section - #define OP(i) (contents[rel->r_offset + (i)]) - #define WARN_REDHAT(type) \ - /* xgettext:c-format */ \ -- _bfd_error_handler (_("%B:%A: Warning: deprecated Red Hat reloc " type " detected against: %s."), \ -+ _bfd_error_handler (_("%B:%A: Warning: deprecated Anolis reloc " type " detected against: %s."), \ - input_bfd, input_section, name) - - /* Check for unsafe relocs in PID mode. These are any relocs where -diff --git a/bfd/po/da.po b/bfd/po/da.po -index add4ce42..2ce40ff2 100644 ---- a/bfd/po/da.po -+++ b/bfd/po/da.po -@@ -2345,8 +2345,8 @@ msgid " [G10]" - msgstr " [G10]" - - #: elf32-rx.c:563 --msgid "%B:%A: Warning: deprecated Red Hat reloc " --msgstr "%B:%A: Advarsel: forældet Red Hat-relokering " -+msgid "%B:%A: Warning: deprecated Anolis reloc " -+msgstr "%B:%A: Advarsel: forældet Anolis-relokering " - - #. Check for unsafe relocs in PID mode. These are any relocs where - #. an absolute address is being computed. There are special cases -diff --git a/bfd/po/es.po b/bfd/po/es.po -index 73e12b5b..742b11f6 100644 ---- a/bfd/po/es.po -+++ b/bfd/po/es.po -@@ -2023,8 +2023,8 @@ msgid "%P: %s not defined in linker created %s\n" - msgstr "%P: no se definió %s en el %s creado por el enlazador\n" - - #: elf32-rx.c:563 --msgid "%B:%A: Warning: deprecated Red Hat reloc " --msgstr "%B:%A: Aviso: reubicación Red Hat obsoleta" -+msgid "%B:%A: Warning: deprecated Anolis reloc " -+msgstr "%B:%A: Aviso: reubicación Anolis obsoleta" - - #. Check for unsafe relocs in PID mode. These are any relocs where - #. an absolute address is being computed. There are special cases -diff --git a/bfd/po/fi.po b/bfd/po/fi.po -index 14752f46..9165fd4a 100644 ---- a/bfd/po/fi.po -+++ b/bfd/po/fi.po -@@ -2330,8 +2330,8 @@ msgid " [G10]" - msgstr " [G10]" - - #: elf32-rx.c:563 --msgid "%B:%A: Warning: deprecated Red Hat reloc " --msgstr "%B:%A: Varoitus: vanhentunut Red Hat reloc -tietue " -+msgid "%B:%A: Warning: deprecated Anolis reloc " -+msgstr "%B:%A: Varoitus: vanhentunut Anolis reloc -tietue " - - #. Check for unsafe relocs in PID mode. These are any relocs where - #. an absolute address is being computed. There are special cases -diff --git a/bfd/po/fr.po b/bfd/po/fr.po -index dc26e566..b339dba8 100644 ---- a/bfd/po/fr.po -+++ b/bfd/po/fr.po -@@ -3303,8 +3303,8 @@ msgstr "%B:%A: l'entrée %s de la table n'est pas alignée sur un mot dans la ta - - #: elf32-rx.c:668 - #, c-format --msgid "%B:%A: Warning: deprecated Red Hat reloc " --msgstr "%B:%A: Attention: réadressage Red Hat réprouvée " -+msgid "%B:%A: Warning: deprecated Anolis reloc " -+msgstr "%B:%A: Attention: réadressage Anolis réprouvée " - - #. Check for unsafe relocs in PID mode. These are any relocs where - #. an absolute address is being computed. There are special cases -diff --git a/bfd/po/hr.po b/bfd/po/hr.po -index 66723aec..d57da036 100644 ---- a/bfd/po/hr.po -+++ b/bfd/po/hr.po -@@ -1981,7 +1981,7 @@ msgid "%P: %s not defined in linker created %s\n" - msgstr "" - - #: elf32-rx.c:563 --msgid "%B:%A: Warning: deprecated Red Hat reloc " -+msgid "%B:%A: Warning: deprecated Anolis reloc " - msgstr "" - - #. Check for unsafe relocs in PID mode. These are any relocs where -diff --git a/bfd/po/id.po b/bfd/po/id.po -index b0acde81..147026a0 100644 ---- a/bfd/po/id.po -+++ b/bfd/po/id.po -@@ -2022,8 +2022,8 @@ msgid "%P: %s not defined in linker created %s\n" - msgstr "%P: %s tidak didefinisikan dalam penyambung dibuat oleh %s\n" - - #: elf32-rx.c:563 --msgid "%B:%A: Warning: deprecated Red Hat reloc " --msgstr "%B:%A: Peringatan: tertinggal Red Hat relokasi" -+msgid "%B:%A: Warning: deprecated Anolis reloc " -+msgstr "%B:%A: Peringatan: tertinggal Anolis relokasi" - - #. Check for unsafe relocs in PID mode. These are any relocs where - #. an absolute address is being computed. There are special cases -diff --git a/bfd/po/ja.po b/bfd/po/ja.po -index da371dcc..9a8e4b8e 100644 ---- a/bfd/po/ja.po -+++ b/bfd/po/ja.po -@@ -2019,8 +2019,8 @@ msgid "%s not defined in linker created %s\n" - msgstr "%s はリンカが作成した %s 内では定義されていません\n" - - #: elf32-rx.c:553 --msgid "%B:%A: Warning: deprecated Red Hat reloc " --msgstr "%B:%A: 警告: 廃止された Red Hat 再配置です " -+msgid "%B:%A: Warning: deprecated Anolis reloc " -+msgstr "%B:%A: 警告: 廃止された Anolis 再配置です " - - #: elf32-rx.c:1095 - msgid "Warning: RX_SYM reloc with an unknown symbol" -diff --git a/bfd/po/ru.po b/bfd/po/ru.po -index 194011d4..f54e6730 100644 ---- a/bfd/po/ru.po -+++ b/bfd/po/ru.po -@@ -3298,8 +3298,8 @@ msgstr "%B:%A: элемент таблицы %s не выровнен в таб - - #: elf32-rx.c:668 - #, c-format --msgid "%B:%A: Warning: deprecated Red Hat reloc " --msgstr "%B:%A: предупреждение: устаревшее перемещение Red Hat " -+msgid "%B:%A: Warning: deprecated Anolis reloc " -+msgstr "%B:%A: предупреждение: устаревшее перемещение Anolis " - - #. Check for unsafe relocs in PID mode. These are any relocs where - #. an absolute address is being computed. There are special cases -diff --git a/bfd/po/sr.po b/bfd/po/sr.po -index c0e8a24f..72b11ee9 100644 ---- a/bfd/po/sr.po -+++ b/bfd/po/sr.po -@@ -2302,7 +2302,7 @@ msgid " [G10]" - msgstr " [Г10]" - - #: elf32-rx.c:563 --msgid "%B:%A: Warning: deprecated Red Hat reloc " -+msgid "%B:%A: Warning: deprecated Anolis reloc " - msgstr "%B:%A: Упозорење: застарело премештање Ред Хета " - - #. Check for unsafe relocs in PID mode. These are any relocs where -diff --git a/bfd/po/sv.po b/bfd/po/sv.po -index 7213fe22..638915c3 100644 ---- a/bfd/po/sv.po -+++ b/bfd/po/sv.po -@@ -2306,8 +2306,8 @@ msgid " [G10]" - msgstr " [G10]" - - #: elf32-rx.c:563 --msgid "%B:%A: Warning: deprecated Red Hat reloc " --msgstr "%B:%A: Varning: föråldrad Red Hat-omlokalisering " -+msgid "%B:%A: Warning: deprecated Anolis reloc " -+msgstr "%B:%A: Varning: föråldrad Anolis-omlokalisering " - - #. Check for unsafe relocs in PID mode. These are any relocs where - #. an absolute address is being computed. There are special cases -diff --git a/bfd/po/uk.po b/bfd/po/uk.po -index 437d767a..dc4596a7 100644 ---- a/bfd/po/uk.po -+++ b/bfd/po/uk.po -@@ -3300,8 +3300,8 @@ msgstr "%B:%A: запис таблиці %s не вирівняно на меж - - #: elf32-rx.c:668 - #, c-format --msgid "%B:%A: Warning: deprecated Red Hat reloc " --msgstr "%B:%A: попередження: застарілий формат пересування Red Hat " -+msgid "%B:%A: Warning: deprecated Anolis reloc " -+msgstr "%B:%A: попередження: застарілий формат пересування Anolis " - - #. Check for unsafe relocs in PID mode. These are any relocs where - #. an absolute address is being computed. There are special cases -diff --git a/bfd/po/vi.po b/bfd/po/vi.po -index 79a6622f..93ef7bd4 100644 ---- a/bfd/po/vi.po -+++ b/bfd/po/vi.po -@@ -2027,8 +2027,8 @@ msgid "%P: %s not defined in linker created %s\n" - msgstr "%P: %s chưa được định nghĩa trong bộ liên kết đã tạo ra %s\n" - - #: elf32-rx.c:563 --msgid "%B:%A: Warning: deprecated Red Hat reloc " --msgstr "%B:%A: Cảnh báo: không tán thành reloc kiểu Red Hat" -+msgid "%B:%A: Warning: deprecated Anolis reloc " -+msgstr "%B:%A: Cảnh báo: không tán thành reloc kiểu Anolis" - - #. Check for unsafe relocs in PID mode. These are any relocs where - #. an absolute address is being computed. There are special cases -diff --git a/bfd/po/zh_CN.po b/bfd/po/zh_CN.po -index 882b3cc2..e702d7f1 100644 ---- a/bfd/po/zh_CN.po -+++ b/bfd/po/zh_CN.po -@@ -2406,7 +2406,7 @@ msgstr "" - - #: elf32-rx.c:563 - #, fuzzy --msgid "%B:%A: Warning: deprecated Red Hat reloc " -+msgid "%B:%A: Warning: deprecated Anolis reloc " - msgstr "%s:0x%lx:警告:无法找到预期的重定位" - - #. Check for unsafe relocs in PID mode. These are any relocs where -diff --git a/zlib/contrib/minizip/configure.ac b/zlib/contrib/minizip/configure.ac -index 5b119709..3d43339d 100644 ---- a/zlib/contrib/minizip/configure.ac -+++ b/zlib/contrib/minizip/configure.ac -@@ -1,7 +1,7 @@ - # -*- Autoconf -*- - # Process this file with autoconf to produce a configure script. - --AC_INIT([minizip], [1.2.11], [bugzilla.redhat.com]) -+AC_INIT([minizip], [1.2.11], [https://bugzilla.openanolis.cn]) - AC_CONFIG_SRCDIR([minizip.c]) - AM_INIT_AUTOMAKE([foreign]) - LT_INIT --- -2.18.4 - diff --git a/binutils-aarch64-rng.patch b/binutils-aarch64-rng.patch new file mode 100644 index 0000000..d560203 --- /dev/null +++ b/binutils-aarch64-rng.patch @@ -0,0 +1,82 @@ +diff -rup binutils.orig/gas/config/tc-aarch64.c binutils-2.30/gas/config/tc-aarch64.c +--- binutils.orig/gas/config/tc-aarch64.c 2022-04-05 10:30:32.735881142 +0100 ++++ binutils-2.30/gas/config/tc-aarch64.c 2022-04-05 10:31:28.198694747 +0100 +@@ -8553,6 +8553,8 @@ static const struct aarch64_option_cpu_v + {"sha3", AARCH64_FEATURE (AARCH64_FEATURE_SHA2 + | AARCH64_FEATURE_SHA3, 0), + AARCH64_ARCH_NONE}, ++ {"rng", AARCH64_FEATURE (AARCH64_FEATURE_RNG, 0), ++ AARCH64_ARCH_NONE}, + {NULL, AARCH64_ARCH_NONE, AARCH64_ARCH_NONE}, + }; + +diff -rup binutils.orig/gas/doc/c-aarch64.texi binutils-2.30/gas/doc/c-aarch64.texi +--- binutils.orig/gas/doc/c-aarch64.texi 2022-04-05 10:30:32.735881142 +0100 ++++ binutils-2.30/gas/doc/c-aarch64.texi 2022-04-05 10:32:35.814423321 +0100 +@@ -179,6 +179,8 @@ automatically cause those extensions to + @item @code{fp16fml} @tab ARMv8.2-A @tab ARMv8.4-A or later + @tab Enable ARMv8.2 16-bit floating-point multiplication variant support. + This implies @code{fp16}. ++@item @code{rng} @tab ARMv8.5-A @tab No ++ @tab Enable ARMv8.5-A random number instructions. + @end multitable + + @node AArch64 Syntax +Only in binutils-2.30/gas/testsuite/gas/aarch64: rng-1.d +Only in binutils-2.30/gas/testsuite/gas/aarch64: rng-1.s +diff -rup binutils.orig/include/opcode/aarch64.h binutils-2.30/include/opcode/aarch64.h +--- binutils.orig/include/opcode/aarch64.h 2022-04-05 10:30:33.256879707 +0100 ++++ binutils-2.30/include/opcode/aarch64.h 2022-04-05 10:42:30.241087320 +0100 +@@ -62,6 +62,7 @@ typedef uint32_t aarch64_insn; + #define AARCH64_FEATURE_COMPNUM 0x40000000 /* Complex # instructions. */ + #define AARCH64_FEATURE_DOTPROD 0x080000000 /* Dot Product instructions. */ + #define AARCH64_FEATURE_F16_FML 0x1000000000ULL /* v8.2 FP16FML ins. */ ++#define AARCH64_FEATURE_RNG 0x80000000000ULL /* Random Number instructions. */ + + /* Architectures are the sum of the base and extensions. */ + #define AARCH64_ARCH_V8 AARCH64_FEATURE (AARCH64_FEATURE_V8, \ +diff -rup binutils.orig/opcodes/aarch64-opc.c binutils-2.30/opcodes/aarch64-opc.c +--- binutils.orig/opcodes/aarch64-opc.c 2022-04-05 10:30:33.019880360 +0100 ++++ binutils-2.30/opcodes/aarch64-opc.c 2022-04-05 10:58:07.179526356 +0100 +@@ -3823,6 +3823,8 @@ const aarch64_sys_reg aarch64_sys_regs [ + { "contextidr_el1", CPENC(3,0,C13,C0,1), 0 }, + { "contextidr_el2", CPENC (3, 4, C13, C0, 1), F_ARCHEXT }, + { "contextidr_el12", CPENC (3, 5, C13, C0, 1), F_ARCHEXT }, ++ { "rndr", CPENC(3,3,C2,C4,0), F_ARCHEXT }, /* RO */ ++ { "rndrrs", CPENC(3,3,C2,C4,1), F_ARCHEXT }, /* RO */ + { "tpidr_el0", CPENC(3,3,C13,C0,2), 0 }, + { "tpidrro_el0", CPENC(3,3,C13,C0,3), 0 }, /* RO */ + { "tpidr_el1", CPENC(3,0,C13,C0,4), 0 }, +@@ -4254,6 +4256,13 @@ aarch64_sys_reg_supported_p (const aarch + && !AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_V8_4)) + return FALSE; + ++ /* Random Number Instructions. For now they are available ++ (and optional) only with ARMv8.5-A. */ ++ if (( reg->value == CPENC (3, 3, C2, C4, 0) ++ || reg->value == CPENC (3, 3, C2, C4, 1)) ++ && !(AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_RNG))) ++ return FALSE; ++ + return TRUE; + } + +--- /dev/null 2022-04-05 09:32:54.900867346 +0100 ++++ binutils-2.30/gas/testsuite/gas/aarch64/rng-1.s 2022-04-05 10:36:04.921589937 +0100 +@@ -0,0 +1,3 @@ ++ .arch armv8.4-a+rng ++ mrs x5, rndr ++ mrs x6, rndrrs +--- /dev/null 2022-04-05 09:32:54.900867346 +0100 ++++ binutils-2.30/gas/testsuite/gas/aarch64/rng-1.d 2022-04-05 10:35:48.937653638 +0100 +@@ -0,0 +1,10 @@ ++#source: rng-1.s ++#objdump: -dr ++ ++.*: file format .* ++ ++Disassembly of section \.text: ++ ++0+ <.*>: ++.*: d53b2405 mrs x5, rndr ++.*: d53b2426 mrs x6, rndrrs diff --git a/binutils-coffgen-buffer-overrun.patch b/binutils-coffgen-buffer-overrun.patch new file mode 100644 index 0000000..88f46c7 --- /dev/null +++ b/binutils-coffgen-buffer-overrun.patch @@ -0,0 +1,14 @@ +--- binutils.orig/bfd/coffgen.c 2022-04-25 13:43:52.724745386 +0100 ++++ binutils-2.30/bfd/coffgen.c 2022-04-25 13:46:39.583596137 +0100 +@@ -1838,10 +1838,7 @@ coff_get_normalized_symtab (bfd *abfd) + internal_ptr->is_sym = TRUE; + + /* PR 17512: file: 1353-1166-0.004. */ +- if (symbol_ptr->u.syment.n_sclass == C_FILE +- && symbol_ptr->u.syment.n_numaux > 0 +- && raw_src + symesz + symbol_ptr->u.syment.n_numaux +- * symesz > raw_end) ++ if (symbol_ptr->u.syment.n_numaux > ((raw_end - 1) - raw_src) / symesz) + { + bfd_release (abfd, internal); + return NULL; diff --git a/binutils-loongarch-support.patch b/binutils-loongarch-support.patch deleted file mode 100644 index 03c8b96..0000000 --- a/binutils-loongarch-support.patch +++ /dev/null @@ -1,10198 +0,0 @@ -From 1f16c64c08b59b8901fd2477a13de69b9376ba39 Mon Sep 17 00:00:00 2001 -From: Li Xing -Date: Thu, 23 Jun 2022 11:18:20 +0800 -Subject: [PATCH] binutils loongarch support - -Signed-off-by: Li Xing -Signed-off-by: Junchao Zhao ---- - bfd/Makefile.am | 17 + - bfd/Makefile.in | 23 + - bfd/archures.c | 5 + - bfd/bfd-in2.h | 48 + - bfd/config.bfd | 15 + - bfd/configure | 2 + - bfd/configure.ac | 2 + - bfd/cpu-loongarch.c | 38 + - bfd/elf-bfd.h | 9 + - bfd/elf.c | 109 + - bfd/elfnn-loongarch.c | 3287 +++++++++++++++++++ - bfd/elfxx-loongarch.c | 172 + - bfd/elfxx-loongarch.h | 11 + - bfd/libbfd.h | 43 + - bfd/reloc.c | 89 + - bfd/targets.c | 7 + - binutils/readelf.c | 30 + - binutils/testsuite/binutils-all/objdump.exp | 4 +- - gas/Makefile.am | 26 +- - gas/Makefile.in | 55 +- - gas/config/loongarch-lex-wrapper.c | 25 + - gas/config/loongarch-lex.l | 39 + - gas/config/loongarch-parse.y | 420 +++ - gas/config/tc-loongarch.c | 1328 ++++++++ - gas/config/tc-loongarch.h | 77 + - gas/configure | 14 +- - gas/configure.ac | 9 + - gas/configure.tgt | 5 +- - include/dis-asm.h | 1 + - include/elf/common.h | 9 + - include/elf/loongarch.h | 95 + - include/opcode/loongarch.h | 215 ++ - ld/Makefile.am | 6 + - ld/Makefile.in | 18 + - ld/configure.tgt | 2 + - ld/emulparams/elf64loongarch-defs.sh | 39 + - ld/emulparams/elf64loongarch.sh | 15 + - ld/emultempl/loongarchelf.em | 90 + - opcodes/Makefile.am | 3 + - opcodes/Makefile.in | 6 + - opcodes/configure | 1 + - opcodes/configure.ac | 1 + - opcodes/disassemble.c | 9 + - opcodes/disassemble.h | 1 + - opcodes/loongarch-coder.c | 446 +++ - opcodes/loongarch-dis.c | 311 ++ - opcodes/loongarch-opc.c | 2128 ++++++++++++ - 47 files changed, 9299 insertions(+), 6 deletions(-) - create mode 100644 bfd/cpu-loongarch.c - create mode 100644 bfd/elfnn-loongarch.c - create mode 100644 bfd/elfxx-loongarch.c - create mode 100644 bfd/elfxx-loongarch.h - create mode 100644 gas/config/loongarch-lex-wrapper.c - create mode 100644 gas/config/loongarch-lex.l - create mode 100644 gas/config/loongarch-parse.y - create mode 100644 gas/config/tc-loongarch.c - create mode 100644 gas/config/tc-loongarch.h - create mode 100644 include/elf/loongarch.h - create mode 100644 include/opcode/loongarch.h - create mode 100644 ld/emulparams/elf64loongarch-defs.sh - create mode 100644 ld/emulparams/elf64loongarch.sh - create mode 100644 ld/emultempl/loongarchelf.em - create mode 100644 opcodes/loongarch-coder.c - create mode 100644 opcodes/loongarch-dis.c - create mode 100644 opcodes/loongarch-opc.c - -diff --git a/bfd/Makefile.am b/bfd/Makefile.am -index a7990571..9b08572a 100644 ---- a/bfd/Makefile.am -+++ b/bfd/Makefile.am -@@ -120,6 +120,7 @@ ALL_MACHINES = \ - cpu-ip2k.lo \ - cpu-iq2000.lo \ - cpu-lm32.lo \ -+ cpu-loongarch.lo \ - cpu-m10200.lo \ - cpu-m10300.lo \ - cpu-m32c.lo \ -@@ -211,6 +212,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 \ -@@ -690,6 +692,8 @@ BFD64_BACKENDS = \ - elf64-ia64.lo \ - elf64-ia64-vms.lo \ - elfxx-ia64.lo \ -+ elf32-loongarch.lo \ -+ elf64-loongarch.lo \ - elfn32-mips.lo \ - elf64-mips.lo \ - elfxx-mips.lo \ -@@ -812,6 +816,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 - -@@ -983,6 +988,18 @@ elf64-ia64.c : elfnn-ia64.c - $(SED) -e s/NN/64/g < $(srcdir)/elfnn-ia64.c > elf64-ia64.new - mv -f elf64-ia64.new elf64-ia64.c - -+elf32-loongarch.c : elfnn-loongarch.c -+ rm -f elf32-loongarch.c -+ echo "#line 1 \"$(srcdir)/elfnn-loongarch.c\"" > elf32-loongarch.new -+ sed -e s/NN/32/g < $(srcdir)/elfnn-loongarch.c >> elf32-loongarch.new -+ mv -f elf32-loongarch.new elf32-loongarch.c -+ -+elf64-loongarch.c : elfnn-loongarch.c -+ rm -f elf64-loongarch.c -+ echo "#line 1 \"$(srcdir)/elfnn-loongarch.c\"" > elf64-loongarch.new -+ sed -e s/NN/64/g < $(srcdir)/elfnn-loongarch.c >> elf64-loongarch.new -+ mv -f elf64-loongarch.new elf64-loongarch.c -+ - elf32-riscv.c : elfnn-riscv.c - rm -f elf32-riscv.c - echo "#line 1 \"$(srcdir)/elfnn-riscv.c\"" > elf32-riscv.new -diff --git a/bfd/Makefile.in b/bfd/Makefile.in -index 659a8d7b..d49f5b44 100644 ---- a/bfd/Makefile.in -+++ b/bfd/Makefile.in -@@ -454,6 +454,7 @@ ALL_MACHINES = \ - cpu-ip2k.lo \ - cpu-iq2000.lo \ - cpu-lm32.lo \ -+ cpu-loongarch.lo \ - cpu-m10200.lo \ - cpu-m10300.lo \ - cpu-m32c.lo \ -@@ -545,6 +546,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 \ -@@ -1017,6 +1019,9 @@ BFD64_BACKENDS = \ - coff64-rs6000.lo \ - demo64.lo \ - elf32-ia64.lo \ -+ elf32-loongarch.lo \ -+ elf64-loongarch.lo \ -+ elfxx-loongarch.lo \ - elf32-mips.lo \ - elf32-score.lo \ - elf32-score7.lo \ -@@ -1082,6 +1087,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 \ -@@ -1150,6 +1156,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 - -@@ -1414,6 +1421,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-k1om.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-l1om.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-lm32.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-loongarch.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m10200.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m10300.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m32c.Plo@am__quote@ -@@ -1515,6 +1523,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-ip2k.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-iq2000.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-lm32.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-loongarch.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m32c.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m32r.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m68hc11.Plo@am__quote@ -@@ -1566,6 +1575,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-hppa.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ia64-vms.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ia64.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-loongarch.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mips.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mmix.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-nfp.Plo@am__quote@ -@@ -1581,6 +1591,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfn32-mips.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-aarch64.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-ia64.Plo@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-loongarch.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-mips.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-riscv.Plo@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-sparc.Plo@am__quote@ -@@ -2122,6 +2133,18 @@ elf64-ia64.c : elfnn-ia64.c - $(SED) -e s/NN/64/g < $(srcdir)/elfnn-ia64.c > elf64-ia64.new - mv -f elf64-ia64.new elf64-ia64.c - -+elf32-loongarch.c : elfnn-loongarch.c -+ rm -f elf32-loongarch.c -+ echo "#line 1 \"$(srcdir)/elfnn-loongarch.c\"" > elf32-loongarch.new -+ sed -e s/NN/32/g < $(srcdir)/elfnn-loongarch.c >> elf32-loongarch.new -+ mv -f elf32-loongarch.new elf32-loongarch.c -+ -+elf64-loongarch.c : elfnn-loongarch.c -+ rm -f elf64-loongarch.c -+ echo "#line 1 \"$(srcdir)/elfnn-loongarch.c\"" > elf64-loongarch.new -+ sed -e s/NN/64/g < $(srcdir)/elfnn-loongarch.c >> elf64-loongarch.new -+ mv -f elf64-loongarch.new elf64-loongarch.c -+ - elf32-riscv.c : elfnn-riscv.c - rm -f elf32-riscv.c - echo "#line 1 \"$(srcdir)/elfnn-riscv.c\"" > elf32-riscv.new -diff --git a/bfd/archures.c b/bfd/archures.c -index a39925c7..efee3fc0 100644 ---- a/bfd/archures.c -+++ b/bfd/archures.c -@@ -540,6 +540,9 @@ DESCRIPTION - . bfd_arch_nfp, {* Netronome Flow Processor *} - .#define bfd_mach_nfp3200 0x3200 - .#define bfd_mach_nfp6000 0x6000 -+. bfd_arch_loongarch, {* Loongarch *} -+.#define bfd_mach_loongarch32 1 -+.#define bfd_mach_loongarch64 2 - . bfd_arch_last - . }; - */ -@@ -614,6 +617,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; -@@ -710,6 +714,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, -diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h -index e60bef9a..893af234 100644 ---- a/bfd/bfd-in2.h -+++ b/bfd/bfd-in2.h -@@ -2404,6 +2404,9 @@ enum bfd_architecture - bfd_arch_nfp, /* Netronome Flow Processor */ - #define bfd_mach_nfp3200 0x3200 - #define bfd_mach_nfp6000 0x6000 -+ bfd_arch_loongarch, /* LoongARCH */ -+#define bfd_mach_loongarch32 1 -+#define bfd_mach_loongarch64 2 - bfd_arch_last - }; - -@@ -6518,6 +6521,51 @@ assembler and not (currently) written to any object files. */ - BFD_RELOC_WASM32_CODE_POINTER, - BFD_RELOC_WASM32_INDEX, - BFD_RELOC_WASM32_PLT_SIG, -+ -+/* LoongISA 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_UNUSED }; - - typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; -diff --git a/bfd/config.bfd b/bfd/config.bfd -index cf02b010..eca16b52 100644 ---- a/bfd/config.bfd -+++ b/bfd/config.bfd -@@ -174,6 +174,7 @@ i[34567]86) targ_archs=bfd_i386_arch ;; - i370) targ_archs=bfd_i370_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 ;; -@@ -938,6 +939,20 @@ case "${targ}" in - targ_selvecs=lm32_elf32_vec - ;; - -+#ifdef BFD64 -+ loongarch32-*) -+ targ_defvec=loongarch_elf32_vec -+ targ_selvecs="loongarch_elf32_vec" -+ want64=false -+ ;; -+ -+ loongarch64-*) -+ targ_defvec=loongarch_elf64_vec -+ targ_selvecs="loongarch_elf32_vec loongarch_elf64_vec" -+ want64=true -+ ;; -+#endif -+ - m32c-*-elf | m32c-*-rtems*) - targ_defvec=m32c_elf32_vec - targ_underscore=yes -diff --git a/bfd/configure b/bfd/configure -index adc6cdf1..58ba9e8c 100755 ---- a/bfd/configure -+++ b/bfd/configure -@@ -14450,6 +14450,8 @@ do - l1om_elf64_fbsd_vec) tb="$tb elf64-x86-64.lo elfxx-x86.lo elf-ifunc.lo elf-nacl.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" ;; -+ loongarch_elf64_vec) tb="$tb elf64-loongarch.lo elf64.lo elfxx-loongarch.lo elf32.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" ;; -diff --git a/bfd/configure.ac b/bfd/configure.ac -index fa2e0ec0..a75c24b6 100644 ---- a/bfd/configure.ac -+++ b/bfd/configure.ac -@@ -508,6 +508,8 @@ do - l1om_elf64_fbsd_vec) tb="$tb elf64-x86-64.lo elfxx-x86.lo elf-ifunc.lo elf-nacl.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" ;; -diff --git a/bfd/cpu-loongarch.c b/bfd/cpu-loongarch.c -new file mode 100644 -index 00000000..c5579f29 ---- /dev/null -+++ b/bfd/cpu-loongarch.c -@@ -0,0 +1,38 @@ -+#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. */ -+ FALSE, /* 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. */ -+}; -+ -+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. */ -+ bfd_mach_loongarch64, /* Machine number of loongarch64 is larger so that loongarch64 is compatible to loongarch32 */ -+ "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. */ -+}; -+ -diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h -index 5b50ef2a..d941e19c 100644 ---- a/bfd/elf-bfd.h -+++ b/bfd/elf-bfd.h -@@ -497,6 +497,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, -@@ -2604,6 +2605,14 @@ extern char *elfcore_write_aarch_hw_break - (bfd *, char *, int *, const void *, int); - extern char *elfcore_write_aarch_hw_watch - (bfd *, char *, int *, 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); - extern char *elfcore_write_lwpstatus - (bfd *, char *, int *, long, int, const void *); - extern char *elfcore_write_register_note -diff --git a/bfd/elf.c b/bfd/elf.c -index ef2c7df0..8e0eb731 100644 ---- a/bfd/elf.c -+++ b/bfd/elf.c -@@ -9421,6 +9421,30 @@ elfcore_grok_aarch_hw_watch (bfd *abfd, Elf_Internal_Note *note) - return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-watch", 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 */ -@@ -9917,6 +9941,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) -@@ -11100,6 +11152,55 @@ elfcore_write_aarch_hw_watch (bfd *abfd, - note_name, NT_ARM_HW_WATCH, aarch_hw_watch, 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, -@@ -11152,6 +11253,14 @@ elfcore_write_register_note (bfd *abfd, - return elfcore_write_aarch_hw_break (abfd, buf, bufsiz, data, size); - if (strcmp (section, ".reg-aarch-hw-watch") == 0) - return elfcore_write_aarch_hw_watch (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; - } - -diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c -new file mode 100644 -index 00000000..f609a756 ---- /dev/null -+++ b/bfd/elfnn-loongarch.c -@@ -0,0 +1,3287 @@ -+#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 ATTRIBUTE_UNUSED, -+ arelent *cache_ptr, -+ Elf_Internal_Rela *dst) -+{ -+ cache_ptr->howto = loongarch_elf_rtype_to_howto (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; -+ -+ /* Track dynamic relocs copied for this symbol. */ -+ struct elf_dyn_relocs *dyn_relocs; -+ -+#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; -+ -+ /* 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 ((struct elf_link_hash_table *) ((p)->hash)) \ -+ == 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) -+ -+/* .got.plt的前两项预留。我们约定: -+ 第一项在运行时被动态连接器填入_dl_runtime_resolve的地址 -+ 第二项在连接时,非0指plt header的地址(在no-pic下或prelink)。 -+ 第二项在运行时被动态连接器填入本模块的struct link_map实例的地址。 -+ 详见$glibc/sysdeps/loongarch/dl-machine.h中的elf_machine_runtime_setup */ -+#define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2) -+ -+/* .got和.got.plt不合并的好处是,.got.plt和.plt的entry是顺序对应的。 -+ 设法使得stub的size为2的幂,知道.plt和stub的地址就知道了index。 */ -+#define elf_backend_want_got_plt 1 -+ -+#define elf_backend_plt_readonly 1 -+ -+#define elf_backend_want_plt_sym 0 -+/* 1. 本来想着定义_PROCEDURE_LINKAGE_TABLE_,多了不嫌多。 -+ 2. 但实际上,这个符号会使得GDB调试ifunc函数失效。因为lazy-bind的情况下, -+ plt GOT entry中的地址都指向这个符号;GDB读取plt GOT entry来确定ifunc的 -+ 目标函数,从而以为_PROCEDURE_LINKAGE_TABLE_就是ifunc的目标函数(好奇的人 -+ 可以把断点打在elf_gnu_ifunc_record_cache上面看一下GDB的行为,总之是校验从 -+ GOT entry中拿到的地址,结果发现 'BMSYMBOL_VALUE_ADDRESS (msym) == addr' -+ 为真),然后直接跳转到plt header上面了,这当然不行。 -+ 3. 我们期望,调用ifunc函数时,要么跳到对应的plt stub上;要么GDB运行一遍 -+ resolver得到ifunc目标函数的地址后再调用(这是GDB公共代码的做法)。 -+ 4. 观察了aarch64的做法,发现他们就没_PROCEDURE_LINKAGE_TABLE_, -+ 就不存在msym.minsym,然后认为从GOT entry读ifunc目标函数失败直接退出了。 -+ 5. 我想了想,_PROCEDURE_LINKAGE_TABLE_的存在没有意义,因为对plt stub -+ 的处理是有重定位R_LARCH_SOP_PUSH_PLT_PCREL由静态连接器一手操办。 -+ 所以就把_PROCEDURE_LINKAGE_TABLE_去了吧。 */ -+#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 -+ -+/* .got的第一项预留。我们约定.got的第一项为.dynamic的连接时地址(如果有) */ -+#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 void -+loongarch_make_plt_header (bfd_vma got_plt_addr, -+ bfd_vma plt_header_addr, -+ uint32_t *entry) -+{ -+ int64_t pcrel = got_plt_addr - plt_header_addr; -+ int64_t hi = (pcrel & 0x800? 1 : 0) + (pcrel >> 12); -+ int64_t lo = pcrel & 0xfff; -+ if ((hi >> 19) != 0 && (hi >> 19) != -1) -+ abort ();//overflow -+ -+ /* 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) + 4 -+ 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) + 4) & 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; -+ } -+} -+ -+/* Generate a PLT entry. */ -+ -+static void -+loongarch_make_plt_entry (bfd_vma got_plt_entry_addr, -+ bfd_vma plt_entry_addr, -+ uint32_t *entry) -+{ -+ int64_t pcrel = got_plt_entry_addr - plt_entry_addr; -+ int64_t hi = (pcrel & 0x800? 1 : 0) + (pcrel >> 12); -+ int64_t lo = pcrel & 0xfff; -+ if ((hi >> 19) != 0 && (hi >> 19) != -1) -+ abort ();//overflow -+ -+ /* pcaddu12i $t3, %hi(%pcrel(.got.plt entry)) -+ ld.[wd] $t3, $t3, %lo(%pcrel(.got.plt entry)) -+ jirl $t1, $t3, 0 -+ addi $r0, $r0, 0 */ -+ -+ 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 */ -+ //entry[2] = 0x1800002d; /* pcaddi $13, 4 */ -+ entry[2] = 0x1c00000d; /* pcaddu12i $13, 4 */ -+ entry[3] = 0x4c0001e0; /* jirl $r0, $15, 0 */ -+} -+ -+/* 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) -+{ -+ /* Allocate the structure if it has not already been allocated by a -+ subclass. */ -+ if (entry == NULL) -+ { -+ entry = bfd_hash_allocate -+ (table, sizeof (struct loongarch_elf_link_hash_entry)); -+ if (entry == NULL) -+ return entry; -+ } -+ -+ /* Call the allocation method of the superclass. */ -+ entry = _bfd_elf_link_hash_newfunc (entry, table, string); -+ if (entry != NULL) -+ { -+ struct loongarch_elf_link_hash_entry *eh; -+ -+ eh = (struct loongarch_elf_link_hash_entry *) entry; -+ eh->dyn_relocs = NULL; -+ 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 -+ = (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 -+_bfd_loongarch_elf_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)) -+ { -+ /* Make sure one of ibfd or obfd e_flags must be set. */ -+ /* FIXME: EF_LARCH_ABI_LP64 ? . */ -+ if (!is_loongarch_elf (ibfd) && !elf_flags_init (obfd)) -+ { -+ elf_flags_init (obfd) = TRUE; -+ elf_elfheader (obfd)->e_flags = EF_LARCH_ABI_LP64; -+ } -+ -+ if (!is_loongarch_elf (obfd) && !elf_flags_init (ibfd)) -+ { -+ elf_flags_init (ibfd) = TRUE; -+ elf_elfheader (ibfd)->e_flags = EF_LARCH_ABI_LP64; -+ } -+ -+ 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 (!elf_flags_init (obfd)) -+ { -+ elf_flags_init (obfd) = TRUE; -+ elf_elfheader (obfd)->e_flags = in_flags; -+ return TRUE; -+ } -+ -+ /* Disallow linking different float ABIs. */ -+ if ((out_flags ^ in_flags) & EF_LARCH_ABI) -+ { -+ _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; -+ 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; -+ -+ s = bfd_make_section_anyway_with_flags -+ (abfd, bed->rela_plts_and_copies_p ? ".rela.got" : ".rel.got", -+ bed->dynamic_sec_flags | SEC_READONLY); -+ if (s == NULL -+ || !bfd_set_section_alignment (abfd, 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 (abfd, 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 (abfd, s, bed->s->log_file_align)) -+ return FALSE; -+ htab->sgotplt = s; -+ -+ /* 相比_bfd_elf_create_got_section: -+ 一方面,RISCV似乎是希望.got.plt和.got都有header; -+ 而且_GLOBAL_OFFSET_TABLE_是.got的开头,而不是.got.plt的开头。 -+ 和公共部分需求有冲突。所以自己实现了 */ -+ -+ /* 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 (_("%pB: Interl 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 : ""); -+ 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; -+ -+ /* 这个函数的遍历每一个重定位,将一些信息归置到符号中。这之后的处理 -+ 都会通过遍历符号进行,根据符号中的信息来确定最终二进制文件的形态。 -+ 1.根据重定位类型记录那个符号是否需要GOT entry -+ 2.根据重定位类型记录那个符号的TLS引用模型 -+ 3.处理IFUNC -+ 4.等等 -+ */ -+ -+ 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; -+ -+ /* 意味着在dynamic_sections_created置位的情况下,这个重定位可能需要动态 -+ 连接器的帮助。如果是这样,我们会在动态重定位表中为其分配一个表项。 */ -+ int need_dynreloc; -+ -+ /* 意味着这个动态重定位仅需要符号的pcrel信息,即符号定义在自身模块内 -+ 及延伸出来的其他信息。如果是这样,我们就在连接时知道了这个重定位的值, -+ 就可以把这个动态重定位取消掉。 */ -+ int only_need_pcrel; -+ -+ 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->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; -+ } -+ -+ if (h && h->type == STT_GNU_IFUNC) -+ { -+ if (htab->elf.dynobj == NULL) -+ htab->elf.dynobj = abfd; -+ -+ if (!htab->elf.splt -+ && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) -+ /* If '.plt' not represent, create '.iplt' to deal with ifunc. */ -+ 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_symbols -+ |= elf_gnu_symbol_ifunc; -+ } -+ -+ need_dynreloc = 0; -+ only_need_pcrel = 0; -+ switch (r_type) -+ { -+ case R_LARCH_SOP_PUSH_GPREL: -+ if (!loongarch_elf_record_tls_and_got_reference -+ (abfd, info, h, r_symndx, GOT_NORMAL)) -+ return FALSE; -+ break; -+ -+ 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_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_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_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. */ -+ /* 这个flag的本质是关注对一个符号的引用能否被动态连接器改变。 -+ 比如la.pcrel,在连接时会将符号的pc相对偏移量写入指令立即数; -+ 而代码段是只读的,动态连接器无法改动指令,这时,那个la只能引用 -+ local的那个符号的定义了,无法被动态连接器改变。 -+ 而使用got表的话,因为got entry可以被动态连接器改变,因此可以改变 -+ la到底哪个模块中的符号。 -+ 动态库里的符号定义可能被可执行文件中的符号定义覆盖,由此,动态库 -+ 中对符号的引用必须可以被动态连接器改变; -+ 而如果在可执行文件中la.pcrel一个动态库中的对象,按常理来说,如果 -+ 不走got表,这个引用是错误的。但如果我们真的把这个符号定义在 -+ 可执行文件中,而将动态库中对象的初始值复制到可执行文件中 -+ (R_LARCH_COPY),这其实等效于引用动态库中的对象了。 -+ 由此,如果某个重定位一旦可能不被动态链接器控制,这个flag被置位, -+ 接下来的处理会根据情况加上R_LARCH_COPY重定位。这样,我们也只能 -+ 在可执行文件中做这件事;动态库中的R_LARCH_COPY是很奇怪的。 */ -+ h->non_got_ref = 1; -+ break; -+ -+ case R_LARCH_SOP_PUSH_PCREL: -+ if (h != NULL) -+ { -+ 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_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) -+ h->non_got_ref = 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 = &((struct loongarch_elf_link_hash_entry *) 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 = loongarch_elf_hash_entry (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; -+ struct loongarch_elf_link_hash_entry * eh; -+ bfd *dynobj; -+ asection *s, *srel; -+ -+ 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; -+ } -+ -+ /* This is a reference to a symbol defined by a dynamic object which -+ is not a function. */ -+ -+ /* If we are creating a shared library, we must presume that the -+ only references to the symbol are via the global offset table. -+ For such cases we need not do anything here; the relocations will -+ be handled correctly by relocate_section. */ -+ if (bfd_link_dll (info)) -+ return TRUE; -+ -+ /* If there are no references to this symbol that do not use the -+ GOT, we don't need to generate a copy reloc. */ -+ if (!h->non_got_ref) -+ return TRUE; -+ -+ /* If -z nocopyreloc was given, we won't generate them either. */ -+ if (info->nocopyreloc) -+ { -+ h->non_got_ref = 0; -+ return TRUE; -+ } -+ -+ /* If we don't find any dynamic relocs in read-only sections, then -+ we'll be keeping the dynamic relocs and avoiding the copy reloc. */ -+ if (!readonly_dynrelocs (h)) -+ { -+ h->non_got_ref = 0; -+ return TRUE; -+ } -+ -+ /* We must allocate the symbol in our .dynbss section, which will -+ become part of the .bss section of the executable. There will be -+ an entry for this symbol in the .dynsym section. The dynamic -+ object will contain position independent code, so all references -+ from the dynamic object to this symbol will go through the global -+ offset table. The dynamic linker will use the .dynsym entry to -+ determine the address it must put in the global offset table, so -+ both the dynamic object and the regular object will refer to the -+ same memory location for the variable. */ -+ -+ /* We must generate a R_LARCH_COPY reloc to tell the dynamic linker -+ to copy the initial value out of the dynamic object and into the -+ runtime process image. We need to remember the offset into the -+ .rel.bss section we are going to use. */ -+ eh = (struct loongarch_elf_link_hash_entry *) h; -+ if (eh->tls_type & ~GOT_NORMAL) -+ { -+ s = htab->sdyntdata; -+ srel = htab->elf.srelbss; -+ } -+ else -+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0) -+ { -+ s = htab->elf.sdynrelro; -+ srel = htab->elf.sreldynrelro; -+ } -+ else -+ { -+ s = htab->elf.sdynbss; -+ srel = htab->elf.srelbss; -+ } -+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) -+ { -+ srel->size += sizeof (ElfNN_External_Rela); -+ h->needs_copy = 1; -+ } -+ -+ return _bfd_elf_adjust_dynamic_copy (info, h, s); -+} -+ -+ -+/* 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 loongarch_elf_link_hash_entry *eh; -+ struct elf_dyn_relocs *p; -+ -+ if (h->root.type == bfd_link_hash_indirect) -+ return TRUE; -+ -+ eh = (struct loongarch_elf_link_hash_entry *) h; -+ info = (struct bfd_link_info *) inf; -+ htab = loongarch_elf_hash_table (info); -+ BFD_ASSERT (htab != NULL); -+ -+ /* 在这里针对符号对.got .iplt .plt的扩充和后续elf_finish_dynamic_symbol补充 -+ 内容对照;WILL_CALL_FINISH_DYNAMIC_SYMBOL似乎指的是这个符号在将来会不会被 -+ finish_dynamic_symbol调用。 -+ a. 对于非IFUNC符号,被allocate_dynrelocs照顾到的符号h要保证在链接后期被 -+ elf_finish_dynamic_symbol调用 -+ b. STT_GNU_IFUNC符号一定走plt,但是对于那些local转化为h的符号,默认是不会 -+ 被调用allocate_dynrelocs和elf_finish_dynamic_symbol的,要手动遍历 -+ 这些符号来调用这两个函数,从而为它们分配plt stub; -+ 而WILL_CALL_FINISH_DYNAMIC_SYMBOL返回false,因此下面的逻辑都是 -+ WILL_CALL_FINISH_DYNAMIC_SYMBOL和对IFUNC的判断配合起来。 */ -+ -+ 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 -+ && !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); -+ -+ h->needs_plt = 1; -+ } -+ while (0); -+ -+ if (!h->needs_plt) -+ h->plt.offset = MINUS_ONE; -+ -+ if (0 < h->got.refcount) -+ { -+ asection *s; -+ bfd_boolean dyn; -+ 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 -+ && !bfd_elf_link_record_dynamic_symbol (info, h)) -+ return FALSE; -+ -+ s = htab->elf.sgot; -+ h->got.offset = s->size; -+ dyn = htab->elf.dynamic_sections_created; -+ 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; -+ 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; -+ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); -+ } -+ } -+ else -+ { -+ s->size += GOT_ENTRY_SIZE; -+ if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) -+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) -+ || h->type == STT_GNU_IFUNC) -+ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); -+ } -+ } -+ else -+ h->got.offset = MINUS_ONE; -+ -+ if (eh->dyn_relocs == NULL) -+ return TRUE; -+ -+ /* 如果某些函数未被定义,SYMBOL_CALLS_LOCAL返回1; -+ 而SYMBOL_REFERENCES_LOCAL返回0。 -+ 似乎是因为未定义的函数可以有plt从而将其转化为local的。 */ -+ if (SYMBOL_REFERENCES_LOCAL (info, h)) -+ { -+ struct elf_dyn_relocs **pp; -+ -+ for (pp = &eh->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)) -+ eh->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. */ -+ && !bfd_elf_link_record_dynamic_symbol (info, h)) -+ return FALSE; -+ } -+ -+ for (p = eh->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; -+} -+ -+static bfd_boolean -+elfNN_loongarch_allocate_local_dynrelocs (void **slot, void *inf) -+{ -+ struct elf_link_hash_entry *h -+ = (struct elf_link_hash_entry *) *slot; -+ -+ if (!h->def_regular -+ || !h->ref_regular -+ || !h->forced_local -+ || h->root.type != bfd_link_hash_defined) -+ abort (); -+ -+ return allocate_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 ((flags & EF_LARCH_ABI) == EF_LARCH_ABI_LP32) -+ interpreter = "/lib32/ld.so.1"; -+ else if ((flags & EF_LARCH_ABI) == EF_LARCH_ABI_LP64) -+ 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; -+ s->size += GOT_ENTRY_SIZE; -+ -+ if (*local_tls_type & GOT_TLS_GD) -+ s->size += GOT_ENTRY_SIZE; -+ -+ if (bfd_link_pic (info) /* R_LARCH_RELATIVE */ -+ || (*local_tls_type & -+ (GOT_TLS_GD /* R_LARCH_TLS_DTPRELNN */ -+ | GOT_TLS_IE /* R_LARCH_TLS_TPRELNN */))) -+ 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 .plt and .got entries, and space for local ifunc symbols. */ -+ htab_traverse (htab->loc_hash_table, -+ elfNN_loongarch_allocate_local_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 lisa_opc_stack[LARCH_LD_STACK_DEPTH]; -+static size_t lisa_stack_top = 0; -+ -+static bfd_reloc_status_type -+loongarch_push (int64_t val) -+{ -+ if (LARCH_LD_STACK_DEPTH <= lisa_stack_top) -+ return bfd_reloc_outofrange; -+ lisa_opc_stack[lisa_stack_top++] = val; -+ return bfd_reloc_ok; -+} -+ -+static bfd_reloc_status_type -+loongarch_pop (int64_t *val) -+{ -+ if (lisa_stack_top == 0) -+ return bfd_reloc_outofrange; -+ BFD_ASSERT (val); -+ *val = lisa_opc_stack[--lisa_stack_top]; -+ return bfd_reloc_ok; -+} -+ -+static bfd_reloc_status_type -+loongarch_top (int64_t *val) -+{ -+ if (lisa_stack_top == 0) -+ return bfd_reloc_outofrange; -+ BFD_ASSERT (val); -+ *val = lisa_opc_stack[lisa_stack_top - 1]; -+ return bfd_reloc_ok; -+} -+ -+static void -+loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel) -+{ -+ const struct elf_backend_data *bed; -+ bfd_byte *loc; -+ -+ bed = get_elf_backend_data (abfd); -+ loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela); -+ bed->s->swap_reloca_out (abfd, rel, loc); -+} -+ -+/* Emplace a static relocation. */ -+ -+static bfd_reloc_status_type -+perform_relocation (const Elf_Internal_Rela *rel, -+ bfd_vma value, -+ bfd *input_bfd, -+ bfd_byte *contents) -+{ -+ -+ uint32_t insn1; -+ int64_t opr1, opr2, opr3; -+ bfd_reloc_status_type r = bfd_reloc_ok; -+ 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 = bfd_reloc_outofrange; -+ if (loongarch_pop (&opr1) != bfd_reloc_ok -+ || loongarch_push (opr1) != bfd_reloc_ok -+ || loongarch_push (opr1) != bfd_reloc_ok) -+ break; -+ r = bfd_reloc_ok; -+ break; -+ -+ case R_LARCH_SOP_ASSERT: -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok && opr1 == FALSE) -+ r = bfd_reloc_notsupported; -+ break; -+ -+ case R_LARCH_SOP_NOT: -+ r = bfd_reloc_outofrange; -+ if (loongarch_pop (&opr1) != bfd_reloc_ok -+ || loongarch_push (!opr1) != bfd_reloc_ok) -+ break; -+ r = bfd_reloc_ok; -+ break; -+ -+ case R_LARCH_SOP_SUB: -+ r = bfd_reloc_outofrange; -+ if (loongarch_pop (&opr2) != bfd_reloc_ok -+ || loongarch_pop (&opr1) != bfd_reloc_ok -+ || loongarch_push (opr1 - opr2) != bfd_reloc_ok) -+ break; -+ r = bfd_reloc_ok; -+ break; -+ -+ case R_LARCH_SOP_SL: -+ r = bfd_reloc_outofrange; -+ if (loongarch_pop (&opr2) != bfd_reloc_ok -+ || loongarch_pop (&opr1) != bfd_reloc_ok -+ || loongarch_push (opr1 << opr2) != bfd_reloc_ok) -+ break; -+ r = bfd_reloc_ok; -+ break; -+ -+ case R_LARCH_SOP_SR: -+ r = bfd_reloc_outofrange; -+ if (loongarch_pop (&opr2) != bfd_reloc_ok -+ || loongarch_pop (&opr1) != bfd_reloc_ok -+ || loongarch_push (opr1 >> opr2) != bfd_reloc_ok) -+ break; -+ r = bfd_reloc_ok; -+ break; -+ -+ case R_LARCH_SOP_AND: -+ r = bfd_reloc_outofrange; -+ if (loongarch_pop (&opr2) != bfd_reloc_ok -+ || loongarch_pop (&opr1) != bfd_reloc_ok -+ || loongarch_push (opr1 & opr2) != bfd_reloc_ok) -+ break; -+ r = bfd_reloc_ok; -+ break; -+ -+ case R_LARCH_SOP_ADD: -+ r = bfd_reloc_outofrange; -+ if (loongarch_pop (&opr2) != bfd_reloc_ok -+ || loongarch_pop (&opr1) != bfd_reloc_ok -+ || loongarch_push (opr1 + opr2) != bfd_reloc_ok) -+ break; -+ r = bfd_reloc_ok; -+ break; -+ -+ case R_LARCH_SOP_IF_ELSE: -+ r = bfd_reloc_outofrange; -+ if (loongarch_pop (&opr3) != bfd_reloc_ok -+ || loongarch_pop (&opr2) != bfd_reloc_ok -+ || loongarch_pop (&opr1) != bfd_reloc_ok -+ || loongarch_push (opr1 ? opr2 : opr3) != bfd_reloc_ok) -+ break; -+ r = bfd_reloc_ok; -+ break; -+ -+ case R_LARCH_SOP_POP_32_S_10_5: -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ if ((opr1 & ~(uint64_t)0xf) != 0x0 -+ && (opr1 & ~(uint64_t)0xf) != ~(uint64_t)0xf) -+ r = bfd_reloc_overflow; -+ if (r != bfd_reloc_ok) -+ break; -+ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); -+ insn1 = (insn1 & (~(uint32_t)0x7c00)) | ((opr1 & 0x1f) << 10); -+ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); -+ break; -+ -+ case R_LARCH_SOP_POP_32_U_10_12: -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ if (opr1 & ~(uint64_t)0xfff) -+ r = bfd_reloc_overflow; -+ if (r != bfd_reloc_ok) -+ break; -+ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); -+ insn1 = (insn1 & (~(uint32_t)0x3ffc00)) | ((opr1 & 0xfff) << 10); -+ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); -+ break; -+ -+ case R_LARCH_SOP_POP_32_S_10_12: -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ if ((opr1 & ~(uint64_t)0x7ff) != 0x0 -+ && (opr1 & ~(uint64_t)0x7ff) != ~(uint64_t)0x7ff) -+ r = bfd_reloc_overflow; -+ if (r != bfd_reloc_ok) -+ break; -+ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); -+ insn1 = (insn1 & (~(uint32_t)0x3ffc00)) | ((opr1 & 0xfff) << 10); -+ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); -+ break; -+ -+ case R_LARCH_SOP_POP_32_S_10_16: -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ if ((opr1 & ~(uint64_t)0x7fff) != 0x0 -+ && (opr1 & ~(uint64_t)0x7fff) != ~(uint64_t)0x7fff) -+ r = bfd_reloc_overflow; -+ if (r != bfd_reloc_ok) -+ break; -+ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); -+ insn1 = (insn1 & 0xfc0003ff) | ((opr1 & 0xffff) << 10); -+ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); -+ break; -+ -+ case R_LARCH_SOP_POP_32_S_10_16_S2: -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ if ((opr1 & 0x3) != 0) -+ r = bfd_reloc_overflow; -+ opr1 >>= 2; -+ if ((opr1 & ~(uint64_t)0x7fff) != 0x0 -+ && (opr1 & ~(uint64_t)0x7fff) != ~(uint64_t)0x7fff) -+ r = bfd_reloc_overflow; -+ if (r != bfd_reloc_ok) -+ break; -+ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); -+ insn1 = (insn1 & 0xfc0003ff) | ((opr1 & 0xffff) << 10); -+ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); -+ break; -+ -+ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ if ((opr1 & 0x3) != 0) -+ r = bfd_reloc_overflow; -+ opr1 >>= 2; -+ if ((opr1 & ~(uint64_t)0xfffff) != 0x0 -+ && (opr1 & ~(uint64_t)0xfffff) != ~(uint64_t)0xfffff) -+ r = bfd_reloc_overflow; -+ if (r != bfd_reloc_ok) -+ break; -+ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); -+ insn1 = (insn1 & 0xfc0003e0) -+ | ((opr1 & 0xffff) << 10) | ((opr1 & 0x1f0000) >> 16); -+ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); -+ break; -+ -+ case R_LARCH_SOP_POP_32_S_5_20: -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ if ((opr1 & ~(uint64_t)0x7ffff) != 0x0 -+ && (opr1 & ~(uint64_t)0x7ffff) != ~(uint64_t)0x7ffff) -+ r = bfd_reloc_overflow; -+ if (r != bfd_reloc_ok) -+ break; -+ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); -+ insn1 = (insn1 & (~(uint32_t)0x1ffffe0)) | ((opr1 & 0xfffff) << 5); -+ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); -+ break; -+ -+ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ if ((opr1 & 0x3) != 0) -+ r = bfd_reloc_overflow; -+ opr1 >>= 2; -+ if ((opr1 & ~(uint64_t)0x1ffffff) != 0x0 -+ && (opr1 & ~(uint64_t)0x1ffffff) != ~(uint64_t)0x1ffffff) -+ r = bfd_reloc_overflow; -+ if (r != bfd_reloc_ok) -+ break; -+ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); -+ insn1 = (insn1 & 0xfc000000) -+ | ((opr1 & 0xffff) << 10) | ((opr1 & 0x3ff0000) >> 16); -+ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); -+ break; -+ -+ case R_LARCH_SOP_POP_32_U: -+ r = loongarch_pop (&opr1); -+ if (r != bfd_reloc_ok) -+ break; -+ if (opr1 & ~(uint64_t)0xffffffff) -+ r = bfd_reloc_overflow; -+ if (r != bfd_reloc_ok) -+ break; -+ bfd_put (32, input_bfd, opr1, contents + rel->r_offset); -+ break; -+ -+ case R_LARCH_TLS_DTPREL32: -+ case R_LARCH_32: -+ bfd_put (32, input_bfd, value, contents + rel->r_offset); -+ break; -+ case R_LARCH_TLS_DTPREL64: -+ case R_LARCH_64: -+ bfd_put (64, input_bfd, value, contents + rel->r_offset); -+ break; -+ case R_LARCH_ADD8: -+ opr1 = bfd_get (8, input_bfd, contents + rel->r_offset); -+ bfd_put (8, input_bfd, opr1 + value, contents + rel->r_offset); -+ break; -+ case R_LARCH_ADD16: -+ opr1 = bfd_get (16, input_bfd, contents + rel->r_offset); -+ bfd_put (16, input_bfd, opr1 + value, contents + rel->r_offset); -+ break; -+ case R_LARCH_ADD24: -+ opr1 = bfd_get (24, input_bfd, contents + rel->r_offset); -+ bfd_put (24, input_bfd, opr1 + value, contents + rel->r_offset); -+ break; -+ case R_LARCH_ADD32: -+ opr1 = bfd_get (32, input_bfd, contents + rel->r_offset); -+ bfd_put (32, input_bfd, opr1 + value, contents + rel->r_offset); -+ break; -+ case R_LARCH_ADD64: -+ opr1 = bfd_get (64, input_bfd, contents + rel->r_offset); -+ bfd_put (64, input_bfd, opr1 + value, contents + rel->r_offset); -+ break; -+ case R_LARCH_SUB8: -+ opr1 = bfd_get (8, input_bfd, contents + rel->r_offset); -+ bfd_put (8, input_bfd, opr1 - value, contents + rel->r_offset); -+ break; -+ case R_LARCH_SUB16: -+ opr1 = bfd_get (16, input_bfd, contents + rel->r_offset); -+ bfd_put (16, input_bfd, opr1 - value, contents + rel->r_offset); -+ break; -+ case R_LARCH_SUB24: -+ opr1 = bfd_get (24, input_bfd, contents + rel->r_offset); -+ bfd_put (24, input_bfd, opr1 - value, contents + rel->r_offset); -+ break; -+ case R_LARCH_SUB32: -+ opr1 = bfd_get (32, input_bfd, contents + rel->r_offset); -+ bfd_put (32, input_bfd, opr1 - value, contents + rel->r_offset); -+ break; -+ case R_LARCH_SUB64: -+ opr1 = bfd_get (64, input_bfd, contents + rel->r_offset); -+ bfd_put (64, input_bfd, opr1 - value, contents + rel->r_offset); -+ 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; -+} lisa_reloc_queue [LARCH_RECENT_RELOC_QUEUE_LENGTH]; -+static size_t lisa_reloc_queue_head = 0; -+static size_t lisa_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 = ""; -+ 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 ((lisa_reloc_queue_head == 0 -+ && lisa_reloc_queue_tail == LARCH_RECENT_RELOC_QUEUE_LENGTH - 1) -+ || (lisa_reloc_queue_head == lisa_reloc_queue_tail + 1)) -+ lisa_reloc_queue_head = -+ (lisa_reloc_queue_head + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH; -+ lisa_reloc_queue[lisa_reloc_queue_tail].bfd = abfd; -+ lisa_reloc_queue[lisa_reloc_queue_tail].section = section; -+ lisa_reloc_queue[lisa_reloc_queue_tail].r_offset = r_offset; -+ lisa_reloc_queue[lisa_reloc_queue_tail].r_type = r_type; -+ lisa_reloc_queue[lisa_reloc_queue_tail].sym = sym; -+ lisa_reloc_queue[lisa_reloc_queue_tail].h = h; -+ lisa_reloc_queue[lisa_reloc_queue_tail].addend = addend; -+ loongarch_top (&lisa_reloc_queue[lisa_reloc_queue_tail].top_then); -+ lisa_reloc_queue_tail = -+ (lisa_reloc_queue_tail + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH; -+} -+ -+static void -+loongarch_dump_reloc_record (void (*p) (const char *fmt, ...)) -+{ -+ size_t i = lisa_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 != lisa_reloc_queue_tail) -+ { -+ if (a_bfd != lisa_reloc_queue[i].bfd -+ || section != lisa_reloc_queue[i].section -+ || r_offset != lisa_reloc_queue[i].r_offset) -+ { -+ a_bfd = lisa_reloc_queue[i].bfd; -+ section = lisa_reloc_queue[i].section; -+ r_offset = lisa_reloc_queue[i].r_offset; -+ p ("\nat %pB(%pA+0x%v):\n", -+ lisa_reloc_queue[i].bfd, -+ lisa_reloc_queue[i].section, -+ lisa_reloc_queue[i].r_offset); -+ } -+ -+ if (!inited) -+ inited = 1, p ("...\n"); -+ -+ reloc_howto_type *howto = -+ loongarch_elf_rtype_to_howto (lisa_reloc_queue[i].r_type); -+ p ("0x%V %s\t`%s'", -+ (bfd_vma) lisa_reloc_queue[i].top_then, -+ howto ? howto->name : "", -+ loongarch_sym_name (lisa_reloc_queue[i].bfd, -+ lisa_reloc_queue[i].h, -+ lisa_reloc_queue[i].sym)); -+ -+ long addend = lisa_reloc_queue[i].addend; -+ if (addend < 0) -+ p (" - %ld", -addend); -+ else if (0 < addend) -+ p (" + %ld(0x%v)", addend, lisa_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_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 = loongarch_elf_rtype_to_howto (r_type); -+ 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; -+ bfd_vma off, ie_off; -+ int i, j; -+ -+ 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; -+ if (bfd_link_relocatable(info) -+ && ELF_ST_TYPE(sym->st_info) == STT_SECTION) { -+ rel->r_addend += sec->output_offset; -+ } -+ } -+ 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' */ -+ -+ /* '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; -+ -+ /* 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)) -+ resolved_dynly = resolved_local = defined_local = FALSE -+ , resolved_to_const = TRUE; -+ -+ if (h && h->type == STT_GNU_IFUNC) -+ { -+ /* a. 动态连接器可以直接处理STT_GNU_IFUNC,因为动态连接器可以察觉到 -+ 一个动态符号是STT_GNU_IFUNC,从而在装载时执行resolver; -+ 但local符号不行,因为根本没有动态符号,所以要将R_LARCH_64转化为 -+ R_LARCH_IRELATIVE,类似的,所有其他重定位类型可能都要针对IFUNC -+ 做一些特殊操作,我觉得有点麻烦了。 -+ b. 此外,比如代码段的重定位无法动态改变其的引用位置,所以必须走plt -+ 来实现IFUNC。 -+ c. 因此,为方便实现,我们将plt stub的位置当作IFUNC符号的定义。 */ -+ if (h->plt.offset == MINUS_ONE) -+ info->callbacks->info -+ ("%X%pB(%pA+0x%v): error: %s against `%s':\n" -+ "STT_GNU_IFUNC must have PLT stub" "\n", -+ input_bfd, input_section, (bfd_vma) rel->r_offset, -+ howto->name, name); -+ 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); -+ -+ /* a. 命题 'resolved_dynly' ==> 'h && h->dynindx != -1' 成立。 -+ b. 需要动态重定位一个符号当然需要动态符号表。这个断言失败意味着某个 -+ 动态符号没有执行bfd_elf_link_record_dynamic_symbol。之前的逻辑有问题 -+ c. 另外,即使resolved_dynly为真,也不一定真的生成动态重定位表项,因为 -+ 有时section没有SEC_ALLOC这个flag,当段不需要被加载进内存自然不需要动态 -+ 重定位。 */ -+ BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1)); -+ -+ BFD_ASSERT (!resolved_local || defined_local); -+ -+ is_ie = FALSE; -+ switch (r_type) -+ { -+#define LARCH_ASSERT(cond, bfd_fail_state, message) \ -+ ({if (!(cond)) { \ -+ r = bfd_fail_state; \ -+ switch (r) { \ -+ /* '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); \ -+ default: \ -+ fatal = TRUE; \ -+ info->callbacks->info \ -+ ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n" \ -+ message "\n", \ -+ input_bfd, input_section, (bfd_vma) rel->r_offset, \ -+ howto->name, is_undefweak? "[undefweak] " : "", name); \ -+ break; \ -+ case bfd_reloc_dangerous: \ -+ info->callbacks->info \ -+ ("%pB(%pA+0x%v): warning: %s against %s`%s':\n" \ -+ message "\n", \ -+ input_bfd, input_section, (bfd_vma) rel->r_offset, \ -+ howto->name, is_undefweak? "[undefweak] " : "", name); \ -+ break; \ -+ case bfd_reloc_ok: \ -+ case bfd_reloc_continue: \ -+ info->callbacks->info \ -+ ("%pB(%pA+0x%v): message: %s against %s`%s':\n" \ -+ message "\n", \ -+ input_bfd, input_section, (bfd_vma) rel->r_offset, \ -+ howto->name, is_undefweak? "[undefweak] " : "", name); \ -+ break; \ -+ } \ -+ if (fatal) break; \ -+ }}) -+ 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); -+ if (resolved_dynly) -+ { -+ 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; -+ } -+ -+ if (unresolved_reloc) -+ 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: -+ LARCH_ASSERT (!resolved_dynly, bfd_reloc_undefined, -+"Can't be resolved dynamically. If this procedure is hand-writing assemble,\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."); -+ 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; -+ } -+ -+ LARCH_ASSERT (!resolved_to_const, bfd_reloc_notsupported, -+ "Internal:"); -+ -+ case R_LARCH_SOP_PUSH_TLS_TPREL: -+ if (resolved_local) -+ { -+ LARCH_ASSERT (elf_hash_table (info)->tls_sec, -+ bfd_reloc_notsupported, "TLS section not be created"); -+ relocation -= elf_hash_table (info)->tls_sec->vma; -+ } -+ -+ LARCH_ASSERT (resolved_local, bfd_reloc_undefined, -+ "TLS LE just can be resolved local only."); -+ break; -+ -+ case R_LARCH_SOP_PUSH_ABSOLUTE: -+ if (is_undefweak) -+ { -+ LARCH_ASSERT (!resolved_dynly, bfd_reloc_dangerous, -+"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; -+ } -+ -+ LARCH_ASSERT (!is_pic, bfd_reloc_notsupported, -+"Under PIC we don't know load address. Re-compile src with '-fpic'?"); -+ -+ if (resolved_dynly) -+ { -+ LARCH_ASSERT (plt && h && h->plt.offset != MINUS_ONE, -+ bfd_reloc_undefined, -+"Can't be resolved dynamically. Try to re-compile src with '-fpic'?"); -+ -+ LARCH_ASSERT (rel->r_addend == 0, bfd_reloc_notsupported, -+ "Shouldn't be with r_addend."); -+ -+ 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 (resolved_to_const) -+ { -+ relocation += rel->r_addend; -+ break; -+ } -+ else if (is_undefweak) -+ { -+ i = 0, j = 0; -+ relocation = 0; -+ if (resolved_dynly) -+ { -+ if (h && h->plt.offset != MINUS_ONE) -+ i = 1, j = 2; -+ else -+ LARCH_ASSERT (0, bfd_reloc_dangerous, -+"Undefweak need to be resolved dynamically, but PLT stub doesn't represent."); -+ } -+ } -+ else -+ { -+ LARCH_ASSERT -+ (defined_local || (h && h->plt.offset != MINUS_ONE), -+ bfd_reloc_undefined, -+ "PLT stub does not represent and symbol not defined."); -+ -+ if (resolved_local) -+ i = 0, j = 2; -+ else /* if (resolved_dynly) */ -+ { -+ LARCH_ASSERT -+ (h && h->plt.offset != MINUS_ONE, bfd_reloc_dangerous, -+"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) -+ { -+ LARCH_ASSERT (rel->r_addend == 0, bfd_reloc_notsupported, -+ "PLT shouldn't be with r_addend."); -+ relocation = sec_addr (plt) + h->plt.offset - pc; -+ break; -+ } -+ } -+ break; -+ -+ case R_LARCH_SOP_PUSH_GPREL: -+ unresolved_reloc = FALSE; -+ -+ LARCH_ASSERT (rel->r_addend == 0, bfd_reloc_notsupported, -+ "Shouldn't be with r_addend."); -+ -+ /* 约定在GOT表中写入连接时地址。动态连接器通过_GLOBAL_OFFSET_TABLE_的 -+ 连接时地址和运行时地址拿到模块的加载地址,拿到连接时地址的办法就是 -+ 拿到那个got entry。一些体系结构通过.dynamic的段基址拿到模块加载 -+ 地址,我没有这么做,因为这个段在static-pie下不存在。 */ -+ -+ if (h != NULL) -+ { -+ off = h->got.offset; -+ -+ LARCH_ASSERT (off != MINUS_ONE, bfd_reloc_notsupported, -+ "Internal: GOT entry doesn't represent."); -+ -+ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, is_pic, h) -+ || (is_pic && 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. */ -+ -+ /* 在这里先不用管STT_GNU_IFUNC。elf_finish_dynamic_symbol -+ 会单独处理。 */ -+ -+ LARCH_ASSERT (!resolved_dynly, bfd_reloc_dangerous, -+ "Internal: here shouldn't dynamic."); -+ LARCH_ASSERT (defined_local || resolved_to_const, -+ bfd_reloc_undefined, "Internal: "); -+ -+ if ((off & 1) != 0) -+ off &= ~1; -+ else -+ { -+ bfd_put_NN (output_bfd, relocation, got->contents + off); -+ h->got.offset |= 1; -+ } -+ } -+ } -+ else -+ { -+ LARCH_ASSERT (local_got_offsets, bfd_reloc_notsupported, -+ "Internal: local got offsets not reporesent."); -+ -+ off = local_got_offsets[r_symndx]; -+ -+ LARCH_ASSERT (off != MINUS_ONE, bfd_reloc_notsupported, -+ "Internal: GOT entry doesn't represent."); -+ -+ /* 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 ((off & 1) != 0) -+ off &= ~1; -+ else -+ { -+ 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; -+ LARCH_ASSERT (s, bfd_reloc_notsupported, -+ "Internal: '.rel.got' not represent"); -+ -+ 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: -+ is_ie = TRUE; -+ case R_LARCH_SOP_PUSH_TLS_GD: -+ unresolved_reloc = FALSE; -+ -+ LARCH_ASSERT (rel->r_addend == 0, bfd_reloc_notsupported, -+ "Shouldn't be with r_addend."); -+ -+ if (resolved_to_const && is_undefweak && h->dynindx != -1) -+ { -+ /* What if undefweak? Let rtld make a decision. */ -+ resolved_to_const = resolved_local = FALSE; -+ resolved_dynly = TRUE; -+ } -+ -+ LARCH_ASSERT (!resolved_to_const, bfd_reloc_notsupported, -+ "Internal: Shouldn't be resolved to const."); -+ -+ if (h != NULL) -+ { -+ off = h->got.offset; -+ h->got.offset |= 1; -+ } -+ else -+ { -+ off = local_got_offsets[r_symndx]; -+ local_got_offsets[r_symndx] |= 1; -+ } -+ -+ LARCH_ASSERT (off != MINUS_ONE, bfd_reloc_notsupported, -+ "Internal: TLS GOT entry doesn't represent."); -+ -+ tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); -+ -+ /* If this symbol is referenced by both GD and IE TLS, the IE -+ reference's GOT slot follows the GD reference's slots. */ -+ ie_off = 0; -+ if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE)) -+ ie_off = 2 * GOT_ENTRY_SIZE; -+ -+ if ((off & 1) != 0) -+ off &= ~1; -+ else -+ { -+ bfd_vma tls_block_off = 0; -+ Elf_Internal_Rela outrel; -+ -+ if (resolved_local) -+ { -+ LARCH_ASSERT -+ (elf_hash_table (info)->tls_sec, bfd_reloc_notsupported, -+ "Internal: TLS sec not represent."); -+ tls_block_off = relocation -+ - elf_hash_table (info)->tls_sec->vma; -+ } -+ -+ if (tls_type & GOT_TLS_GD) -+ { -+ outrel.r_offset = sec_addr (got) + off; -+ outrel.r_addend = 0; -+ bfd_put_NN (output_bfd, 0, got->contents + off); -+ if (resolved_local && bfd_link_executable (info)) -+ /* a. 第一个被装载模块的Module ID为1。$glibc/elf/rtld.c中 -+ 的dl_main有一句'main_map->l_tls_modid = 1'; -+ b. 静态程序的Module ID不重要,但为了省事仍然是1。 -+ 详见$glibc/csu/libc-tls.c中的init_static_tls。 */ -+ bfd_put_NN (output_bfd, 1, got->contents + off); -+ else if (resolved_local/* && !bfd_link_executable (info) */) -+ { -+ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN); -+ loongarch_elf_append_rela -+ (output_bfd, htab->elf.srelgot, &outrel); -+ } -+ else /* if (resolved_dynly) */ -+ { -+ outrel.r_info = -+ ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPMODNN); -+ loongarch_elf_append_rela -+ (output_bfd, htab->elf.srelgot, &outrel); -+ } -+ -+ outrel.r_offset += GOT_ENTRY_SIZE; -+ bfd_put_NN (output_bfd, tls_block_off, -+ got->contents + off + GOT_ENTRY_SIZE); -+ if (resolved_local) -+ /* DTPREL known */; -+ else /* if (resolved_dynly) */ -+ { -+ outrel.r_info = -+ ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPRELNN); -+ loongarch_elf_append_rela -+ (output_bfd, htab->elf.srelgot, &outrel); -+ } -+ } -+ -+ if (tls_type & GOT_TLS_IE) -+ { -+ outrel.r_offset = sec_addr (got) + off + ie_off; -+ bfd_put_NN (output_bfd, tls_block_off, -+ got->contents + off + ie_off); -+ if (resolved_local && bfd_link_executable (info)) -+ /* TPREL known */; -+ else if (resolved_local/* && !bfd_link_executable (info) */) -+ { -+ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); -+ outrel.r_addend = tls_block_off; -+ loongarch_elf_append_rela -+ (output_bfd, htab->elf.srelgot, &outrel); -+ } -+ else /* if (resolved_dynly) */ -+ { -+ outrel.r_info = -+ ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_TPRELNN); -+ outrel.r_addend = 0; -+ loongarch_elf_append_rela -+ (output_bfd, htab->elf.srelgot, &outrel); -+ } -+ } -+ } -+ -+ relocation = off + (is_ie ? ie_off : 0); -+ 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) -+ { -+ LARCH_ASSERT (0, bfd_reloc_dangerous, -+ "Seems dynamic linker not process sections 'SEC_DEBUGGING'."); -+ break; -+ } -+ if (!is_dyn) -+ break; -+ -+ if ((info->flags & DF_TEXTREL) == 0) -+ if (input_section->output_section->flags & SEC_READONLY) -+ info->flags |= DF_TEXTREL; -+ } -+ while (0); -+#undef LARCH_ASSERT -+ -+ 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, 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; -+ break; -+ } -+ -+ 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); -+ asection *plt = NULL; -+ -+ if (h->plt.offset != MINUS_ONE) -+ { -+ size_t i, plt_idx; -+ asection *gotplt, *relplt; -+ bfd_vma got_address; -+ uint32_t plt_entry[PLT_ENTRY_INSNS]; -+ bfd_byte *loc; -+ Elf_Internal_Rela rela; -+ -+ plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; -+ -+ /* one of '.plt' and '.iplt' represents */ -+ BFD_ASSERT (!!htab->elf.splt ^ !!htab->elf.iplt); -+ -+ 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; -+ relplt = htab->elf.srelplt; -+ 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; -+ 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. */ -+ loongarch_make_plt_entry -+ (got_address, sec_addr (plt) + h->plt.offset, plt_entry); -+ 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; -+ if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h)) -+ { -+ 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; -+ } -+ 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->type == STT_GNU_IFUNC) -+ { -+ if (/* 加入这个条件的原因是,对于静态链接,IRELATIVE重定位类型在 -+ __libc_start_main中调用apply_irel,通过链接脚本提供的 -+ __rela_iplt_start和__rela_iplt_end遍历.rela.iplt中的动态重定位 -+ 表项,来调用各个resolver并将返回结果写入.igot.plt中。 -+ 问题是照顾不到.rela.iplt之外的IRELATIVE重定位,因此我们在静态 -+ 连接的情况下绝对不将IRELATIVE写入.igot.plt之外。这样做在运行时 -+ 可能会有一些性能影响,毕竟ifunc函数都走plt,需要load两次 -+ got entry。没什么好的解决方法,未来可以搞.iplt2用于延迟调用 -+ resolver。 */ -+ elf_hash_table (info)->dynamic_sections_created -+ -+ && 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 (plt); -+ rela.r_info = -+ ELFNN_R_INFO -+ (0, bfd_link_pic (info) ? R_LARCH_RELATIVE : R_LARCH_NONE); -+ rela.r_addend = plt->output_section->vma -+ + plt->output_offset -+ + h->plt.offset; -+ bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off); -+ } -+ } -+ else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) -+ { -+ BFD_ASSERT (h->got.offset & 1/* has been filled in addr */); -+ 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->got.offset & 1) == 0); -+ 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); -+ } -+ -+ if (h->needs_copy) -+ { -+ Elf_Internal_Rela rela; -+ asection *s; -+ -+ /* This symbols needs a copy reloc. Set it up. */ -+ BFD_ASSERT (h->dynindx != -1); -+ -+ rela.r_offset = sec_addr (h->root.u.def.section) + h->root.u.def.value; -+ rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_COPY); -+ rela.r_addend = 0; -+ if (h->root.u.def.section == htab->elf.sdynrelro) -+ s = htab->elf.sreldynrelro; -+ else -+ s = htab->elf.srelbss; -+ loongarch_elf_append_rela (output_bfd, s, &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; -+ 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; -+ } -+ -+ if ((plt = htab->elf.splt)) -+ gotplt = htab->elf.sgotplt; -+ else if ((plt = htab->elf.iplt)) -+ gotplt = htab->elf.igotplt; -+ -+ if (plt && 0 < plt->size) -+ { -+ size_t i; -+ uint32_t plt_header[PLT_HEADER_INSNS]; -+ loongarch_make_plt_header (sec_addr (gotplt), sec_addr (plt), plt_header); -+ 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); -+ -+ /* 第二项非0时动态连接器认为它是plt header的地址,从而影响到所有 -+ R_LARCH_JUMP_SLOT。这似乎是为了prelink预留的。 */ -+ 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, 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. -+ 一定要保证先完成非IFUNC重定位。因为如果IFUNC的resolover尚未完成 -+ 重定位,那么调用它返回的结果是错误的。非IFUNC重定位类型,比如R_LARCH_64 -+ 也可以携带IFUNC符号信息。我们在elf_machine_rela中可以察觉到一个符号是 -+ IFUNC,而在动态重定位时调用resolver。但八成这个resolver也需要一个 -+ R_LARCH_64重定位,可能还未完成,这时就会出问题。 -+ 在这里识别出来和STT_GNU_IFUNC相关的重定位,将他们往后排。 */ -+ 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 loongarch_elf_link_hash_entry *edir, *eind; -+ -+ edir = (struct loongarch_elf_link_hash_entry *) dir; -+ eind = (struct loongarch_elf_link_hash_entry *) 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) -+ { -+ edir->tls_type = eind->tls_type; -+ eind->tls_type = GOT_UNKNOWN; -+ } -+ _bfd_elf_link_hash_copy_indirect (info, dir, ind); -+} -+ -+//#if ARCH_SIZE == 32 -+//# define PRSTATUS_SIZE 0 /* FIXME */ -+//# define PRSTATUS_OFFSET_PR_CURSIG 0 -+//# define PRSTATUS_OFFSET_PR_PID 0 -+//# define PRSTATUS_OFFSET_PR_REG 0 -+//# define ELF_GREGSET_T_SIZE 264 -+//# define PRPSINFO_SIZE 0 -+//# define PRPSINFO_OFFSET_PR_PID 0 -+//# define PRPSINFO_OFFSET_PR_FNAME 0 -+//# define PRPSINFO_OFFSET_PR_PSARGS 0 -+//#else -+#define PRSTATUS_SIZE 384 -+#define PRSTATUS_OFFSET_PR_CURSIG 12 -+#define PRSTATUS_OFFSET_PR_PID 32 -+#define PRSTATUS_OFFSET_PR_REG 112 -+#define ELF_GREGSET_T_SIZE 264 -+ -+#define PRPSINFO_SIZE 144 -+#define PRPSINFO_OFFSET_PR_PID 32 -+#define PRPSINFO_OFFSET_PR_FNAME 48 -+#define PRPSINFO_OFFSET_PR_PSARGS 64 -+#define PRPSINFO_SIZE_PR_FNAMW 16 -+#define PRPSINFO_SIZE_PR_PSARGS 80 -+//#endif -+ -+/* 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; -+ -+ case PRSTATUS_SIZE: /* sizeof(struct elf_prstatus) on Linux/Loongarch. */ -+ /* 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); -+} -+ -+static bfd_boolean -+loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) -+{ -+ switch (note->descsz) -+ { -+ default: -+ return FALSE; -+ -+ case PRPSINFO_SIZE: /* sizeof(struct elf_prpsinfo) on Linux/Loongarch. */ -+ /* 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_OFFSET_PR_FNAME); -+ -+ /* pr_psargs */ -+ elf_tdata (abfd)->core->command = _bfd_elfcore_strndup -+ (abfd, note->descdata + PRPSINFO_OFFSET_PR_PSARGS, PRPSINFO_SIZE_PR_PSARGS); -+ 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); -+} -+ -+static bfd_boolean -+_loongarch_bfd_set_section_contents(bfd *abfd, -+ sec_ptr section, -+ const void *location, -+ file_ptr offset, -+ bfd_size_type conut) -+ -+{ -+ if (elf_elfheader(abfd)->e_flags ==0) -+ if(abfd->arch_info->arch == bfd_arch_loongarch) -+ if (abfd->arch_info->mach ==bfd_mach_loongarch32) -+ elf_elfheader(abfd)->e_flags = EF_LARCH_ABI_LP32; -+ else if (abfd->arch_info->mach ==bfd_mach_loongarch64) -+ elf_elfheader(abfd)->e_flags = EF_LARCH_ABI_LP64; -+ else -+ return FALSE; -+ return _bfd_elf_set_section_contents(abfd,section,location,offset,conut); -+} -+ -+ -+ -+#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 \ -+ _bfd_loongarch_elf_merge_private_bfd_data -+ -+#define bfd_elfNN_set_section_contents _loongarch_bfd_set_section_contents -+ -+ -+#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 -+ -+#include "elfNN-target.h" -diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c -new file mode 100644 -index 00000000..3f8534bf ---- /dev/null -+++ b/bfd/elfxx-loongarch.c -@@ -0,0 +1,172 @@ -+#include "sysdep.h" -+#include "bfd.h" -+#include "libbfd.h" -+#include "elf-bfd.h" -+#include "elf/loongarch.h" -+#include "elfxx-loongarch.h" -+ -+ -+ -+/* This does not include any relocation information, but should be -+ good enough for GDB or objdump to read the file. */ -+ -+static reloc_howto_type howto_table[] = -+{ -+#define LOONGARCH_HOWTO(r_name) HOWTO (R_LARCH_##r_name,0,3,32,FALSE,0,complain_overflow_signed,bfd_elf_generic_reloc,"R_LARCH_"#r_name,FALSE,0,0,FALSE) -+LOONGARCH_HOWTO (NONE), -+LOONGARCH_HOWTO (32), -+LOONGARCH_HOWTO (64), -+LOONGARCH_HOWTO (RELATIVE), -+LOONGARCH_HOWTO (COPY), -+LOONGARCH_HOWTO (JUMP_SLOT), -+LOONGARCH_HOWTO (TLS_DTPMOD32), -+LOONGARCH_HOWTO (TLS_DTPMOD64), -+LOONGARCH_HOWTO (TLS_DTPREL32), -+LOONGARCH_HOWTO (TLS_DTPREL64), -+LOONGARCH_HOWTO (TLS_TPREL32), -+LOONGARCH_HOWTO (TLS_TPREL64), -+LOONGARCH_HOWTO (IRELATIVE), -+ -+LOONGARCH_HOWTO (MARK_LA), -+LOONGARCH_HOWTO (MARK_PCREL), -+ HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type */ -+ 2, /* rightshift */ -+ 3, /* 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 */ -+LOONGARCH_HOWTO (SOP_PUSH_ABSOLUTE), -+LOONGARCH_HOWTO (SOP_PUSH_DUP), -+LOONGARCH_HOWTO (SOP_PUSH_GPREL), -+LOONGARCH_HOWTO (SOP_PUSH_TLS_TPREL), -+LOONGARCH_HOWTO (SOP_PUSH_TLS_GOT), -+LOONGARCH_HOWTO (SOP_PUSH_TLS_GD), -+LOONGARCH_HOWTO (SOP_PUSH_PLT_PCREL), -+LOONGARCH_HOWTO (SOP_ASSERT), -+LOONGARCH_HOWTO (SOP_NOT), -+LOONGARCH_HOWTO (SOP_SUB), -+LOONGARCH_HOWTO (SOP_SL), -+LOONGARCH_HOWTO (SOP_SR), -+LOONGARCH_HOWTO (SOP_ADD), -+LOONGARCH_HOWTO (SOP_AND), -+LOONGARCH_HOWTO (SOP_IF_ELSE), -+LOONGARCH_HOWTO (SOP_POP_32_S_10_5), -+LOONGARCH_HOWTO (SOP_POP_32_U_10_12), -+LOONGARCH_HOWTO (SOP_POP_32_S_10_12), -+LOONGARCH_HOWTO (SOP_POP_32_S_10_16), -+LOONGARCH_HOWTO (SOP_POP_32_S_10_16_S2), -+LOONGARCH_HOWTO (SOP_POP_32_S_5_20), -+LOONGARCH_HOWTO (SOP_POP_32_S_0_5_10_16_S2), -+LOONGARCH_HOWTO (SOP_POP_32_S_0_10_10_16_S2), -+LOONGARCH_HOWTO (SOP_POP_32_U), -+LOONGARCH_HOWTO (ADD8), -+LOONGARCH_HOWTO (ADD16), -+LOONGARCH_HOWTO (ADD24), -+LOONGARCH_HOWTO (ADD32), -+LOONGARCH_HOWTO (ADD64), -+LOONGARCH_HOWTO (SUB8), -+LOONGARCH_HOWTO (SUB16), -+LOONGARCH_HOWTO (SUB24), -+LOONGARCH_HOWTO (SUB32), -+LOONGARCH_HOWTO (SUB64), -+}; -+ -+struct elf_reloc_map -+{ -+ bfd_reloc_code_real_type bfd_val; -+ enum elf_loongarch_reloc_type elf_val; -+}; -+ -+static const struct elf_reloc_map loong_reloc_map[] = -+{ -+ { BFD_RELOC_NONE, R_LARCH_NONE }, -+ { BFD_RELOC_32, R_LARCH_32 }, -+ { BFD_RELOC_64, R_LARCH_64 }, -+ -+#define LOONGARCH_reloc_map(r_name) {BFD_RELOC_LARCH_##r_name,R_LARCH_##r_name} -+LOONGARCH_reloc_map (TLS_DTPMOD32), -+LOONGARCH_reloc_map (TLS_DTPMOD64), -+LOONGARCH_reloc_map (TLS_DTPREL32), -+LOONGARCH_reloc_map (TLS_DTPREL64), -+LOONGARCH_reloc_map (TLS_TPREL32), -+LOONGARCH_reloc_map (TLS_TPREL64), -+ -+LOONGARCH_reloc_map (MARK_LA), -+LOONGARCH_reloc_map (MARK_PCREL), -+LOONGARCH_reloc_map (SOP_PUSH_PCREL), -+LOONGARCH_reloc_map (SOP_PUSH_ABSOLUTE), -+LOONGARCH_reloc_map (SOP_PUSH_DUP), -+LOONGARCH_reloc_map (SOP_PUSH_GPREL), -+LOONGARCH_reloc_map (SOP_PUSH_TLS_TPREL), -+LOONGARCH_reloc_map (SOP_PUSH_TLS_GOT), -+LOONGARCH_reloc_map (SOP_PUSH_TLS_GD), -+LOONGARCH_reloc_map (SOP_PUSH_PLT_PCREL), -+LOONGARCH_reloc_map (SOP_ASSERT), -+LOONGARCH_reloc_map (SOP_NOT), -+LOONGARCH_reloc_map (SOP_SUB), -+LOONGARCH_reloc_map (SOP_SL), -+LOONGARCH_reloc_map (SOP_SR), -+LOONGARCH_reloc_map (SOP_ADD), -+LOONGARCH_reloc_map (SOP_AND), -+LOONGARCH_reloc_map (SOP_IF_ELSE), -+LOONGARCH_reloc_map (SOP_POP_32_S_10_5), -+LOONGARCH_reloc_map (SOP_POP_32_U_10_12), -+LOONGARCH_reloc_map (SOP_POP_32_S_10_12), -+LOONGARCH_reloc_map (SOP_POP_32_S_10_16), -+LOONGARCH_reloc_map (SOP_POP_32_S_10_16_S2), -+LOONGARCH_reloc_map (SOP_POP_32_S_5_20), -+LOONGARCH_reloc_map (SOP_POP_32_S_0_5_10_16_S2), -+LOONGARCH_reloc_map (SOP_POP_32_S_0_10_10_16_S2), -+LOONGARCH_reloc_map (SOP_POP_32_U), -+LOONGARCH_reloc_map (ADD8), -+LOONGARCH_reloc_map (ADD16), -+LOONGARCH_reloc_map (ADD24), -+LOONGARCH_reloc_map (ADD32), -+LOONGARCH_reloc_map (ADD64), -+LOONGARCH_reloc_map (SUB8), -+LOONGARCH_reloc_map (SUB16), -+LOONGARCH_reloc_map (SUB24), -+LOONGARCH_reloc_map (SUB32), -+LOONGARCH_reloc_map (SUB64), -+}; -+ -+reloc_howto_type * -+loongarch_elf_rtype_to_howto (unsigned int r_type) -+{ -+ size_t i; -+ for (i = 0; i < ARRAY_SIZE (howto_table); i++) -+ if (howto_table[i].type == r_type) -+ return &howto_table[i]; -+ return NULL; -+} -+ -+reloc_howto_type * -+loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) -+{ -+ unsigned int i; -+ for (i = 0; i < ARRAY_SIZE (loong_reloc_map); i++) -+ if (loong_reloc_map[i].bfd_val == code) -+ return loongarch_elf_rtype_to_howto ((int) loong_reloc_map[i].elf_val); -+ // return &howto_table[(int) loong_reloc_map[i].elf_val]; -+ -+ return NULL; -+} -+ -+reloc_howto_type * -+loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) -+{ -+ unsigned int i; -+ -+ for (i = 0; i < ARRAY_SIZE (howto_table); i++) -+ if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0) -+ return &howto_table[i]; -+ -+ return NULL; -+} -diff --git a/bfd/elfxx-loongarch.h b/bfd/elfxx-loongarch.h -new file mode 100644 -index 00000000..0e980864 ---- /dev/null -+++ b/bfd/elfxx-loongarch.h -@@ -0,0 +1,11 @@ -+#include "elf/common.h" -+#include "elf/internal.h" -+ -+extern reloc_howto_type * -+loongarch_elf_rtype_to_howto (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); -diff --git a/bfd/libbfd.h b/bfd/libbfd.h -index bc5ce1a4..4b1d1c63 100644 ---- a/bfd/libbfd.h -+++ b/bfd/libbfd.h -@@ -3189,6 +3189,49 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", - "BFD_RELOC_WASM32_CODE_POINTER", - "BFD_RELOC_WASM32_INDEX", - "BFD_RELOC_WASM32_PLT_SIG", -+ "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", - "@@overflow: BFD_RELOC_UNUSED@@", - }; - #endif -diff --git a/bfd/reloc.c b/bfd/reloc.c -index 074223f5..6a923a61 100644 ---- a/bfd/reloc.c -+++ b/bfd/reloc.c -@@ -7939,6 +7939,95 @@ ENUMX - ENUMDOC - WebAssembly relocations. - -+ENUM -+ BFD_RELOC_LARCH_TLS_DTPMOD32 -+ENUMX -+ BFD_RELOC_LARCH_TLS_DTPREL32 -+ENUMX -+ BFD_RELOC_LARCH_TLS_DTPMOD64 -+ENUMX -+ BFD_RELOC_LARCH_TLS_DTPREL64 -+ENUMX -+ BFD_RELOC_LARCH_TLS_TPREL32 -+ENUMX -+ BFD_RELOC_LARCH_TLS_TPREL64 -+ENUMX -+ BFD_RELOC_LARCH_MARK_LA -+ENUMX -+ BFD_RELOC_LARCH_MARK_PCREL -+ENUMX -+ BFD_RELOC_LARCH_SOP_PUSH_PCREL -+ENUMX -+ BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE -+ENUMX -+ BFD_RELOC_LARCH_SOP_PUSH_DUP -+ENUMX -+ BFD_RELOC_LARCH_SOP_PUSH_GPREL -+ENUMX -+ BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL -+ENUMX -+ BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT -+ENUMX -+ BFD_RELOC_LARCH_SOP_PUSH_TLS_GD -+ENUMX -+ BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL -+ENUMX -+ BFD_RELOC_LARCH_SOP_ASSERT -+ENUMX -+ BFD_RELOC_LARCH_SOP_NOT -+ENUMX -+ BFD_RELOC_LARCH_SOP_SUB -+ENUMX -+ BFD_RELOC_LARCH_SOP_SL -+ENUMX -+ BFD_RELOC_LARCH_SOP_SR -+ENUMX -+ BFD_RELOC_LARCH_SOP_ADD -+ENUMX -+ BFD_RELOC_LARCH_SOP_AND -+ENUMX -+ BFD_RELOC_LARCH_SOP_IF_ELSE -+ENUMX -+ BFD_RELOC_LARCH_SOP_POP_32_S_10_5 -+ENUMX -+ BFD_RELOC_LARCH_SOP_POP_32_U_10_12 -+ENUMX -+ BFD_RELOC_LARCH_SOP_POP_32_S_10_12 -+ENUMX -+ BFD_RELOC_LARCH_SOP_POP_32_S_10_16 -+ENUMX -+ BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2 -+ENUMX -+ BFD_RELOC_LARCH_SOP_POP_32_S_5_20 -+ENUMX -+ BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2 -+ENUMX -+ BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2 -+ENUMX -+ BFD_RELOC_LARCH_SOP_POP_32_U -+ENUMX -+ BFD_RELOC_LARCH_ADD8 -+ENUMX -+ BFD_RELOC_LARCH_ADD16 -+ENUMX -+ BFD_RELOC_LARCH_ADD24 -+ENUMX -+ BFD_RELOC_LARCH_ADD32 -+ENUMX -+ BFD_RELOC_LARCH_ADD64 -+ENUMX -+ BFD_RELOC_LARCH_SUB8 -+ENUMX -+ BFD_RELOC_LARCH_SUB16 -+ENUMX -+ BFD_RELOC_LARCH_SUB24 -+ENUMX -+ BFD_RELOC_LARCH_SUB32 -+ENUMX -+ BFD_RELOC_LARCH_SUB64 -+ENUMDOC -+ LoongISA relocations. -+ - ENDSENUM - BFD_RELOC_UNUSED - CODE_FRAGMENT -diff --git a/bfd/targets.c b/bfd/targets.c -index 02c6de4f..ef678ee3 100644 ---- a/bfd/targets.c -+++ b/bfd/targets.c -@@ -710,6 +710,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_elf32_vec; -+extern const bfd_target loongarch_elf64_vec; - extern const bfd_target m32c_elf32_vec; - extern const bfd_target m32r_elf32_vec; - extern const bfd_target m32r_elf32_le_vec; -@@ -1166,6 +1168,11 @@ static const bfd_target * const _bfd_target_vector[] = - - &lm32_elf32_vec, - -+#ifdef BFD64 -+ &loongarch_elf32_vec, -+ &loongarch_elf64_vec, -+#endif -+ - &m32c_elf32_vec, - - &m32r_elf32_vec, -diff --git a/binutils/readelf.c b/binutils/readelf.c -index 212b9810..f3e989c8 100644 ---- a/binutils/readelf.c -+++ b/binutils/readelf.c -@@ -114,6 +114,7 @@ - #include "elf/ia64.h" - #include "elf/ip2k.h" - #include "elf/lm32.h" -+#include "elf/loongarch.h" - #include "elf/iq2000.h" - #include "elf/m32c.h" - #include "elf/m32r.h" -@@ -990,6 +991,7 @@ guess_is_rela (unsigned int e_machine) - case EM_MICROBLAZE: - case EM_MICROBLAZE_OLD: - case EM_WEBASSEMBLY: -+ case EM_LOONGARCH: - return TRUE; - - case EM_68HC05: -@@ -1701,6 +1703,10 @@ dump_relocations (Filedata * filedata, - else - rtype = elf_nfp_reloc_type (type); - break; -+ -+ case EM_LOONGARCH: -+ rtype = elf_loongarch_reloc_type (type); -+ break; - } - - if (rtype == NULL) -@@ -2643,6 +2649,7 @@ get_machine_name (unsigned e_machine) - case EM_CYGNUS_MEP: return "Toshiba MeP Media Engine"; - case EM_ADAPTEVA_EPIPHANY: return "Adapteva EPIPHANY"; - case EM_CYGNUS_FRV: return "Fujitsu FR-V"; -+ case EM_LOONGARCH: return "LoongArch"; - - default: - snprintf (buff, sizeof (buff), _(": 0x%x"), e_machine); -@@ -3850,6 +3857,16 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) - - if (e_flags & ~ EF_MSP430_MACH) - strcat (buf, _(": unknown extra flag bits also present")); -+ break; -+ -+ case EM_LOONGARCH: -+ switch (e_flags & EF_LARCH_ABI) -+ { -+ case EF_LARCH_ABI_LP64: strcat (buf, ", LP64"); break; -+ case EF_LARCH_ABI_XLP32: strcat (buf, ", XLP32"); break; -+ case EF_LARCH_ABI_LP32: strcat (buf, ", LP32"); break; -+ } -+ break; - } - } - -@@ -12502,6 +12519,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) - return reloc_type == 2; /* R_IQ2000_32. */ - case EM_LATTICEMICO32: - return reloc_type == 3; /* R_LM32_32. */ -+ case EM_LOONGARCH: -+ return reloc_type == 1; /* R_LARCH_32. */ - case EM_M32C_OLD: - case EM_M32C: - return reloc_type == 3; /* R_M32C_32. */ -@@ -12710,6 +12729,8 @@ is_64bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) - case EM_IA_64: - return (reloc_type == 0x26 /* R_IA64_DIR64MSB. */ - || reloc_type == 0x27 /* R_IA64_DIR64LSB. */); -+ case EM_LOONGARCH: -+ return reloc_type == 2; /* R_LARCH_64 */ - case EM_PARISC: - return reloc_type == 80; /* R_PARISC_DIR64. */ - case EM_PPC64: -@@ -13034,6 +13055,7 @@ is_none_reloc (Filedata * filedata, unsigned int reloc_type) - case EM_X86_64: /* R_X86_64_NONE. */ - case EM_XC16X: - case EM_WEBASSEMBLY: /* R_WASM32_NONE. */ -+ case EM_LOONGARCH: /* R_LARCH_NONE */ - return reloc_type == 0; - - case EM_AARCH64: -@@ -16852,6 +16874,14 @@ get_note_type (Filedata * filedata, unsigned e_type) - return _("NT_ARM_HW_BREAK (AArch hardware breakpoint registers)"); - case NT_ARM_HW_WATCH: - return _("NT_ARM_HW_WATCH (AArch hardware watchpoint registers)"); -+ case NT_LARCH_CPUCFG: -+ return _("NT_LARCH_CPUCFG (Loongarch CPU config registers)"); -+ case NT_LARCH_LBT: -+ return _("NT_LARCH_LBT (Loongarch Loongson Binary Translation registers)"); -+ case NT_LARCH_LSX: -+ return _("NT_LARCH_LSX (Loongarch Loongson SIMD Extension registers)"); -+ case NT_LARCH_LASX: -+ return _("NT_LARCH_LASX (Loongarch Loongson Advanced SIMD Extension registers)"); - case NT_PSTATUS: - return _("NT_PSTATUS (pstatus structure)"); - case NT_FPREGS: -diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp -index f006d64f..9c07394f 100644 ---- a/binutils/testsuite/binutils-all/objdump.exp -+++ b/binutils/testsuite/binutils-all/objdump.exp -@@ -34,8 +34,8 @@ send_user "Version [binutil_version $OBJDUMP]" - set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -i"] - - set cpus_expected [list] --lappend cpus_expected aarch64 alpha am33-2 arc ARC700 ARCv2 arm cris --lappend cpus_expected d10v d30v fr30 fr500 fr550 h8 hppa i386 i860 i960 iamcu ip2022 -+lappend cpus_expected aarch64 alpha am33-2 arc ARC700 ARCv2 arm cris d10v d30v -+lappend cpus_expected fr30 fr500 fr550 h8 hppa i386 i860 i960 iamcu ip2022 Loongarch64 - lappend cpus_expected m16c m32c m32r m68hc11 m68hc12 m68k m88k MCore mep c5 h1 MicroBlaze - lappend cpus_expected mips mn10200 mn10300 ms1 msp MSP430 nds32 n1h_v3 ns32k - lappend cpus_expected or1k or1knd pj powerpc pyramid riscv romp rs6000 s390 sh sparc -diff --git a/gas/Makefile.am b/gas/Makefile.am -index 758f41dc..3ae74dab 100644 ---- a/gas/Makefile.am -+++ b/gas/Makefile.am -@@ -156,6 +156,7 @@ TARGET_CPU_CFILES = \ - config/tc-ip2k.c \ - config/tc-iq2000.c \ - config/tc-lm32.c \ -+ config/tc-loongarch.c \ - config/tc-m32c.c \ - config/tc-m32r.c \ - config/tc-m68hc11.c \ -@@ -233,6 +234,7 @@ TARGET_CPU_HFILES = \ - config/tc-ip2k.h \ - config/tc-iq2000.h \ - config/tc-lm32.h \ -+ config/tc-loongarch.h \ - config/tc-m32c.h \ - config/tc-m32r.h \ - config/tc-m68hc11.h \ -@@ -380,7 +382,8 @@ EXTRA_SCRIPTS = .gdbinit - EXTRA_DIST = m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c \ - bfin-parse.c bfin-parse.h bfin-lex.c \ - rl78-parse.c rl78-parse.h \ -- rx-parse.c rx-parse.h -+ rx-parse.c rx-parse.h \ -+ loongarch-parse.c loongarch-parse.h loongarch-lex.c - - diststuff: $(EXTRA_DIST) info - -@@ -521,6 +524,24 @@ rx-parse.h: rx-parse.c - rx-defs.h: ; @true - $(srcdir)/config/rx-defs.h: ; @true - -+EXTRA_as_new_SOURCES += config/loongarch-parse.y -+loongarch-parse.c loongarch-parse.h: $(srcdir)/config/loongarch-parse.y -+ $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-parse.y y.tab.c loongarch-parse.c y.tab.h loongarch-parse.h -- $(YACCCOMPILE) -d ; -+ -+loongarch-lex.c: $(srcdir)/config/loongarch-lex.l -+ $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-lex.l lex.yy.c loongarch-lex.c -- $(LEXCOMPILE) -+loongarch-lex-wrapper.@OBJEXT@: $(srcdir)/config/loongarch-lex-wrapper.c loongarch-lex.c loongarch-parse.h -+if am__fastdepCC -+ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $(srcdir)/config/loongarch-lex-wrapper.c $(NO_WERROR) -+ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -+else -+if AMDEP -+ source='loongarch-lex-wrapper.c' object='$@' libtool=no @AMDEPBACKSLASH@ -+ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+endif -+ $(COMPILE) -c $(srcdir)/config/loongarch-lex-wrapper.c $(NO_WERROR) -+endif -+ - # The instruction table specification lexical analyzer and parser. - - # Disable -Werror, if it has been enabled, since old versions of bison/ -diff --git a/gas/Makefile.in b/gas/Makefile.in -index b55f2b88..d59a936a 100644 ---- a/gas/Makefile.in -+++ b/gas/Makefile.in -@@ -80,6 +80,7 @@ DIST_COMMON = NEWS README ChangeLog $(srcdir)/Makefile.in \ - $(srcdir)/../mkinstalldirs $(srcdir)/gdbinit.in \ - $(srcdir)/gdbinit.in $(top_srcdir)/po/Make-in m68k-parse.c \ - bfin-parse.c rl78-parse.c rx-parse.c itbl-parse.c itbl-lex.c \ -+ loongarch-parse.c loongarch-lex.c \ - $(srcdir)/../depcomp $(srcdir)/../ylwrap - ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 - am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \ -@@ -451,6 +452,7 @@ TARGET_CPU_CFILES = \ - config/tc-ip2k.c \ - config/tc-iq2000.c \ - config/tc-lm32.c \ -+ config/tc-loongarch.c \ - config/tc-m32c.c \ - config/tc-m32r.c \ - config/tc-m68hc11.c \ -@@ -528,6 +530,7 @@ TARGET_CPU_HFILES = \ - config/tc-ip2k.h \ - config/tc-iq2000.h \ - config/tc-lm32.h \ -+ config/tc-loongarch.h \ - config/tc-m32c.h \ - config/tc-m32r.h \ - config/tc-m68hc11.h \ -@@ -666,6 +669,7 @@ POTFILES = $(MULTI_CFILES) $(CONFIG_ATOF_CFILES) \ - noinst_SCRIPTS = $(GDBINIT) - EXTRA_SCRIPTS = .gdbinit - EXTRA_DIST = m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c \ -+ loongarch-parse.c loongarch-parse.h loongarch-lex.c \ - bfin-parse.c bfin-parse.h bfin-lex.c \ - rl78-parse.c rl78-parse.h \ - rx-parse.c rx-parse.h -@@ -706,7 +710,7 @@ EXTRA_as_new_SOURCES = $(CFILES) $(HFILES) $(TARGET_CPU_CFILES) \ - $(TARGET_CPU_HFILES) $(OBJ_FORMAT_CFILES) $(OBJ_FORMAT_HFILES) \ - $(TARG_ENV_CFILES) $(CONFIG_ATOF_CFILES) $(MULTI_CFILES) \ - config/m68k-parse.y config/bfin-parse.y config/rl78-parse.y \ -- config/rx-parse.y -+ config/rx-parse.y config/loongarch-parse.y - EXPECT = expect - RUNTEST = runtest - RUNTESTFLAGS = -@@ -841,6 +845,8 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/itbl-parse.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listing.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/literal.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loongarch-parse.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loongarch-lex.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m68k-parse.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macro.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messages.Po@am__quote@ -@@ -888,6 +894,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-ip2k.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-iq2000.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-lm32.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-loongarch.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m32c.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m32r.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m68hc11.Po@am__quote@ -@@ -1325,6 +1332,34 @@ tc-lm32.obj: config/tc-lm32.c - @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ - @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-lm32.obj `if test -f 'config/tc-lm32.c'; then $(CYGPATH_W) 'config/tc-lm32.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-lm32.c'; fi` - -+tc-loongarch.o: config/tc-loongarch.c -+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-loongarch.o -MD -MP -MF $(DEPDIR)/tc-loongarch.Tpo -c -o tc-loongarch.o `test -f 'config/tc-loongarch.c' || echo '$(srcdir)/'`config/tc-loongarch.c -+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-loongarch.Tpo $(DEPDIR)/tc-loongarch.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-loongarch.c' object='tc-loongarch.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-loongarch.o `test -f 'config/tc-loongarch.c' || echo '$(srcdir)/'`config/tc-loongarch.c -+ -+loongarch-parse.o: config/loongarch-parse.c loongarch-parse.h -+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT loongarch-parse.o -MD -MP -MF $(DEPDIR)/loongarch-parse.Tpo -c -o loongarch-parse.o `test -f 'config/loongarch-parse.c' || echo '$(srcdir)/'`config/loongarch-parse.c -+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/loongarch-parse.Tpo $(DEPDIR)/loongarch-parse.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/loongarch-parse.c' object='loongarch-parse.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o loongarch-parse.o `test -f 'config/loongarch-parse.c' || echo '$(srcdir)/'`config/loongarch-parse.c -+ -+loongarch-lex.o: config/loongarch-lex.c -+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT loongarch-lex.o -MD -MP -MF $(DEPDIR)/loongarch-lex.Tpo -c -o loongarch-lex.o `test -f 'config/loongarch-lex.c' || echo '$(srcdir)/'`config/loongarch-lex.c -+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/loongarch-lex.Tpo $(DEPDIR)/loongarch-lex.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/loongarch-lex.c' object='loongarch-lex.o' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o loongarch-lex.o `test -f 'config/loongarch-lex.c' || echo '$(srcdir)/'`config/loongarch-lex.c -+ -+tc-loongarch.obj: config/tc-loongarch.c -+@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-loongarch.obj -MD -MP -MF $(DEPDIR)/tc-loongarch.Tpo -c -o tc-loongarch.obj `if test -f 'config/tc-loongarch.c'; then $(CYGPATH_W) 'config/tc-loongarch.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-loongarch.c'; fi` -+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-loongarch.Tpo $(DEPDIR)/tc-loongarch.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-loongarch.c' object='tc-loongarch.obj' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-loongarch.obj `if test -f 'config/tc-loongarch.c'; then $(CYGPATH_W) 'config/tc-loongarch.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-loongarch.c'; fi` -+ - tc-m32c.o: config/tc-m32c.c - @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-m32c.o -MD -MP -MF $(DEPDIR)/tc-m32c.Tpo -c -o tc-m32c.o `test -f 'config/tc-m32c.c' || echo '$(srcdir)/'`config/tc-m32c.c - @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-m32c.Tpo $(DEPDIR)/tc-m32c.Po -@@ -2485,6 +2520,8 @@ maintainer-clean-generic: - -rm -f bfin-parse.c - -rm -f itbl-lex.c - -rm -f itbl-parse.c -+ -rm -f loongarch-parse.c -+ -rm -f loongarch-lex.c - -rm -f m68k-parse.c - -rm -f rl78-parse.c - -rm -f rx-parse.c -@@ -2642,6 +2679,19 @@ m68k-parse.@OBJEXT@: m68k-parse.c - # Don't let the .y.h rule clobber m68k-parse.h. - m68k-parse.h: ; @true - $(srcdir)/config/m68k-parse.h: ; @true -+ -+loongarch-parse.c loongarch-parse.h: $(srcdir)/config/loongarch-parse.y -+ $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-parse.y y.tab.c loongarch-parse.c y.tab.h loongarch-parse.h -- $(YACCCOMPILE) -d ; -+ -+loongarch-lex.c: $(srcdir)/config/loongarch-lex.l -+ $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-lex.l lex.yy.c loongarch-lex.c -- $(LEXCOMPILE) -+loongarch-lex-wrapper.@OBJEXT@: $(srcdir)/config/loongarch-lex-wrapper.c loongarch-lex.c loongarch-parse.h -+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $(srcdir)/config/loongarch-lex-wrapper.c $(NO_WERROR) -+@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='loongarch-lex-wrapper.c' object='$@' libtool=no @AMDEPBACKSLASH@ -+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -+@am__fastdepCC_FALSE@ $(COMPILE) -c $(srcdir)/config/loongarch-lex-wrapper.c $(NO_WERROR) -+ - bfin-parse.c: $(srcdir)/config/bfin-parse.y - $(SHELL) $(YLWRAP) $(srcdir)/config/bfin-parse.y y.tab.c bfin-parse.c y.tab.h bfin-parse.h -- $(YACCCOMPILE) -d ; - bfin-parse.h: bfin-parse.c -diff --git a/gas/config/loongarch-lex-wrapper.c b/gas/config/loongarch-lex-wrapper.c -new file mode 100644 -index 00000000..8ddf1dd2 ---- /dev/null -+++ b/gas/config/loongarch-lex-wrapper.c -@@ -0,0 +1,25 @@ -+/* Copyright (C) 2012-2018 Free Software Foundation, Inc. -+ -+ This file is part of GAS, the GNU Assembler. -+ -+ GAS 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. -+ -+ GAS 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 GAS; see the file COPYING. If not, write to the Free -+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA -+ 02110-1301, USA. */ -+ -+/* The C source file generated by flex includes stdio.h before any of -+ the C code in bfin-lex.l. Make sure we include sysdep.h first, so -+ that config.h can set the correct values for various things. */ -+ -+#include "sysdep.h" -+#include "loongarch-lex.c" -diff --git a/gas/config/loongarch-lex.l b/gas/config/loongarch-lex.l -new file mode 100644 -index 00000000..d88fc93a ---- /dev/null -+++ b/gas/config/loongarch-lex.l -@@ -0,0 +1,39 @@ -+%option noyywrap -+%{ -+#include "as.h" -+#include "loongarch-parse.h" -+%} -+ -+D [0-9] -+/* We consider anything greater than \x7f to be a "letter" for UTF-8 -+ support. See the lex_type array in ../read.c. */ -+L [a-zA-Z_\.\$\x80-\xff] -+H [0-9A-Fa-f] -+ -+hex 0[xX]{H}+ -+oct 0[0-7]+ -+bin 0[bB][01]+ -+dec ([1-9]{D}*)|0 -+id ({D}+[fb])|({L}({D}|{L})*)|(:{dec}[bf]) -+ws [ \t\v\f]+ -+ -+%% -+ -+{dec} { yylval.imm = strtoull (yytext, 0, 0); return INTEGER; } -+{hex} { yylval.imm = strtoull (yytext + 2, 0, 16); return INTEGER; } -+{bin} { yylval.imm = strtoull (yytext + 2, 0, 2); return INTEGER; } -+{oct} { yylval.imm = strtoull (yytext + 1, 0, 8); return INTEGER; } -+{id} { yylval.c_str = strdup (yytext);return IDENTIFIER; } -+{ws} { } -+ -+">>" { return RIGHT_OP; } -+"<<" { return LEFT_OP; } -+"&&" { return AND_OP; } -+"||" { return OR_OP; } -+"<=" { return LE_OP; } -+">=" { return GE_OP; } -+"==" { return EQ_OP; } -+"!=" { return NE_OP; } -+. { return yytext[0];} -+ -+%% -diff --git a/gas/config/loongarch-parse.y b/gas/config/loongarch-parse.y -new file mode 100644 -index 00000000..aa7e51f5 ---- /dev/null -+++ b/gas/config/loongarch-parse.y -@@ -0,0 +1,420 @@ -+%{ -+#include "as.h" -+#include "loongarch-parse.h" -+void yyerror(const char *s) {} -+extern int yylex (void); -+extern void yy_scan_string (const char *); -+extern void -+get_internal_label (expressionS *label_expr, -+ unsigned long label, -+ int augend); -+ -+ -+static struct reloc_info *top, *end; -+ -+static expressionS const_0 = -+{ -+ .X_op = O_constant, -+ .X_add_number = 0 -+}; -+ -+static int -+is_const (struct reloc_info *info) -+{ -+ return info->type == BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE -+ && info->value.X_op == O_constant; -+} -+ -+int -+loongarch_parse_expr (const char *expr, -+ struct reloc_info *reloc_stack_top, -+ size_t max_reloc_num, -+ size_t *reloc_num, -+ offsetT *imm) -+{ -+ int ret; -+ top = reloc_stack_top; -+ end = top + max_reloc_num; -+ yy_scan_string (expr); -+ ret = yyparse (); -+ if (ret == 0) -+ { -+ if (is_const (top - 1)) -+ *imm = (--top)->value.X_add_number; -+ else -+ *imm = 0; -+ *reloc_num = top - reloc_stack_top; -+ } -+ return ret; -+} -+ -+static void -+emit_const (offsetT imm) -+{ -+ if (end <= top) -+ as_fatal (_("expr too huge")); -+ top->type = BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE; -+ top->value.X_op = O_constant; -+ top->value.X_add_number = imm; -+ top++; -+} -+ -+static const char * -+my_getExpression (expressionS *ep, const char *str) -+{ -+ char *save_in, *ret; -+ if (*str == ':') -+ { -+ unsigned long j; -+ char *str_1 = (char *) str; -+ str_1++; -+ j = strtol (str_1, &str_1, 10); -+ get_internal_label (ep, j, *str_1 == 'f'); -+ return NULL; -+ } -+ save_in = input_line_pointer; -+ input_line_pointer = (char *)str; -+ expression (ep); -+ ret = input_line_pointer; -+ input_line_pointer = save_in; -+ return ret; -+} -+ -+static void -+reloc (const char *op_c_str, const char *id_c_str, offsetT addend) -+{ -+ expressionS id_sym_expr; -+ -+ if (end <= top) -+ as_fatal (_("expr too huge")); -+ -+ if (id_c_str) -+ { -+ my_getExpression (&id_sym_expr, id_c_str); -+ id_sym_expr.X_add_number += addend; -+ } -+ else -+ { -+ id_sym_expr.X_op = O_constant; -+ id_sym_expr.X_add_number = addend; -+ } -+ -+ if (strcmp (op_c_str, "abs") == 0) -+ { -+ top->value = id_sym_expr; -+ top->type = BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE; -+ top++; -+ } -+ else if (strcmp (op_c_str, "pcrel") == 0) -+ { -+ top->value = id_sym_expr; -+ top->type = BFD_RELOC_LARCH_SOP_PUSH_PCREL; -+ top++; -+ } -+ else if (strcmp (op_c_str, "gprel") == 0) -+ { -+ top->value = id_sym_expr; -+ top->type = BFD_RELOC_LARCH_SOP_PUSH_GPREL; -+ top++; -+ } -+ else if (strcmp (op_c_str, "tprel") == 0) -+ { -+ top->value = id_sym_expr; -+ top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL; -+ top++; -+ } -+ else if (strcmp (op_c_str, "tlsgot") == 0) -+ { -+ top->value = id_sym_expr; -+ top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT; -+ top++; -+ } -+ else if (strcmp (op_c_str, "tlsgd") == 0) -+ { -+ top->value = id_sym_expr; -+ top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_GD; -+ top++; -+ } -+ else if (strcmp (op_c_str, "plt") == 0) -+ { -+ top->value = id_sym_expr; -+ top->type = BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL; -+ top++; -+ } -+ else -+ as_fatal (_("unknown reloc hint: %s"), op_c_str); -+} -+ -+static void -+emit_unary (char op) -+{ -+ struct reloc_info *s_top = top - 1; -+ if (is_const (s_top)) -+ { -+ offsetT opr = s_top->value.X_add_number; -+ switch (op) -+ { -+ case '+': -+ break; -+ case '-': -+ opr = -opr; -+ break; -+ case '~': -+ opr = ~opr; -+ break; -+ case '!': -+ opr = !opr; -+ break; -+ default: -+ abort (); -+ } -+ s_top->value.X_add_number = opr; -+ } -+ else -+ { -+ if (end <= top) -+ as_fatal (_("expr too huge")); -+ switch (op) -+ { -+ case '!': -+ top->type = BFD_RELOC_LARCH_SOP_NOT; -+ default: -+ abort (); -+ } -+ top->value = const_0; -+ top++; -+ } -+} -+ -+static void -+emit_bin (int op) -+{ -+ struct reloc_info *last_1st = top - 1, *last_2nd = top - 2; -+ if (is_const (last_1st) && is_const (last_2nd)) -+ { -+ offsetT opr1 = last_2nd->value.X_add_number; -+ offsetT opr2 = last_1st->value.X_add_number; -+ switch (op) -+ { -+ case '*': -+ opr1 = opr1 * opr2; -+ break; -+ case '/': -+ opr1 = opr1 / opr2; -+ break; -+ case '%': -+ opr1 = opr1 % opr2; -+ break; -+ case '+': -+ opr1 = opr1 + opr2; -+ break; -+ case '-': -+ opr1 = opr1 - opr2; -+ break; -+ case LEFT_OP: -+ opr1 = opr1 << opr2; -+ break; -+ case RIGHT_OP: -+ /* Algorithm right shift */ -+ opr1 = (offsetT)opr1 >> (offsetT)opr2; -+ break; -+ case '<': -+ opr1 = opr1 < opr2; -+ break; -+ case '>': -+ opr1 = opr1 > opr2; -+ break; -+ case LE_OP: -+ opr1 = opr1 <= opr2; -+ break; -+ case GE_OP: -+ opr1 = opr1 >= opr2; -+ break; -+ case EQ_OP: -+ opr1 = opr1 == opr2; -+ break; -+ case NE_OP: -+ opr1 = opr1 != opr2; -+ break; -+ case '&': -+ opr1 = opr1 & opr2; -+ break; -+ case '^': -+ opr1 = opr1 ^ opr2; -+ break; -+ case '|': -+ opr1 = opr1 | opr2; -+ break; -+ case AND_OP: -+ opr1 = opr1 && opr2; -+ break; -+ case OR_OP: -+ opr1 = opr1 || opr2; -+ break; -+ default: -+ abort (); -+ } -+ last_2nd->value.X_add_number = opr1; -+ last_1st->type = 0; -+ top--; -+ } -+ else -+ { -+ if (end <= top) -+ as_fatal (_("expr too huge")); -+ switch (op) -+ { -+ case '+': -+ top->type = BFD_RELOC_LARCH_SOP_ADD; -+ break; -+ case '-': -+ top->type = BFD_RELOC_LARCH_SOP_SUB; -+ break; -+ case LEFT_OP: -+ top->type = BFD_RELOC_LARCH_SOP_SL; -+ break; -+ case RIGHT_OP: -+ top->type = BFD_RELOC_LARCH_SOP_SR; -+ break; -+ case '&': -+ top->type = BFD_RELOC_LARCH_SOP_AND; -+ break; -+ default: -+ abort (); -+ } -+ top->value = const_0; -+ top++; -+ } -+} -+ -+static void -+emit_if_else (void) -+{ -+ struct reloc_info *last_1st = top - 1; -+ struct reloc_info *last_2nd = top - 2; -+ struct reloc_info *last_3rd = top - 3; -+ if (is_const (last_1st) && is_const (last_2nd) && is_const (last_3rd)) -+ { -+ offsetT opr1 = last_3rd->value.X_add_number; -+ offsetT opr2 = last_2nd->value.X_add_number; -+ offsetT opr3 = last_1st->value.X_add_number; -+ opr1 = opr1 ? opr2 : opr3; -+ last_3rd->value.X_add_number = opr1; -+ last_2nd->type = 0; -+ last_1st->type = 0; -+ top -= 2; -+ } -+ else -+ { -+ if (end <= top) -+ as_fatal (_("expr too huge")); -+ top->type = BFD_RELOC_LARCH_SOP_IF_ELSE; -+ top->value = const_0; -+ top++; -+ } -+} -+ -+%} -+ -+%union { -+char *c_str; -+offsetT imm; -+} -+ -+%token INTEGER -+%token IDENTIFIER -+%type addend -+ -+%token LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP AND_OP OR_OP -+%start expression -+%% -+ -+primary_expression -+ : INTEGER {emit_const ($1);} -+ | '(' expression ')' -+ | '%' IDENTIFIER '(' IDENTIFIER addend ')' {reloc ($2, $4, $5); free ($2); free ($4);} -+ | '%' IDENTIFIER '(' INTEGER addend ')' {reloc ($2, NULL, $4 + $5); free ($2);} -+ ; -+ -+addend -+ : addend '-' INTEGER {$$ -= $3;} -+ | addend '+' INTEGER {$$ += $3;} -+ | {$$ = 0;} -+ ; -+ -+unary_expression -+ : primary_expression -+ | '+' unary_expression {emit_unary ('+');} -+ | '-' unary_expression {emit_unary ('-');} -+ | '~' unary_expression {emit_unary ('~');} -+ | '!' unary_expression {emit_unary ('!');} -+ ; -+ -+multiplicative_expression -+ : unary_expression -+ | multiplicative_expression '*' unary_expression {emit_bin ('*');} -+ | multiplicative_expression '/' unary_expression {emit_bin ('/');} -+ | multiplicative_expression '%' unary_expression {emit_bin ('%');} -+ ; -+ -+additive_expression -+ : multiplicative_expression -+ | additive_expression '+' multiplicative_expression {emit_bin ('+');} -+ | additive_expression '-' multiplicative_expression {emit_bin ('-');} -+ ; -+ -+shift_expression -+ : additive_expression -+ | shift_expression LEFT_OP additive_expression {emit_bin (LEFT_OP);} -+ | shift_expression RIGHT_OP additive_expression {emit_bin (RIGHT_OP);} -+ ; -+ -+relational_expression -+ : shift_expression -+ | relational_expression '<' shift_expression {emit_bin ('<');} -+ | relational_expression '>' shift_expression {emit_bin ('>');} -+ | relational_expression LE_OP shift_expression {emit_bin (LE_OP);} -+ | relational_expression GE_OP shift_expression {emit_bin (GE_OP);} -+ ; -+ -+equality_expression -+ : relational_expression -+ | equality_expression EQ_OP relational_expression {emit_bin (EQ_OP);} -+ | equality_expression NE_OP relational_expression {emit_bin (NE_OP);} -+ ; -+ -+and_expression -+ : equality_expression -+ | and_expression '&' equality_expression {emit_bin ('&');} -+ ; -+ -+exclusive_or_expression -+ : and_expression -+ | exclusive_or_expression '^' and_expression {emit_bin ('^');} -+ ; -+ -+inclusive_or_expression -+ : exclusive_or_expression -+ | inclusive_or_expression '|' exclusive_or_expression {emit_bin ('|');} -+ ; -+ -+logical_and_expression -+ : inclusive_or_expression -+ | logical_and_expression AND_OP inclusive_or_expression {emit_bin (AND_OP);} -+ ; -+ -+logical_or_expression -+ : logical_and_expression -+ | logical_or_expression OR_OP logical_and_expression {emit_bin (OR_OP);} -+ ; -+ -+conditional_expression -+ : logical_or_expression -+ | logical_or_expression '?' expression ':' conditional_expression {emit_if_else ();} -+ ; -+ -+expression -+ : conditional_expression -+ ; -+%% -+ -diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c -new file mode 100644 -index 00000000..9c4a9102 ---- /dev/null -+++ b/gas/config/tc-loongarch.c -@@ -0,0 +1,1328 @@ -+#include "as.h" -+#include "dw2gencfi.h" -+#include "tc-loongarch.h" -+#include "elf/loongarch.h" -+#include "opcode/loongarch.h" -+#include "obj-elf.h" -+#include -+#include -+#include -+#include -+ -+/* All information about an instruction during assemble */ -+struct loongarch_cl_insn -+{ -+ /* First split string */ -+ const char *name; -+ const char *arg_strs[MAX_ARG_NUM_PLUS_2]; -+ size_t arg_num; -+ -+ /* Second analyze name_str and each actual args string to match the insn -+ in 'loongarch-opc.c'. And actual args may need be relocated. -+ We get length of insn. If 'insn_length == 0 && insn_mo->macro != NULL', -+ it's a macro insntruction and we call 'md_assemble' recursively -+ after expanding it. */ -+ int match_now; -+ int all_match; -+ -+ const struct loongarch_opcode *insn; -+ size_t insn_length; -+ -+ offsetT args[MAX_ARG_NUM_PLUS_2]; -+ struct reloc_info reloc_info[MAX_RELOC_NUMBER_A_INSN]; -+ size_t reloc_num; -+ -+ /* For relax reserved. We not support relax now. -+ 'insn_length < relax_max_length' means need to relax. -+ And 'insn_length == relax_max_length' means no need to relax. */ -+ size_t relax_max_length; -+ relax_substateT subtype; -+ -+ /* Then we get the binary representation of insn -+ and write it in to section. */ -+ insn_t insn_bin; -+ -+ /* The frag that contains the instruction. */ -+ struct frag *frag; -+ /* The offset into FRAG of the first instruction byte. */ -+ long where; -+ /* The relocs associated with the instruction, if any. */ -+ fixS *fixp[MAX_RELOC_NUMBER_A_INSN]; -+}; -+ -+/* This array holds the chars that always start a comment. If the -+ pre-processor is disabled, these aren't very useful */ -+const char comment_chars[] = "#"; -+ -+/* This array holds the chars that only start a comment at the beginning of -+ a line. If the line seems to have the form '# 123 filename' -+ .line and .file directives will appear in the pre-processed output */ -+/* Note that input_file.c hand checks for '#' at the beginning of the -+ first line of the input file. This is because the compiler outputs -+#NO_APP at the beginning of its output. */ -+/* Also note that C style comments are always supported. */ -+const char line_comment_chars[] = "#"; -+ -+/* This array holds machine specific line separator characters. */ -+const char line_separator_chars[] = ";"; -+ -+/* Chars that can be used to separate mant from exp in floating point nums */ -+const char EXP_CHARS[] = "eE"; -+ -+/* Chars that mean this number is a floating point constant */ -+/* As in 0f12.456 */ -+/* or 0d1.2345e12 */ -+const char FLT_CHARS[] = "rRsSfFdDxXpP"; -+ -+const char *md_shortopts = "O::g::G:"; -+ -+enum options -+{ -+ OPTION_IGNORE = OPTION_MD_BASE, -+ -+ OPTION_SOFT_FLOAT, -+ OPTION_HARD_FLOAT, -+ OPTION_ABI, -+ -+ OPTION_LA_LOCAL_WITH_ABS, -+ OPTION_LA_GLOBAL_WITH_PCREL, -+ OPTION_LA_GLOBAL_WITH_ABS, -+ -+ OPTION_END_OF_ENUM, -+}; -+ -+struct option md_longopts[] = -+{ -+ {"msoft-float", no_argument, NULL, OPTION_SOFT_FLOAT}, -+ {"mhard-float", no_argument, NULL, OPTION_HARD_FLOAT}, -+ {"mabi", required_argument, NULL, OPTION_ABI}, -+ -+ {"mla-local-with-abs", no_argument, NULL, OPTION_LA_LOCAL_WITH_ABS}, -+ {"mla-global-with-pcrel", no_argument, NULL, OPTION_LA_GLOBAL_WITH_PCREL}, -+ {"mla-global-with-abs", no_argument, NULL, OPTION_LA_GLOBAL_WITH_ABS}, -+ -+ {NULL, no_argument, NULL, 0} -+}; -+ -+size_t md_longopts_size = sizeof (md_longopts); -+ -+int -+md_parse_option (int c, const char *arg) -+{ -+ int ret = 1; -+ switch (c) -+ { -+ case OPTION_SOFT_FLOAT: -+ LARCH_opts.ase_float = 0; -+ break; -+ case OPTION_HARD_FLOAT: -+ LARCH_opts.ase_float = 1; -+ break; -+ case OPTION_ABI: -+ if (strcasecmp (arg, "lp64") == 0) -+ LARCH_opts.abi_is_lp64 = 1; -+ else if (strcasecmp (arg, "lp32") == 0) -+ LARCH_opts.abi_is_lp32 = 1; -+ else -+ ret = 0; -+ break; -+ case OPTION_LA_LOCAL_WITH_ABS: -+ LARCH_opts.la_local_with_abs = 1; -+ break; -+ case OPTION_LA_GLOBAL_WITH_PCREL: -+ LARCH_opts.la_global_with_pcrel = 1; -+ break; -+ case OPTION_LA_GLOBAL_WITH_ABS: -+ LARCH_opts.la_global_with_abs = 1; -+ break; -+ case OPTION_IGNORE: -+ break; -+ } -+ return ret; -+} -+ -+static struct hash_control *r_htab = NULL; -+static struct hash_control *f_htab = NULL; -+static struct hash_control *c_htab = NULL; -+static struct hash_control *cr_htab = NULL; -+static struct hash_control *v_htab = NULL; -+static struct hash_control *x_htab = NULL; -+ -+void -+loongarch_after_parse_args () -+{ -+ size_t i; -+ -+ LARCH_opts.ase_test = 1; -+ LARCH_opts.ase_fix = 1; -+ LARCH_opts.ase_float = 1; -+ LARCH_opts.ase_128vec = 1; -+ LARCH_opts.ase_256vec = 1; -+ -+ if (!r_htab) -+ r_htab = hash_new (), hash_insert (r_htab, "", 0); -+ if (!f_htab) -+ f_htab = hash_new (), hash_insert (f_htab, "", 0); -+ if (!c_htab) -+ c_htab = hash_new (), hash_insert (c_htab, "", 0); -+ if (!cr_htab) -+ cr_htab = hash_new (), hash_insert (cr_htab, "", 0); -+ if (!v_htab) -+ v_htab = hash_new (), hash_insert (v_htab, "", 0); -+ if (!x_htab) -+ x_htab = hash_new (), hash_insert (x_htab, "", 0); -+ -+ for (i = 0; i < ARRAY_SIZE (loongarch_r_normal_name); i++) -+ hash_insert (r_htab, loongarch_r_normal_name[i], (void *) (i + 1)); -+ for (i = 0; i < ARRAY_SIZE (loongarch_f_normal_name); i++) -+ hash_insert (f_htab, loongarch_f_normal_name[i], (void *) (i + 1)); -+ for (i = 0; i < ARRAY_SIZE (loongarch_c_normal_name); i++) -+ hash_insert (c_htab, loongarch_c_normal_name[i], (void *) (i + 1)); -+ for (i = 0; i < ARRAY_SIZE (loongarch_cr_normal_name); i++) -+ hash_insert (cr_htab, loongarch_cr_normal_name[i], (void *) (i + 1)); -+ for (i = 0; i < ARRAY_SIZE (loongarch_v_normal_name); i++) -+ hash_insert (v_htab, loongarch_v_normal_name[i], (void *) (i + 1)); -+ for (i = 0; i < ARRAY_SIZE (loongarch_x_normal_name); i++) -+ hash_insert (x_htab, loongarch_x_normal_name[i], (void *) (i + 1)); -+ -+ if (LARCH_opts.abi_is_lp64 -+ + LARCH_opts.abi_is_lp32 -+ == 0) -+ { -+ // as_warn (_("default LoongISA ABI is lp64")); -+ LARCH_opts.abi_is_lp64 = 1; -+ } -+ -+ if (1 < LARCH_opts.abi_is_lp64 -+ + LARCH_opts.abi_is_lp32) -+ as_fatal (_("we can specify only ONE abi")); -+ -+ if (LARCH_opts.abi_is_lp64) -+ { -+ LARCH_opts.addrwidth_is_64 = 1; -+ LARCH_opts.rlen_is_64 = 1; -+ for (i = 0; i < ARRAY_SIZE (loongarch_r_lp64_name); i++) -+ hash_insert (r_htab, loongarch_r_lp64_name[i], (void *) (i + 1)); -+ for (i = 0; i < ARRAY_SIZE (loongarch_r_lp64_name1); i++) -+ hash_insert (r_htab, loongarch_r_lp64_name1[i], (void *) (i + 1)); -+ for (i = 0; i < ARRAY_SIZE (loongarch_f_lp64_name); i++) -+ hash_insert (f_htab, loongarch_f_lp64_name[i], (void *) (i + 1)); -+ for (i = 0; i < ARRAY_SIZE (loongarch_f_lp64_name1); i++) -+ hash_insert (f_htab, loongarch_f_lp64_name1[i], (void *) (i + 1)); -+ } -+ -+ if (LARCH_opts.abi_is_lp32) -+ { -+ LARCH_opts.addrwidth_is_32 = 1; -+ LARCH_opts.rlen_is_32 = 1; -+ } -+ -+} -+ -+const char * -+loongarch_target_format () -+{ -+ return LARCH_opts.addrwidth_is_32? "elf32-loongarch" : "elf64-loongarch"; -+} -+ -+void -+md_begin () -+{ -+ if (LARCH_opts.ase_test) -+ { -+ const struct loongarch_opcode *it; -+ struct loongarch_ase *ase; -+ for (ase = loongarch_ASEs; ase->enabled; ase++) -+ for (it = ase->opcodes; it->name; it++) -+ { -+ if (loongarch_check_format (it->format) != 0) -+ as_fatal (_("insn name: %s\tformat: %s\tsyntax error"), -+ it->name, it->format); -+ if (it->mask == 0 && it->macro == 0) -+ as_fatal (_("insn name: %s\nformat: %s\nwe want macro but macro is NULL"), -+ it->name, it->format); -+ if (it->macro && loongarch_check_macro (it->format, it->macro) != 0) -+ as_fatal (_("insn name: %s\nformat: %s\nmacro: %s\tsyntax error"), -+ it->name, it->format, it->macro); -+ } -+ } -+ -+ /* FIXME: expressionS use 'offsetT' as constant, we want this is 64-bit type */ -+ assert (8 <= sizeof (offsetT)); -+} -+ -+void -+md_operand (expressionS *e) -+{ -+ /* Because we use 'expression' to check if a actual arg is a expr at first. -+ If not, we want a returning. */ -+ if (e->X_op == O_absent) -+ e->X_op = O_illegal; -+} -+ -+static const expressionS const_0 = {.X_op = O_constant, .X_add_number = 0}; -+ -+static const char * -+my_getExpression (expressionS *ep, const char *str) -+{ -+ char *save_in, *ret; -+ save_in = input_line_pointer; -+ input_line_pointer = (char *)str; -+ expression (ep); -+ ret = input_line_pointer; -+ input_line_pointer = save_in; -+ return ret; -+} -+ -+ -+/* for compitable with MIPS pesudo insn like '.set reorder' -+ but actually ignore them. */ -+static void -+s_loongarch_set (int x ATTRIBUTE_UNUSED) -+{ -+ char *name = input_line_pointer, ch; -+ -+ while (!is_end_of_line[(unsigned char) *input_line_pointer]) -+ ++input_line_pointer; -+ ch = *input_line_pointer; -+ *input_line_pointer = '\0'; -+ -+ if (strchr (name, ',')) -+ { -+ /* Generic ".set" directive; use the generic handler. */ -+ *input_line_pointer = ch; -+ input_line_pointer = name; -+ s_set (0); -+ return; -+ } -+ -+ *input_line_pointer = ch; -+ demand_empty_rest_of_line (); -+} -+ -+static void -+s_loongarch_align (int arg) -+{ -+ const char *t = input_line_pointer; -+ while (!is_end_of_line[(unsigned char) *t] && *t != ',') -+ ++t; -+ if (*t == ',') -+ s_align_ptwo (arg); -+ else -+ s_align_ptwo (0); -+} -+ -+/* Handle the .dtprelword and .dtpreldword pseudo-ops. They generate -+ a 32-bit or 64-bit DTP-relative relocation (BYTES says which) for -+ use in DWARF debug information. */ -+ -+static void -+s_dtprel (int bytes) -+{ -+ expressionS ex; -+ char *p; -+ -+ expression (&ex); -+ -+ if (ex.X_op != O_symbol) -+ { -+ as_bad (_("Unsupported use of %s"), (bytes == 8 -+ ? ".dtpreldword" -+ : ".dtprelword")); -+ ignore_rest_of_line (); -+ } -+ -+ p = frag_more (bytes); -+ md_number_to_chars (p, 0, bytes); -+ fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE, -+ (bytes == 8 -+ ? BFD_RELOC_LARCH_TLS_DTPREL64 -+ : BFD_RELOC_LARCH_TLS_DTPREL32)); -+ -+ demand_empty_rest_of_line (); -+} -+ -+static const pseudo_typeS loongarch_pseudo_table[] = -+{ -+ {"align", s_loongarch_align, -4}, -+ {"dword", cons, 8}, -+ {"word", cons, 4}, -+ {"half", cons, 2}, -+ {"dtprelword", s_dtprel, 4}, -+ {"dtpreldword", s_dtprel, 8}, -+ { NULL, NULL, 0 }, -+}; -+ -+void -+loongarch_pop_insert (void) -+{ -+ pop_insert (loongarch_pseudo_table); -+} -+ -+ -+#define INTERNAL_LABEL_SPECIAL 10 -+static unsigned long internal_label_count[INTERNAL_LABEL_SPECIAL] = {0}; -+ -+static const char * -+loongarch_internal_label_name (unsigned long label, int augend) -+{ -+ static char symbol_name_build[24]; -+ unsigned long want_label; -+ char *p; -+ -+ want_label = internal_label_count[label] + augend; -+ -+ p = symbol_name_build; -+#ifdef LOCAL_LABEL_PREFIX -+ *p++ = LOCAL_LABEL_PREFIX; -+#endif -+ *p++ = 'L'; -+ for (; label; label /= 10) -+ *p++ = label % 10 + '0'; -+ /* make sure internal label never belong to normal label namespace */ -+ *p++ = ':'; -+ for (; want_label; want_label /= 10) -+ *p++ = want_label % 10 + '0'; -+ *p++ = '\0'; -+ return symbol_name_build; -+} -+ -+static void -+setup_internal_label_here (unsigned long label) -+{ -+ assert (label < INTERNAL_LABEL_SPECIAL); -+ internal_label_count[label]++; -+ colon (loongarch_internal_label_name (label ,0)); -+} -+ -+extern void /* no static. used by 'loongarch-parse.y' */ -+get_internal_label (expressionS *label_expr, -+ unsigned long label, -+ int augend/* 0 for previous, 1 for next */); -+ -+void -+get_internal_label (expressionS *label_expr, -+ unsigned long label, -+ int augend/* 0 for previous, 1 for next */) -+{ -+ assert (label < INTERNAL_LABEL_SPECIAL); -+ if (augend == 0 && internal_label_count[label] == 0) -+ as_fatal (_("internal error: we have no internal label yet")); -+ label_expr->X_op = O_symbol; -+ label_expr->X_add_symbol = -+ symbol_find_or_make (loongarch_internal_label_name (label, augend)); -+ label_expr->X_add_number = 0; -+} -+ -+extern int loongarch_parse_expr (const char *expr, -+ struct reloc_info *reloc_stack_top, -+ size_t max_reloc_num, size_t *reloc_num, -+ offsetT *imm_if_no_reloc); -+ -+int -+is_internal_label (const char *c_str) -+{ -+ do -+ { -+ if (*c_str != ':') -+ break; -+ c_str++; -+ if (!('0' <= *c_str && *c_str <= '9')) -+ break; -+ while ('0' <= *c_str && *c_str <= '9') -+ c_str++; -+ if (*c_str != 'b' && *c_str != 'f') -+ break; -+ c_str++; -+ return *c_str == '\0'; -+ } -+ while (0); -+ return 0; -+} -+ -+int -+is_label (const char *c_str) -+{ -+ if (is_internal_label (c_str)) -+ return 1; -+ else if ('0' <= *c_str && *c_str <= '9') -+ { -+ /* [0-9]+[bf] */ -+ while ('0' <= *c_str && *c_str <= '9') -+ c_str++; -+ return *c_str == 'b' || *c_str == 'f'; -+ } -+ else if (is_name_beginner (*c_str)) -+ { -+ /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */ -+ c_str++; -+ while (is_part_of_name (*c_str)) -+ c_str++; -+ return *c_str == '\0'; -+ } -+ else -+ return 0; -+} -+ -+int -+is_label_with_addend (const char *c_str) -+{ -+ if (is_internal_label (c_str)) -+ return 1; -+ else if ('0' <= *c_str && *c_str <= '9') -+ { -+ /* [0-9]+[bf] */ -+ while ('0' <= *c_str && *c_str <= '9') -+ c_str++; -+ if (*c_str == 'b' || *c_str == 'f') -+ c_str++; -+ else -+ return 0; -+ return *c_str == '\0' -+ || ((*c_str == '-' || *c_str == '+') -+ && is_unsigned (c_str + 1)); -+ } -+ else if (is_name_beginner (*c_str)) -+ { -+ /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */ -+ c_str++; -+ while (is_part_of_name (*c_str)) -+ c_str++; -+ return *c_str == '\0' -+ || ((*c_str == '-' || *c_str == '+') -+ && is_unsigned (c_str + 1)); -+ } -+ else -+ return 0; -+} -+ -+extern int -+loongarch_parse_expr (const char *expr, -+ struct reloc_info *reloc_stack_top, -+ size_t max_reloc_num, -+ size_t *reloc_num, -+ offsetT *imm_if_no_reloc); -+ -+static int32_t -+loongarch_args_parser_can_match_arg_helper (char esc_ch1, -+ char esc_ch2, -+ const char *bit_field, -+ const char *arg, -+ void *context) -+{ -+ struct loongarch_cl_insn *ip = context; -+ offsetT imm, ret = 0; -+ size_t reloc_num_we_have = MAX_RELOC_NUMBER_A_INSN - ip->reloc_num; -+ size_t reloc_num = 0; -+ -+ if (!ip->match_now) -+ return 0; -+ -+ switch (esc_ch1) -+ { -+ case 'l': -+ switch (esc_ch2) -+ { -+ default: -+ ip->match_now = is_label (arg); -+ if (!ip->match_now && is_label_with_addend (arg)) -+ as_fatal (_("This label shouldn't be with addend.")); -+ break; -+ case 'a': -+ ip->match_now = is_label_with_addend (arg); -+ break; -+ } -+ break; -+ case 's': -+ case 'u': -+ ip->match_now = -+ loongarch_parse_expr (arg, ip->reloc_info + ip->reloc_num, -+ reloc_num_we_have, &reloc_num, &imm) == 0; -+ -+ if (!ip->match_now) -+ break; -+ -+ if (esc_ch1 == 's') -+ switch (esc_ch2) -+ { -+ case 'c': -+ ip->match_now = reloc_num == 0; -+ break; -+ } -+ else -+ switch (esc_ch2) -+ { -+ case 'c': -+ ip->match_now = reloc_num == 0 && 0 <= imm; -+ break; -+ } -+ -+ if (!ip->match_now) -+ break; -+ -+ ret = imm; -+ if (reloc_num) -+ { -+ bfd_reloc_code_real_type reloc_type = BFD_RELOC_NONE; -+ reloc_num_we_have -= reloc_num; -+ if (reloc_num_we_have == 0) -+ as_fatal (_("expr too huge") /* want one more reloc */); -+ if (esc_ch1 == 'u') -+ { -+ if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0) -+ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_U_10_12; -+ } -+ else if (esc_ch1 == 's') -+ { -+ if (strncmp (bit_field, "10:16<<2", strlen ("10:16<<2")) == 0) -+ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2; -+ else if (strncmp (bit_field, "0:5|10:16<<2", strlen ("0:5|10:16<<2")) == 0) -+ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2; -+ else if (strncmp (bit_field, "0:10|10:16<<2", strlen ("0:10|10:16<<2")) == 0) -+ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2; -+ else if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0) -+ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_12; -+ else if (strncmp (bit_field, "5:20", strlen ("5:20")) == 0) -+ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_5_20; -+ else if (strncmp (bit_field, "10:16", strlen ("10:16")) == 0) -+ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16; -+ else if (strncmp (bit_field, "10:5", strlen ("10:5")) == 0) -+ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_5; -+ } -+ if (reloc_type == BFD_RELOC_NONE) -+ as_fatal (_("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"), -+ esc_ch1, esc_ch2, bit_field , arg); -+ reloc_num++; -+ ip->reloc_num += reloc_num; -+ ip->reloc_info[ip->reloc_num - 1].type = reloc_type; -+ ip->reloc_info[ip->reloc_num - 1].value = const_0; -+ } -+ break; -+ case 'r': -+ imm = (offsetT) hash_find (r_htab, arg); -+ ip->match_now = 0 < imm; -+ ret = imm - 1; -+ break; -+ case 'f': -+ imm = (offsetT) hash_find (f_htab, arg); -+ ip->match_now = 0 < imm; -+ ret = imm - 1; -+ break; -+ case 'c': -+ switch (esc_ch2) -+ { -+ case 'r': -+ imm = (offsetT) hash_find (cr_htab, arg); -+ break; -+ default: -+ imm = (offsetT) hash_find (c_htab, arg); -+ } -+ ip->match_now = 0 < imm; -+ ret = imm - 1; -+ break; -+ case 'v': -+ imm = (offsetT) hash_find (v_htab, arg); -+ ip->match_now = 0 < imm; -+ ret = imm - 1; -+ break; -+ case 'x': -+ imm = (offsetT) hash_find (x_htab, arg); -+ ip->match_now = 0 < imm; -+ ret = imm - 1; -+ break; -+ case '\0': -+ ip->all_match = ip->match_now; -+ ip->insn_length = ip->insn->mask ? loongarch_insn_length (ip->insn->match) : 0; -+ /* FIXME: now we have no relax insn */ -+ ip->relax_max_length = ip->insn_length; -+ break; -+ default: -+ as_fatal (_("unknown escape")); -+ } -+ -+ do -+ { -+ // check imm overflow -+ int bit_width, bits_needed_s, bits_needed_u; -+ char *t; -+ -+ if (!ip->match_now) -+ break; -+ -+ if (0 < reloc_num) -+ break; -+ -+ bit_width = loongarch_get_bit_field_width (bit_field, &t); -+ -+ if (bit_width == -1) -+ // no specify bit width -+ break; -+ -+ // 在这里求出实际填入的二进制数。这部分内容和 loongarch_encode_imm -+ // 有重合。但是需要在这里加入一些判断内容,比如分支指令立即数 -+ // 右移两位,要保证立即数低两位为0 -+ imm = ret; -+ if (t[0] == '<' && t[1] == '<') -+ { -+ int i = strtol (t += 2, &t, 10), j; -+ for (j = i; 0 < j; j--, imm >>= 1) -+ if (imm & 1) -+ as_fatal (_("require imm low %d bit is 0."), i); -+ } -+ -+ if (*t == '+') -+ imm -= strtol (t, &t, 10); -+ -+ bits_needed_s = loongarch_bits_imm_needed (imm, 1); -+ bits_needed_u = loongarch_bits_imm_needed (imm, 0); -+ -+ // 在这里判断立即数是否溢出。关于有符号立即数我有两种理解 -+ // 一是代数意义上的溢出,如果传入的值超出定义域,那么报错。 -+ // 二是程序员可能希望指定位域表示,那么值可能是一个使得符号位为1的正数。 -+ // riscv的溢出判断是第一种,这里按照riscv的方法来做 -+ if ((esc_ch1 == 's' && bit_width < bits_needed_s) -+ || (esc_ch1 != 's' && bit_width < bits_needed_u)) -+ // how to do after we detect overflow -+ as_fatal (_("Immediate overflow.\n" -+ "format: %c%c%s\n" -+ "arg: %s"), -+ esc_ch1, esc_ch2, bit_field, arg); -+ } -+ while (0); -+ -+ if (esc_ch1 != '\0') -+ { -+ ip->args[ip->arg_num] = ret; -+ ip->arg_num++; -+ } -+ return ret; -+} -+ -+static void -+get_loongarch_opcode (struct loongarch_cl_insn *insn) -+{ -+ const struct loongarch_opcode *it; -+ struct loongarch_ase *ase; -+ for (ase = loongarch_ASEs; ase->enabled; ase++) -+ { -+ if (!*ase->enabled -+ || (ase->include && !*ase->include) -+ || (ase->exclude && *ase->exclude)) -+ continue; -+ -+ if (!ase->name_hash_entry) -+ { -+ ase->name_hash_entry = hash_new (); -+ for (it = ase->opcodes; it->name; it++) -+ hash_insert (ase->name_hash_entry, it->name, (void *) it); -+ } -+ -+ if ((it = hash_find (ase->name_hash_entry, insn->name)) == NULL) -+ continue; -+ -+ do -+ { -+ insn->insn = it; -+ insn->match_now = 1; -+ insn->all_match = 0; -+ insn->arg_num = 0; -+ insn->reloc_num = 0; -+ insn->insn_bin = -+ loongarch_foreach_args (it->format, insn->arg_strs, -+ loongarch_args_parser_can_match_arg_helper, insn); -+ if (insn->all_match -+ && !(it->include && !*it->include) -+ && !(it->exclude && *it->exclude)) -+ { -+ insn->insn_bin |= it->match; -+ return; -+ } -+ it++; -+ } -+ while (it->name && strcasecmp (it->name, insn->name) == 0); -+ } -+} -+ -+static int -+check_this_insn_before_appending (struct loongarch_cl_insn *ip) -+{ -+ int ret = 0; -+ if (strcmp (ip->name, "la.abs") == 0) -+ { -+ ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_MARK_LA; -+ my_getExpression (&ip->reloc_info[ip->reloc_num].value, ip->arg_strs[1]); -+ ip->reloc_num++; -+ } -+ else if (ip->insn->mask == 0xffff8000 -+ && ((ip->insn_bin & 0xfff00000) == 0x38600000 -+ || (ip->insn_bin & 0xffff0000) == 0x38700000 -+ || (ip->insn_bin & 0xffff0000) == 0x38710000)) -+ { -+ /* for AMO insn amswap.[wd], amadd.[wd], etc. */ -+ if (ip->args[0] != 0 && -+ (ip->args[0] == ip->args[1] || ip->args[0] == ip->args[2])) -+ as_fatal (_( -+"AMO insns require rd != base && rd != rt when rd isn't $r0")); -+ } -+ else if ((ip->insn->mask == 0xffe08000 -+ && (ip->insn_bin & 0xffe00000) == 0x00600000) -+ || (ip->insn->mask == 0xffc00000 -+ && (ip->insn_bin & 0xff800000) == 0x00800000)) -+ { -+ /* for bstr(ins|pick).[wd] */ -+ if (ip->args[2] < ip->args[3]) -+ as_fatal (_("bstr(ins|pick).[wd] require msbd >= lsbd")); -+ } -+ else if (ip->insn->mask != 0 -+ && (ip->insn_bin & 0xfe0003c0) == 0x04000000 -+ && (strcmp ("csrxchg", ip->name) == 0 -+ || strcmp ("gcsrxchg", ip->name) == 0)) -+ as_fatal (_("g?csrxchg require rj != $r0 && rj != $r1")); -+ -+ return ret; -+} -+ -+static void -+install_insn (const struct loongarch_cl_insn *insn) -+{ -+ char *f = insn->frag->fr_literal + insn->where; -+ if (0 < insn->insn_length) -+ md_number_to_chars (f, insn->insn_bin, insn->insn_length); -+} -+ -+static void -+move_insn (struct loongarch_cl_insn *insn, fragS *frag, long where) -+{ -+ size_t i; -+ insn->frag = frag; -+ insn->where = where; -+ for (i = 0; i < insn->reloc_num; i++) -+ { -+ insn->fixp[i]->fx_frag = frag; -+ insn->fixp[i]->fx_where = where; -+ } -+ install_insn (insn); -+} -+ -+/* Add INSN to the end of the output. */ -+static void -+append_fixed_insn (struct loongarch_cl_insn *insn) -+{ -+ char *f = frag_more (insn->insn_length); -+ move_insn (insn, frag_now, f - frag_now->fr_literal); -+} -+ -+static void -+append_fixp_and_insn (struct loongarch_cl_insn *ip) -+{ -+ reloc_howto_type *howto; -+ bfd_reloc_code_real_type reloc_type; -+ struct reloc_info *reloc_info = ip->reloc_info; -+ size_t i; -+ for (i = 0; i < ip->reloc_num; i++) -+ { -+ reloc_type = reloc_info[i].type; -+ howto = bfd_reloc_type_lookup (stdoutput, reloc_type); -+ if (howto == NULL) -+ as_fatal (_("no HOWTO loong relocation number %d"), reloc_type); -+ -+ ip->fixp[i] = -+ fix_new_exp (ip->frag, ip->where, bfd_get_reloc_size (howto), -+ &reloc_info[i].value, FALSE, reloc_type); -+ } -+ -+ if (ip->insn_length < ip->relax_max_length) -+ as_fatal (_("Internal error: not support relax now")); -+ else -+ append_fixed_insn (ip); -+ dwarf2_emit_insn (0); -+} -+ -+//ask helper for returning a malloced c_str or NULL -+static char * -+assember_macro_helper (const char * const args[], void *context_ptr) -+{ -+ struct loongarch_cl_insn *insn = context_ptr; -+ char *ret = NULL; -+ if (strcmp (insn->name, "li.d") == 0 -+ || strcmp (insn->name, "li.w") == 0) -+ { -+ char args_buf[50], insns_buf[200]; -+ const char *arg_strs[6]; -+ uint32_t hi32, lo32; -+ -+ /* We pay attention to sign extend beacause it is chance of reduce insn. -+ The exception is 12-bit and hi-12-bit unsigned, -+ we need a 'ori' or a 'lu52i.d' accordingly. */ -+ char all0_bit_vec, sign_bit_vec, allf_bit_vec, paritial_is_sext_of_prev; -+ -+ lo32 = insn->args[1] & 0xffffffff; -+ hi32 = insn->args[1] >> 32; -+ -+ -+ if (strcmp (insn->name, "li.w") == 0) -+ { -+ if (hi32 != 0 && hi32 != 0xffffffff) -+ as_fatal (_("li overflow: hi32:0x%x lo32:0x%x"), hi32, lo32); -+ hi32 = lo32 & 0x80000000 ? 0xffffffff : 0; -+ } -+ -+ if (strcmp (insn->name, "li.d") == 0 && LARCH_opts.rlen_is_32) -+ as_fatal (_("we can't li.d on 32bit-arch")); -+ -+ snprintf (args_buf, sizeof (args_buf), "0x%x,0x%x,0x%x,0x%x,%s", -+ (hi32 >> 20) & 0xfff, hi32 & 0xfffff, -+ (lo32 >> 12) & 0xfffff, lo32 & 0xfff, args[0]); -+ loongarch_split_args_by_comma (args_buf, arg_strs); -+ -+ all0_bit_vec = (((hi32 & 0xfff00000) == 0) << 3) -+ | (((hi32 & 0x000fffff) == 0) << 2) -+ | (((lo32 & 0xfffff000) == 0) << 1) -+ | ((lo32 & 0x00000fff) == 0); -+ sign_bit_vec = (((hi32 & 0x80000000) != 0) << 3) -+ | (((hi32 & 0x00080000) != 0) << 2) -+ | (((lo32 & 0x80000000) != 0) << 1) -+ | ((lo32 & 0x00000800) != 0); -+ allf_bit_vec = (((hi32 & 0xfff00000) == 0xfff00000) << 3) -+ | (((hi32 & 0x000fffff) == 0x000fffff) << 2) -+ | (((lo32 & 0xfffff000) == 0xfffff000) << 1) -+ | ((lo32 & 0x00000fff) == 0x00000fff); -+ paritial_is_sext_of_prev = (all0_bit_vec ^ allf_bit_vec) -+ & (all0_bit_vec ^ (sign_bit_vec << 1)); -+ -+ static const char * const li_32bit [] = { -+ "lu12i.w %5,%3&0x80000?%3-0x100000:%3;ori %5,%5,%4;", -+ "lu12i.w %5,%3&0x80000?%3-0x100000:%3;", -+ "addi.w %5,$r0,%4&0x800?%4-0x1000:%4;", -+ "or %5,$r0,$r0;", -+ }; -+ static const char * const li_hi_32bit[] = { -+ "lu32i.d %5,%2&0x80000?%2-0x100000:%2;" -+ "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;", -+ "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;", -+ "lu32i.d %5,%2&0x80000?%2-0x100000:%2;", -+ "", -+ }; -+ do -+ { -+ insns_buf[0] = '\0'; -+ if (paritial_is_sext_of_prev == 0x7) -+ { -+ strcat (insns_buf, "lu52i.d %5,$r0,%1&0x800?%1-0x1000:%1;"); -+ break; -+ } -+ if ((all0_bit_vec & 0x3) == 0x2) -+ strcat (insns_buf, "ori %5,$r0,%4;"); -+ else -+ strcat (insns_buf, li_32bit[paritial_is_sext_of_prev & 0x3]); -+ strcat (insns_buf, li_hi_32bit[paritial_is_sext_of_prev >> 2]); -+ } -+ while (0); -+ -+ ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL); -+ } -+ return ret; -+} -+ -+//accept instructions separated by ';' -+//assuming 'not starting with space and not ending with space' or pass in empty c_str -+static void -+loongarch_assemble_INSNs (char *str) -+{ -+ char *rest; -+ -+ for (rest = str; *rest != ';' && *rest != '\0'; rest++); -+ if (*rest == ';') -+ *rest++ = '\0'; -+ -+ if (*str == ':') -+ { -+ str++; -+ setup_internal_label_here (strtol (str, &str, 10)); -+ str++; -+ } -+ -+ do -+ { -+ if (*str == '\0') -+ break; -+ -+ struct loongarch_cl_insn the_one = {0}; -+ the_one.name = str; -+ -+ for (; *str && *str != ' '; str++); -+ if (*str == ' ') -+ *str++ = '\0'; -+ -+ loongarch_split_args_by_comma (str, the_one.arg_strs); -+ get_loongarch_opcode (&the_one); -+ -+ if (!the_one.all_match) -+ as_fatal (_("no match insn: %s\t%s"), -+ the_one.name, loongarch_cat_splited_strs (the_one.arg_strs)); -+ -+ if (check_this_insn_before_appending (&the_one) != 0) -+ break; -+ -+ append_fixp_and_insn (&the_one); -+ if (the_one.insn_length == 0 && the_one.insn->macro) -+ { -+ char *c_str = -+ loongarch_expand_macro (the_one.insn->macro, -+ the_one.arg_strs, assember_macro_helper, &the_one); -+ loongarch_assemble_INSNs (c_str); -+ free (c_str); -+ } -+ } -+ while (0); -+ -+ if (*rest != '\0') -+ loongarch_assemble_INSNs (rest); -+} -+ -+void -+md_assemble (char *str) -+{ -+ loongarch_assemble_INSNs (str); -+} -+ -+const char *md_atof (int type, char *litP, int *sizeP) -+{ -+ return ieee_md_atof (type, litP, sizeP, FALSE); -+} -+ -+void md_number_to_chars (char *buf, valueT val, int n) -+{ -+ number_to_chars_littleendian (buf, val, n); -+} -+ -+/* The location from which a PC relative jump should be calculated, -+ given a PC relative reloc. */ -+long -+md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED) -+{ -+ return 0; -+} -+ -+void -+md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) -+{ -+ static int64_t stack_top; -+ static int last_reloc_is_sop_push_pcrel_1 = 0; -+ int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1; -+ insn_t insn; -+ last_reloc_is_sop_push_pcrel_1 = 0; -+ -+ char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; -+ switch (fixP->fx_r_type) -+ { -+ case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL: -+ case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD: -+ case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT: -+ if (fixP->fx_addsy) -+ S_SET_THREAD_LOCAL (fixP->fx_addsy); -+ case BFD_RELOC_LARCH_SOP_PUSH_PCREL: -+ case BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL: -+ if (fixP->fx_addsy == NULL) -+ as_bad_where (fixP->fx_file, fixP->fx_line, -+ _("Relocation against a constant")); -+ if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_PCREL) -+ { -+ /* 分支到内部符号的重定位尽量在这里解决。一方面是为了反汇编更好看; -+ 也是为了方便PMON的模块加载。PMON连接器的重定位类型枚举空间很小, -+ 无法实现全的重定位。编译时加入-mabiabs使得所有外部符号都有la.abs, -+ 从而有MARK_LA这个重定位,PMON连接器重定位时填4条la指令。 */ -+ last_reloc_is_sop_push_pcrel_1 = 1; -+ if (S_GET_SEGMENT (fixP->fx_addsy) == seg) -+ stack_top = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset -+ - (fixP->fx_where + fixP->fx_frag->fr_address); -+ else -+ stack_top = 0; -+ } -+ break; -+ -+ case BFD_RELOC_LARCH_SOP_POP_32_S_10_5: -+ if (!last_reloc_is_sop_push_pcrel) -+ break; -+ if ((stack_top & ~(uint64_t)0xf) != 0x0 -+ && (stack_top & ~(uint64_t)0xf) != ~(uint64_t)0xf) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ insn = bfd_getl32 (buf); -+ insn = (insn & (~(uint32_t)0x7c00)) | ((stack_top & 0x1f) << 10); -+ bfd_putl32 (insn, buf); -+ break; -+ -+ case BFD_RELOC_LARCH_SOP_POP_32_U_10_12: -+ if (!last_reloc_is_sop_push_pcrel) -+ break; -+ if (stack_top & ~(uint64_t)0xfff) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ insn = bfd_getl32 (buf); -+ insn = (insn & (~(uint32_t)0x3ffc00)) | ((stack_top & 0xfff) << 10); -+ bfd_putl32 (insn, buf); -+ break; -+ -+ case BFD_RELOC_LARCH_SOP_POP_32_S_10_12: -+ if (!last_reloc_is_sop_push_pcrel) -+ break; -+ if ((stack_top & ~(uint64_t)0x7ff) != 0x0 -+ && (stack_top & ~(uint64_t)0x7ff) != ~(uint64_t)0x7ff) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ insn = bfd_getl32 (buf); -+ insn = (insn & (~(uint32_t)0x3ffc00)) | ((stack_top & 0xfff) << 10); -+ bfd_putl32 (insn, buf); -+ break; -+ -+ case BFD_RELOC_LARCH_SOP_POP_32_S_10_16: -+ if (!last_reloc_is_sop_push_pcrel) -+ break; -+ if ((stack_top & ~(uint64_t)0x7fff) != 0x0 -+ && (stack_top & ~(uint64_t)0x7fff) != ~(uint64_t)0x7fff) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ insn = bfd_getl32 (buf); -+ insn = (insn & 0xfc0003ff) | ((stack_top & 0xffff) << 10); -+ bfd_putl32 (insn, buf); -+ break; -+ -+ case BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2: -+ if (!last_reloc_is_sop_push_pcrel) -+ break; -+ if ((stack_top & 0x3) != 0) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ stack_top >>= 2; -+ if ((stack_top & ~(uint64_t)0x7fff) != 0x0 -+ && (stack_top & ~(uint64_t)0x7fff) != ~(uint64_t)0x7fff) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ insn = bfd_getl32 (buf); -+ insn = (insn & 0xfc0003ff) | ((stack_top & 0xffff) << 10); -+ bfd_putl32 (insn, buf); -+ break; -+ -+ case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2: -+ if (!last_reloc_is_sop_push_pcrel) -+ break; -+ if ((stack_top & 0x3) != 0) -+ break; -+ stack_top >>= 2; -+ if ((stack_top & ~(uint64_t)0xfffff) != 0x0 -+ && (stack_top & ~(uint64_t)0xfffff) != ~(uint64_t)0xfffff) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ insn = bfd_getl32 (buf); -+ insn = (insn & 0xfc0003e0) -+ | ((stack_top & 0xffff) << 10) | ((stack_top & 0x1f0000) >> 16); -+ bfd_putl32 (insn, buf); -+ break; -+ -+ case BFD_RELOC_LARCH_SOP_POP_32_S_5_20: -+ if (!last_reloc_is_sop_push_pcrel) -+ break; -+ if ((stack_top & ~(uint64_t)0x7ffff) != 0x0 -+ && (stack_top & ~(uint64_t)0x7ffff) != ~(uint64_t)0x7ffff) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ insn = bfd_getl32 (buf); -+ insn = (insn & (~(uint32_t)0x1ffffe0)) | ((stack_top & 0xfffff) << 5); -+ bfd_putl32 (insn, buf); -+ break; -+ -+ case BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2: -+ if (!last_reloc_is_sop_push_pcrel) -+ break; -+ if ((stack_top & 0x3) != 0) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ stack_top >>= 2; -+ if ((stack_top & ~(uint64_t)0x1ffffff) != 0x0 -+ && (stack_top & ~(uint64_t)0x1ffffff) != ~(uint64_t)0x1ffffff) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ insn = bfd_getl32 (buf); -+ insn = (insn & 0xfc000000) -+ | ((stack_top & 0xffff) << 10) | ((stack_top & 0x3ff0000) >> 16); -+ bfd_putl32 (insn, buf); -+ break; -+ -+ case BFD_RELOC_LARCH_SOP_POP_32_U: -+ if (!last_reloc_is_sop_push_pcrel) -+ break; -+ if (stack_top & ~(uint64_t)0xffffffff) -+ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); -+ bfd_putl32 (stack_top, buf); -+ break; -+ -+ case BFD_RELOC_64: -+ case BFD_RELOC_32: -+ if (fixP->fx_subsy) -+ { -+ case BFD_RELOC_24: -+ case BFD_RELOC_16: -+ case BFD_RELOC_8: -+ fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP)); -+ fixP->fx_next->fx_addsy = fixP->fx_subsy; -+ fixP->fx_next->fx_subsy = NULL; -+ fixP->fx_next->fx_offset = 0; -+ fixP->fx_subsy = NULL; -+ -+ switch (fixP->fx_r_type) -+ { -+ case BFD_RELOC_64: -+ fixP->fx_r_type = BFD_RELOC_LARCH_ADD64; -+ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB64; -+ break; -+ case BFD_RELOC_32: -+ fixP->fx_r_type = BFD_RELOC_LARCH_ADD32; -+ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32; -+ break; -+ case BFD_RELOC_24: -+ fixP->fx_r_type = BFD_RELOC_LARCH_ADD24; -+ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24; -+ break; -+ case BFD_RELOC_16: -+ fixP->fx_r_type = BFD_RELOC_LARCH_ADD16; -+ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16; -+ break; -+ case BFD_RELOC_8: -+ fixP->fx_r_type = BFD_RELOC_LARCH_ADD8; -+ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8; -+ break; -+ default: -+ break; -+ } -+ md_number_to_chars (buf, 0, fixP->fx_size); -+ if (fixP->fx_next->fx_addsy == NULL) -+ fixP->fx_next->fx_done = 1; -+ } -+ if (fixP->fx_addsy == NULL) -+ { -+ fixP->fx_done = 1; -+ md_number_to_chars (buf, *valP, fixP->fx_size); -+ } -+ break; -+ -+ default: -+ break; -+ } -+} -+ -+int -+loongarch_relax_frag (asection *sec ATTRIBUTE_UNUSED, fragS *fragp ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED) -+{ -+ return 0; -+} -+ -+int -+md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED, asection *segtype ATTRIBUTE_UNUSED) -+{ -+ return 0; -+} -+ -+/* Translate internal representation of relocation info to BFD target -+ format. */ -+arelent * -+tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) -+{ -+ arelent *reloc = (arelent *) xmalloc (sizeof (arelent)); -+ -+ reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); -+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); -+ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; -+ reloc->addend = fixp->fx_offset; -+ -+ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); -+ if (reloc->howto == NULL) -+ { -+ as_bad_where (fixp->fx_file, fixp->fx_line, -+ _("cannot represent %s relocation in object file"), -+ bfd_get_reloc_code_name (fixp->fx_r_type)); -+ return NULL; -+ } -+ -+ return reloc; -+} -+ -+/* Convert a machine dependent frag. */ -+void -+md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED, fragS *fragp ATTRIBUTE_UNUSED) -+{ -+ // fragp->fr_fix += 8; -+} -+ -+/* Standard calling conventions leave the CFA at SP on entry. */ -+void -+loongarch_cfi_frame_initial_instructions (void) -+{ -+ cfi_add_CFA_def_cfa_register (3 /* $sp */); -+} -+ -+int -+loongarch_dwarf2_addr_size (void) -+{ -+ return LARCH_opts.addrwidth_is_32? 4 : 8; -+} -+ -+void -+tc_loongarch_parse_to_dw2regnum (expressionS *exp) -+{ -+ expression_and_evaluate (exp); -+} -+ -+void -+md_show_usage (FILE *stream) -+{ -+ fprintf (stream, _("\ -+ LoongISA options:\n\ -+ ")); -+} -+ -+/* Fill in an rs_align_code fragment. We want to fill 'andi $r0,$r0,0'. */ -+void -+loongarch_handle_align (fragS *fragp) -+{ -+// char nop_opcode; -+ char *p; -+ int bytes, size, excess; -+ valueT opcode; -+ -+ if (fragp->fr_type != rs_align_code) -+ return; -+ -+ struct loongarch_cl_insn nop = -+ {.name = "andi", .arg_strs = {"$r0", "$r0", "0", NULL}}; -+ -+ get_loongarch_opcode (&nop); -+ gas_assert (nop.all_match); -+ -+ p = fragp->fr_literal + fragp->fr_fix; -+ opcode = nop.insn_bin; -+ size = 4; -+ -+ bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; -+ excess = bytes % size; -+ -+ /* Handle the leading part if we're not inserting a whole number of -+ instructions, and make it the end of the fixed part of the frag. -+ Try to fit in a short microMIPS NOP if applicable and possible, -+ and use zeroes otherwise. */ -+ gas_assert (excess < 4); -+ fragp->fr_fix += excess; -+ switch (excess) -+ { -+ case 3: -+ *p++ = '\0'; -+ case 2: -+ *p++ = '\0'; -+ case 1: -+ *p++ = '\0'; -+ case 0: -+ break; -+ } -+ -+ md_number_to_chars (p, opcode, size); -+ fragp->fr_var = size; -+} -+ -+void -+loongarch_elf_final_processing (void) -+{ -+ if (LARCH_opts.abi_is_lp64) -+ elf_elfheader (stdoutput)->e_flags |= EF_LARCH_ABI_LP64; -+ else if (LARCH_opts.abi_is_lp32) -+ elf_elfheader (stdoutput)->e_flags |= EF_LARCH_ABI_LP32; -+} -diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h -new file mode 100644 -index 00000000..f2647972 ---- /dev/null -+++ b/gas/config/tc-loongarch.h -@@ -0,0 +1,77 @@ -+#ifndef TC_LOONGARCH -+#define TC_LOONGARCH -+ -+#define TARGET_BYTES_BIG_ENDIAN 0 -+#define TARGET_ARCH bfd_arch_loongarch -+ -+#define WORKING_DOT_WORD 1 -+#define REPEAT_CONS_EXPRESSIONS -+ -+// early than md_begin -+#define md_after_parse_args loongarch_after_parse_args -+extern void loongarch_after_parse_args (void); -+ -+extern void loongarch_pop_insert (void); -+#define md_pop_insert() loongarch_pop_insert () -+ -+#define TARGET_FORMAT loongarch_target_format() -+extern const char * loongarch_target_format (void); -+ -+ -+#define md_relax_frag(segment, fragp, stretch) \ -+ loongarch_relax_frag (segment, fragp, stretch) -+extern int loongarch_relax_frag (asection *, struct frag *, long); -+#define md_section_align(seg,size) (size) -+#define md_undefined_symbol(name) (0) -+ -+/* This is called to see whether a reloc against a defined symbol -+ should be converted into a reloc against a section. */ -+#define tc_fix_adjustable(fixp) 0 -+ -+/* Values passed to md_apply_fix don't include symbol values. */ -+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) 1 -+#define TC_VALIDATE_FIX_SUB(FIX, SEG) 1 -+#define DIFF_EXPR_OK 1 -+ -+#define TARGET_USE_CFIPOP 1 -+#define DWARF2_DEFAULT_RETURN_COLUMN 1 /* $ra */ -+#define DWARF2_CIE_DATA_ALIGNMENT -4 -+extern int loongarch_dwarf2_addr_size (void); -+#define DWARF2_FDE_RELOC_SIZE loongarch_dwarf2_addr_size () -+#define DWARF2_ADDR_SIZE(bfd) loongarch_dwarf2_addr_size () -+#define CFI_DIFF_EXPR_OK 0 -+ -+#define tc_cfi_frame_initial_instructions loongarch_cfi_frame_initial_instructions -+extern void loongarch_cfi_frame_initial_instructions (void); -+ -+// 我们不实现 tc_regname_to_dw2regnum,而是重载tc_parse_to_dw2regnum。 -+// 因为MIPS汇编兼容需要CFA来实现C++异常抛出。我们仅仅对数字作映射, -+// 不再考虑寄存器的名字了。 -+//#define tc_regname_to_dw2regnum tc_loongarch_regname_to_dw2regnum -+#define tc_parse_to_dw2regnum tc_loongarch_parse_to_dw2regnum -+extern void tc_loongarch_parse_to_dw2regnum (expressionS *); -+ -+// a enumerated values to specific how to deal with align in '.text' -+// now we want to fill 'andi $r0,$r0,0x0' -+#define loongarch_nop_opcode() 0 -+#define NOP_OPCODE (loongarch_nop_opcode ()) -+ -+#define HANDLE_ALIGN(fragp) loongarch_handle_align (fragp) -+extern void loongarch_handle_align (struct frag *); -+#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4) -+ -+#define elf_tc_final_processing loongarch_elf_final_processing -+extern void loongarch_elf_final_processing (void); -+ -+#define MAX_RELOC_NUMBER_A_INSN 20 -+ -+struct reloc_info -+{ -+ bfd_reloc_code_real_type type; -+ expressionS value; -+}; -+ -+int is_label_with_addend (const char *); -+int is_label (const char *); -+ -+#endif -diff --git a/gas/configure b/gas/configure -index f4a4b125..5917b777 100755 ---- a/gas/configure -+++ b/gas/configure -@@ -12503,6 +12503,18 @@ _ACEOF - fi - ;; - -+ loongarch) -+ echo ${extra_objects} | grep -s "loongarch-parse.o" -+ if test $? -ne 0 ; then -+ extra_objects="$extra_objects loongarch-parse.o" -+ fi -+ -+ echo ${extra_objects} | grep -s "loongarch-lex-wrapper.o" -+ if test $? -ne 0 ; then -+ extra_objects="$extra_objects loongarch-lex-wrapper.o" -+ fi -+ ;; -+ - epiphany | fr30 | ip2k | iq2000 | lm32 | m32r | or1k) - using_cgen=yes - ;; -@@ -12639,7 +12651,7 @@ $as_echo "#define NDS32_DEFAULT_AUDIO_EXT 1" >>confdefs.h - $as_echo "$enable_audio_ext" >&6; } - ;; - -- aarch64 | i386 | riscv | s390 | sparc) -+ aarch64 | i386 | riscv | s390 | sparc | loongarch) - if test $this_target = $target ; then - - cat >>confdefs.h <<_ACEOF -diff --git a/gas/configure.ac b/gas/configure.ac -index 4bd2077c..41f779ee 100644 ---- a/gas/configure.ac -+++ b/gas/configure.ac -@@ -430,6 +430,15 @@ changequote([,])dnl - using_cgen=yes - ;; - -+ loongarch) -+ for f in loongarch-parse.o loongarch-lex-wrapper.o; do -+ case " $extra_objects " in -+ *" $f "*) ;; -+ *) extra_objects="$extra_objects $f" ;; -+ esac -+ done -+ ;; -+ - m32c) - using_cgen=yes - ;; -diff --git a/gas/configure.tgt b/gas/configure.tgt -index abf7e02e..76b1abcb 100644 ---- a/gas/configure.tgt -+++ b/gas/configure.tgt -@@ -67,6 +67,7 @@ case ${cpu} in - ip2k) cpu_type=ip2k endian=big ;; - iq2000) cpu_type=iq2000 endian=big ;; - lm32) cpu_type=lm32 ;; -+ loongarch*) cpu_type=loongarch ;; - m32c) cpu_type=m32c endian=little ;; - m32r) cpu_type=m32r endian=big ;; - m32rle) cpu_type=m32r endian=little ;; -@@ -311,6 +312,8 @@ case ${generic_target} in - - lm32-*-*) fmt=elf ;; - -+ loongarch*) fmt=elf ;; -+ - m32c-*-elf) fmt=elf ;; - - m32r-*-elf*) fmt=elf ;; -@@ -497,7 +500,7 @@ case ${generic_target} in - esac - - case ${cpu_type} in -- aarch64 | alpha | arm | i386 | ia64 | microblaze | mips | ns32k | or1k | or1knd | pdp11 | ppc | riscv | sparc | z80 | z8k) -+ aarch64 | alpha | arm | i386 | ia64 | loongarch | microblaze | mips | ns32k | or1k | or1knd | pdp11 | ppc | riscv | sparc | z80 | z8k) - bfd_gas=yes - ;; - esac -diff --git a/include/dis-asm.h b/include/dis-asm.h -index 0ddf0475..055b8ce8 100644 ---- a/include/dis-asm.h -+++ b/include/dis-asm.h -@@ -258,6 +258,7 @@ extern void print_mips_disassembler_options (FILE *); - extern void print_nfp_disassembler_options (FILE *); - extern void print_ppc_disassembler_options (FILE *); - extern void print_riscv_disassembler_options (FILE *); -+extern void print_loongarch_disassembler_options (FILE *); - extern void print_arm_disassembler_options (FILE *); - extern void print_arc_disassembler_options (FILE *); - extern void print_s390_disassembler_options (FILE *); -diff --git a/include/elf/common.h b/include/elf/common.h -index 8a470745..0de652c4 100644 ---- a/include/elf/common.h -+++ b/include/elf/common.h -@@ -339,6 +339,7 @@ - #define EM_LANAI 244 /* Lanai 32-bit processor. */ - #define EM_BPF 247 /* Linux BPF – in-kernel virtual machine. */ - #define EM_NFP 250 /* Netronome Flow Processor. */ -+#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 -@@ -642,6 +643,14 @@ - /* note name must be "LINUX". */ - #define NT_ARM_SVE 0x405 /* AArch SVE registers. */ - /* note name must be "LINUX". */ -+#define NT_LARCH_CPUCFG 0x900 /* Loongarch CPU config registers */ -+ /* note name must be "LINUX". */ -+#define NT_LARCH_LBT 0x901 /* Loongarch Loongson Binary Translation registers */ -+ /* note name must be "LINUX". */ -+#define NT_LARCH_LSX 0x902 /* Loongarch Loongson SIMD Extension registers */ -+ /* note name must be "LINUX". */ -+#define NT_LARCH_LASX 0x903 /* Loongarch Loongson Advanced SIMD Extension registers */ -+ /* note name must be "LINUX". */ - #define NT_SIGINFO 0x53494749 /* Fields of siginfo_t. */ - #define NT_FILE 0x46494c45 /* Description of mapped files. */ - -diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h -new file mode 100644 -index 00000000..02085dd3 ---- /dev/null -+++ b/include/elf/loongarch.h -@@ -0,0 +1,95 @@ -+#ifndef _ELF_LOONG_H -+#define _ELF_LOONG_H -+ -+#include -+#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) -+ -+/* 这个重定位类型将symbol距离重定位位置的pc相对位置偏移量压栈。 -+ 它against symbol,因为如果是个常数,虽然在no-pic的情况下可以得到结果,但因为 -+ 重定位位置相对这个常数的偏移量一定很大,八成填不进去;而在pic的情况下, -+ 偏移量无法在静态连接时确定。因此我们约定这个重定位不可能against constant */ -+RELOC_NUMBER (R_LARCH_SOP_PUSH_PCREL, 22) -+ -+/* 这个重定位against a symbol or a constant。它将symbol的运行时绝对地址 -+ 或常数压栈,因此在pic的情况下会报错。另外我不太清楚常数和ABS段的关系。 */ -+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 */ -+/* 这几个重定位类型是为了照顾到 ".dword sym1 - sym2" 这种求差的写法。 -+ 这些重定位类型处理的是连接时地址,一般情况下它们是成对出现的。 -+ 在直接求负数".dword - sym1"的情况下,R_LARCH_SUBxx会单独出现。但注意, -+ 那个位置填进去的是连接时地址。 */ -+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) -+ -+END_RELOC_NUMBERS (R_LARCH_count) -+ -+ -+/* Processor specific flags for the ELF header e_flags field. */ -+ -+#define EF_LARCH_ABI 0x0003 -+#define EF_LARCH_ABI_LP64 0x0003 -+#define EF_LARCH_ABI_XLP32 0x0002 -+#define EF_LARCH_ABI_LP32 0x0001 -+ -+#endif /* _ELF_LOONG_H */ -diff --git a/include/opcode/loongarch.h b/include/opcode/loongarch.h -new file mode 100644 -index 00000000..47a9d94b ---- /dev/null -+++ b/include/opcode/loongarch.h -@@ -0,0 +1,215 @@ -+#ifndef _LOONGARCH_H_ -+#define _LOONGARCH_H_ -+#include -+ -+#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. -+As for marco insn "b" in MIPS, we can say its name is "b", format is "l", macro is "j %1". So "b 3f" will be expanded to "j 3f". -+As for marco insn "li" in MIPS, we can say its name is "li", format is "s", macro is "ori" -+ -+ -+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 hash_control *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); -+extern char * -+loongarch_expand_macro (const char *macro, const char * const arg_strs[], -+ char * (*helper) (const char * const arg_strs[], -+ void *context), -+ void *context); -+extern size_t -+loongarch_bits_imm_needed (int64_t imm, int si); -+ -+/* 将字符串中指定的连续字符化为1个 */ -+extern void -+loongarch_eliminate_adjacent_repeat_char (char *dest, char c); -+ -+/* 下面两个函数计划作为libopcode.a拿出来给一些系统软件反汇编用 */ -+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 -+{ -+ int ase_test; -+ int ase_fix; -+ int ase_float; -+ int ase_128vec; -+ int ase_256vec; -+ -+ int addrwidth_is_32; -+ int addrwidth_is_64; -+ int rlen_is_32; -+ int rlen_is_64; -+ int la_local_with_abs; -+ int la_global_with_pcrel; -+ int la_global_with_abs; -+ -+ int abi_is_lp32; -+ int abi_is_lp64; -+} LARCH_opts; -+ -+extern size_t loongarch_insn_length (insn_t insn); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* _LOONGARCH_H_ */ -diff --git a/ld/Makefile.am b/ld/Makefile.am -index 82718165..ee4a5790 100644 ---- a/ld/Makefile.am -+++ b/ld/Makefile.am -@@ -492,6 +492,7 @@ ALL_64_EMULATION_SOURCES = \ - eelf64btsmip.c \ - eelf64btsmip_fbsd.c \ - eelf64hppa.c \ -+ eelf64loongarch.c \ - eelf64lppc.c \ - eelf64lriscv.c \ - eelf64ltsmip.c \ -@@ -1988,6 +1989,11 @@ eelf64btsmip_fbsd.c: $(srcdir)/emulparams/elf64btsmip_fbsd.sh \ - eelf64hppa.c: $(srcdir)/emulparams/elf64hppa.sh \ - $(ELF_DEPS) $(srcdir)/scripttempl/elf64hppa.sc ${GEN_DEPENDS} - -+eelf64loongarch.c: $(srcdir)/emulparams/elf64loongarch.sh \ -+ $(srcdir)/emulparams/elf64loongarch-defs.sh $(ELF_DEPS) \ -+ $(srcdir)/emultempl/loongarchelf.em $(srcdir)/scripttempl/elf.sc \ -+ ${GEN_DEPENDS} -+ - eelf64lppc.c: $(srcdir)/emulparams/elf64lppc.sh \ - $(srcdir)/emulparams/elf64ppc.sh \ - $(srcdir)/emulparams/dynamic_undefined_weak.sh \ -diff --git a/ld/Makefile.in b/ld/Makefile.in -index bf7877ac..553b6334 100644 ---- a/ld/Makefile.in -+++ b/ld/Makefile.in -@@ -619,6 +619,7 @@ ALL_EMULATION_SOURCES = \ - eelf32iq2000.c \ - eelf32lm32.c \ - eelf32lm32fd.c \ -+ eelf32lloongarch.c \ - eelf32lppc.c \ - eelf32lppclinux.c \ - eelf32lppcnto.c \ -@@ -859,11 +860,13 @@ ALL_64_EMULATION_SOURCES = \ - eelf64btsmip.c \ - eelf64btsmip_fbsd.c \ - eelf64hppa.c \ -+ eelf64lloongarch.c \ - eelf64lppc.c \ - eelf64lriscv.c \ - eelf64ltsmip.c \ - eelf64ltsmip_fbsd.c \ - eelf64mmix.c \ -+ eelf64loongarch.c \ - eelf64ppc.c \ - eelf64ppc_fbsd.c \ - eelf64rdos.c \ -@@ -1248,6 +1251,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lm32.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lm32fd.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lmip.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lloongarch.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppc.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppclinux.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppcnto.Po@am__quote@ -@@ -1307,6 +1311,7 @@ distclean-compile: - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip_fbsd.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64hppa.Po@am__quote@ -+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lloongarch.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lppc.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv.Po@am__quote@ - @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip.Po@am__quote@ -@@ -2719,6 +2724,13 @@ eelf32lmip.c: $(srcdir)/emulparams/elf32lmip.sh \ - $(srcdir)/emulparams/elf32bmip.sh $(ELF_DEPS) \ - $(srcdir)/emultempl/mipself.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} - -+eelf32lloongarch.c: $(srcdir)/emulparams/elf32loongarch.sh \ -+ $(srcdir)/emulparams/elf32loongarchcommon.sh \ -+ $(srcdir)/emulparams/elf32loongarch.sh \ -+ $(srcdir)/emulparams/dynamic_undefined_weak.sh \ -+ $(srcdir)/emultempl/loongarch32elf.em ldemul-list.h \ -+ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} -+ - eelf32lppc.c: $(srcdir)/emulparams/elf32lppc.sh \ - $(srcdir)/emulparams/elf32ppccommon.sh \ - $(srcdir)/emulparams/elf32ppc.sh \ -@@ -3551,6 +3563,12 @@ eelf64btsmip_fbsd.c: $(srcdir)/emulparams/elf64btsmip_fbsd.sh \ - eelf64hppa.c: $(srcdir)/emulparams/elf64hppa.sh \ - $(ELF_DEPS) $(srcdir)/scripttempl/elf64hppa.sc ${GEN_DEPENDS} - -+eelf64lloongarch.c: $(srcdir)/emulparams/elf64lloongarch.sh \ -+ $(srcdir)/emulparams/elf64loongarch.sh \ -+ $(srcdir)/emulparams/dynamic_undefined_weak.sh \ -+ $(srcdir)/emultempl/loongarch64elf.em ldemul-list.h \ -+ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} -+ - eelf64lppc.c: $(srcdir)/emulparams/elf64lppc.sh \ - $(srcdir)/emulparams/elf64ppc.sh \ - $(srcdir)/emulparams/dynamic_undefined_weak.sh \ -diff --git a/ld/configure.tgt b/ld/configure.tgt -index 1a70497a..a9a46150 100644 ---- a/ld/configure.tgt -+++ b/ld/configure.tgt -@@ -432,6 +432,8 @@ iq2000-*-elf) targ_emul=elf32iq2000 ; targ_extra_emuls="elf32iq10" - lm32-*-*linux*) targ_emul=elf32lm32fd ;; - lm32-*-*) targ_emul=elf32lm32 ; targ_extra_emuls="elf32lm32fd" - ;; -+loongarch32-*) targ_emul=elf32loongarch ;; -+loongarch64-*) targ_emul=elf64loongarch ;; - m32c-*-elf | m32c-*-rtems*) - targ_emul=elf32m32c - ;; -diff --git a/ld/emulparams/elf64loongarch-defs.sh b/ld/emulparams/elf64loongarch-defs.sh -new file mode 100644 -index 00000000..072519ea ---- /dev/null -+++ b/ld/emulparams/elf64loongarch-defs.sh -@@ -0,0 +1,39 @@ -+# This is an ELF platform. -+SCRIPT_NAME=elf -+ARCH=loongarch -+NO_REL_RELOCS=yes -+ -+TEMPLATE_NAME=elf32 -+EXTRA_EM_FILE=loongarchelf -+ -+ELFSIZE=64 -+ -+if test `echo "$host" | sed -e s/64//` = `echo "$target" | sed -e s/64//`; then -+ case " $EMULATION_LIBPATH " in -+ *" ${EMULATION_NAME} "*) -+ NATIVE=yes -+ ;; -+ esac -+fi -+ -+# Enable shared library support for everything except an embedded elf target. -+case "$target" in -+ loongarch*-elf) -+ ;; -+ *) -+ GENERATE_SHLIB_SCRIPT=yes -+ GENERATE_PIE_SCRIPT=yes -+ ;; -+esac -+ -+# In all cases, the number is big-endian. -+# LoongArch nop is 'andi $r0,$r0,0'. -+NOP=0x00004003 -+ -+TEXT_START_ADDR=0x120000000 -+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" -+COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)" -+ -+SEPARATE_GOTPLT=0 -+INITIAL_READONLY_SECTIONS=".interp : { *(.interp) } ${CREATE_PIE-${INITIAL_READONLY_SECTIONS}}" -+INITIAL_READONLY_SECTIONS="${RELOCATING+${CREATE_SHLIB-${INITIAL_READONLY_SECTIONS}}}" -diff --git a/ld/emulparams/elf64loongarch.sh b/ld/emulparams/elf64loongarch.sh -new file mode 100644 -index 00000000..7331fe16 ---- /dev/null -+++ b/ld/emulparams/elf64loongarch.sh -@@ -0,0 +1,15 @@ -+# LA64 code using LP64D ABI. -+# ABI not in emulation name to avoid breaking backward compatibility. -+. ${srcdir}/emulparams/elf64loongarch-defs.sh -+OUTPUT_FORMAT="elf64-loongarch" -+ -+# On Linux, first look for 64 bit LP64D target libraries in /lib64/lp64d as per -+# the glibc ABI, and then /lib64 for backward compatility. -+case "$target" in -+ loong64*-linux*) -+ case "$EMULATION_NAME" in -+ *64*) -+ LIBPATH_SUFFIX="64/lib64 64";; -+ esac -+ ;; -+esac -diff --git a/ld/emultempl/loongarchelf.em b/ld/emultempl/loongarchelf.em -new file mode 100644 -index 00000000..3570797f ---- /dev/null -+++ b/ld/emultempl/loongarchelf.em -@@ -0,0 +1,90 @@ -+# This shell script emits a C file. -*- C -*- -+# Copyright (C) 2004-2018 Free Software Foundation, Inc. -+# -+# This file is part of the GNU Binutils. -+# -+# This program is free software; you can redistribute it and/or modify -+# it under the terms of the GNU General Public License as published by -+# the Free Software Foundation; either version 3 of the License, or -+# (at your option) any later version. -+# -+# This program is distributed in the hope that it will be useful, -+# but WITHOUT ANY WARRANTY; without even the implied warranty of -+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+# GNU General Public License for more details. -+# -+# You should have received a copy of the GNU General Public License -+# along with this program; if not, write to the Free Software -+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, -+# MA 02110-1301, USA. -+ -+fragment <>= 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); -+ -+ if (si) -+ { -+ ret <<= sizeof (ret) * 8 - len; -+ ret >>= sizeof (ret) * 8 - len; -+ } -+ 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, i; -+ -+ width = loongarch_get_bit_field_width (t, &t); -+ if (width == -1) -+ return ret; -+ -+ if (*t == '<' && *(++t) == '<') -+ width += atoi (t + 1); -+ else if (*t == '+') -+ imm -= atoi (t + 1); -+ -+ imm <<= sizeof (imm) * 8 - width; -+ 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 = imm; -+ i >>= sizeof (i) * 8 - width; -+ i <<= b_start; -+ ret |= i; -+ imm <<= 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); -+ 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) -+{ -+ 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; -+ char buffer[8192]; -+ -+ 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 strdup (buffer); -+} -+ -+char * -+loongarch_expand_macro (const char *macro, const char * const arg_strs[], -+ char * (*helper) (const char * const arg_strs[], -+ void *context), -+ void *context) -+{ -+ return loongarch_expand_macro_with_format_map -+ (NULL, macro, arg_strs, I, helper, context); -+} -+ -+size_t -+loongarch_bits_imm_needed (int64_t imm, int si) -+{ -+ size_t ret; -+ if (si) -+ { -+ if (imm < 0) -+ { -+ for (ret = 0; imm < 0; imm <<= 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++; -+ } -+} -diff --git a/opcodes/loongarch-dis.c b/opcodes/loongarch-dis.c -new file mode 100644 -index 00000000..888c55f5 ---- /dev/null -+++ b/opcodes/loongarch-dis.c -@@ -0,0 +1,311 @@ -+#include "sysdep.h" -+#include "disassemble.h" -+#include "opintl.h" -+#include "opcode/loongarch.h" -+#include -+ -+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_test = 1; -+ LARCH_opts.ase_fix = 1; -+ LARCH_opts.ase_float = 1; -+ LARCH_opts.ase_128vec = 1; -+ LARCH_opts.ase_256vec = 1; -+ -+ loongarch_r_disname = loongarch_r_normal_name; -+ loongarch_f_disname = loongarch_f_normal_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 ATTRIBUTE_UNUSED) -+{ -+ 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[strlen (opts_in) + 1], *opt, *opt_end; -+ 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; -+ } -+ 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, "%s", opc->name); -+ -+ { -+ char fake_args[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); -+ } -+ -+ if (info->insn_type == dis_branch || info->insn_type == dis_condbranch -+ /* || someother if we have extra info to print */) -+ info->fprintf_func (info->stream, " #"); -+ -+ 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\ -+ LoongISA:\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); -+} -diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c -new file mode 100644 -index 00000000..2c543027 ---- /dev/null -+++ b/opcodes/loongarch-opc.c -@@ -0,0 +1,2128 @@ -+#include -+#include "opcode/loongarch.h" -+ -+struct loongarch_ASEs_option LARCH_opts = -+{ -+ .ase_test = 0, -+ .ase_fix = 0, -+ .ase_float = 0, -+ .ase_128vec = 0, -+ .ase_256vec = 0, -+ -+ .addrwidth_is_32 = 0, -+ .addrwidth_is_64 = 0, -+ .rlen_is_32 = 0, -+ .rlen_is_64 = 0, -+ .la_local_with_abs = 0, -+ .la_global_with_pcrel = 0, -+ .la_global_with_abs = 0, -+ -+ .abi_is_lp32 = 0, -+ .abi_is_lp64 = 0, -+}; -+ -+/* 预留。按理来说应该传入足够的信息使得这个函数可以返回指令长度 */ -+size_t loongarch_insn_length (insn_t insn) -+{ -+ return insn ? 4 : 4; /* eliminate warning */ -+} -+ -+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", -+}; -+ -+#define SOME_INFORMATION 0 -+const int ALWAYS_EXCLUSION = 1; -+static int FIX_FOR_SOME_ARCH = 1; -+ -+static struct loongarch_opcode loongarch_test_opcodes[] = { -+/* match, mask, name, format, macro, include, exclude, pinfo */ -+{ -+0, 0, "a insn always excluded", "r0:5,r5:5,r10:5", -+"insn_1 args_1" -+"insn_2 args_2" -+, 0, &ALWAYS_EXCLUSION, SOME_INFORMATION -+}, -+{ -+0, 0, -+"never disassemble when mask is 0" -+"and we only expand marco when mask is 0 for assemble", -+"r", "macro expand %1" -+, 0, 0, 0 -+}, -+{0, 0, "wrong_insn", "r", -+"throw_error use_fake_insn.for_example.something_goes_wrong_with_%1" -+, 0, 0, 0}, -+ -+{0, 0, "normal_insn", "r", -+"overloading of insn for your arch", &FIX_FOR_SOME_ARCH, 0, 0}, -+{0, 0, "normal_insn", "l", -+"throw_error if_you_dont_want", &FIX_FOR_SOME_ARCH, 0, 0}, -+ -+{0, 0, "normal_insn", "r", "", 0, 0, 0}, -+{0, 0, "normal_insn", "l", "", 0, 0, 0}, -+{0} /* Terminate the list. */ -+}; -+ -+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.la_global_with_pcrel, 0, 0}, -+{0, 0, "la.global", "r,r,la", "la.pcrel %1,%2,%3", &LARCH_opts.la_global_with_pcrel, 0, 0}, -+{0, 0, "la.global", "r,la", "la.abs %1,%2", &LARCH_opts.la_global_with_abs, 0, 0}, -+{0, 0, "la.global", "r,r,la", "la.abs %1,%3", &LARCH_opts.la_global_with_abs, 0, 0}, -+{0, 0, "la.global", "r,l", "la.got %1,%2", 0, 0, 0}, -+{0, 0, "la.global", "r,r,l", "la.got %1,%2,%3", 0, 0, 0}, -+ -+{0, 0, "la.local", "r,la", "la.abs %1,%2", &LARCH_opts.la_local_with_abs, 0, 0}, -+{0, 0, "la.local", "r,r,la", "la.abs %1,%3", &LARCH_opts.la_local_with_abs, 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", 0, 0, 0}, -+ -+{0, 0, "la.abs", "r,la", -+"lu12i.w %1,%%abs(%2)>>12;" -+"ori %1,%1,%%abs(%2)&0xfff;" -+, &LARCH_opts.addrwidth_is_32, 0, 0}, -+{0, 0, "la.abs", "r,la", -+"lu12i.w %1,%%abs(%2)<<32>>44;" -+"ori %1,%1,%%abs(%2)&0xfff;" -+"lu32i.d %1,%%abs(%2)<<12>>44;" -+"lu52i.d %1,%1,%%abs(%2)>>52;" -+, &LARCH_opts.addrwidth_is_64, 0, 0}, -+ -+{0, 0, "la.pcrel", "r,la", -+"pcaddu12i %1,%%pcrel(%2+0x800)<<32>>44;" -+"addi.w %1,%1,%%pcrel(%2+4)-(%%pcrel(%2+4+0x800)>>12<<12);" -+, &LARCH_opts.addrwidth_is_32, 0, 0}, -+ -+{0, 0, "la.pcrel", "r,la", -+"pcaddu12i %1,%%pcrel(%2+0x800)>>12;" -+"addi.d %1,%1,%%pcrel(%2+4)-(%%pcrel(%2+4+0x800)>>12<<12);" -+, &LARCH_opts.addrwidth_is_64, 0, 0}, -+{0, 0, "la.pcrel", "r,r,la", -+"pcaddu12i %1,(%%pcrel(%3)-(%%pcrel(%3+0x80000000)>>32<<32))<<32>>44;" -+"ori %2,$r0,(%%pcrel(%3+4)-(%%pcrel(%3+4+0x80000000)>>32<<32))&0xfff;" -+"lu32i.d %2,%%pcrel(%3+8+0x80000000)<<12>>44;" -+"lu52i.d %2,%2,%%pcrel(%3+12+0x80000000)>>52;" -+"add.d %1,%1,%2;" -+, &LARCH_opts.addrwidth_is_64, 0, 0}, -+ -+{0, 0, "la.got", "r,l", -+"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%gprel(%2))<<32>>44;" -+"ld.w %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%gprel(%2))>>12<<12);" -+, &LARCH_opts.addrwidth_is_32, 0, 0}, -+ -+{0, 0, "la.got", "r,l", -+"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%gprel(%2))>>12;" -+"ld.d %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%gprel(%2))>>12<<12);" -+, &LARCH_opts.addrwidth_is_64, 0, 0}, -+{0, 0, "la.got", "r,r,l", -+"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%gprel(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+0x80000000)+%%gprel(%3))>>32<<32))<<32>>44;" -+"ori %2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x80000000)+%%gprel(%3))>>32<<32))&0xfff;" -+"lu32i.d %2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%gprel(%3))<<12>>44;" -+"lu52i.d %2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%gprel(%3))>>52;" -+"ldx.d %1,%1,%2;" -+, &LARCH_opts.addrwidth_is_64, 0, 0}, -+ -+{0, 0, "la.tls.le", "r,la", -+"lu12i.w %1,%%tprel(%2)>>12;" -+"ori %1,%1,%%tprel(%2)&0xfff" -+, &LARCH_opts.addrwidth_is_32, 0, 0}, -+//{0, 0, "la.tls.le", "r,la", -+//"lu12i.w %1,%%tprel(%2)>>12;" -+//"ori %1,%1,%%tprel(%2)&0xfff" -+//, &LARCH_opts.addrwidth_is_64, 0, 0}, -+{0, 0, "la.tls.le", "r,la", -+"lu12i.w %1,%%tprel(%2)<<32>>44;" -+"ori %1,%1,%%tprel(%2)&0xfff;" -+"lu32i.d %1,%%tprel(%2)<<12>>44;" -+"lu52i.d %1,%1,%%tprel(%2)>>52;" -+, &LARCH_opts.addrwidth_is_64, 0, 0}, -+ -+{0, 0, "la.tls.ie", "r,l", -+"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgot(%2))<<32>>44;" -+"ld.w %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%tlsgot(%2))>>12<<12);" -+, &LARCH_opts.addrwidth_is_32, 0, 0}, -+ -+{0, 0, "la.tls.ie", "r,l", -+"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgot(%2))>>12;" -+"ld.d %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%tlsgot(%2))>>12<<12);" -+, &LARCH_opts.addrwidth_is_64, 0, 0}, -+{0, 0, "la.tls.ie", "r,r,l", -+"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%tlsgot(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+0x80000000)+%%tlsgot(%3))>>32<<32))<<32>>44;" -+"ori %2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x80000000)+%%tlsgot(%3))>>32<<32))&0xfff;" -+"lu32i.d %2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%tlsgot(%3))<<12>>44;" -+"lu52i.d %2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%tlsgot(%3))>>52;" -+"ldx.d %1,%1,%2;" -+, &LARCH_opts.addrwidth_is_64, 0, 0}, -+ -+{0, 0, "la.tls.ld", "r,l", "la.tls.gd %1,%2", 0, 0, 0}, -+{0, 0, "la.tls.ld", "r,r,l", -+"la.tls.gd %1,%2,%3" -+, &LARCH_opts.addrwidth_is_64, 0, 0}, -+ -+ -+{0, 0, "la.tls.gd", "r,l", -+"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgd(%2))<<32>>44;" -+"addi.w %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%tlsgd(%2))>>12<<12);" -+, &LARCH_opts.addrwidth_is_32, 0, 0}, -+ -+{0, 0, "la.tls.gd", "r,l", -+"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgd(%2))>>12;" -+"addi.d %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%tlsgd(%2))>>12<<12);" -+, &LARCH_opts.addrwidth_is_64, 0, 0}, -+{0, 0, "la.tls.gd", "r,r,l", -+"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%tlsgd(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+0x80000000)+%%tlsgd(%3))>>32<<32))<<32>>44;" -+"ori %2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x80000000)+%%tlsgd(%3))>>32<<32))&0xfff;" -+"lu32i.d %2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%tlsgd(%3))<<12>>44;" -+"lu52i.d %2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%tlsgd(%3))>>52;" -+"add.d %1,%1,%2;" -+, &LARCH_opts.addrwidth_is_64, 0, 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_lmm_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, 0, 0, 0 }, -+ { 0x38380000, 0xffff8000, "fstx.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, -+ { 0x38740000, 0xffff8000, "fldgt.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, -+ { 0x38750000, 0xffff8000, "fldle.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, -+ { 0x38760000, 0xffff8000, "fstgt.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, -+ { 0x38770000, 0xffff8000, "fstle.s", "f0:5,r5:5,r10:5", 0, 0, 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, 0, 0, 0 }, -+ { 0x383c0000, 0xffff8000, "fstx.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, -+ { 0x38748000, 0xffff8000, "fldgt.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, -+ { 0x38758000, 0xffff8000, "fldle.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, -+ { 0x38768000, 0xffff8000, "fstgt.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, -+ { 0x38778000, 0xffff8000, "fstle.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, -+ { 0 } /* Terminate the list. */ -+}; -+ -+static struct loongarch_opcode loongarch_float_jmp_opcodes[] = -+{ -+ { 0x0, 0x0, "bceqz", "c,la", "bceqz %1,%%pcrel(%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,%%pcrel(%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,%%pcrel(%2)", 0, 0, 0 }, -+ { 0x60000000, 0xfc00001f, "bltz", "r5:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bgtz", "r,la", "bgtz %1,%%pcrel(%2)", 0, 0, 0 }, -+ { 0x60000000, 0xfc0003e0, "bgtz", "r0:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bgez", "r,la", "bgez %1,%%pcrel(%2)", 0, 0, 0 }, -+ { 0x64000000, 0xfc00001f, "bgez", "r5:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "blez", "r,la", "blez %1,%%pcrel(%2)", 0, 0, 0 }, -+ { 0x64000000, 0xfc0003e0, "blez", "r0:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "beqz", "r,la", "beqz %1,%%pcrel(%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,%%pcrel(%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 %%pcrel(%1)", 0, 0, 0 }, -+ { 0x4c000000, 0xfc000000, "jirl", "r0:5,r5:5,s10:16<<2", 0, 0, 0, 0 }, -+ { 0x0, 0x0, "bl", "la", "bl %%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%3)", 0, 0, 0 }, -+ { 0x6c000000, 0xfc000000, "bleu", "r0:5,r5:5,sb10:16<<2", 0, 0, 0, 0 }, -+ { 0 } /* Terminate the list. */ -+}; -+static struct loongarch_opcode loongarch_128vec_opcodes[] = { -+/* match, mask, name, format, macro, include, exclude, pinfo */ -+{0x70000000, 0xffff8000, "vseq.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70008000, 0xffff8000, "vseq.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70010000, 0xffff8000, "vseq.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70018000, 0xffff8000, "vseq.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70020000, 0xffff8000, "vsle.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70028000, 0xffff8000, "vsle.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70030000, 0xffff8000, "vsle.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70038000, 0xffff8000, "vsle.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70040000, 0xffff8000, "vsle.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70048000, 0xffff8000, "vsle.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70050000, 0xffff8000, "vsle.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70058000, 0xffff8000, "vsle.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70060000, 0xffff8000, "vslt.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70068000, 0xffff8000, "vslt.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70070000, 0xffff8000, "vslt.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70078000, 0xffff8000, "vslt.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70080000, 0xffff8000, "vslt.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70088000, 0xffff8000, "vslt.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70090000, 0xffff8000, "vslt.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70098000, 0xffff8000, "vslt.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x700a0000, 0xffff8000, "vadd.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x700a8000, 0xffff8000, "vadd.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x700b0000, 0xffff8000, "vadd.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x700b8000, 0xffff8000, "vadd.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x700c0000, 0xffff8000, "vsub.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x700c8000, 0xffff8000, "vsub.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x700d0000, 0xffff8000, "vsub.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x700d8000, 0xffff8000, "vsub.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70460000, 0xffff8000, "vsadd.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70468000, 0xffff8000, "vsadd.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70470000, 0xffff8000, "vsadd.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70478000, 0xffff8000, "vsadd.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70480000, 0xffff8000, "vssub.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70488000, 0xffff8000, "vssub.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70490000, 0xffff8000, "vssub.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70498000, 0xffff8000, "vssub.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x704a0000, 0xffff8000, "vsadd.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x704a8000, 0xffff8000, "vsadd.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x704b0000, 0xffff8000, "vsadd.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x704b8000, 0xffff8000, "vsadd.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x704c0000, 0xffff8000, "vssub.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x704c8000, 0xffff8000, "vssub.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x704d0000, 0xffff8000, "vssub.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x704d8000, 0xffff8000, "vssub.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70540000, 0xffff8000, "vhaddw.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70548000, 0xffff8000, "vhaddw.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70550000, 0xffff8000, "vhaddw.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70558000, 0xffff8000, "vhaddw.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70560000, 0xffff8000, "vhsubw.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70568000, 0xffff8000, "vhsubw.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70570000, 0xffff8000, "vhsubw.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70578000, 0xffff8000, "vhsubw.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70580000, 0xffff8000, "vhaddw.hu.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70588000, 0xffff8000, "vhaddw.wu.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70590000, 0xffff8000, "vhaddw.du.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70598000, 0xffff8000, "vhaddw.qu.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x705a0000, 0xffff8000, "vhsubw.hu.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x705a8000, 0xffff8000, "vhsubw.wu.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x705b0000, 0xffff8000, "vhsubw.du.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x705b8000, 0xffff8000, "vhsubw.qu.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x705c0000, 0xffff8000, "vadda.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x705c8000, 0xffff8000, "vadda.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x705d0000, 0xffff8000, "vadda.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x705d8000, 0xffff8000, "vadda.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70600000, 0xffff8000, "vabsd.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70608000, 0xffff8000, "vabsd.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70610000, 0xffff8000, "vabsd.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70618000, 0xffff8000, "vabsd.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70620000, 0xffff8000, "vabsd.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70628000, 0xffff8000, "vabsd.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70630000, 0xffff8000, "vabsd.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70638000, 0xffff8000, "vabsd.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70640000, 0xffff8000, "vavg.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70648000, 0xffff8000, "vavg.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70650000, 0xffff8000, "vavg.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70658000, 0xffff8000, "vavg.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70660000, 0xffff8000, "vavg.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70668000, 0xffff8000, "vavg.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70670000, 0xffff8000, "vavg.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70678000, 0xffff8000, "vavg.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70680000, 0xffff8000, "vavgr.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70688000, 0xffff8000, "vavgr.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70690000, 0xffff8000, "vavgr.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70698000, 0xffff8000, "vavgr.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x706a0000, 0xffff8000, "vavgr.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x706a8000, 0xffff8000, "vavgr.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x706b0000, 0xffff8000, "vavgr.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x706b8000, 0xffff8000, "vavgr.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70700000, 0xffff8000, "vmax.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70708000, 0xffff8000, "vmax.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70710000, 0xffff8000, "vmax.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70718000, 0xffff8000, "vmax.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70720000, 0xffff8000, "vmin.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70728000, 0xffff8000, "vmin.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70730000, 0xffff8000, "vmin.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70738000, 0xffff8000, "vmin.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70740000, 0xffff8000, "vmax.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70748000, 0xffff8000, "vmax.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70750000, 0xffff8000, "vmax.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70758000, 0xffff8000, "vmax.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70760000, 0xffff8000, "vmin.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70768000, 0xffff8000, "vmin.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70770000, 0xffff8000, "vmin.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70778000, 0xffff8000, "vmin.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70840000, 0xffff8000, "vmul.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70848000, 0xffff8000, "vmul.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70850000, 0xffff8000, "vmul.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70858000, 0xffff8000, "vmul.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70860000, 0xffff8000, "vmuh.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70868000, 0xffff8000, "vmuh.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70870000, 0xffff8000, "vmuh.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70878000, 0xffff8000, "vmuh.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70880000, 0xffff8000, "vmuh.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70888000, 0xffff8000, "vmuh.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70890000, 0xffff8000, "vmuh.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70898000, 0xffff8000, "vmuh.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a80000, 0xffff8000, "vmadd.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a88000, 0xffff8000, "vmadd.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a90000, 0xffff8000, "vmadd.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a98000, 0xffff8000, "vmadd.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70aa0000, 0xffff8000, "vmsub.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70aa8000, 0xffff8000, "vmsub.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ab0000, 0xffff8000, "vmsub.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ab8000, 0xffff8000, "vmsub.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e00000, 0xffff8000, "vdiv.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e08000, 0xffff8000, "vdiv.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e10000, 0xffff8000, "vdiv.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e18000, 0xffff8000, "vdiv.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e20000, 0xffff8000, "vmod.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e28000, 0xffff8000, "vmod.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e30000, 0xffff8000, "vmod.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e38000, 0xffff8000, "vmod.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e40000, 0xffff8000, "vdiv.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e48000, 0xffff8000, "vdiv.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e50000, 0xffff8000, "vdiv.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e58000, 0xffff8000, "vdiv.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e60000, 0xffff8000, "vmod.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e68000, 0xffff8000, "vmod.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e70000, 0xffff8000, "vmod.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e78000, 0xffff8000, "vmod.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e80000, 0xffff8000, "vsll.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e88000, 0xffff8000, "vsll.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e90000, 0xffff8000, "vsll.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70e98000, 0xffff8000, "vsll.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ea0000, 0xffff8000, "vsrl.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ea8000, 0xffff8000, "vsrl.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70eb0000, 0xffff8000, "vsrl.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70eb8000, 0xffff8000, "vsrl.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ec0000, 0xffff8000, "vsra.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ec8000, 0xffff8000, "vsra.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ed0000, 0xffff8000, "vsra.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ed8000, 0xffff8000, "vsra.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ee0000, 0xffff8000, "vrotr.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ee8000, 0xffff8000, "vrotr.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ef0000, 0xffff8000, "vrotr.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ef8000, 0xffff8000, "vrotr.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f00000, 0xffff8000, "vsrlr.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f08000, 0xffff8000, "vsrlr.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f10000, 0xffff8000, "vsrlr.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f18000, 0xffff8000, "vsrlr.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f20000, 0xffff8000, "vsrar.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f28000, 0xffff8000, "vsrar.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f30000, 0xffff8000, "vsrar.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f38000, 0xffff8000, "vsrar.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f48000, 0xffff8000, "vsrln.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f50000, 0xffff8000, "vsrln.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f58000, 0xffff8000, "vsrln.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f68000, 0xffff8000, "vsran.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f70000, 0xffff8000, "vsran.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f78000, 0xffff8000, "vsran.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f88000, 0xffff8000, "vsrlrn.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f90000, 0xffff8000, "vsrlrn.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70f98000, 0xffff8000, "vsrlrn.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70fa8000, 0xffff8000, "vsrarn.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70fb0000, 0xffff8000, "vsrarn.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70fb8000, 0xffff8000, "vsrarn.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70fc8000, 0xffff8000, "vssrln.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70fd0000, 0xffff8000, "vssrln.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70fd8000, 0xffff8000, "vssrln.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70fe8000, 0xffff8000, "vssran.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ff0000, 0xffff8000, "vssran.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ff8000, 0xffff8000, "vssran.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71008000, 0xffff8000, "vssrlrn.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71010000, 0xffff8000, "vssrlrn.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71018000, 0xffff8000, "vssrlrn.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71028000, 0xffff8000, "vssrarn.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71030000, 0xffff8000, "vssrarn.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71038000, 0xffff8000, "vssrarn.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71048000, 0xffff8000, "vssrln.bu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71050000, 0xffff8000, "vssrln.hu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71058000, 0xffff8000, "vssrln.wu.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71068000, 0xffff8000, "vssran.bu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71070000, 0xffff8000, "vssran.hu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71078000, 0xffff8000, "vssran.wu.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71088000, 0xffff8000, "vssrlrn.bu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71090000, 0xffff8000, "vssrlrn.hu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71098000, 0xffff8000, "vssrlrn.wu.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710a8000, 0xffff8000, "vssrarn.bu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710b0000, 0xffff8000, "vssrarn.hu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710b8000, 0xffff8000, "vssrarn.wu.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710c0000, 0xffff8000, "vbitclr.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710c8000, 0xffff8000, "vbitclr.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710d0000, 0xffff8000, "vbitclr.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710d8000, 0xffff8000, "vbitclr.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710e0000, 0xffff8000, "vbitset.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710e8000, 0xffff8000, "vbitset.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710f0000, 0xffff8000, "vbitset.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x710f8000, 0xffff8000, "vbitset.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71100000, 0xffff8000, "vbitrev.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71108000, 0xffff8000, "vbitrev.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71110000, 0xffff8000, "vbitrev.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71118000, 0xffff8000, "vbitrev.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71160000, 0xffff8000, "vpackev.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71168000, 0xffff8000, "vpackev.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71170000, 0xffff8000, "vpackev.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71178000, 0xffff8000, "vpackev.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71180000, 0xffff8000, "vpackod.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71188000, 0xffff8000, "vpackod.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71190000, 0xffff8000, "vpackod.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71198000, 0xffff8000, "vpackod.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711a0000, 0xffff8000, "vilvl.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711a8000, 0xffff8000, "vilvl.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711b0000, 0xffff8000, "vilvl.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711b8000, 0xffff8000, "vilvl.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711c0000, 0xffff8000, "vilvh.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711c8000, 0xffff8000, "vilvh.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711d0000, 0xffff8000, "vilvh.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711d8000, 0xffff8000, "vilvh.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711e0000, 0xffff8000, "vpickev.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711e8000, 0xffff8000, "vpickev.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711f0000, 0xffff8000, "vpickev.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x711f8000, 0xffff8000, "vpickev.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71200000, 0xffff8000, "vpickod.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71208000, 0xffff8000, "vpickod.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71210000, 0xffff8000, "vpickod.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71218000, 0xffff8000, "vpickod.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71220000, 0xffff8000, "vreplve.b", "v0:5,v5:5,r10:5", 0, 0, 0, 0}, -+{0x71228000, 0xffff8000, "vreplve.h", "v0:5,v5:5,r10:5", 0, 0, 0, 0}, -+{0x71230000, 0xffff8000, "vreplve.w", "v0:5,v5:5,r10:5", 0, 0, 0, 0}, -+{0x71238000, 0xffff8000, "vreplve.d", "v0:5,v5:5,r10:5", 0, 0, 0, 0}, -+{0x71260000, 0xffff8000, "vand.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71268000, 0xffff8000, "vor.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71270000, 0xffff8000, "vxor.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71278000, 0xffff8000, "vnor.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71280000, 0xffff8000, "vandn.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71288000, 0xffff8000, "vorn.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x712b0000, 0xffff8000, "vfrstp.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x712b8000, 0xffff8000, "vfrstp.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x712d0000, 0xffff8000, "vadd.q", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x712d8000, 0xffff8000, "vsub.q", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x712e0000, 0xffff8000, "vsigncov.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x712e8000, 0xffff8000, "vsigncov.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x712f0000, 0xffff8000, "vsigncov.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x712f8000, 0xffff8000, "vsigncov.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71308000, 0xffff8000, "vfadd.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71310000, 0xffff8000, "vfadd.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71328000, 0xffff8000, "vfsub.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71330000, 0xffff8000, "vfsub.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71388000, 0xffff8000, "vfmul.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71390000, 0xffff8000, "vfmul.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x713a8000, 0xffff8000, "vfdiv.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x713b0000, 0xffff8000, "vfdiv.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x713c8000, 0xffff8000, "vfmax.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x713d0000, 0xffff8000, "vfmax.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x713e8000, 0xffff8000, "vfmin.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x713f0000, 0xffff8000, "vfmin.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71408000, 0xffff8000, "vfmaxa.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71410000, 0xffff8000, "vfmaxa.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71428000, 0xffff8000, "vfmina.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71430000, 0xffff8000, "vfmina.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71460000, 0xffff8000, "vfcvt.h.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71468000, 0xffff8000, "vfcvt.s.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71480000, 0xffff8000, "vffint.s.l", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x71498000, 0xffff8000, "vftint.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x714a0000, 0xffff8000, "vftintrm.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x714a8000, 0xffff8000, "vftintrp.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x714b0000, 0xffff8000, "vftintrz.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x714b8000, 0xffff8000, "vftintrne.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x717a8000, 0xffff8000, "vshuf.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x717b0000, 0xffff8000, "vshuf.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x717b8000, 0xffff8000, "vshuf.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x72800000, 0xffff8000, "vseqi.b", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72808000, 0xffff8000, "vseqi.h", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72810000, 0xffff8000, "vseqi.w", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72818000, 0xffff8000, "vseqi.d", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72820000, 0xffff8000, "vslei.b", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72828000, 0xffff8000, "vslei.h", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72830000, 0xffff8000, "vslei.w", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72838000, 0xffff8000, "vslei.d", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72840000, 0xffff8000, "vslei.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72848000, 0xffff8000, "vslei.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72850000, 0xffff8000, "vslei.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72858000, 0xffff8000, "vslei.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72860000, 0xffff8000, "vslti.b", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72868000, 0xffff8000, "vslti.h", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72870000, 0xffff8000, "vslti.w", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72878000, 0xffff8000, "vslti.d", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72880000, 0xffff8000, "vslti.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72888000, 0xffff8000, "vslti.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72890000, 0xffff8000, "vslti.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72898000, 0xffff8000, "vslti.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x728a0000, 0xffff8000, "vaddi.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x728a8000, 0xffff8000, "vaddi.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x728b0000, 0xffff8000, "vaddi.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x728b8000, 0xffff8000, "vaddi.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x728c0000, 0xffff8000, "vsubi.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x728c8000, 0xffff8000, "vsubi.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x728d0000, 0xffff8000, "vsubi.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x728d8000, 0xffff8000, "vsubi.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x728e0000, 0xffff8000, "vbsll.v", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x728e8000, 0xffff8000, "vbsrl.v", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72900000, 0xffff8000, "vmaxi.b", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72908000, 0xffff8000, "vmaxi.h", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72910000, 0xffff8000, "vmaxi.w", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72918000, 0xffff8000, "vmaxi.d", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72920000, 0xffff8000, "vmini.b", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72928000, 0xffff8000, "vmini.h", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72930000, 0xffff8000, "vmini.w", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72938000, 0xffff8000, "vmini.d", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, -+{0x72940000, 0xffff8000, "vmaxi.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72948000, 0xffff8000, "vmaxi.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72950000, 0xffff8000, "vmaxi.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72958000, 0xffff8000, "vmaxi.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72960000, 0xffff8000, "vmini.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72968000, 0xffff8000, "vmini.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72970000, 0xffff8000, "vmini.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72978000, 0xffff8000, "vmini.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x729a0000, 0xffff8000, "vfrstpi.b", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x729a8000, 0xffff8000, "vfrstpi.h", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x729c0000, 0xfffffc00, "vclo.b", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c0400, 0xfffffc00, "vclo.h", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c0800, 0xfffffc00, "vclo.w", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c0c00, 0xfffffc00, "vclo.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c1000, 0xfffffc00, "vclz.b", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c1400, 0xfffffc00, "vclz.h", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c1800, 0xfffffc00, "vclz.w", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c1c00, 0xfffffc00, "vclz.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c2000, 0xfffffc00, "vpcnt.b", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c2400, 0xfffffc00, "vpcnt.h", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c2800, 0xfffffc00, "vpcnt.w", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c2c00, 0xfffffc00, "vpcnt.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c3000, 0xfffffc00, "vneg.b", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c3400, 0xfffffc00, "vneg.h", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c3800, 0xfffffc00, "vneg.w", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c3c00, 0xfffffc00, "vneg.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c4000, 0xfffffc00, "vmskltz.b", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c4400, 0xfffffc00, "vmskltz.h", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c4800, 0xfffffc00, "vmskltz.w", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c4c00, 0xfffffc00, "vmskltz.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c5000, 0xfffffc00, "vmskgez.b", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c6000, 0xfffffc00, "vmsknz.b", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729c9800, 0xfffffc18, "vseteqz.v", "c0:3,v5:5", 0, 0, 0, 0}, -+{0x729c9c00, 0xfffffc18, "vsetnez.v", "c0:3,v5:5", 0, 0, 0, 0}, -+{0x729ca000, 0xfffffc18, "vsetanyeqz.b", "c0:3,v5:5", 0, 0, 0, 0}, -+{0x729ca400, 0xfffffc18, "vsetanyeqz.h", "c0:3,v5:5", 0, 0, 0, 0}, -+{0x729ca800, 0xfffffc18, "vsetanyeqz.w", "c0:3,v5:5", 0, 0, 0, 0}, -+{0x729cac00, 0xfffffc18, "vsetanyeqz.d", "c0:3,v5:5", 0, 0, 0, 0}, -+{0x729cb000, 0xfffffc18, "vsetallnez.b", "c0:3,v5:5", 0, 0, 0, 0}, -+{0x729cb400, 0xfffffc18, "vsetallnez.h", "c0:3,v5:5", 0, 0, 0, 0}, -+{0x729cb800, 0xfffffc18, "vsetallnez.w", "c0:3,v5:5", 0, 0, 0, 0}, -+{0x729cbc00, 0xfffffc18, "vsetallnez.d", "c0:3,v5:5", 0, 0, 0, 0}, -+{0x729cc400, 0xfffffc00, "vflogb.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729cc800, 0xfffffc00, "vflogb.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729cd400, 0xfffffc00, "vfclass.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729cd800, 0xfffffc00, "vfclass.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729ce400, 0xfffffc00, "vfsqrt.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729ce800, 0xfffffc00, "vfsqrt.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729cf400, 0xfffffc00, "vfrecip.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729cf800, 0xfffffc00, "vfrecip.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d0400, 0xfffffc00, "vfrsqrt.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d0800, 0xfffffc00, "vfrsqrt.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d3400, 0xfffffc00, "vfrint.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d3800, 0xfffffc00, "vfrint.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d4400, 0xfffffc00, "vfrintrm.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d4800, 0xfffffc00, "vfrintrm.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d5400, 0xfffffc00, "vfrintrp.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d5800, 0xfffffc00, "vfrintrp.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d6400, 0xfffffc00, "vfrintrz.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d6800, 0xfffffc00, "vfrintrz.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d7400, 0xfffffc00, "vfrintrne.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729d7800, 0xfffffc00, "vfrintrne.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729de800, 0xfffffc00, "vfcvtl.s.h", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729dec00, 0xfffffc00, "vfcvth.s.h", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729df000, 0xfffffc00, "vfcvtl.d.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729df400, 0xfffffc00, "vfcvth.d.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e0000, 0xfffffc00, "vffint.s.w", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e0400, 0xfffffc00, "vffint.s.wu", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e0800, 0xfffffc00, "vffint.d.l", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e0c00, 0xfffffc00, "vffint.d.lu", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e1000, 0xfffffc00, "vffintl.d.w", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e1400, 0xfffffc00, "vffinth.d.w", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e3000, 0xfffffc00, "vftint.w.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e3400, 0xfffffc00, "vftint.l.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e3800, 0xfffffc00, "vftintrm.w.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e3c00, 0xfffffc00, "vftintrm.l.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e4000, 0xfffffc00, "vftintrp.w.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e4400, 0xfffffc00, "vftintrp.l.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e4800, 0xfffffc00, "vftintrz.w.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e4c00, 0xfffffc00, "vftintrz.l.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e5000, 0xfffffc00, "vftintrne.w.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e5400, 0xfffffc00, "vftintrne.l.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e5800, 0xfffffc00, "vftint.wu.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e5c00, 0xfffffc00, "vftint.lu.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e7000, 0xfffffc00, "vftintrz.wu.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e7400, 0xfffffc00, "vftintrz.lu.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e8000, 0xfffffc00, "vftintl.l.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e8400, 0xfffffc00, "vftinth.l.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e8800, 0xfffffc00, "vftintrml.l.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e8c00, 0xfffffc00, "vftintrmh.l.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e9000, 0xfffffc00, "vftintrpl.l.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e9400, 0xfffffc00, "vftintrph.l.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e9800, 0xfffffc00, "vftintrzl.l.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729e9c00, 0xfffffc00, "vftintrzh.l.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729ea000, 0xfffffc00, "vftintrnel.l.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729ea400, 0xfffffc00, "vftintrneh.l.s", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729ee000, 0xfffffc00, "vexth.h.b", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729ee400, 0xfffffc00, "vexth.w.h", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729ee800, 0xfffffc00, "vexth.d.w", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729eec00, 0xfffffc00, "vexth.q.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729ef000, 0xfffffc00, "vexth.hu.bu", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729ef400, 0xfffffc00, "vexth.wu.hu", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729ef800, 0xfffffc00, "vexth.du.wu", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729efc00, 0xfffffc00, "vexth.qu.du", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x729f0000, 0xfffffc00, "vreplgr2vr.b", "v0:5,r5:5", 0, 0, 0, 0}, -+{0x729f0400, 0xfffffc00, "vreplgr2vr.h", "v0:5,r5:5", 0, 0, 0, 0}, -+{0x729f0800, 0xfffffc00, "vreplgr2vr.w", "v0:5,r5:5", 0, 0, 0, 0}, -+{0x729f0c00, 0xfffffc00, "vreplgr2vr.d", "v0:5,r5:5", 0, 0, 0, 0}, -+{0x72a02000, 0xffffe000, "vrotri.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x72a04000, 0xffffc000, "vrotri.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x72a08000, 0xffff8000, "vrotri.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72a10000, 0xffff0000, "vrotri.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x72a42000, 0xffffe000, "vsrlri.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x72a44000, 0xffffc000, "vsrlri.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x72a48000, 0xffff8000, "vsrlri.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72a50000, 0xffff0000, "vsrlri.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x72a82000, 0xffffe000, "vsrari.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x72a84000, 0xffffc000, "vsrari.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x72a88000, 0xffff8000, "vsrari.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x72a90000, 0xffff0000, "vsrari.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x72eb8000, 0xffffc000, "vinsgr2vr.b", "v0:5,r5:5,u10:4", 0, 0, 0, 0}, -+{0x72ebc000, 0xffffe000, "vinsgr2vr.h", "v0:5,r5:5,u10:3", 0, 0, 0, 0}, -+{0x72ebe000, 0xfffff000, "vinsgr2vr.w", "v0:5,r5:5,u10:2", 0, 0, 0, 0}, -+{0x72ebf000, 0xfffff800, "vinsgr2vr.d", "v0:5,r5:5,u10:1", 0, 0, 0, 0}, -+{0x72ef8000, 0xffffc000, "vpickve2gr.b", "r0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x72efc000, 0xffffe000, "vpickve2gr.h", "r0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x72efe000, 0xfffff000, "vpickve2gr.w", "r0:5,v5:5,u10:2", 0, 0, 0, 0}, -+{0x72eff000, 0xfffff800, "vpickve2gr.d", "r0:5,v5:5,u10:1", 0, 0, 0, 0}, -+{0x72f38000, 0xffffc000, "vpickve2gr.bu", "r0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x72f3c000, 0xffffe000, "vpickve2gr.hu", "r0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x72f3e000, 0xfffff000, "vpickve2gr.wu", "r0:5,v5:5,u10:2", 0, 0, 0, 0}, -+{0x72f3f000, 0xfffff800, "vpickve2gr.du", "r0:5,v5:5,u10:1", 0, 0, 0, 0}, -+{0x72f78000, 0xffffc000, "vreplvei.b", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x72f7c000, 0xffffe000, "vreplvei.h", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x72f7e000, 0xfffff000, "vreplvei.w", "v0:5,v5:5,u10:2", 0, 0, 0, 0}, -+{0x72f7f000, 0xfffff800, "vreplvei.d", "v0:5,v5:5,u10:1", 0, 0, 0, 0}, -+{0x73082000, 0xffffe000, "vsllwil.h.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x73084000, 0xffffc000, "vsllwil.w.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73088000, 0xffff8000, "vsllwil.d.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73090000, 0xfffffc00, "vextl.q.d", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x730c2000, 0xffffe000, "vsllwil.hu.bu", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x730c4000, 0xffffc000, "vsllwil.wu.hu", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x730c8000, 0xffff8000, "vsllwil.du.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x730d0000, 0xfffffc00, "vextl.qu.du", "v0:5,v5:5", 0, 0, 0, 0}, -+{0x73102000, 0xffffe000, "vbitclri.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x73104000, 0xffffc000, "vbitclri.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73108000, 0xffff8000, "vbitclri.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73110000, 0xffff0000, "vbitclri.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73142000, 0xffffe000, "vbitseti.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x73144000, 0xffffc000, "vbitseti.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73148000, 0xffff8000, "vbitseti.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73150000, 0xffff0000, "vbitseti.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73182000, 0xffffe000, "vbitrevi.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x73184000, 0xffffc000, "vbitrevi.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73188000, 0xffff8000, "vbitrevi.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73190000, 0xffff0000, "vbitrevi.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73242000, 0xffffe000, "vsat.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x73244000, 0xffffc000, "vsat.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73248000, 0xffff8000, "vsat.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73250000, 0xffff0000, "vsat.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73282000, 0xffffe000, "vsat.bu", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x73284000, 0xffffc000, "vsat.hu", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73288000, 0xffff8000, "vsat.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73290000, 0xffff0000, "vsat.du", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x732c2000, 0xffffe000, "vslli.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x732c4000, 0xffffc000, "vslli.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x732c8000, 0xffff8000, "vslli.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x732d0000, 0xffff0000, "vslli.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73302000, 0xffffe000, "vsrli.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x73304000, 0xffffc000, "vsrli.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73308000, 0xffff8000, "vsrli.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73310000, 0xffff0000, "vsrli.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73342000, 0xffffe000, "vsrai.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, -+{0x73344000, 0xffffc000, "vsrai.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73348000, 0xffff8000, "vsrai.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73350000, 0xffff0000, "vsrai.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73404000, 0xffffc000, "vsrlni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73408000, 0xffff8000, "vsrlni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73410000, 0xffff0000, "vsrlni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73420000, 0xfffe0000, "vsrlni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x73484000, 0xffffc000, "vssrlni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73488000, 0xffff8000, "vssrlni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73490000, 0xffff0000, "vssrlni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x734a0000, 0xfffe0000, "vssrlni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x73444000, 0xffffc000, "vsrlrni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73448000, 0xffff8000, "vsrlrni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73450000, 0xffff0000, "vsrlrni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73460000, 0xfffe0000, "vsrlrni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x734c4000, 0xffffc000, "vssrlni.bu.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x734c8000, 0xffff8000, "vssrlni.hu.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x734d0000, 0xffff0000, "vssrlni.wu.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x734e0000, 0xfffe0000, "vssrlni.du.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x73504000, 0xffffc000, "vssrlrni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73508000, 0xffff8000, "vssrlrni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73510000, 0xffff0000, "vssrlrni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73520000, 0xfffe0000, "vssrlrni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x73544000, 0xffffc000, "vssrlrni.bu.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73548000, 0xffff8000, "vssrlrni.hu.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73550000, 0xffff0000, "vssrlrni.wu.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73560000, 0xfffe0000, "vssrlrni.du.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x73584000, 0xffffc000, "vsrani.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73588000, 0xffff8000, "vsrani.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73590000, 0xffff0000, "vsrani.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x735a0000, 0xfffe0000, "vsrani.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x735c4000, 0xffffc000, "vsrarni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x735c8000, 0xffff8000, "vsrarni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x735d0000, 0xffff0000, "vsrarni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x735e0000, 0xfffe0000, "vsrarni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x73604000, 0xffffc000, "vssrani.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73608000, 0xffff8000, "vssrani.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73610000, 0xffff0000, "vssrani.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73620000, 0xfffe0000, "vssrani.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x73644000, 0xffffc000, "vssrani.bu.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73648000, 0xffff8000, "vssrani.hu.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73650000, 0xffff0000, "vssrani.wu.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x73660000, 0xfffe0000, "vssrani.du.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x73684000, 0xffffc000, "vssrarni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x73688000, 0xffff8000, "vssrarni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x73690000, 0xffff0000, "vssrarni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x736a0000, 0xfffe0000, "vssrarni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x736c4000, 0xffffc000, "vssrarni.bu.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, -+{0x736c8000, 0xffff8000, "vssrarni.hu.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, -+{0x736d0000, 0xffff0000, "vssrarni.wu.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, -+{0x736e0000, 0xfffe0000, "vssrarni.du.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, -+{0x73800000, 0xfffc0000, "vextrins.d", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x73840000, 0xfffc0000, "vextrins.w", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x73880000, 0xfffc0000, "vextrins.h", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x738c0000, 0xfffc0000, "vextrins.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x73900000, 0xfffc0000, "vshuf4i.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x73940000, 0xfffc0000, "vshuf4i.h", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x73980000, 0xfffc0000, "vshuf4i.w", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x739c0000, 0xfffc0000, "vshuf4i.d", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x73c40000, 0xfffc0000, "vbitseli.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x73d00000, 0xfffc0000, "vandi.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x73d40000, 0xfffc0000, "vori.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x73d80000, 0xfffc0000, "vxori.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0x73dc0000, 0xfffc0000, "vnori.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0, 0, "vrepli.b", "v,s0:10", "vldi %1,(%2)&0x3ff", 0, 0, 0}, -+ -+{0x701e0000, 0xffff8000, "vaddwev.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x701e8000, 0xffff8000, "vaddwev.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x701f0000, 0xffff8000, "vaddwev.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x701f8000, 0xffff8000, "vaddwev.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x702e0000, 0xffff8000, "vaddwev.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x702e8000, 0xffff8000, "vaddwev.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x702f0000, 0xffff8000, "vaddwev.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x702f8000, 0xffff8000, "vaddwev.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x703e0000, 0xffff8000, "vaddwev.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x703e8000, 0xffff8000, "vaddwev.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x703f0000, 0xffff8000, "vaddwev.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x703f8000, 0xffff8000, "vaddwev.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70220000, 0xffff8000, "vaddwod.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70228000, 0xffff8000, "vaddwod.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70230000, 0xffff8000, "vaddwod.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70238000, 0xffff8000, "vaddwod.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70320000, 0xffff8000, "vaddwod.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70328000, 0xffff8000, "vaddwod.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70330000, 0xffff8000, "vaddwod.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70338000, 0xffff8000, "vaddwod.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70400000, 0xffff8000, "vaddwod.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70408000, 0xffff8000, "vaddwod.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70410000, 0xffff8000, "vaddwod.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70418000, 0xffff8000, "vaddwod.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ac0000, 0xffff8000, "vmaddwev.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ac8000, 0xffff8000, "vmaddwev.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ad0000, 0xffff8000, "vmaddwev.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ad8000, 0xffff8000, "vmaddwev.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70b40000, 0xffff8000, "vmaddwev.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70b48000, 0xffff8000, "vmaddwev.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70b50000, 0xffff8000, "vmaddwev.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70b58000, 0xffff8000, "vmaddwev.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70bc0000, 0xffff8000, "vmaddwev.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70bc8000, 0xffff8000, "vmaddwev.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70bd0000, 0xffff8000, "vmaddwev.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70bd8000, 0xffff8000, "vmaddwev.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ae0000, 0xffff8000, "vmaddwod.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70ae8000, 0xffff8000, "vmaddwod.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70af0000, 0xffff8000, "vmaddwod.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70af8000, 0xffff8000, "vmaddwod.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70b60000, 0xffff8000, "vmaddwod.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70b68000, 0xffff8000, "vmaddwod.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70b70000, 0xffff8000, "vmaddwod.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70b78000, 0xffff8000, "vmaddwod.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70be0000, 0xffff8000, "vmaddwod.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70be8000, 0xffff8000, "vmaddwod.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70bf0000, 0xffff8000, "vmaddwod.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70bf8000, 0xffff8000, "vmaddwod.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70900000, 0xffff8000, "vmulwev.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70908000, 0xffff8000, "vmulwev.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70910000, 0xffff8000, "vmulwev.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70918000, 0xffff8000, "vmulwev.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70980000, 0xffff8000, "vmulwev.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70988000, 0xffff8000, "vmulwev.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70990000, 0xffff8000, "vmulwev.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70998000, 0xffff8000, "vmulwev.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a00000, 0xffff8000, "vmulwev.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a08000, 0xffff8000, "vmulwev.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a10000, 0xffff8000, "vmulwev.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a18000, 0xffff8000, "vmulwev.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70920000, 0xffff8000, "vmulwod.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70928000, 0xffff8000, "vmulwod.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70930000, 0xffff8000, "vmulwod.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70938000, 0xffff8000, "vmulwod.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x709a0000, 0xffff8000, "vmulwod.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x709a8000, 0xffff8000, "vmulwod.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x709b0000, 0xffff8000, "vmulwod.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x709b8000, 0xffff8000, "vmulwod.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a20000, 0xffff8000, "vmulwod.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a28000, 0xffff8000, "vmulwod.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a30000, 0xffff8000, "vmulwod.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70a38000, 0xffff8000, "vmulwod.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70200000, 0xffff8000, "vsubwev.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70208000, 0xffff8000, "vsubwev.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70210000, 0xffff8000, "vsubwev.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70218000, 0xffff8000, "vsubwev.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70300000, 0xffff8000, "vsubwev.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70308000, 0xffff8000, "vsubwev.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70310000, 0xffff8000, "vsubwev.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70318000, 0xffff8000, "vsubwev.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70240000, 0xffff8000, "vsubwod.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70248000, 0xffff8000, "vsubwod.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70250000, 0xffff8000, "vsubwod.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70258000, 0xffff8000, "vsubwod.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70340000, 0xffff8000, "vsubwod.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70348000, 0xffff8000, "vsubwod.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70350000, 0xffff8000, "vsubwod.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0x70358000, 0xffff8000, "vsubwod.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, -+{0, 0, "vrepli.d", "v,s0:10", "vldi %1,((%2)&0x3ff)|0xc00", 0, 0, 0}, -+{0, 0, "vrepli.h", "v,s0:10", "vldi %1,((%2)&0x3ff)|0x400", 0, 0, 0}, -+{0, 0, "vrepli.w", "v,s0:10", "vldi %1,((%2)&0x3ff)|0x800", 0, 0, 0}, -+{0x73e00000, 0xfffc0000, "vldi", "v0:5,s5:13", 0, 0, 0, 0}, -+{0x73e40000, 0xfffc0000, "vpermi.w", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, -+{0} /* Terminate the list. */ -+}; -+ -+static struct loongarch_opcode loongarch_256vec_opcodes[] = { -+/* match, mask, name, format, macro, include, exclude, pinfo */ -+{0x74000000, 0xffff8000, "xvseq.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74008000, 0xffff8000, "xvseq.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74010000, 0xffff8000, "xvseq.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74018000, 0xffff8000, "xvseq.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74020000, 0xffff8000, "xvsle.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74028000, 0xffff8000, "xvsle.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74030000, 0xffff8000, "xvsle.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74038000, 0xffff8000, "xvsle.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74040000, 0xffff8000, "xvsle.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74048000, 0xffff8000, "xvsle.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74050000, 0xffff8000, "xvsle.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74058000, 0xffff8000, "xvsle.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74060000, 0xffff8000, "xvslt.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74068000, 0xffff8000, "xvslt.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74070000, 0xffff8000, "xvslt.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74078000, 0xffff8000, "xvslt.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74080000, 0xffff8000, "xvslt.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74088000, 0xffff8000, "xvslt.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74090000, 0xffff8000, "xvslt.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74098000, 0xffff8000, "xvslt.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x740a0000, 0xffff8000, "xvadd.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x740a8000, 0xffff8000, "xvadd.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x740b0000, 0xffff8000, "xvadd.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x740b8000, 0xffff8000, "xvadd.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x740c0000, 0xffff8000, "xvsub.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x740c8000, 0xffff8000, "xvsub.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x740d0000, 0xffff8000, "xvsub.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x740d8000, 0xffff8000, "xvsub.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74460000, 0xffff8000, "xvsadd.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74468000, 0xffff8000, "xvsadd.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74470000, 0xffff8000, "xvsadd.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74478000, 0xffff8000, "xvsadd.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74480000, 0xffff8000, "xvssub.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74488000, 0xffff8000, "xvssub.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74490000, 0xffff8000, "xvssub.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74498000, 0xffff8000, "xvssub.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x744a0000, 0xffff8000, "xvsadd.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x744a8000, 0xffff8000, "xvsadd.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x744b0000, 0xffff8000, "xvsadd.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x744b8000, 0xffff8000, "xvsadd.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x744c0000, 0xffff8000, "xvssub.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x744c8000, 0xffff8000, "xvssub.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x744d0000, 0xffff8000, "xvssub.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x744d8000, 0xffff8000, "xvssub.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74540000, 0xffff8000, "xvhaddw.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74548000, 0xffff8000, "xvhaddw.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74550000, 0xffff8000, "xvhaddw.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74558000, 0xffff8000, "xvhaddw.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74560000, 0xffff8000, "xvhsubw.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74568000, 0xffff8000, "xvhsubw.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74570000, 0xffff8000, "xvhsubw.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74578000, 0xffff8000, "xvhsubw.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74580000, 0xffff8000, "xvhaddw.hu.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74588000, 0xffff8000, "xvhaddw.wu.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74590000, 0xffff8000, "xvhaddw.du.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74598000, 0xffff8000, "xvhaddw.qu.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x745a0000, 0xffff8000, "xvhsubw.hu.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x745a8000, 0xffff8000, "xvhsubw.wu.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x745b0000, 0xffff8000, "xvhsubw.du.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x745b8000, 0xffff8000, "xvhsubw.qu.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x741e0000, 0xffff8000, "xvaddwev.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x741e8000, 0xffff8000, "xvaddwev.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x741f0000, 0xffff8000, "xvaddwev.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x741f8000, 0xffff8000, "xvaddwev.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x742e0000, 0xffff8000, "xvaddwev.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x742e8000, 0xffff8000, "xvaddwev.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x742f0000, 0xffff8000, "xvaddwev.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x742f8000, 0xffff8000, "xvaddwev.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x743e0000, 0xffff8000, "xvaddwev.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x743e8000, 0xffff8000, "xvaddwev.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x743f0000, 0xffff8000, "xvaddwev.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x743f8000, 0xffff8000, "xvaddwev.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74220000, 0xffff8000, "xvaddwod.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74228000, 0xffff8000, "xvaddwod.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74230000, 0xffff8000, "xvaddwod.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74238000, 0xffff8000, "xvaddwod.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74320000, 0xffff8000, "xvaddwod.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74328000, 0xffff8000, "xvaddwod.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74330000, 0xffff8000, "xvaddwod.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74338000, 0xffff8000, "xvaddwod.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74400000, 0xffff8000, "xvaddwod.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74408000, 0xffff8000, "xvaddwod.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74410000, 0xffff8000, "xvaddwod.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74418000, 0xffff8000, "xvaddwod.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ac0000, 0xffff8000, "xvmaddwev.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ac8000, 0xffff8000, "xvmaddwev.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ad0000, 0xffff8000, "xvmaddwev.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ad8000, 0xffff8000, "xvmaddwev.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74bc0000, 0xffff8000, "xvmaddwev.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74bc8000, 0xffff8000, "xvmaddwev.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74bd0000, 0xffff8000, "xvmaddwev.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74bd8000, 0xffff8000, "xvmaddwev.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74b40000, 0xffff8000, "xvmaddwev.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74b48000, 0xffff8000, "xvmaddwev.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74b50000, 0xffff8000, "xvmaddwev.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74b58000, 0xffff8000, "xvmaddwev.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ae0000, 0xffff8000, "xvmaddwod.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ae8000, 0xffff8000, "xvmaddwod.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74af0000, 0xffff8000, "xvmaddwod.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74af8000, 0xffff8000, "xvmaddwod.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74b60000, 0xffff8000, "xvmaddwod.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74b68000, 0xffff8000, "xvmaddwod.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74b70000, 0xffff8000, "xvmaddwod.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74b78000, 0xffff8000, "xvmaddwod.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74be0000, 0xffff8000, "xvmaddwod.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74be8000, 0xffff8000, "xvmaddwod.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74bf0000, 0xffff8000, "xvmaddwod.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74bf8000, 0xffff8000, "xvmaddwod.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74900000, 0xffff8000, "xvmulwev.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74908000, 0xffff8000, "xvmulwev.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74910000, 0xffff8000, "xvmulwev.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74918000, 0xffff8000, "xvmulwev.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74980000, 0xffff8000, "xvmulwev.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74988000, 0xffff8000, "xvmulwev.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74990000, 0xffff8000, "xvmulwev.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74998000, 0xffff8000, "xvmulwev.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a00000, 0xffff8000, "xvmulwev.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a08000, 0xffff8000, "xvmulwev.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a10000, 0xffff8000, "xvmulwev.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a18000, 0xffff8000, "xvmulwev.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74920000, 0xffff8000, "xvmulwod.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74928000, 0xffff8000, "xvmulwod.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74930000, 0xffff8000, "xvmulwod.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74938000, 0xffff8000, "xvmulwod.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x749a0000, 0xffff8000, "xvmulwod.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x749a8000, 0xffff8000, "xvmulwod.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x749b0000, 0xffff8000, "xvmulwod.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x749b8000, 0xffff8000, "xvmulwod.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a20000, 0xffff8000, "xvmulwod.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a28000, 0xffff8000, "xvmulwod.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a30000, 0xffff8000, "xvmulwod.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a38000, 0xffff8000, "xvmulwod.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74200000, 0xffff8000, "xvsubwev.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74208000, 0xffff8000, "xvsubwev.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74210000, 0xffff8000, "xvsubwev.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74218000, 0xffff8000, "xvsubwev.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74300000, 0xffff8000, "xvsubwev.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74308000, 0xffff8000, "xvsubwev.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74310000, 0xffff8000, "xvsubwev.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74318000, 0xffff8000, "xvsubwev.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74240000, 0xffff8000, "xvsubwod.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74248000, 0xffff8000, "xvsubwod.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74250000, 0xffff8000, "xvsubwod.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74258000, 0xffff8000, "xvsubwod.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74340000, 0xffff8000, "xvsubwod.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74348000, 0xffff8000, "xvsubwod.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74350000, 0xffff8000, "xvsubwod.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74358000, 0xffff8000, "xvsubwod.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x745c0000, 0xffff8000, "xvadda.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x745c8000, 0xffff8000, "xvadda.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x745d0000, 0xffff8000, "xvadda.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x745d8000, 0xffff8000, "xvadda.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74600000, 0xffff8000, "xvabsd.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74608000, 0xffff8000, "xvabsd.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74610000, 0xffff8000, "xvabsd.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74618000, 0xffff8000, "xvabsd.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74620000, 0xffff8000, "xvabsd.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74628000, 0xffff8000, "xvabsd.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74630000, 0xffff8000, "xvabsd.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74638000, 0xffff8000, "xvabsd.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74640000, 0xffff8000, "xvavg.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74648000, 0xffff8000, "xvavg.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74650000, 0xffff8000, "xvavg.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74658000, 0xffff8000, "xvavg.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74660000, 0xffff8000, "xvavg.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74668000, 0xffff8000, "xvavg.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74670000, 0xffff8000, "xvavg.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74678000, 0xffff8000, "xvavg.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74680000, 0xffff8000, "xvavgr.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74688000, 0xffff8000, "xvavgr.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74690000, 0xffff8000, "xvavgr.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74698000, 0xffff8000, "xvavgr.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x746a0000, 0xffff8000, "xvavgr.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x746a8000, 0xffff8000, "xvavgr.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x746b0000, 0xffff8000, "xvavgr.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x746b8000, 0xffff8000, "xvavgr.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74700000, 0xffff8000, "xvmax.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74708000, 0xffff8000, "xvmax.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74710000, 0xffff8000, "xvmax.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74718000, 0xffff8000, "xvmax.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74720000, 0xffff8000, "xvmin.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74728000, 0xffff8000, "xvmin.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74730000, 0xffff8000, "xvmin.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74738000, 0xffff8000, "xvmin.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74740000, 0xffff8000, "xvmax.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74748000, 0xffff8000, "xvmax.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74750000, 0xffff8000, "xvmax.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74758000, 0xffff8000, "xvmax.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74760000, 0xffff8000, "xvmin.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74768000, 0xffff8000, "xvmin.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74770000, 0xffff8000, "xvmin.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74778000, 0xffff8000, "xvmin.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74840000, 0xffff8000, "xvmul.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74848000, 0xffff8000, "xvmul.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74850000, 0xffff8000, "xvmul.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74858000, 0xffff8000, "xvmul.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74860000, 0xffff8000, "xvmuh.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74868000, 0xffff8000, "xvmuh.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74870000, 0xffff8000, "xvmuh.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74878000, 0xffff8000, "xvmuh.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74880000, 0xffff8000, "xvmuh.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74888000, 0xffff8000, "xvmuh.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74890000, 0xffff8000, "xvmuh.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74898000, 0xffff8000, "xvmuh.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a80000, 0xffff8000, "xvmadd.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a88000, 0xffff8000, "xvmadd.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a90000, 0xffff8000, "xvmadd.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74a98000, 0xffff8000, "xvmadd.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74aa0000, 0xffff8000, "xvmsub.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74aa8000, 0xffff8000, "xvmsub.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ab0000, 0xffff8000, "xvmsub.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ab8000, 0xffff8000, "xvmsub.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e00000, 0xffff8000, "xvdiv.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e08000, 0xffff8000, "xvdiv.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e10000, 0xffff8000, "xvdiv.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e18000, 0xffff8000, "xvdiv.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e20000, 0xffff8000, "xvmod.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e28000, 0xffff8000, "xvmod.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e30000, 0xffff8000, "xvmod.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e38000, 0xffff8000, "xvmod.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e40000, 0xffff8000, "xvdiv.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e48000, 0xffff8000, "xvdiv.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e50000, 0xffff8000, "xvdiv.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e58000, 0xffff8000, "xvdiv.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e60000, 0xffff8000, "xvmod.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e68000, 0xffff8000, "xvmod.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e70000, 0xffff8000, "xvmod.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e78000, 0xffff8000, "xvmod.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e80000, 0xffff8000, "xvsll.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e88000, 0xffff8000, "xvsll.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e90000, 0xffff8000, "xvsll.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74e98000, 0xffff8000, "xvsll.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ea0000, 0xffff8000, "xvsrl.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ea8000, 0xffff8000, "xvsrl.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74eb0000, 0xffff8000, "xvsrl.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74eb8000, 0xffff8000, "xvsrl.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ec0000, 0xffff8000, "xvsra.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ec8000, 0xffff8000, "xvsra.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ed0000, 0xffff8000, "xvsra.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ed8000, 0xffff8000, "xvsra.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ee0000, 0xffff8000, "xvrotr.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ee8000, 0xffff8000, "xvrotr.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ef0000, 0xffff8000, "xvrotr.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ef8000, 0xffff8000, "xvrotr.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f00000, 0xffff8000, "xvsrlr.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f08000, 0xffff8000, "xvsrlr.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f10000, 0xffff8000, "xvsrlr.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f18000, 0xffff8000, "xvsrlr.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f20000, 0xffff8000, "xvsrar.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f28000, 0xffff8000, "xvsrar.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f30000, 0xffff8000, "xvsrar.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f38000, 0xffff8000, "xvsrar.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f48000, 0xffff8000, "xvsrln.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f50000, 0xffff8000, "xvsrln.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f58000, 0xffff8000, "xvsrln.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f68000, 0xffff8000, "xvsran.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f70000, 0xffff8000, "xvsran.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f78000, 0xffff8000, "xvsran.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f88000, 0xffff8000, "xvsrlrn.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f90000, 0xffff8000, "xvsrlrn.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74f98000, 0xffff8000, "xvsrlrn.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74fa8000, 0xffff8000, "xvsrarn.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74fb0000, 0xffff8000, "xvsrarn.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74fb8000, 0xffff8000, "xvsrarn.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74fc8000, 0xffff8000, "xvssrln.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74fd0000, 0xffff8000, "xvssrln.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74fd8000, 0xffff8000, "xvssrln.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74fe8000, 0xffff8000, "xvssran.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ff0000, 0xffff8000, "xvssran.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x74ff8000, 0xffff8000, "xvssran.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75008000, 0xffff8000, "xvssrlrn.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75010000, 0xffff8000, "xvssrlrn.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75018000, 0xffff8000, "xvssrlrn.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75028000, 0xffff8000, "xvssrarn.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75030000, 0xffff8000, "xvssrarn.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75038000, 0xffff8000, "xvssrarn.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75048000, 0xffff8000, "xvssrln.bu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75050000, 0xffff8000, "xvssrln.hu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75058000, 0xffff8000, "xvssrln.wu.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75068000, 0xffff8000, "xvssran.bu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75070000, 0xffff8000, "xvssran.hu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75078000, 0xffff8000, "xvssran.wu.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75088000, 0xffff8000, "xvssrlrn.bu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75090000, 0xffff8000, "xvssrlrn.hu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75098000, 0xffff8000, "xvssrlrn.wu.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750a8000, 0xffff8000, "xvssrarn.bu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750b0000, 0xffff8000, "xvssrarn.hu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750b8000, 0xffff8000, "xvssrarn.wu.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750c0000, 0xffff8000, "xvbitclr.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750c8000, 0xffff8000, "xvbitclr.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750d0000, 0xffff8000, "xvbitclr.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750d8000, 0xffff8000, "xvbitclr.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750e0000, 0xffff8000, "xvbitset.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750e8000, 0xffff8000, "xvbitset.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750f0000, 0xffff8000, "xvbitset.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x750f8000, 0xffff8000, "xvbitset.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75100000, 0xffff8000, "xvbitrev.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75108000, 0xffff8000, "xvbitrev.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75110000, 0xffff8000, "xvbitrev.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75118000, 0xffff8000, "xvbitrev.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75160000, 0xffff8000, "xvpackev.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75168000, 0xffff8000, "xvpackev.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75170000, 0xffff8000, "xvpackev.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75178000, 0xffff8000, "xvpackev.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75180000, 0xffff8000, "xvpackod.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75188000, 0xffff8000, "xvpackod.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75190000, 0xffff8000, "xvpackod.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75198000, 0xffff8000, "xvpackod.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751a0000, 0xffff8000, "xvilvl.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751a8000, 0xffff8000, "xvilvl.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751b0000, 0xffff8000, "xvilvl.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751b8000, 0xffff8000, "xvilvl.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751c0000, 0xffff8000, "xvilvh.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751c8000, 0xffff8000, "xvilvh.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751d0000, 0xffff8000, "xvilvh.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751d8000, 0xffff8000, "xvilvh.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751e0000, 0xffff8000, "xvpickev.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751e8000, 0xffff8000, "xvpickev.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751f0000, 0xffff8000, "xvpickev.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x751f8000, 0xffff8000, "xvpickev.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75200000, 0xffff8000, "xvpickod.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75208000, 0xffff8000, "xvpickod.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75210000, 0xffff8000, "xvpickod.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75218000, 0xffff8000, "xvpickod.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75220000, 0xffff8000, "xvreplve.b", "x0:5,x5:5,r10:5", 0, 0, 0, 0}, -+{0x75228000, 0xffff8000, "xvreplve.h", "x0:5,x5:5,r10:5", 0, 0, 0, 0}, -+{0x75230000, 0xffff8000, "xvreplve.w", "x0:5,x5:5,r10:5", 0, 0, 0, 0}, -+{0x75238000, 0xffff8000, "xvreplve.d", "x0:5,x5:5,r10:5", 0, 0, 0, 0}, -+{0x75260000, 0xffff8000, "xvand.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75268000, 0xffff8000, "xvor.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75270000, 0xffff8000, "xvxor.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75278000, 0xffff8000, "xvnor.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75280000, 0xffff8000, "xvandn.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75288000, 0xffff8000, "xvorn.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x752b0000, 0xffff8000, "xvfrstp.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x752b8000, 0xffff8000, "xvfrstp.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x752d0000, 0xffff8000, "xvadd.q", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x752d8000, 0xffff8000, "xvsub.q", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x752e0000, 0xffff8000, "xvsigncov.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x752e8000, 0xffff8000, "xvsigncov.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x752f0000, 0xffff8000, "xvsigncov.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x752f8000, 0xffff8000, "xvsigncov.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75308000, 0xffff8000, "xvfadd.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75310000, 0xffff8000, "xvfadd.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75328000, 0xffff8000, "xvfsub.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75330000, 0xffff8000, "xvfsub.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75388000, 0xffff8000, "xvfmul.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75390000, 0xffff8000, "xvfmul.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x753a8000, 0xffff8000, "xvfdiv.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x753b0000, 0xffff8000, "xvfdiv.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x753c8000, 0xffff8000, "xvfmax.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x753d0000, 0xffff8000, "xvfmax.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x753e8000, 0xffff8000, "xvfmin.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x753f0000, 0xffff8000, "xvfmin.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75408000, 0xffff8000, "xvfmaxa.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75410000, 0xffff8000, "xvfmaxa.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75428000, 0xffff8000, "xvfmina.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75430000, 0xffff8000, "xvfmina.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75460000, 0xffff8000, "xvfcvt.h.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75468000, 0xffff8000, "xvfcvt.s.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75480000, 0xffff8000, "xvffint.s.l", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x75498000, 0xffff8000, "xvftint.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x754a0000, 0xffff8000, "xvftintrm.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x754a8000, 0xffff8000, "xvftintrp.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x754b0000, 0xffff8000, "xvftintrz.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x754b8000, 0xffff8000, "xvftintrne.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x757a8000, 0xffff8000, "xvshuf.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x757b0000, 0xffff8000, "xvshuf.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x757b8000, 0xffff8000, "xvshuf.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x757d0000, 0xffff8000, "xvperm.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, -+{0x76800000, 0xffff8000, "xvseqi.b", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76808000, 0xffff8000, "xvseqi.h", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76810000, 0xffff8000, "xvseqi.w", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76818000, 0xffff8000, "xvseqi.d", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76820000, 0xffff8000, "xvslei.b", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76828000, 0xffff8000, "xvslei.h", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76830000, 0xffff8000, "xvslei.w", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76838000, 0xffff8000, "xvslei.d", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76840000, 0xffff8000, "xvslei.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76848000, 0xffff8000, "xvslei.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76850000, 0xffff8000, "xvslei.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76858000, 0xffff8000, "xvslei.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76860000, 0xffff8000, "xvslti.b", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76868000, 0xffff8000, "xvslti.h", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76870000, 0xffff8000, "xvslti.w", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76878000, 0xffff8000, "xvslti.d", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76880000, 0xffff8000, "xvslti.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76888000, 0xffff8000, "xvslti.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76890000, 0xffff8000, "xvslti.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76898000, 0xffff8000, "xvslti.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x768a0000, 0xffff8000, "xvaddi.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x768a8000, 0xffff8000, "xvaddi.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x768b0000, 0xffff8000, "xvaddi.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x768b8000, 0xffff8000, "xvaddi.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x768c0000, 0xffff8000, "xvsubi.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x768c8000, 0xffff8000, "xvsubi.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x768d0000, 0xffff8000, "xvsubi.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x768d8000, 0xffff8000, "xvsubi.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x768e0000, 0xffff8000, "xvbsll.v", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x768e8000, 0xffff8000, "xvbsrl.v", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76900000, 0xffff8000, "xvmaxi.b", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76908000, 0xffff8000, "xvmaxi.h", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76910000, 0xffff8000, "xvmaxi.w", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76918000, 0xffff8000, "xvmaxi.d", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76920000, 0xffff8000, "xvmini.b", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76928000, 0xffff8000, "xvmini.h", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76930000, 0xffff8000, "xvmini.w", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76938000, 0xffff8000, "xvmini.d", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, -+{0x76940000, 0xffff8000, "xvmaxi.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76948000, 0xffff8000, "xvmaxi.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76950000, 0xffff8000, "xvmaxi.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76958000, 0xffff8000, "xvmaxi.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76960000, 0xffff8000, "xvmini.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76968000, 0xffff8000, "xvmini.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76970000, 0xffff8000, "xvmini.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76978000, 0xffff8000, "xvmini.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x769a0000, 0xffff8000, "xvfrstpi.b", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x769a8000, 0xffff8000, "xvfrstpi.h", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x769c0000, 0xfffffc00, "xvclo.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c0400, 0xfffffc00, "xvclo.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c0800, 0xfffffc00, "xvclo.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c0c00, 0xfffffc00, "xvclo.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c1000, 0xfffffc00, "xvclz.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c1400, 0xfffffc00, "xvclz.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c1800, 0xfffffc00, "xvclz.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c1c00, 0xfffffc00, "xvclz.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c2000, 0xfffffc00, "xvpcnt.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c2400, 0xfffffc00, "xvpcnt.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c2800, 0xfffffc00, "xvpcnt.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c2c00, 0xfffffc00, "xvpcnt.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c3000, 0xfffffc00, "xvneg.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c3400, 0xfffffc00, "xvneg.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c3800, 0xfffffc00, "xvneg.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c3c00, 0xfffffc00, "xvneg.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c4000, 0xfffffc00, "xvmskltz.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c4400, 0xfffffc00, "xvmskltz.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c4800, 0xfffffc00, "xvmskltz.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c4c00, 0xfffffc00, "xvmskltz.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c5000, 0xfffffc00, "xvmskgez.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c6000, 0xfffffc00, "xvmsknz.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769c9800, 0xfffffc18, "xvseteqz.v", "c0:3,x5:5", 0, 0, 0, 0}, -+{0x769c9c00, 0xfffffc18, "xvsetnez.v", "c0:3,x5:5", 0, 0, 0, 0}, -+{0x769ca000, 0xfffffc18, "xvsetanyeqz.b", "c0:3,x5:5", 0, 0, 0, 0}, -+{0x769ca400, 0xfffffc18, "xvsetanyeqz.h", "c0:3,x5:5", 0, 0, 0, 0}, -+{0x769ca800, 0xfffffc18, "xvsetanyeqz.w", "c0:3,x5:5", 0, 0, 0, 0}, -+{0x769cac00, 0xfffffc18, "xvsetanyeqz.d", "c0:3,x5:5", 0, 0, 0, 0}, -+{0x769cb000, 0xfffffc18, "xvsetallnez.b", "c0:3,x5:5", 0, 0, 0, 0}, -+{0x769cb400, 0xfffffc18, "xvsetallnez.h", "c0:3,x5:5", 0, 0, 0, 0}, -+{0x769cb800, 0xfffffc18, "xvsetallnez.w", "c0:3,x5:5", 0, 0, 0, 0}, -+{0x769cbc00, 0xfffffc18, "xvsetallnez.d", "c0:3,x5:5", 0, 0, 0, 0}, -+{0x769cc400, 0xfffffc00, "xvflogb.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769cc800, 0xfffffc00, "xvflogb.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769cd400, 0xfffffc00, "xvfclass.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769cd800, 0xfffffc00, "xvfclass.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769ce400, 0xfffffc00, "xvfsqrt.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769ce800, 0xfffffc00, "xvfsqrt.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769cf400, 0xfffffc00, "xvfrecip.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769cf800, 0xfffffc00, "xvfrecip.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d0400, 0xfffffc00, "xvfrsqrt.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d0800, 0xfffffc00, "xvfrsqrt.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d3400, 0xfffffc00, "xvfrint.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d3800, 0xfffffc00, "xvfrint.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d4400, 0xfffffc00, "xvfrintrm.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d4800, 0xfffffc00, "xvfrintrm.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d5400, 0xfffffc00, "xvfrintrp.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d5800, 0xfffffc00, "xvfrintrp.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d6400, 0xfffffc00, "xvfrintrz.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d6800, 0xfffffc00, "xvfrintrz.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d7400, 0xfffffc00, "xvfrintrne.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769d7800, 0xfffffc00, "xvfrintrne.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769de800, 0xfffffc00, "xvfcvtl.s.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769dec00, 0xfffffc00, "xvfcvth.s.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769df000, 0xfffffc00, "xvfcvtl.d.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769df400, 0xfffffc00, "xvfcvth.d.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e0000, 0xfffffc00, "xvffint.s.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e0400, 0xfffffc00, "xvffint.s.wu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e0800, 0xfffffc00, "xvffint.d.l", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e0c00, 0xfffffc00, "xvffint.d.lu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e1000, 0xfffffc00, "xvffintl.d.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e1400, 0xfffffc00, "xvffinth.d.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e3000, 0xfffffc00, "xvftint.w.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e3400, 0xfffffc00, "xvftint.l.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e3800, 0xfffffc00, "xvftintrm.w.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e3c00, 0xfffffc00, "xvftintrm.l.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e4000, 0xfffffc00, "xvftintrp.w.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e4400, 0xfffffc00, "xvftintrp.l.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e4800, 0xfffffc00, "xvftintrz.w.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e4c00, 0xfffffc00, "xvftintrz.l.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e5000, 0xfffffc00, "xvftintrne.w.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e5400, 0xfffffc00, "xvftintrne.l.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e5800, 0xfffffc00, "xvftint.wu.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e5c00, 0xfffffc00, "xvftint.lu.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e7000, 0xfffffc00, "xvftintrz.wu.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e7400, 0xfffffc00, "xvftintrz.lu.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e8000, 0xfffffc00, "xvftintl.l.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e8400, 0xfffffc00, "xvftinth.l.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e8800, 0xfffffc00, "xvftintrml.l.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e8c00, 0xfffffc00, "xvftintrmh.l.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e9000, 0xfffffc00, "xvftintrpl.l.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e9400, 0xfffffc00, "xvftintrph.l.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e9800, 0xfffffc00, "xvftintrzl.l.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769e9c00, 0xfffffc00, "xvftintrzh.l.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769ea000, 0xfffffc00, "xvftintrnel.l.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769ea400, 0xfffffc00, "xvftintrneh.l.s", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769ee000, 0xfffffc00, "xvexth.h.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769ee400, 0xfffffc00, "xvexth.w.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769ee800, 0xfffffc00, "xvexth.d.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769eec00, 0xfffffc00, "xvexth.q.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769ef000, 0xfffffc00, "xvexth.hu.bu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769ef400, 0xfffffc00, "xvexth.wu.hu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769ef800, 0xfffffc00, "xvexth.du.wu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769efc00, 0xfffffc00, "xvexth.qu.du", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f0000, 0xfffffc00, "xvreplgr2vr.b", "x0:5,r5:5", 0, 0, 0, 0}, -+{0x769f0400, 0xfffffc00, "xvreplgr2vr.h", "x0:5,r5:5", 0, 0, 0, 0}, -+{0x769f0800, 0xfffffc00, "xvreplgr2vr.w", "x0:5,r5:5", 0, 0, 0, 0}, -+{0x769f0c00, 0xfffffc00, "xvreplgr2vr.d", "x0:5,r5:5", 0, 0, 0, 0}, -+{0x769f1000, 0xfffffc00, "vext2xv.h.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f1400, 0xfffffc00, "vext2xv.w.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f1800, 0xfffffc00, "vext2xv.d.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f1c00, 0xfffffc00, "vext2xv.w.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f2000, 0xfffffc00, "vext2xv.d.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f2400, 0xfffffc00, "vext2xv.d.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f2800, 0xfffffc00, "vext2xv.hu.bu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f2c00, 0xfffffc00, "vext2xv.wu.bu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f3000, 0xfffffc00, "vext2xv.du.bu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f3400, 0xfffffc00, "vext2xv.wu.hu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f3800, 0xfffffc00, "vext2xv.du.hu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f3c00, 0xfffffc00, "vext2xv.du.wu", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x769f8000, 0xffff8000, "xvhseli.d", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76a02000, 0xffffe000, "xvrotri.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x76a04000, 0xffffc000, "xvrotri.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x76a08000, 0xffff8000, "xvrotri.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76a10000, 0xffff0000, "xvrotri.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x76a42000, 0xffffe000, "xvsrlri.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x76a44000, 0xffffc000, "xvsrlri.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x76a48000, 0xffff8000, "xvsrlri.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76a50000, 0xffff0000, "xvsrlri.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x76a82000, 0xffffe000, "xvsrari.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x76a84000, 0xffffc000, "xvsrari.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x76a88000, 0xffff8000, "xvsrari.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x76a90000, 0xffff0000, "xvsrari.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x76ebc000, 0xffffe000, "xvinsgr2vr.w", "x0:5,r5:5,u10:3", 0, 0, 0, 0}, -+{0x76ebe000, 0xfffff000, "xvinsgr2vr.d", "x0:5,r5:5,u10:2", 0, 0, 0, 0}, -+{0x76efc000, 0xffffe000, "xvpickve2gr.w", "r0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x76efe000, 0xfffff000, "xvpickve2gr.d", "r0:5,x5:5,u10:2", 0, 0, 0, 0}, -+{0x76f3c000, 0xffffe000, "xvpickve2gr.wu", "r0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x76f3e000, 0xfffff000, "xvpickve2gr.du", "r0:5,x5:5,u10:2", 0, 0, 0, 0}, -+{0x76f78000, 0xffffc000, "xvrepl128vei.b", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x76f7c000, 0xffffe000, "xvrepl128vei.h", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x76f7e000, 0xfffff000, "xvrepl128vei.w", "x0:5,x5:5,u10:2", 0, 0, 0, 0}, -+{0x76f7f000, 0xfffff800, "xvrepl128vei.d", "x0:5,x5:5,u10:1", 0, 0, 0, 0}, -+{0x76ffc000, 0xffffe000, "xvinsve0.w", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x76ffe000, 0xfffff000, "xvinsve0.d", "x0:5,x5:5,u10:2", 0, 0, 0, 0}, -+{0x7703c000, 0xffffe000, "xvpickve.w", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x7703e000, 0xfffff000, "xvpickve.d", "x0:5,x5:5,u10:2", 0, 0, 0, 0}, -+{0x77070000, 0xfffffc00, "xvreplve0.b", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x77078000, 0xfffffc00, "xvreplve0.h", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x7707c000, 0xfffffc00, "xvreplve0.w", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x7707e000, 0xfffffc00, "xvreplve0.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x7707f000, 0xfffffc00, "xvreplve0.q", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x77082000, 0xffffe000, "xvsllwil.h.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x77084000, 0xffffc000, "xvsllwil.w.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77088000, 0xffff8000, "xvsllwil.d.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77090000, 0xfffffc00, "xvextl.q.d", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x770c2000, 0xffffe000, "xvsllwil.hu.bu", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x770c4000, 0xffffc000, "xvsllwil.wu.hu", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x770c8000, 0xffff8000, "xvsllwil.du.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x770d0000, 0xfffffc00, "xvextl.qu.du", "x0:5,x5:5", 0, 0, 0, 0}, -+{0x77102000, 0xffffe000, "xvbitclri.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x77104000, 0xffffc000, "xvbitclri.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77108000, 0xffff8000, "xvbitclri.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77110000, 0xffff0000, "xvbitclri.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77142000, 0xffffe000, "xvbitseti.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x77144000, 0xffffc000, "xvbitseti.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77148000, 0xffff8000, "xvbitseti.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77150000, 0xffff0000, "xvbitseti.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77182000, 0xffffe000, "xvbitrevi.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x77184000, 0xffffc000, "xvbitrevi.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77188000, 0xffff8000, "xvbitrevi.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77190000, 0xffff0000, "xvbitrevi.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77242000, 0xffffe000, "xvsat.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x77244000, 0xffffc000, "xvsat.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77248000, 0xffff8000, "xvsat.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77250000, 0xffff0000, "xvsat.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77282000, 0xffffe000, "xvsat.bu", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x77284000, 0xffffc000, "xvsat.hu", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77288000, 0xffff8000, "xvsat.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77290000, 0xffff0000, "xvsat.du", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x772c2000, 0xffffe000, "xvslli.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x772c4000, 0xffffc000, "xvslli.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x772c8000, 0xffff8000, "xvslli.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x772d0000, 0xffff0000, "xvslli.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77302000, 0xffffe000, "xvsrli.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x77304000, 0xffffc000, "xvsrli.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77308000, 0xffff8000, "xvsrli.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77310000, 0xffff0000, "xvsrli.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77342000, 0xffffe000, "xvsrai.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, -+{0x77344000, 0xffffc000, "xvsrai.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77348000, 0xffff8000, "xvsrai.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77350000, 0xffff0000, "xvsrai.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77404000, 0xffffc000, "xvsrlni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77408000, 0xffff8000, "xvsrlni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77410000, 0xffff0000, "xvsrlni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77420000, 0xfffe0000, "xvsrlni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x77444000, 0xffffc000, "xvsrlrni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77448000, 0xffff8000, "xvsrlrni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77450000, 0xffff0000, "xvsrlrni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77460000, 0xfffe0000, "xvsrlrni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x77484000, 0xffffc000, "xvssrlni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77488000, 0xffff8000, "xvssrlni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77490000, 0xffff0000, "xvssrlni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x774a0000, 0xfffe0000, "xvssrlni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x774c4000, 0xffffc000, "xvssrlni.bu.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x774c8000, 0xffff8000, "xvssrlni.hu.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x774d0000, 0xffff0000, "xvssrlni.wu.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x774e0000, 0xfffe0000, "xvssrlni.du.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x77504000, 0xffffc000, "xvssrlrni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77508000, 0xffff8000, "xvssrlrni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77510000, 0xffff0000, "xvssrlrni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77520000, 0xfffe0000, "xvssrlrni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x77544000, 0xffffc000, "xvssrlrni.bu.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77548000, 0xffff8000, "xvssrlrni.hu.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77550000, 0xffff0000, "xvssrlrni.wu.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77560000, 0xfffe0000, "xvssrlrni.du.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x77584000, 0xffffc000, "xvsrani.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77588000, 0xffff8000, "xvsrani.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77590000, 0xffff0000, "xvsrani.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x775a0000, 0xfffe0000, "xvsrani.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x775c4000, 0xffffc000, "xvsrarni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x775c8000, 0xffff8000, "xvsrarni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x775d0000, 0xffff0000, "xvsrarni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x775e0000, 0xfffe0000, "xvsrarni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x77604000, 0xffffc000, "xvssrani.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77608000, 0xffff8000, "xvssrani.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77610000, 0xffff0000, "xvssrani.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77620000, 0xfffe0000, "xvssrani.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x77644000, 0xffffc000, "xvssrani.bu.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77648000, 0xffff8000, "xvssrani.hu.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77650000, 0xffff0000, "xvssrani.wu.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x77660000, 0xfffe0000, "xvssrani.du.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x77684000, 0xffffc000, "xvssrarni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x77688000, 0xffff8000, "xvssrarni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x77690000, 0xffff0000, "xvssrarni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x776a0000, 0xfffe0000, "xvssrarni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x776c4000, 0xffffc000, "xvssrarni.bu.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, -+{0x776c8000, 0xffff8000, "xvssrarni.hu.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, -+{0x776d0000, 0xffff0000, "xvssrarni.wu.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, -+{0x776e0000, 0xfffe0000, "xvssrarni.du.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, -+{0x77800000, 0xfffc0000, "xvextrins.d", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77840000, 0xfffc0000, "xvextrins.w", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77880000, 0xfffc0000, "xvextrins.h", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x778c0000, 0xfffc0000, "xvextrins.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77900000, 0xfffc0000, "xvshuf4i.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77940000, 0xfffc0000, "xvshuf4i.h", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77980000, 0xfffc0000, "xvshuf4i.w", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x779c0000, 0xfffc0000, "xvshuf4i.d", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77c40000, 0xfffc0000, "xvbitseli.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77d00000, 0xfffc0000, "xvandi.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77d40000, 0xfffc0000, "xvori.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77d80000, 0xfffc0000, "xvxori.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77dc0000, 0xfffc0000, "xvnori.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0, 0, "xvrepli.b", "x,s0:10", "xvldi %1,(%2)&0x3ff", 0, 0, 0}, -+{0, 0, "xvrepli.d", "x,s0:10", "xvldi %1,((%2)&0x3ff)|0xc00", 0, 0, 0}, -+{0, 0, "xvrepli.h", "x,s0:10", "xvldi %1,((%2)&0x3ff)|0x400", 0, 0, 0}, -+{0, 0, "xvrepli.w", "x,s0:10", "xvldi %1,((%2)&0x3ff)|0x800", 0, 0, 0}, -+{0x77e00000, 0xfffc0000, "xvldi", "x0:5,s5:13", 0, 0, 0, 0}, -+{0x77e40000, 0xfffc0000, "xvpermi.w", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77e80000, 0xfffc0000, "xvpermi.d", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0x77ec0000, 0xfffc0000, "xvpermi.q", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, -+{0} /* Terminate the list. */ -+ -+}; -+ -+struct loongarch_ase loongarch_ASEs[] = { -+ {&LARCH_opts.ase_fix, loongarch_macro_opcodes, 0, 0, {0}, 0, 0}, -+ { &LARCH_opts.ase_fix, loongarch_lmm_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_fix, loongarch_privilege_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_fix, loongarch_load_store_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_fix, loongarch_fix_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_fix, loongarch_jmp_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_float, loongarch_float_jmp_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_float, loongarch_single_float_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_float, loongarch_double_float_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_float, loongarch_4opt_single_float_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_float, loongarch_4opt_double_float_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_float, loongarch_single_float_load_store_opcodes, 0, 0, { 0 }, 0, 0 }, -+ { &LARCH_opts.ase_float, loongarch_double_float_load_store_opcodes, 0, 0, { 0 }, 0, 0 }, -+ {&LARCH_opts.ase_128vec, loongarch_128vec_opcodes, 0, 0, {0}, 0, 0}, -+ {&LARCH_opts.ase_256vec, loongarch_256vec_opcodes, 0, 0, {0}, 0, 0}, -+ {0}, -+}; -+ --- -2.20.1 - diff --git a/binutils-s390-z16.patch b/binutils-s390-z16.patch new file mode 100644 index 0000000..bada8ad --- /dev/null +++ b/binutils-s390-z16.patch @@ -0,0 +1,53 @@ +diff -rup binutils.orig/gas/config/tc-s390.c binutils-2.30/gas/config/tc-s390.c +--- binutils.orig/gas/config/tc-s390.c 2022-04-11 09:54:43.234516094 +0100 ++++ binutils-2.30/gas/config/tc-s390.c 2022-04-11 09:55:31.670168952 +0100 +@@ -292,9 +292,9 @@ s390_parse_cpu (const char * arg + S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX }, + { STRING_COMMA_LEN ("z14"), STRING_COMMA_LEN ("arch12"), + S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX }, +- { STRING_COMMA_LEN (""), STRING_COMMA_LEN ("arch13"), ++ { STRING_COMMA_LEN ("z15"), STRING_COMMA_LEN ("arch13"), + S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX }, +- { STRING_COMMA_LEN (""), STRING_COMMA_LEN ("arch14"), ++ { STRING_COMMA_LEN ("z16"), STRING_COMMA_LEN ("arch14"), + S390_INSTR_FLAG_HTM | S390_INSTR_FLAG_VX } + }; + static struct +diff -rup binutils.orig/gas/doc/c-s390.texi binutils-2.30/gas/doc/c-s390.texi +--- binutils.orig/gas/doc/c-s390.texi 2022-04-11 09:54:43.236516079 +0100 ++++ binutils-2.30/gas/doc/c-s390.texi 2022-04-11 09:56:40.709674135 +0100 +@@ -18,7 +18,7 @@ and eleven chip levels. The architecture + Architecture (ESA) and the newer z/Architecture mode. The chip levels + are g5 (or arch3), g6, z900 (or arch5), z990 (or arch6), z9-109, z9-ec + (or arch7), z10 (or arch8), z196 (or arch9), zEC12 (or arch10), z13 +-(or arch11), z14 (or arch12), z15 (or arch13), or arch14. ++(or arch11), z14 (or arch12), z15 (or arch13), or z16 (or arch14). + + @menu + * s390 Options:: Command-line Options. +@@ -72,7 +72,7 @@ are recognized: + @code{z13} (or @code{arch11}), + @code{z14} (or @code{arch12}), + @code{z15} (or @code{arch13}), and +-@code{arch14}. ++@code{z16} (or @code{arch14}). + + Assembling an instruction that is not supported on the target + processor results in an error message. +diff -rup binutils.orig/opcodes/s390-mkopc.c binutils-2.30/opcodes/s390-mkopc.c +--- binutils.orig/opcodes/s390-mkopc.c 2022-04-11 09:54:43.491514252 +0100 ++++ binutils-2.30/opcodes/s390-mkopc.c 2022-04-11 09:58:24.228932192 +0100 +@@ -377,9 +377,11 @@ main (void) + else if (strcmp (cpu_string, "z14") == 0 + || strcmp (cpu_string, "arch12") == 0) + min_cpu = S390_OPCODE_ARCH12; +- else if (strcmp (cpu_string, "arch13") == 0) ++ else if ((strcmp (cpu_string, "z15") == 0 ++ || strcmp (cpu_string, "arch13") == 0)) + min_cpu = S390_OPCODE_ARCH13; +- else if (strcmp (cpu_string, "arch14") == 0) ++ else if ((strcmp (cpu_string, "z16") == 0 ++ || strcmp (cpu_string, "arch14") == 0)) + min_cpu = S390_OPCODE_ARCH14; + else { + fprintf (stderr, "Couldn't parse cpu string %s\n", cpu_string); diff --git a/binutils-verdef.patch b/binutils-verdef.patch new file mode 100644 index 0000000..105a138 --- /dev/null +++ b/binutils-verdef.patch @@ -0,0 +1,12 @@ +--- binutils.orig/bfd/elflink.c 2022-03-07 14:59:10.275856785 +0000 ++++ binutils-2.30/bfd/elflink.c 2022-03-07 15:00:19.129562705 +0000 +@@ -4578,7 +4578,8 @@ error_free_dyn: + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + +- if (elf_tdata (abfd)->verdef != NULL ++ if (h->versioned != unversioned ++ && elf_tdata (abfd)->verdef != NULL + && vernum > 1 + && definition) + h->verinfo.verdef = &elf_tdata (abfd)->verdef[vernum - 1]; diff --git a/binutils.spec b/binutils.spec index 6010e0f..89119a1 100644 --- a/binutils.spec +++ b/binutils.spec @@ -24,7 +24,6 @@ # /usr/bin/aarch64-linux-gnu-ar # /usr/bin/aarch64-linux-gnu-as # [etc] -%define anolis_release .0.3 %if 0%{!?binutils_target:1} @@ -44,7 +43,7 @@ Summary: A GNU collection of binary utilities Name: binutils%{?name_cross}%{?_with_debug:-debug} Version: 2.30 -Release: 113%{anolis_release}%{?dist} +Release: 117%{?dist} License: GPLv3+ URL: https://sourceware.org/binutils @@ -612,13 +611,22 @@ Patch96: binutils-undefined-unversioned-symbols.patch # Lifetime: Fixed in 2.35 Patch97: binutils-plugin-error.patch -#Add by Anolis -Patch1000: 0001-binutils-anolis-rebrand.patch +# Purpose: Don't set version info on unversioned symbols. +# Lifetime: Fixed in 2.37 +Patch98: binutils-verdef.patch + +# Purpose: Allow the AArch64 RNG extension to be used, and do not require v8.5 support. +# Lifetime: Fixed in 2.39 +Patch99: binutils-aarch64-rng.patch + +# Purpose: Allow z16 to be used as an alias for the arch14 extenstions to the s390 architecture. +# Lifetime: Fixed in 2.39 +Patch100: binutils-s390-z16.patch + +# Purpose: Fix a potential buffer overrun in the BFD library. +# Lifetime: Fixed in 2.35 +Patch101: binutils-coffgen-buffer-overrun.patch -Patch1001: binutils-loongarch-support.patch -Patch1002: 0001-LoongArch-Fix-wrong-line-number-in-.debug_line.patch -Patch1003: binutils-LoongArch-Add-missing-opcode.patch -#end #---------------------------------------------------------------------------- Provides: bundled(libiberty) @@ -652,13 +660,10 @@ Buildroot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) # Perl, sed and touch are all used in the %%prep section of this spec file. BuildRequires: gcc, perl, sed, coreutils -# Loongarch needs yyac -BuildRequires: bison - # Gold needs bison in order to build gold/yyscript.c. # Bison needs m4. %if "%{build_gold}" == "both" -BuildRequires: m4, gcc-c++ +BuildRequires: bison, m4, gcc-c++ %endif %if %{without bootstrap} @@ -856,10 +861,10 @@ using libelf instead of BFD. %patch95 -p1 %patch96 -p1 %patch97 -p1 -%patch1000 -p1 -%patch1001 -p1 -%patch1002 -p1 -%patch1003 -p1 +%patch98 -p1 +%patch99 -p1 +%patch100 -p1 +%patch101 -p1 # We cannot run autotools as there is an exact requirement of autoconf-2.59. # FIXME - this is no longer true. Maybe try reinstating autotool use ? @@ -915,7 +920,7 @@ export CFLAGS="$RPM_OPT_FLAGS" CARGS= -case %{binutils_target} in i?86*|sparc*|ppc*|s390*|sh*|arm*|aarch64*|loongarch64) +case %{binutils_target} in i?86*|sparc*|ppc*|s390*|sh*|arm*|aarch64*) CARGS="$CARGS --enable-64-bit-bfd" ;; esac @@ -1020,7 +1025,7 @@ export LDFLAGS=$RPM_LD_FLAGS %endif $CARGS \ --enable-plugins \ - --with-bugurl=https://bugzilla.openanolis.cn + --with-bugurl=http://bugzilla.redhat.com/bugzilla/ %if %{with docs} %make_build %{_smp_mflags} tooldir=%{_prefix} all @@ -1309,15 +1314,17 @@ exit 0 #---------------------------------------------------------------------------- %changelog -* Thu Dec 1 2022 Xing Li - 2.30-113.0.3 -- Fixup LoongArch wrong debug line. -- Add LoongArch missing opcode. +* Mon Apr 25 2022 Nick Clifton - 2.30-117 +- Fix a potential buffer overrun in the BFD library's PE handling code. (#2076973) + +* Mon Apr 11 2022 Nick Clifton - 2.30-116 +- Allow z16 to be used as an alias for the s390 architecture's arch14 extensions. (#2073384) -* Wed Jun 22 2022 Xing Li - 2.30-113.0.2 -- Add loongarch support. +* Tue Apr 05 2022 Nick Clifton - 2.30-115 +- Add support for the AArch64 architecture's RNG extension. (#2056691) -* Wed Apr 13 2022 Xue haolin - 2.30-113.0.1 -- Rebrand to Anolis OS. +* Mon Mar 07 2022 Nick Clifton - 2.30-114 +- Do not set version info on unversion symbols. (#2055179) * Wed Jan 19 2022 Nick Clifton - 2.30-113 - When searching for plugins, do not complain if incompatible ones are found. (#2039117) diff --git a/dist b/dist new file mode 100644 index 0000000..9c0e36e --- /dev/null +++ b/dist @@ -0,0 +1 @@ +an8 -- Gitee From f05e85e98155bfb33ad7592167004d68ccfcde46 Mon Sep 17 00:00:00 2001 From: yangxiaoxuan Date: Mon, 25 Jan 2021 09:30:12 +0800 Subject: [PATCH 2/5] rebrand: Rebrand to Anolis OS Signed-off-by: yangxiaoxuan --- 0001-binutils-anolis-rebrand.patch | 241 +++++++++++++++++++++++++++++ binutils.spec | 12 +- 2 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 0001-binutils-anolis-rebrand.patch diff --git a/0001-binutils-anolis-rebrand.patch b/0001-binutils-anolis-rebrand.patch new file mode 100644 index 0000000..0b71807 --- /dev/null +++ b/0001-binutils-anolis-rebrand.patch @@ -0,0 +1,241 @@ +From e784eaaa48e00d5ba8da5c74a57459c662c078f6 Mon Sep 17 00:00:00 2001 +From: xuehaolin +Date: Sun, 24 Jan 2021 10:55:25 +0800 +Subject: [PATCH] rebrand + +--- + bfd/elf32-rx.c | 2 +- + bfd/po/da.po | 4 ++-- + bfd/po/es.po | 4 ++-- + bfd/po/fi.po | 4 ++-- + bfd/po/fr.po | 4 ++-- + bfd/po/hr.po | 2 +- + bfd/po/id.po | 4 ++-- + bfd/po/ja.po | 4 ++-- + bfd/po/ru.po | 4 ++-- + bfd/po/sr.po | 2 +- + bfd/po/sv.po | 4 ++-- + bfd/po/uk.po | 4 ++-- + bfd/po/vi.po | 4 ++-- + bfd/po/zh_CN.po | 2 +- + zlib/contrib/minizip/configure.ac | 2 +- + 15 files changed, 25 insertions(+), 25 deletions(-) + +diff --git a/bfd/elf32-rx.c b/bfd/elf32-rx.c +index a0e1f782..559a9d2a 100644 +--- a/bfd/elf32-rx.c ++++ b/bfd/elf32-rx.c +@@ -665,7 +665,7 @@ rx_elf_relocate_section + #define OP(i) (contents[rel->r_offset + (i)]) + #define WARN_REDHAT(type) \ + /* xgettext:c-format */ \ +- _bfd_error_handler (_("%B:%A: Warning: deprecated Red Hat reloc " type " detected against: %s."), \ ++ _bfd_error_handler (_("%B:%A: Warning: deprecated Anolis reloc " type " detected against: %s."), \ + input_bfd, input_section, name) + + /* Check for unsafe relocs in PID mode. These are any relocs where +diff --git a/bfd/po/da.po b/bfd/po/da.po +index add4ce42..2ce40ff2 100644 +--- a/bfd/po/da.po ++++ b/bfd/po/da.po +@@ -2345,8 +2345,8 @@ msgid " [G10]" + msgstr " [G10]" + + #: elf32-rx.c:563 +-msgid "%B:%A: Warning: deprecated Red Hat reloc " +-msgstr "%B:%A: Advarsel: forældet Red Hat-relokering " ++msgid "%B:%A: Warning: deprecated Anolis reloc " ++msgstr "%B:%A: Advarsel: forældet Anolis-relokering " + + #. Check for unsafe relocs in PID mode. These are any relocs where + #. an absolute address is being computed. There are special cases +diff --git a/bfd/po/es.po b/bfd/po/es.po +index 73e12b5b..742b11f6 100644 +--- a/bfd/po/es.po ++++ b/bfd/po/es.po +@@ -2023,8 +2023,8 @@ msgid "%P: %s not defined in linker created %s\n" + msgstr "%P: no se definió %s en el %s creado por el enlazador\n" + + #: elf32-rx.c:563 +-msgid "%B:%A: Warning: deprecated Red Hat reloc " +-msgstr "%B:%A: Aviso: reubicación Red Hat obsoleta" ++msgid "%B:%A: Warning: deprecated Anolis reloc " ++msgstr "%B:%A: Aviso: reubicación Anolis obsoleta" + + #. Check for unsafe relocs in PID mode. These are any relocs where + #. an absolute address is being computed. There are special cases +diff --git a/bfd/po/fi.po b/bfd/po/fi.po +index 14752f46..9165fd4a 100644 +--- a/bfd/po/fi.po ++++ b/bfd/po/fi.po +@@ -2330,8 +2330,8 @@ msgid " [G10]" + msgstr " [G10]" + + #: elf32-rx.c:563 +-msgid "%B:%A: Warning: deprecated Red Hat reloc " +-msgstr "%B:%A: Varoitus: vanhentunut Red Hat reloc -tietue " ++msgid "%B:%A: Warning: deprecated Anolis reloc " ++msgstr "%B:%A: Varoitus: vanhentunut Anolis reloc -tietue " + + #. Check for unsafe relocs in PID mode. These are any relocs where + #. an absolute address is being computed. There are special cases +diff --git a/bfd/po/fr.po b/bfd/po/fr.po +index dc26e566..b339dba8 100644 +--- a/bfd/po/fr.po ++++ b/bfd/po/fr.po +@@ -3303,8 +3303,8 @@ msgstr "%B:%A: l'entrée %s de la table n'est pas alignée sur un mot dans la ta + + #: elf32-rx.c:668 + #, c-format +-msgid "%B:%A: Warning: deprecated Red Hat reloc " +-msgstr "%B:%A: Attention: réadressage Red Hat réprouvée " ++msgid "%B:%A: Warning: deprecated Anolis reloc " ++msgstr "%B:%A: Attention: réadressage Anolis réprouvée " + + #. Check for unsafe relocs in PID mode. These are any relocs where + #. an absolute address is being computed. There are special cases +diff --git a/bfd/po/hr.po b/bfd/po/hr.po +index 66723aec..d57da036 100644 +--- a/bfd/po/hr.po ++++ b/bfd/po/hr.po +@@ -1981,7 +1981,7 @@ msgid "%P: %s not defined in linker created %s\n" + msgstr "" + + #: elf32-rx.c:563 +-msgid "%B:%A: Warning: deprecated Red Hat reloc " ++msgid "%B:%A: Warning: deprecated Anolis reloc " + msgstr "" + + #. Check for unsafe relocs in PID mode. These are any relocs where +diff --git a/bfd/po/id.po b/bfd/po/id.po +index b0acde81..147026a0 100644 +--- a/bfd/po/id.po ++++ b/bfd/po/id.po +@@ -2022,8 +2022,8 @@ msgid "%P: %s not defined in linker created %s\n" + msgstr "%P: %s tidak didefinisikan dalam penyambung dibuat oleh %s\n" + + #: elf32-rx.c:563 +-msgid "%B:%A: Warning: deprecated Red Hat reloc " +-msgstr "%B:%A: Peringatan: tertinggal Red Hat relokasi" ++msgid "%B:%A: Warning: deprecated Anolis reloc " ++msgstr "%B:%A: Peringatan: tertinggal Anolis relokasi" + + #. Check for unsafe relocs in PID mode. These are any relocs where + #. an absolute address is being computed. There are special cases +diff --git a/bfd/po/ja.po b/bfd/po/ja.po +index da371dcc..9a8e4b8e 100644 +--- a/bfd/po/ja.po ++++ b/bfd/po/ja.po +@@ -2019,8 +2019,8 @@ msgid "%s not defined in linker created %s\n" + msgstr "%s はリンカが作成した %s 内では定義されていません\n" + + #: elf32-rx.c:553 +-msgid "%B:%A: Warning: deprecated Red Hat reloc " +-msgstr "%B:%A: 警告: 廃止された Red Hat 再配置です " ++msgid "%B:%A: Warning: deprecated Anolis reloc " ++msgstr "%B:%A: 警告: 廃止された Anolis 再配置です " + + #: elf32-rx.c:1095 + msgid "Warning: RX_SYM reloc with an unknown symbol" +diff --git a/bfd/po/ru.po b/bfd/po/ru.po +index 194011d4..f54e6730 100644 +--- a/bfd/po/ru.po ++++ b/bfd/po/ru.po +@@ -3298,8 +3298,8 @@ msgstr "%B:%A: элемент таблицы %s не выровнен в таб + + #: elf32-rx.c:668 + #, c-format +-msgid "%B:%A: Warning: deprecated Red Hat reloc " +-msgstr "%B:%A: предупреждение: устаревшее перемещение Red Hat " ++msgid "%B:%A: Warning: deprecated Anolis reloc " ++msgstr "%B:%A: предупреждение: устаревшее перемещение Anolis " + + #. Check for unsafe relocs in PID mode. These are any relocs where + #. an absolute address is being computed. There are special cases +diff --git a/bfd/po/sr.po b/bfd/po/sr.po +index c0e8a24f..72b11ee9 100644 +--- a/bfd/po/sr.po ++++ b/bfd/po/sr.po +@@ -2302,7 +2302,7 @@ msgid " [G10]" + msgstr " [Г10]" + + #: elf32-rx.c:563 +-msgid "%B:%A: Warning: deprecated Red Hat reloc " ++msgid "%B:%A: Warning: deprecated Anolis reloc " + msgstr "%B:%A: Упозорење: застарело премештање Ред Хета " + + #. Check for unsafe relocs in PID mode. These are any relocs where +diff --git a/bfd/po/sv.po b/bfd/po/sv.po +index 7213fe22..638915c3 100644 +--- a/bfd/po/sv.po ++++ b/bfd/po/sv.po +@@ -2306,8 +2306,8 @@ msgid " [G10]" + msgstr " [G10]" + + #: elf32-rx.c:563 +-msgid "%B:%A: Warning: deprecated Red Hat reloc " +-msgstr "%B:%A: Varning: föråldrad Red Hat-omlokalisering " ++msgid "%B:%A: Warning: deprecated Anolis reloc " ++msgstr "%B:%A: Varning: föråldrad Anolis-omlokalisering " + + #. Check for unsafe relocs in PID mode. These are any relocs where + #. an absolute address is being computed. There are special cases +diff --git a/bfd/po/uk.po b/bfd/po/uk.po +index 437d767a..dc4596a7 100644 +--- a/bfd/po/uk.po ++++ b/bfd/po/uk.po +@@ -3300,8 +3300,8 @@ msgstr "%B:%A: запис таблиці %s не вирівняно на меж + + #: elf32-rx.c:668 + #, c-format +-msgid "%B:%A: Warning: deprecated Red Hat reloc " +-msgstr "%B:%A: попередження: застарілий формат пересування Red Hat " ++msgid "%B:%A: Warning: deprecated Anolis reloc " ++msgstr "%B:%A: попередження: застарілий формат пересування Anolis " + + #. Check for unsafe relocs in PID mode. These are any relocs where + #. an absolute address is being computed. There are special cases +diff --git a/bfd/po/vi.po b/bfd/po/vi.po +index 79a6622f..93ef7bd4 100644 +--- a/bfd/po/vi.po ++++ b/bfd/po/vi.po +@@ -2027,8 +2027,8 @@ msgid "%P: %s not defined in linker created %s\n" + msgstr "%P: %s chưa được định nghĩa trong bộ liên kết đã tạo ra %s\n" + + #: elf32-rx.c:563 +-msgid "%B:%A: Warning: deprecated Red Hat reloc " +-msgstr "%B:%A: Cảnh báo: không tán thành reloc kiểu Red Hat" ++msgid "%B:%A: Warning: deprecated Anolis reloc " ++msgstr "%B:%A: Cảnh báo: không tán thành reloc kiểu Anolis" + + #. Check for unsafe relocs in PID mode. These are any relocs where + #. an absolute address is being computed. There are special cases +diff --git a/bfd/po/zh_CN.po b/bfd/po/zh_CN.po +index 882b3cc2..e702d7f1 100644 +--- a/bfd/po/zh_CN.po ++++ b/bfd/po/zh_CN.po +@@ -2406,7 +2406,7 @@ msgstr "" + + #: elf32-rx.c:563 + #, fuzzy +-msgid "%B:%A: Warning: deprecated Red Hat reloc " ++msgid "%B:%A: Warning: deprecated Anolis reloc " + msgstr "%s:0x%lx:警告:无法找到预期的重定位" + + #. Check for unsafe relocs in PID mode. These are any relocs where +diff --git a/zlib/contrib/minizip/configure.ac b/zlib/contrib/minizip/configure.ac +index 5b119709..3d43339d 100644 +--- a/zlib/contrib/minizip/configure.ac ++++ b/zlib/contrib/minizip/configure.ac +@@ -1,7 +1,7 @@ + # -*- Autoconf -*- + # Process this file with autoconf to produce a configure script. + +-AC_INIT([minizip], [1.2.11], [bugzilla.redhat.com]) ++AC_INIT([minizip], [1.2.11], [https://bugzilla.openanolis.cn]) + AC_CONFIG_SRCDIR([minizip.c]) + AM_INIT_AUTOMAKE([foreign]) + LT_INIT +-- +2.18.4 + diff --git a/binutils.spec b/binutils.spec index 89119a1..19453c9 100644 --- a/binutils.spec +++ b/binutils.spec @@ -24,6 +24,7 @@ # /usr/bin/aarch64-linux-gnu-ar # /usr/bin/aarch64-linux-gnu-as # [etc] +%define anolis_release .0.1 %if 0%{!?binutils_target:1} @@ -43,7 +44,7 @@ Summary: A GNU collection of binary utilities Name: binutils%{?name_cross}%{?_with_debug:-debug} Version: 2.30 -Release: 117%{?dist} +Release: 117%{anolis_release}%{?dist} License: GPLv3+ URL: https://sourceware.org/binutils @@ -627,6 +628,9 @@ Patch100: binutils-s390-z16.patch # Lifetime: Fixed in 2.35 Patch101: binutils-coffgen-buffer-overrun.patch +#Add by Anolis +Patch1000: 0001-binutils-anolis-rebrand.patch +#end #---------------------------------------------------------------------------- Provides: bundled(libiberty) @@ -865,6 +869,7 @@ using libelf instead of BFD. %patch99 -p1 %patch100 -p1 %patch101 -p1 +%patch1000 -p1 # We cannot run autotools as there is an exact requirement of autoconf-2.59. # FIXME - this is no longer true. Maybe try reinstating autotool use ? @@ -1025,7 +1030,7 @@ export LDFLAGS=$RPM_LD_FLAGS %endif $CARGS \ --enable-plugins \ - --with-bugurl=http://bugzilla.redhat.com/bugzilla/ + --with-bugurl=https://bugzilla.openanolis.cn %if %{with docs} %make_build %{_smp_mflags} tooldir=%{_prefix} all @@ -1314,6 +1319,9 @@ exit 0 #---------------------------------------------------------------------------- %changelog +* Tue Dec 27 2022 Xue haolin - 2.30-117.0.1 +- Rebrand to Anolis OS. + * Mon Apr 25 2022 Nick Clifton - 2.30-117 - Fix a potential buffer overrun in the BFD library's PE handling code. (#2076973) -- Gitee From dcfb616897ad19688c58c9a4f89e49de024fc1bb Mon Sep 17 00:00:00 2001 From: Xing Li Date: Wed, 22 Jun 2022 17:35:39 +0800 Subject: [PATCH 3/5] Add loongarch support Signed-off-by: Xing Li Signed-off-by: JunChao Zhao --- binutils-loongarch-support.patch | 10204 +++++++++++++++++++++++++++++ binutils.spec | 6 +- 2 files changed, 10209 insertions(+), 1 deletion(-) create mode 100644 binutils-loongarch-support.patch diff --git a/binutils-loongarch-support.patch b/binutils-loongarch-support.patch new file mode 100644 index 0000000..9fdf38d --- /dev/null +++ b/binutils-loongarch-support.patch @@ -0,0 +1,10204 @@ +From 1f16c64c08b59b8901fd2477a13de69b9376ba39 Mon Sep 17 00:00:00 2001 +From: Li Xing +Date: Thu, 23 Jun 2022 11:18:20 +0800 +Subject: [PATCH] binutils loongarch support + +Signed-off-by: Li Xing +Signed-off-by: Junchao Zhao +--- + bfd/Makefile.am | 17 + + bfd/Makefile.in | 23 + + bfd/archures.c | 5 + + bfd/bfd-in2.h | 48 + + bfd/config.bfd | 15 + + bfd/configure | 2 + + bfd/configure.ac | 2 + + bfd/cpu-loongarch.c | 38 + + bfd/elf-bfd.h | 9 + + bfd/elf.c | 109 + + bfd/elfnn-loongarch.c | 3287 +++++++++++++++++++ + bfd/elfxx-loongarch.c | 172 + + bfd/elfxx-loongarch.h | 11 + + bfd/libbfd.h | 43 + + bfd/reloc.c | 89 + + bfd/targets.c | 7 + + binutils/readelf.c | 30 + + binutils/testsuite/binutils-all/objdump.exp | 4 +- + gas/Makefile.am | 26 +- + gas/Makefile.in | 55 +- + gas/config/loongarch-lex-wrapper.c | 25 + + gas/config/loongarch-lex.l | 39 + + gas/config/loongarch-parse.y | 420 +++ + gas/config/tc-loongarch.c | 1328 ++++++++ + gas/config/tc-loongarch.h | 77 + + gas/configure | 14 +- + gas/configure.ac | 9 + + gas/configure.tgt | 5 +- + include/dis-asm.h | 1 + + include/elf/common.h | 9 + + include/elf/loongarch.h | 95 + + include/opcode/loongarch.h | 215 ++ + ld/Makefile.am | 6 + + ld/Makefile.in | 18 + + ld/configure.tgt | 2 + + ld/emulparams/elf64loongarch-defs.sh | 39 + + ld/emulparams/elf64loongarch.sh | 15 + + ld/emultempl/loongarchelf.em | 90 + + opcodes/Makefile.am | 3 + + opcodes/Makefile.in | 6 + + opcodes/configure | 1 + + opcodes/configure.ac | 1 + + opcodes/disassemble.c | 9 + + opcodes/disassemble.h | 1 + + opcodes/loongarch-coder.c | 446 +++ + opcodes/loongarch-dis.c | 311 ++ + opcodes/loongarch-opc.c | 2128 ++++++++++++ + 47 files changed, 9299 insertions(+), 6 deletions(-) + create mode 100644 bfd/cpu-loongarch.c + create mode 100644 bfd/elfnn-loongarch.c + create mode 100644 bfd/elfxx-loongarch.c + create mode 100644 bfd/elfxx-loongarch.h + create mode 100644 gas/config/loongarch-lex-wrapper.c + create mode 100644 gas/config/loongarch-lex.l + create mode 100644 gas/config/loongarch-parse.y + create mode 100644 gas/config/tc-loongarch.c + create mode 100644 gas/config/tc-loongarch.h + create mode 100644 include/elf/loongarch.h + create mode 100644 include/opcode/loongarch.h + create mode 100644 ld/emulparams/elf64loongarch-defs.sh + create mode 100644 ld/emulparams/elf64loongarch.sh + create mode 100644 ld/emultempl/loongarchelf.em + create mode 100644 opcodes/loongarch-coder.c + create mode 100644 opcodes/loongarch-dis.c + create mode 100644 opcodes/loongarch-opc.c + +diff --git a/bfd/Makefile.am b/bfd/Makefile.am +index a7990571..9b08572a 100644 +--- a/bfd/Makefile.am ++++ b/bfd/Makefile.am +@@ -120,6 +120,7 @@ ALL_MACHINES = \ + cpu-ip2k.lo \ + cpu-iq2000.lo \ + cpu-lm32.lo \ ++ cpu-loongarch.lo \ + cpu-m10200.lo \ + cpu-m10300.lo \ + cpu-m32c.lo \ +@@ -211,6 +212,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 \ +@@ -690,6 +692,8 @@ BFD64_BACKENDS = \ + elf64-ia64.lo \ + elf64-ia64-vms.lo \ + elfxx-ia64.lo \ ++ elf32-loongarch.lo \ ++ elf64-loongarch.lo \ + elfn32-mips.lo \ + elf64-mips.lo \ + elfxx-mips.lo \ +@@ -812,6 +816,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 + +@@ -983,6 +988,18 @@ elf64-ia64.c : elfnn-ia64.c + $(SED) -e s/NN/64/g < $(srcdir)/elfnn-ia64.c > elf64-ia64.new + mv -f elf64-ia64.new elf64-ia64.c + ++elf32-loongarch.c : elfnn-loongarch.c ++ rm -f elf32-loongarch.c ++ echo "#line 1 \"$(srcdir)/elfnn-loongarch.c\"" > elf32-loongarch.new ++ sed -e s/NN/32/g < $(srcdir)/elfnn-loongarch.c >> elf32-loongarch.new ++ mv -f elf32-loongarch.new elf32-loongarch.c ++ ++elf64-loongarch.c : elfnn-loongarch.c ++ rm -f elf64-loongarch.c ++ echo "#line 1 \"$(srcdir)/elfnn-loongarch.c\"" > elf64-loongarch.new ++ sed -e s/NN/64/g < $(srcdir)/elfnn-loongarch.c >> elf64-loongarch.new ++ mv -f elf64-loongarch.new elf64-loongarch.c ++ + elf32-riscv.c : elfnn-riscv.c + rm -f elf32-riscv.c + echo "#line 1 \"$(srcdir)/elfnn-riscv.c\"" > elf32-riscv.new +diff --git a/bfd/Makefile.in b/bfd/Makefile.in +index 659a8d7b..d49f5b44 100644 +--- a/bfd/Makefile.in ++++ b/bfd/Makefile.in +@@ -454,6 +454,7 @@ ALL_MACHINES = \ + cpu-ip2k.lo \ + cpu-iq2000.lo \ + cpu-lm32.lo \ ++ cpu-loongarch.lo \ + cpu-m10200.lo \ + cpu-m10300.lo \ + cpu-m32c.lo \ +@@ -545,6 +546,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 \ +@@ -1017,6 +1019,9 @@ BFD64_BACKENDS = \ + coff64-rs6000.lo \ + demo64.lo \ + elf32-ia64.lo \ ++ elf32-loongarch.lo \ ++ elf64-loongarch.lo \ ++ elfxx-loongarch.lo \ + elf32-mips.lo \ + elf32-score.lo \ + elf32-score7.lo \ +@@ -1082,6 +1087,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 \ +@@ -1150,6 +1156,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 + +@@ -1414,6 +1421,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-k1om.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-l1om.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-lm32.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-loongarch.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m10200.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m10300.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-m32c.Plo@am__quote@ +@@ -1515,6 +1523,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-ip2k.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-iq2000.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-lm32.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-loongarch.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m32c.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m32r.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-m68hc11.Plo@am__quote@ +@@ -1566,6 +1575,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-hppa.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ia64-vms.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ia64.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-loongarch.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mips.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-mmix.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-nfp.Plo@am__quote@ +@@ -1581,6 +1591,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfn32-mips.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-aarch64.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-ia64.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-loongarch.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-mips.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-riscv.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elfxx-sparc.Plo@am__quote@ +@@ -2122,6 +2133,18 @@ elf64-ia64.c : elfnn-ia64.c + $(SED) -e s/NN/64/g < $(srcdir)/elfnn-ia64.c > elf64-ia64.new + mv -f elf64-ia64.new elf64-ia64.c + ++elf32-loongarch.c : elfnn-loongarch.c ++ rm -f elf32-loongarch.c ++ echo "#line 1 \"$(srcdir)/elfnn-loongarch.c\"" > elf32-loongarch.new ++ sed -e s/NN/32/g < $(srcdir)/elfnn-loongarch.c >> elf32-loongarch.new ++ mv -f elf32-loongarch.new elf32-loongarch.c ++ ++elf64-loongarch.c : elfnn-loongarch.c ++ rm -f elf64-loongarch.c ++ echo "#line 1 \"$(srcdir)/elfnn-loongarch.c\"" > elf64-loongarch.new ++ sed -e s/NN/64/g < $(srcdir)/elfnn-loongarch.c >> elf64-loongarch.new ++ mv -f elf64-loongarch.new elf64-loongarch.c ++ + elf32-riscv.c : elfnn-riscv.c + rm -f elf32-riscv.c + echo "#line 1 \"$(srcdir)/elfnn-riscv.c\"" > elf32-riscv.new +diff --git a/bfd/archures.c b/bfd/archures.c +index a39925c7..efee3fc0 100644 +--- a/bfd/archures.c ++++ b/bfd/archures.c +@@ -540,6 +540,9 @@ DESCRIPTION + . bfd_arch_nfp, {* Netronome Flow Processor *} + .#define bfd_mach_nfp3200 0x3200 + .#define bfd_mach_nfp6000 0x6000 ++. bfd_arch_loongarch, {* Loongarch *} ++.#define bfd_mach_loongarch32 1 ++.#define bfd_mach_loongarch64 2 + . bfd_arch_last + . }; + */ +@@ -614,6 +617,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; +@@ -710,6 +714,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, +diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h +index e60bef9a..893af234 100644 +--- a/bfd/bfd-in2.h ++++ b/bfd/bfd-in2.h +@@ -2404,6 +2404,9 @@ enum bfd_architecture + bfd_arch_nfp, /* Netronome Flow Processor */ + #define bfd_mach_nfp3200 0x3200 + #define bfd_mach_nfp6000 0x6000 ++ bfd_arch_loongarch, /* LoongARCH */ ++#define bfd_mach_loongarch32 1 ++#define bfd_mach_loongarch64 2 + bfd_arch_last + }; + +@@ -6518,6 +6521,51 @@ assembler and not (currently) written to any object files. */ + BFD_RELOC_WASM32_CODE_POINTER, + BFD_RELOC_WASM32_INDEX, + BFD_RELOC_WASM32_PLT_SIG, ++ ++/* LoongISA 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_UNUSED }; + + typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; +diff --git a/bfd/config.bfd b/bfd/config.bfd +index cf02b010..eca16b52 100644 +--- a/bfd/config.bfd ++++ b/bfd/config.bfd +@@ -174,6 +174,7 @@ i[34567]86) targ_archs=bfd_i386_arch ;; + i370) targ_archs=bfd_i370_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 ;; +@@ -938,6 +939,20 @@ case "${targ}" in + targ_selvecs=lm32_elf32_vec + ;; + ++#ifdef BFD64 ++ loongarch32-*) ++ targ_defvec=loongarch_elf32_vec ++ targ_selvecs="loongarch_elf32_vec" ++ want64=false ++ ;; ++ ++ loongarch64-*) ++ targ_defvec=loongarch_elf64_vec ++ targ_selvecs="loongarch_elf32_vec loongarch_elf64_vec" ++ want64=true ++ ;; ++#endif ++ + m32c-*-elf | m32c-*-rtems*) + targ_defvec=m32c_elf32_vec + targ_underscore=yes +diff --git a/bfd/configure b/bfd/configure +index adc6cdf1..58ba9e8c 100755 +--- a/bfd/configure ++++ b/bfd/configure +@@ -14450,6 +14450,8 @@ do + l1om_elf64_fbsd_vec) tb="$tb elf64-x86-64.lo elfxx-x86.lo elf-ifunc.lo elf-nacl.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" ;; ++ loongarch_elf64_vec) tb="$tb elf64-loongarch.lo elf64.lo elfxx-loongarch.lo elf32.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" ;; +diff --git a/bfd/configure.ac b/bfd/configure.ac +index fa2e0ec0..a75c24b6 100644 +--- a/bfd/configure.ac ++++ b/bfd/configure.ac +@@ -508,6 +508,8 @@ do + l1om_elf64_fbsd_vec) tb="$tb elf64-x86-64.lo elfxx-x86.lo elf-ifunc.lo elf-nacl.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" ;; +diff --git a/bfd/cpu-loongarch.c b/bfd/cpu-loongarch.c +new file mode 100644 +index 00000000..c5579f29 +--- /dev/null ++++ b/bfd/cpu-loongarch.c +@@ -0,0 +1,38 @@ ++#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. */ ++ FALSE, /* 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. */ ++}; ++ ++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. */ ++ bfd_mach_loongarch64, /* Machine number of loongarch64 is larger so that loongarch64 is compatible to loongarch32 */ ++ "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. */ ++}; ++ +diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h +index 5b50ef2a..d941e19c 100644 +--- a/bfd/elf-bfd.h ++++ b/bfd/elf-bfd.h +@@ -497,6 +497,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, +@@ -2604,6 +2605,14 @@ extern char *elfcore_write_aarch_hw_break + (bfd *, char *, int *, const void *, int); + extern char *elfcore_write_aarch_hw_watch + (bfd *, char *, int *, 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); + extern char *elfcore_write_lwpstatus + (bfd *, char *, int *, long, int, const void *); + extern char *elfcore_write_register_note +diff --git a/bfd/elf.c b/bfd/elf.c +index ef2c7df0..8e0eb731 100644 +--- a/bfd/elf.c ++++ b/bfd/elf.c +@@ -9421,6 +9421,30 @@ elfcore_grok_aarch_hw_watch (bfd *abfd, Elf_Internal_Note *note) + return elfcore_make_note_pseudosection (abfd, ".reg-aarch-hw-watch", 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 */ +@@ -9917,6 +9941,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) +@@ -11100,6 +11152,55 @@ elfcore_write_aarch_hw_watch (bfd *abfd, + note_name, NT_ARM_HW_WATCH, aarch_hw_watch, 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, +@@ -11152,6 +11253,14 @@ elfcore_write_register_note (bfd *abfd, + return elfcore_write_aarch_hw_break (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-aarch-hw-watch") == 0) + return elfcore_write_aarch_hw_watch (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; + } + +diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c +new file mode 100644 +index 00000000..f609a756 +--- /dev/null ++++ b/bfd/elfnn-loongarch.c +@@ -0,0 +1,3287 @@ ++#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 ATTRIBUTE_UNUSED, ++ arelent *cache_ptr, ++ Elf_Internal_Rela *dst) ++{ ++ cache_ptr->howto = loongarch_elf_rtype_to_howto (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; ++ ++ /* Track dynamic relocs copied for this symbol. */ ++ struct elf_dyn_relocs *dyn_relocs; ++ ++#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; ++ ++ /* 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 ((struct elf_link_hash_table *) ((p)->hash)) \ ++ == 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) ++ ++/* .got.plt的前两项预留。我们约定: ++ 第一项在运行时被动态连接器填入_dl_runtime_resolve的地址 ++ 第二项在连接时,非0指plt header的地址(在no-pic下或prelink)。 ++ 第二项在运行时被动态连接器填入本模块的struct link_map实例的地址。 ++ 详见$glibc/sysdeps/loongarch/dl-machine.h中的elf_machine_runtime_setup */ ++#define GOTPLT_HEADER_SIZE (GOT_ENTRY_SIZE * 2) ++ ++/* .got和.got.plt不合并的好处是,.got.plt和.plt的entry是顺序对应的。 ++ 设法使得stub的size为2的幂,知道.plt和stub的地址就知道了index。 */ ++#define elf_backend_want_got_plt 1 ++ ++#define elf_backend_plt_readonly 1 ++ ++#define elf_backend_want_plt_sym 0 ++/* 1. 本来想着定义_PROCEDURE_LINKAGE_TABLE_,多了不嫌多。 ++ 2. 但实际上,这个符号会使得GDB调试ifunc函数失效。因为lazy-bind的情况下, ++ plt GOT entry中的地址都指向这个符号;GDB读取plt GOT entry来确定ifunc的 ++ 目标函数,从而以为_PROCEDURE_LINKAGE_TABLE_就是ifunc的目标函数(好奇的人 ++ 可以把断点打在elf_gnu_ifunc_record_cache上面看一下GDB的行为,总之是校验从 ++ GOT entry中拿到的地址,结果发现 'BMSYMBOL_VALUE_ADDRESS (msym) == addr' ++ 为真),然后直接跳转到plt header上面了,这当然不行。 ++ 3. 我们期望,调用ifunc函数时,要么跳到对应的plt stub上;要么GDB运行一遍 ++ resolver得到ifunc目标函数的地址后再调用(这是GDB公共代码的做法)。 ++ 4. 观察了aarch64的做法,发现他们就没_PROCEDURE_LINKAGE_TABLE_, ++ 就不存在msym.minsym,然后认为从GOT entry读ifunc目标函数失败直接退出了。 ++ 5. 我想了想,_PROCEDURE_LINKAGE_TABLE_的存在没有意义,因为对plt stub ++ 的处理是有重定位R_LARCH_SOP_PUSH_PLT_PCREL由静态连接器一手操办。 ++ 所以就把_PROCEDURE_LINKAGE_TABLE_去了吧。 */ ++#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 ++ ++/* .got的第一项预留。我们约定.got的第一项为.dynamic的连接时地址(如果有) */ ++#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 void ++loongarch_make_plt_header (bfd_vma got_plt_addr, ++ bfd_vma plt_header_addr, ++ uint32_t *entry) ++{ ++ int64_t pcrel = got_plt_addr - plt_header_addr; ++ int64_t hi = (pcrel & 0x800? 1 : 0) + (pcrel >> 12); ++ int64_t lo = pcrel & 0xfff; ++ if ((hi >> 19) != 0 && (hi >> 19) != -1) ++ abort ();//overflow ++ ++ /* 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) + 4 ++ 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) + 4) & 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; ++ } ++} ++ ++/* Generate a PLT entry. */ ++ ++static void ++loongarch_make_plt_entry (bfd_vma got_plt_entry_addr, ++ bfd_vma plt_entry_addr, ++ uint32_t *entry) ++{ ++ int64_t pcrel = got_plt_entry_addr - plt_entry_addr; ++ int64_t hi = (pcrel & 0x800? 1 : 0) + (pcrel >> 12); ++ int64_t lo = pcrel & 0xfff; ++ if ((hi >> 19) != 0 && (hi >> 19) != -1) ++ abort ();//overflow ++ ++ /* pcaddu12i $t3, %hi(%pcrel(.got.plt entry)) ++ ld.[wd] $t3, $t3, %lo(%pcrel(.got.plt entry)) ++ jirl $t1, $t3, 0 ++ addi $r0, $r0, 0 */ ++ ++ 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 */ ++ //entry[2] = 0x1800002d; /* pcaddi $13, 4 */ ++ entry[2] = 0x1c00000d; /* pcaddu12i $13, 4 */ ++ entry[3] = 0x4c0001e0; /* jirl $r0, $15, 0 */ ++} ++ ++/* 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) ++{ ++ /* Allocate the structure if it has not already been allocated by a ++ subclass. */ ++ if (entry == NULL) ++ { ++ entry = bfd_hash_allocate ++ (table, sizeof (struct loongarch_elf_link_hash_entry)); ++ if (entry == NULL) ++ return entry; ++ } ++ ++ /* Call the allocation method of the superclass. */ ++ entry = _bfd_elf_link_hash_newfunc (entry, table, string); ++ if (entry != NULL) ++ { ++ struct loongarch_elf_link_hash_entry *eh; ++ ++ eh = (struct loongarch_elf_link_hash_entry *) entry; ++ eh->dyn_relocs = NULL; ++ 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 ++ = (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 ++_bfd_loongarch_elf_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)) ++ { ++ /* Make sure one of ibfd or obfd e_flags must be set. */ ++ /* FIXME: EF_LARCH_ABI_LP64 ? . */ ++ if (!is_loongarch_elf (ibfd) && !elf_flags_init (obfd)) ++ { ++ elf_flags_init (obfd) = TRUE; ++ elf_elfheader (obfd)->e_flags = EF_LARCH_ABI_LP64; ++ } ++ ++ if (!is_loongarch_elf (obfd) && !elf_flags_init (ibfd)) ++ { ++ elf_flags_init (ibfd) = TRUE; ++ elf_elfheader (ibfd)->e_flags = EF_LARCH_ABI_LP64; ++ } ++ ++ 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 (!elf_flags_init (obfd)) ++ { ++ elf_flags_init (obfd) = TRUE; ++ elf_elfheader (obfd)->e_flags = in_flags; ++ return TRUE; ++ } ++ ++ /* Disallow linking different float ABIs. */ ++ if ((out_flags ^ in_flags) & EF_LARCH_ABI) ++ { ++ _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; ++ 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; ++ ++ s = bfd_make_section_anyway_with_flags ++ (abfd, bed->rela_plts_and_copies_p ? ".rela.got" : ".rel.got", ++ bed->dynamic_sec_flags | SEC_READONLY); ++ if (s == NULL ++ || !bfd_set_section_alignment (abfd, 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 (abfd, 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 (abfd, s, bed->s->log_file_align)) ++ return FALSE; ++ htab->sgotplt = s; ++ ++ /* 相比_bfd_elf_create_got_section: ++ 一方面,RISCV似乎是希望.got.plt和.got都有header; ++ 而且_GLOBAL_OFFSET_TABLE_是.got的开头,而不是.got.plt的开头。 ++ 和公共部分需求有冲突。所以自己实现了 */ ++ ++ /* 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 (_("%pB: Interl 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 : ""); ++ 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; ++ ++ /* 这个函数的遍历每一个重定位,将一些信息归置到符号中。这之后的处理 ++ 都会通过遍历符号进行,根据符号中的信息来确定最终二进制文件的形态。 ++ 1.根据重定位类型记录那个符号是否需要GOT entry ++ 2.根据重定位类型记录那个符号的TLS引用模型 ++ 3.处理IFUNC ++ 4.等等 ++ */ ++ ++ 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; ++ ++ /* 意味着在dynamic_sections_created置位的情况下,这个重定位可能需要动态 ++ 连接器的帮助。如果是这样,我们会在动态重定位表中为其分配一个表项。 */ ++ int need_dynreloc; ++ ++ /* 意味着这个动态重定位仅需要符号的pcrel信息,即符号定义在自身模块内 ++ 及延伸出来的其他信息。如果是这样,我们就在连接时知道了这个重定位的值, ++ 就可以把这个动态重定位取消掉。 */ ++ int only_need_pcrel; ++ ++ 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->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; ++ } ++ ++ if (h && h->type == STT_GNU_IFUNC) ++ { ++ if (htab->elf.dynobj == NULL) ++ htab->elf.dynobj = abfd; ++ ++ if (!htab->elf.splt ++ && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) ++ /* If '.plt' not represent, create '.iplt' to deal with ifunc. */ ++ 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_symbols ++ |= elf_gnu_symbol_ifunc; ++ } ++ ++ need_dynreloc = 0; ++ only_need_pcrel = 0; ++ switch (r_type) ++ { ++ case R_LARCH_SOP_PUSH_GPREL: ++ if (!loongarch_elf_record_tls_and_got_reference ++ (abfd, info, h, r_symndx, GOT_NORMAL)) ++ return FALSE; ++ break; ++ ++ 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_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_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_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. */ ++ /* 这个flag的本质是关注对一个符号的引用能否被动态连接器改变。 ++ 比如la.pcrel,在连接时会将符号的pc相对偏移量写入指令立即数; ++ 而代码段是只读的,动态连接器无法改动指令,这时,那个la只能引用 ++ local的那个符号的定义了,无法被动态连接器改变。 ++ 而使用got表的话,因为got entry可以被动态连接器改变,因此可以改变 ++ la到底哪个模块中的符号。 ++ 动态库里的符号定义可能被可执行文件中的符号定义覆盖,由此,动态库 ++ 中对符号的引用必须可以被动态连接器改变; ++ 而如果在可执行文件中la.pcrel一个动态库中的对象,按常理来说,如果 ++ 不走got表,这个引用是错误的。但如果我们真的把这个符号定义在 ++ 可执行文件中,而将动态库中对象的初始值复制到可执行文件中 ++ (R_LARCH_COPY),这其实等效于引用动态库中的对象了。 ++ 由此,如果某个重定位一旦可能不被动态链接器控制,这个flag被置位, ++ 接下来的处理会根据情况加上R_LARCH_COPY重定位。这样,我们也只能 ++ 在可执行文件中做这件事;动态库中的R_LARCH_COPY是很奇怪的。 */ ++ h->non_got_ref = 1; ++ break; ++ ++ case R_LARCH_SOP_PUSH_PCREL: ++ if (h != NULL) ++ { ++ 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_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) ++ h->non_got_ref = 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 = &((struct loongarch_elf_link_hash_entry *) 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 = loongarch_elf_hash_entry (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; ++ struct loongarch_elf_link_hash_entry * eh; ++ bfd *dynobj; ++ asection *s, *srel; ++ ++ 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; ++ } ++ ++ /* This is a reference to a symbol defined by a dynamic object which ++ is not a function. */ ++ ++ /* If we are creating a shared library, we must presume that the ++ only references to the symbol are via the global offset table. ++ For such cases we need not do anything here; the relocations will ++ be handled correctly by relocate_section. */ ++ if (bfd_link_dll (info)) ++ return TRUE; ++ ++ /* If there are no references to this symbol that do not use the ++ GOT, we don't need to generate a copy reloc. */ ++ if (!h->non_got_ref) ++ return TRUE; ++ ++ /* If -z nocopyreloc was given, we won't generate them either. */ ++ if (info->nocopyreloc) ++ { ++ h->non_got_ref = 0; ++ return TRUE; ++ } ++ ++ /* If we don't find any dynamic relocs in read-only sections, then ++ we'll be keeping the dynamic relocs and avoiding the copy reloc. */ ++ if (!readonly_dynrelocs (h)) ++ { ++ h->non_got_ref = 0; ++ return TRUE; ++ } ++ ++ /* We must allocate the symbol in our .dynbss section, which will ++ become part of the .bss section of the executable. There will be ++ an entry for this symbol in the .dynsym section. The dynamic ++ object will contain position independent code, so all references ++ from the dynamic object to this symbol will go through the global ++ offset table. The dynamic linker will use the .dynsym entry to ++ determine the address it must put in the global offset table, so ++ both the dynamic object and the regular object will refer to the ++ same memory location for the variable. */ ++ ++ /* We must generate a R_LARCH_COPY reloc to tell the dynamic linker ++ to copy the initial value out of the dynamic object and into the ++ runtime process image. We need to remember the offset into the ++ .rel.bss section we are going to use. */ ++ eh = (struct loongarch_elf_link_hash_entry *) h; ++ if (eh->tls_type & ~GOT_NORMAL) ++ { ++ s = htab->sdyntdata; ++ srel = htab->elf.srelbss; ++ } ++ else ++ if ((h->root.u.def.section->flags & SEC_READONLY) != 0) ++ { ++ s = htab->elf.sdynrelro; ++ srel = htab->elf.sreldynrelro; ++ } ++ else ++ { ++ s = htab->elf.sdynbss; ++ srel = htab->elf.srelbss; ++ } ++ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0) ++ { ++ srel->size += sizeof (ElfNN_External_Rela); ++ h->needs_copy = 1; ++ } ++ ++ return _bfd_elf_adjust_dynamic_copy (info, h, s); ++} ++ ++ ++/* 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 loongarch_elf_link_hash_entry *eh; ++ struct elf_dyn_relocs *p; ++ ++ if (h->root.type == bfd_link_hash_indirect) ++ return TRUE; ++ ++ eh = (struct loongarch_elf_link_hash_entry *) h; ++ info = (struct bfd_link_info *) inf; ++ htab = loongarch_elf_hash_table (info); ++ BFD_ASSERT (htab != NULL); ++ ++ /* 在这里针对符号对.got .iplt .plt的扩充和后续elf_finish_dynamic_symbol补充 ++ 内容对照;WILL_CALL_FINISH_DYNAMIC_SYMBOL似乎指的是这个符号在将来会不会被 ++ finish_dynamic_symbol调用。 ++ a. 对于非IFUNC符号,被allocate_dynrelocs照顾到的符号h要保证在链接后期被 ++ elf_finish_dynamic_symbol调用 ++ b. STT_GNU_IFUNC符号一定走plt,但是对于那些local转化为h的符号,默认是不会 ++ 被调用allocate_dynrelocs和elf_finish_dynamic_symbol的,要手动遍历 ++ 这些符号来调用这两个函数,从而为它们分配plt stub; ++ 而WILL_CALL_FINISH_DYNAMIC_SYMBOL返回false,因此下面的逻辑都是 ++ WILL_CALL_FINISH_DYNAMIC_SYMBOL和对IFUNC的判断配合起来。 */ ++ ++ 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 ++ && !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); ++ ++ h->needs_plt = 1; ++ } ++ while (0); ++ ++ if (!h->needs_plt) ++ h->plt.offset = MINUS_ONE; ++ ++ if (0 < h->got.refcount) ++ { ++ asection *s; ++ bfd_boolean dyn; ++ 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 ++ && !bfd_elf_link_record_dynamic_symbol (info, h)) ++ return FALSE; ++ ++ s = htab->elf.sgot; ++ h->got.offset = s->size; ++ dyn = htab->elf.dynamic_sections_created; ++ 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; ++ 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; ++ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); ++ } ++ } ++ else ++ { ++ s->size += GOT_ENTRY_SIZE; ++ if ((WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h) ++ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) ++ || h->type == STT_GNU_IFUNC) ++ htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); ++ } ++ } ++ else ++ h->got.offset = MINUS_ONE; ++ ++ if (eh->dyn_relocs == NULL) ++ return TRUE; ++ ++ /* 如果某些函数未被定义,SYMBOL_CALLS_LOCAL返回1; ++ 而SYMBOL_REFERENCES_LOCAL返回0。 ++ 似乎是因为未定义的函数可以有plt从而将其转化为local的。 */ ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ { ++ struct elf_dyn_relocs **pp; ++ ++ for (pp = &eh->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)) ++ eh->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. */ ++ && !bfd_elf_link_record_dynamic_symbol (info, h)) ++ return FALSE; ++ } ++ ++ for (p = eh->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; ++} ++ ++static bfd_boolean ++elfNN_loongarch_allocate_local_dynrelocs (void **slot, void *inf) ++{ ++ struct elf_link_hash_entry *h ++ = (struct elf_link_hash_entry *) *slot; ++ ++ if (!h->def_regular ++ || !h->ref_regular ++ || !h->forced_local ++ || h->root.type != bfd_link_hash_defined) ++ abort (); ++ ++ return allocate_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 ((flags & EF_LARCH_ABI) == EF_LARCH_ABI_LP32) ++ interpreter = "/lib32/ld.so.1"; ++ else if ((flags & EF_LARCH_ABI) == EF_LARCH_ABI_LP64) ++ 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; ++ s->size += GOT_ENTRY_SIZE; ++ ++ if (*local_tls_type & GOT_TLS_GD) ++ s->size += GOT_ENTRY_SIZE; ++ ++ if (bfd_link_pic (info) /* R_LARCH_RELATIVE */ ++ || (*local_tls_type & ++ (GOT_TLS_GD /* R_LARCH_TLS_DTPRELNN */ ++ | GOT_TLS_IE /* R_LARCH_TLS_TPRELNN */))) ++ 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 .plt and .got entries, and space for local ifunc symbols. */ ++ htab_traverse (htab->loc_hash_table, ++ elfNN_loongarch_allocate_local_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 lisa_opc_stack[LARCH_LD_STACK_DEPTH]; ++static size_t lisa_stack_top = 0; ++ ++static bfd_reloc_status_type ++loongarch_push (int64_t val) ++{ ++ if (LARCH_LD_STACK_DEPTH <= lisa_stack_top) ++ return bfd_reloc_outofrange; ++ lisa_opc_stack[lisa_stack_top++] = val; ++ return bfd_reloc_ok; ++} ++ ++static bfd_reloc_status_type ++loongarch_pop (int64_t *val) ++{ ++ if (lisa_stack_top == 0) ++ return bfd_reloc_outofrange; ++ BFD_ASSERT (val); ++ *val = lisa_opc_stack[--lisa_stack_top]; ++ return bfd_reloc_ok; ++} ++ ++static bfd_reloc_status_type ++loongarch_top (int64_t *val) ++{ ++ if (lisa_stack_top == 0) ++ return bfd_reloc_outofrange; ++ BFD_ASSERT (val); ++ *val = lisa_opc_stack[lisa_stack_top - 1]; ++ return bfd_reloc_ok; ++} ++ ++static void ++loongarch_elf_append_rela (bfd *abfd, asection *s, Elf_Internal_Rela *rel) ++{ ++ const struct elf_backend_data *bed; ++ bfd_byte *loc; ++ ++ bed = get_elf_backend_data (abfd); ++ loc = s->contents + (s->reloc_count++ * bed->s->sizeof_rela); ++ bed->s->swap_reloca_out (abfd, rel, loc); ++} ++ ++/* Emplace a static relocation. */ ++ ++static bfd_reloc_status_type ++perform_relocation (const Elf_Internal_Rela *rel, ++ bfd_vma value, ++ bfd *input_bfd, ++ bfd_byte *contents) ++{ ++ ++ uint32_t insn1; ++ int64_t opr1, opr2, opr3; ++ bfd_reloc_status_type r = bfd_reloc_ok; ++ 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 = bfd_reloc_outofrange; ++ if (loongarch_pop (&opr1) != bfd_reloc_ok ++ || loongarch_push (opr1) != bfd_reloc_ok ++ || loongarch_push (opr1) != bfd_reloc_ok) ++ break; ++ r = bfd_reloc_ok; ++ break; ++ ++ case R_LARCH_SOP_ASSERT: ++ r = loongarch_pop (&opr1); ++ if (r != bfd_reloc_ok && opr1 == FALSE) ++ r = bfd_reloc_notsupported; ++ break; ++ ++ case R_LARCH_SOP_NOT: ++ r = bfd_reloc_outofrange; ++ if (loongarch_pop (&opr1) != bfd_reloc_ok ++ || loongarch_push (!opr1) != bfd_reloc_ok) ++ break; ++ r = bfd_reloc_ok; ++ break; ++ ++ case R_LARCH_SOP_SUB: ++ r = bfd_reloc_outofrange; ++ if (loongarch_pop (&opr2) != bfd_reloc_ok ++ || loongarch_pop (&opr1) != bfd_reloc_ok ++ || loongarch_push (opr1 - opr2) != bfd_reloc_ok) ++ break; ++ r = bfd_reloc_ok; ++ break; ++ ++ case R_LARCH_SOP_SL: ++ r = bfd_reloc_outofrange; ++ if (loongarch_pop (&opr2) != bfd_reloc_ok ++ || loongarch_pop (&opr1) != bfd_reloc_ok ++ || loongarch_push (opr1 << opr2) != bfd_reloc_ok) ++ break; ++ r = bfd_reloc_ok; ++ break; ++ ++ case R_LARCH_SOP_SR: ++ r = bfd_reloc_outofrange; ++ if (loongarch_pop (&opr2) != bfd_reloc_ok ++ || loongarch_pop (&opr1) != bfd_reloc_ok ++ || loongarch_push (opr1 >> opr2) != bfd_reloc_ok) ++ break; ++ r = bfd_reloc_ok; ++ break; ++ ++ case R_LARCH_SOP_AND: ++ r = bfd_reloc_outofrange; ++ if (loongarch_pop (&opr2) != bfd_reloc_ok ++ || loongarch_pop (&opr1) != bfd_reloc_ok ++ || loongarch_push (opr1 & opr2) != bfd_reloc_ok) ++ break; ++ r = bfd_reloc_ok; ++ break; ++ ++ case R_LARCH_SOP_ADD: ++ r = bfd_reloc_outofrange; ++ if (loongarch_pop (&opr2) != bfd_reloc_ok ++ || loongarch_pop (&opr1) != bfd_reloc_ok ++ || loongarch_push (opr1 + opr2) != bfd_reloc_ok) ++ break; ++ r = bfd_reloc_ok; ++ break; ++ ++ case R_LARCH_SOP_IF_ELSE: ++ r = bfd_reloc_outofrange; ++ if (loongarch_pop (&opr3) != bfd_reloc_ok ++ || loongarch_pop (&opr2) != bfd_reloc_ok ++ || loongarch_pop (&opr1) != bfd_reloc_ok ++ || loongarch_push (opr1 ? opr2 : opr3) != bfd_reloc_ok) ++ break; ++ r = bfd_reloc_ok; ++ break; ++ ++ case R_LARCH_SOP_POP_32_S_10_5: ++ r = loongarch_pop (&opr1); ++ if (r != bfd_reloc_ok) ++ break; ++ if ((opr1 & ~(uint64_t)0xf) != 0x0 ++ && (opr1 & ~(uint64_t)0xf) != ~(uint64_t)0xf) ++ r = bfd_reloc_overflow; ++ if (r != bfd_reloc_ok) ++ break; ++ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); ++ insn1 = (insn1 & (~(uint32_t)0x7c00)) | ((opr1 & 0x1f) << 10); ++ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); ++ break; ++ ++ case R_LARCH_SOP_POP_32_U_10_12: ++ r = loongarch_pop (&opr1); ++ if (r != bfd_reloc_ok) ++ break; ++ if (opr1 & ~(uint64_t)0xfff) ++ r = bfd_reloc_overflow; ++ if (r != bfd_reloc_ok) ++ break; ++ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); ++ insn1 = (insn1 & (~(uint32_t)0x3ffc00)) | ((opr1 & 0xfff) << 10); ++ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); ++ break; ++ ++ case R_LARCH_SOP_POP_32_S_10_12: ++ r = loongarch_pop (&opr1); ++ if (r != bfd_reloc_ok) ++ break; ++ if ((opr1 & ~(uint64_t)0x7ff) != 0x0 ++ && (opr1 & ~(uint64_t)0x7ff) != ~(uint64_t)0x7ff) ++ r = bfd_reloc_overflow; ++ if (r != bfd_reloc_ok) ++ break; ++ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); ++ insn1 = (insn1 & (~(uint32_t)0x3ffc00)) | ((opr1 & 0xfff) << 10); ++ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); ++ break; ++ ++ case R_LARCH_SOP_POP_32_S_10_16: ++ r = loongarch_pop (&opr1); ++ if (r != bfd_reloc_ok) ++ break; ++ if ((opr1 & ~(uint64_t)0x7fff) != 0x0 ++ && (opr1 & ~(uint64_t)0x7fff) != ~(uint64_t)0x7fff) ++ r = bfd_reloc_overflow; ++ if (r != bfd_reloc_ok) ++ break; ++ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); ++ insn1 = (insn1 & 0xfc0003ff) | ((opr1 & 0xffff) << 10); ++ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); ++ break; ++ ++ case R_LARCH_SOP_POP_32_S_10_16_S2: ++ r = loongarch_pop (&opr1); ++ if (r != bfd_reloc_ok) ++ break; ++ if ((opr1 & 0x3) != 0) ++ r = bfd_reloc_overflow; ++ opr1 >>= 2; ++ if ((opr1 & ~(uint64_t)0x7fff) != 0x0 ++ && (opr1 & ~(uint64_t)0x7fff) != ~(uint64_t)0x7fff) ++ r = bfd_reloc_overflow; ++ if (r != bfd_reloc_ok) ++ break; ++ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); ++ insn1 = (insn1 & 0xfc0003ff) | ((opr1 & 0xffff) << 10); ++ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); ++ break; ++ ++ case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: ++ r = loongarch_pop (&opr1); ++ if (r != bfd_reloc_ok) ++ break; ++ if ((opr1 & 0x3) != 0) ++ r = bfd_reloc_overflow; ++ opr1 >>= 2; ++ if ((opr1 & ~(uint64_t)0xfffff) != 0x0 ++ && (opr1 & ~(uint64_t)0xfffff) != ~(uint64_t)0xfffff) ++ r = bfd_reloc_overflow; ++ if (r != bfd_reloc_ok) ++ break; ++ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); ++ insn1 = (insn1 & 0xfc0003e0) ++ | ((opr1 & 0xffff) << 10) | ((opr1 & 0x1f0000) >> 16); ++ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); ++ break; ++ ++ case R_LARCH_SOP_POP_32_S_5_20: ++ r = loongarch_pop (&opr1); ++ if (r != bfd_reloc_ok) ++ break; ++ if ((opr1 & ~(uint64_t)0x7ffff) != 0x0 ++ && (opr1 & ~(uint64_t)0x7ffff) != ~(uint64_t)0x7ffff) ++ r = bfd_reloc_overflow; ++ if (r != bfd_reloc_ok) ++ break; ++ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); ++ insn1 = (insn1 & (~(uint32_t)0x1ffffe0)) | ((opr1 & 0xfffff) << 5); ++ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); ++ break; ++ ++ case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: ++ r = loongarch_pop (&opr1); ++ if (r != bfd_reloc_ok) ++ break; ++ if ((opr1 & 0x3) != 0) ++ r = bfd_reloc_overflow; ++ opr1 >>= 2; ++ if ((opr1 & ~(uint64_t)0x1ffffff) != 0x0 ++ && (opr1 & ~(uint64_t)0x1ffffff) != ~(uint64_t)0x1ffffff) ++ r = bfd_reloc_overflow; ++ if (r != bfd_reloc_ok) ++ break; ++ insn1 = bfd_get (32, input_bfd, contents + rel->r_offset); ++ insn1 = (insn1 & 0xfc000000) ++ | ((opr1 & 0xffff) << 10) | ((opr1 & 0x3ff0000) >> 16); ++ bfd_put (32, input_bfd, insn1, contents + rel->r_offset); ++ break; ++ ++ case R_LARCH_SOP_POP_32_U: ++ r = loongarch_pop (&opr1); ++ if (r != bfd_reloc_ok) ++ break; ++ if (opr1 & ~(uint64_t)0xffffffff) ++ r = bfd_reloc_overflow; ++ if (r != bfd_reloc_ok) ++ break; ++ bfd_put (32, input_bfd, opr1, contents + rel->r_offset); ++ break; ++ ++ case R_LARCH_TLS_DTPREL32: ++ case R_LARCH_32: ++ bfd_put (32, input_bfd, value, contents + rel->r_offset); ++ break; ++ case R_LARCH_TLS_DTPREL64: ++ case R_LARCH_64: ++ bfd_put (64, input_bfd, value, contents + rel->r_offset); ++ break; ++ case R_LARCH_ADD8: ++ opr1 = bfd_get (8, input_bfd, contents + rel->r_offset); ++ bfd_put (8, input_bfd, opr1 + value, contents + rel->r_offset); ++ break; ++ case R_LARCH_ADD16: ++ opr1 = bfd_get (16, input_bfd, contents + rel->r_offset); ++ bfd_put (16, input_bfd, opr1 + value, contents + rel->r_offset); ++ break; ++ case R_LARCH_ADD24: ++ opr1 = bfd_get (24, input_bfd, contents + rel->r_offset); ++ bfd_put (24, input_bfd, opr1 + value, contents + rel->r_offset); ++ break; ++ case R_LARCH_ADD32: ++ opr1 = bfd_get (32, input_bfd, contents + rel->r_offset); ++ bfd_put (32, input_bfd, opr1 + value, contents + rel->r_offset); ++ break; ++ case R_LARCH_ADD64: ++ opr1 = bfd_get (64, input_bfd, contents + rel->r_offset); ++ bfd_put (64, input_bfd, opr1 + value, contents + rel->r_offset); ++ break; ++ case R_LARCH_SUB8: ++ opr1 = bfd_get (8, input_bfd, contents + rel->r_offset); ++ bfd_put (8, input_bfd, opr1 - value, contents + rel->r_offset); ++ break; ++ case R_LARCH_SUB16: ++ opr1 = bfd_get (16, input_bfd, contents + rel->r_offset); ++ bfd_put (16, input_bfd, opr1 - value, contents + rel->r_offset); ++ break; ++ case R_LARCH_SUB24: ++ opr1 = bfd_get (24, input_bfd, contents + rel->r_offset); ++ bfd_put (24, input_bfd, opr1 - value, contents + rel->r_offset); ++ break; ++ case R_LARCH_SUB32: ++ opr1 = bfd_get (32, input_bfd, contents + rel->r_offset); ++ bfd_put (32, input_bfd, opr1 - value, contents + rel->r_offset); ++ break; ++ case R_LARCH_SUB64: ++ opr1 = bfd_get (64, input_bfd, contents + rel->r_offset); ++ bfd_put (64, input_bfd, opr1 - value, contents + rel->r_offset); ++ 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; ++} lisa_reloc_queue [LARCH_RECENT_RELOC_QUEUE_LENGTH]; ++static size_t lisa_reloc_queue_head = 0; ++static size_t lisa_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 = ""; ++ 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 ((lisa_reloc_queue_head == 0 ++ && lisa_reloc_queue_tail == LARCH_RECENT_RELOC_QUEUE_LENGTH - 1) ++ || (lisa_reloc_queue_head == lisa_reloc_queue_tail + 1)) ++ lisa_reloc_queue_head = ++ (lisa_reloc_queue_head + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH; ++ lisa_reloc_queue[lisa_reloc_queue_tail].bfd = abfd; ++ lisa_reloc_queue[lisa_reloc_queue_tail].section = section; ++ lisa_reloc_queue[lisa_reloc_queue_tail].r_offset = r_offset; ++ lisa_reloc_queue[lisa_reloc_queue_tail].r_type = r_type; ++ lisa_reloc_queue[lisa_reloc_queue_tail].sym = sym; ++ lisa_reloc_queue[lisa_reloc_queue_tail].h = h; ++ lisa_reloc_queue[lisa_reloc_queue_tail].addend = addend; ++ loongarch_top (&lisa_reloc_queue[lisa_reloc_queue_tail].top_then); ++ lisa_reloc_queue_tail = ++ (lisa_reloc_queue_tail + 1) % LARCH_RECENT_RELOC_QUEUE_LENGTH; ++} ++ ++static void ++loongarch_dump_reloc_record (void (*p) (const char *fmt, ...)) ++{ ++ size_t i = lisa_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 != lisa_reloc_queue_tail) ++ { ++ if (a_bfd != lisa_reloc_queue[i].bfd ++ || section != lisa_reloc_queue[i].section ++ || r_offset != lisa_reloc_queue[i].r_offset) ++ { ++ a_bfd = lisa_reloc_queue[i].bfd; ++ section = lisa_reloc_queue[i].section; ++ r_offset = lisa_reloc_queue[i].r_offset; ++ p ("\nat %pB(%pA+0x%v):\n", ++ lisa_reloc_queue[i].bfd, ++ lisa_reloc_queue[i].section, ++ lisa_reloc_queue[i].r_offset); ++ } ++ ++ if (!inited) ++ inited = 1, p ("...\n"); ++ ++ reloc_howto_type *howto = ++ loongarch_elf_rtype_to_howto (lisa_reloc_queue[i].r_type); ++ p ("0x%V %s\t`%s'", ++ (bfd_vma) lisa_reloc_queue[i].top_then, ++ howto ? howto->name : "", ++ loongarch_sym_name (lisa_reloc_queue[i].bfd, ++ lisa_reloc_queue[i].h, ++ lisa_reloc_queue[i].sym)); ++ ++ long addend = lisa_reloc_queue[i].addend; ++ if (addend < 0) ++ p (" - %ld", -addend); ++ else if (0 < addend) ++ p (" + %ld(0x%v)", addend, lisa_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_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 = loongarch_elf_rtype_to_howto (r_type); ++ 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; ++ bfd_vma off, ie_off; ++ int i, j; ++ ++ 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; ++ if (bfd_link_relocatable(info) ++ && ELF_ST_TYPE(sym->st_info) == STT_SECTION) { ++ rel->r_addend += sec->output_offset; ++ } ++ } ++ 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' */ ++ ++ /* '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; ++ ++ /* 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)) ++ resolved_dynly = resolved_local = defined_local = FALSE ++ , resolved_to_const = TRUE; ++ ++ if (h && h->type == STT_GNU_IFUNC) ++ { ++ /* a. 动态连接器可以直接处理STT_GNU_IFUNC,因为动态连接器可以察觉到 ++ 一个动态符号是STT_GNU_IFUNC,从而在装载时执行resolver; ++ 但local符号不行,因为根本没有动态符号,所以要将R_LARCH_64转化为 ++ R_LARCH_IRELATIVE,类似的,所有其他重定位类型可能都要针对IFUNC ++ 做一些特殊操作,我觉得有点麻烦了。 ++ b. 此外,比如代码段的重定位无法动态改变其的引用位置,所以必须走plt ++ 来实现IFUNC。 ++ c. 因此,为方便实现,我们将plt stub的位置当作IFUNC符号的定义。 */ ++ if (h->plt.offset == MINUS_ONE) ++ info->callbacks->info ++ ("%X%pB(%pA+0x%v): error: %s against `%s':\n" ++ "STT_GNU_IFUNC must have PLT stub" "\n", ++ input_bfd, input_section, (bfd_vma) rel->r_offset, ++ howto->name, name); ++ 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); ++ ++ /* a. 命题 'resolved_dynly' ==> 'h && h->dynindx != -1' 成立。 ++ b. 需要动态重定位一个符号当然需要动态符号表。这个断言失败意味着某个 ++ 动态符号没有执行bfd_elf_link_record_dynamic_symbol。之前的逻辑有问题 ++ c. 另外,即使resolved_dynly为真,也不一定真的生成动态重定位表项,因为 ++ 有时section没有SEC_ALLOC这个flag,当段不需要被加载进内存自然不需要动态 ++ 重定位。 */ ++ BFD_ASSERT (!resolved_dynly || (h && h->dynindx != -1)); ++ ++ BFD_ASSERT (!resolved_local || defined_local); ++ ++ is_ie = FALSE; ++ switch (r_type) ++ { ++#define LARCH_ASSERT(cond, bfd_fail_state, message) \ ++ ({if (!(cond)) { \ ++ r = bfd_fail_state; \ ++ switch (r) { \ ++ /* '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); \ ++ default: \ ++ fatal = TRUE; \ ++ info->callbacks->info \ ++ ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n" \ ++ message "\n", \ ++ input_bfd, input_section, (bfd_vma) rel->r_offset, \ ++ howto->name, is_undefweak? "[undefweak] " : "", name); \ ++ break; \ ++ case bfd_reloc_dangerous: \ ++ info->callbacks->info \ ++ ("%pB(%pA+0x%v): warning: %s against %s`%s':\n" \ ++ message "\n", \ ++ input_bfd, input_section, (bfd_vma) rel->r_offset, \ ++ howto->name, is_undefweak? "[undefweak] " : "", name); \ ++ break; \ ++ case bfd_reloc_ok: \ ++ case bfd_reloc_continue: \ ++ info->callbacks->info \ ++ ("%pB(%pA+0x%v): message: %s against %s`%s':\n" \ ++ message "\n", \ ++ input_bfd, input_section, (bfd_vma) rel->r_offset, \ ++ howto->name, is_undefweak? "[undefweak] " : "", name); \ ++ break; \ ++ } \ ++ if (fatal) break; \ ++ }}) ++ 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); ++ if (resolved_dynly) ++ { ++ 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; ++ } ++ ++ if (unresolved_reloc) ++ 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: ++ LARCH_ASSERT (!resolved_dynly, bfd_reloc_undefined, ++"Can't be resolved dynamically. If this procedure is hand-writing assemble,\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."); ++ 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; ++ } ++ ++ LARCH_ASSERT (!resolved_to_const, bfd_reloc_notsupported, ++ "Internal:"); ++ ++ case R_LARCH_SOP_PUSH_TLS_TPREL: ++ if (resolved_local) ++ { ++ LARCH_ASSERT (elf_hash_table (info)->tls_sec, ++ bfd_reloc_notsupported, "TLS section not be created"); ++ relocation -= elf_hash_table (info)->tls_sec->vma; ++ } ++ ++ LARCH_ASSERT (resolved_local, bfd_reloc_undefined, ++ "TLS LE just can be resolved local only."); ++ break; ++ ++ case R_LARCH_SOP_PUSH_ABSOLUTE: ++ if (is_undefweak) ++ { ++ LARCH_ASSERT (!resolved_dynly, bfd_reloc_dangerous, ++"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; ++ } ++ ++ LARCH_ASSERT (!is_pic, bfd_reloc_notsupported, ++"Under PIC we don't know load address. Re-compile src with '-fpic'?"); ++ ++ if (resolved_dynly) ++ { ++ LARCH_ASSERT (plt && h && h->plt.offset != MINUS_ONE, ++ bfd_reloc_undefined, ++"Can't be resolved dynamically. Try to re-compile src with '-fpic'?"); ++ ++ LARCH_ASSERT (rel->r_addend == 0, bfd_reloc_notsupported, ++ "Shouldn't be with r_addend."); ++ ++ 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 (resolved_to_const) ++ { ++ relocation += rel->r_addend; ++ break; ++ } ++ else if (is_undefweak) ++ { ++ i = 0, j = 0; ++ relocation = 0; ++ if (resolved_dynly) ++ { ++ if (h && h->plt.offset != MINUS_ONE) ++ i = 1, j = 2; ++ else ++ LARCH_ASSERT (0, bfd_reloc_dangerous, ++"Undefweak need to be resolved dynamically, but PLT stub doesn't represent."); ++ } ++ } ++ else ++ { ++ LARCH_ASSERT ++ (defined_local || (h && h->plt.offset != MINUS_ONE), ++ bfd_reloc_undefined, ++ "PLT stub does not represent and symbol not defined."); ++ ++ if (resolved_local) ++ i = 0, j = 2; ++ else /* if (resolved_dynly) */ ++ { ++ LARCH_ASSERT ++ (h && h->plt.offset != MINUS_ONE, bfd_reloc_dangerous, ++"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) ++ { ++ LARCH_ASSERT (rel->r_addend == 0, bfd_reloc_notsupported, ++ "PLT shouldn't be with r_addend."); ++ relocation = sec_addr (plt) + h->plt.offset - pc; ++ break; ++ } ++ } ++ break; ++ ++ case R_LARCH_SOP_PUSH_GPREL: ++ unresolved_reloc = FALSE; ++ ++ LARCH_ASSERT (rel->r_addend == 0, bfd_reloc_notsupported, ++ "Shouldn't be with r_addend."); ++ ++ /* 约定在GOT表中写入连接时地址。动态连接器通过_GLOBAL_OFFSET_TABLE_的 ++ 连接时地址和运行时地址拿到模块的加载地址,拿到连接时地址的办法就是 ++ 拿到那个got entry。一些体系结构通过.dynamic的段基址拿到模块加载 ++ 地址,我没有这么做,因为这个段在static-pie下不存在。 */ ++ ++ if (h != NULL) ++ { ++ off = h->got.offset; ++ ++ LARCH_ASSERT (off != MINUS_ONE, bfd_reloc_notsupported, ++ "Internal: GOT entry doesn't represent."); ++ ++ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, is_pic, h) ++ || (is_pic && 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. */ ++ ++ /* 在这里先不用管STT_GNU_IFUNC。elf_finish_dynamic_symbol ++ 会单独处理。 */ ++ ++ LARCH_ASSERT (!resolved_dynly, bfd_reloc_dangerous, ++ "Internal: here shouldn't dynamic."); ++ LARCH_ASSERT (defined_local || resolved_to_const, ++ bfd_reloc_undefined, "Internal: "); ++ ++ if ((off & 1) != 0) ++ off &= ~1; ++ else ++ { ++ bfd_put_NN (output_bfd, relocation, got->contents + off); ++ h->got.offset |= 1; ++ } ++ } ++ } ++ else ++ { ++ LARCH_ASSERT (local_got_offsets, bfd_reloc_notsupported, ++ "Internal: local got offsets not reporesent."); ++ ++ off = local_got_offsets[r_symndx]; ++ ++ LARCH_ASSERT (off != MINUS_ONE, bfd_reloc_notsupported, ++ "Internal: GOT entry doesn't represent."); ++ ++ /* 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 ((off & 1) != 0) ++ off &= ~1; ++ else ++ { ++ 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; ++ LARCH_ASSERT (s, bfd_reloc_notsupported, ++ "Internal: '.rel.got' not represent"); ++ ++ 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: ++ is_ie = TRUE; ++ case R_LARCH_SOP_PUSH_TLS_GD: ++ unresolved_reloc = FALSE; ++ ++ LARCH_ASSERT (rel->r_addend == 0, bfd_reloc_notsupported, ++ "Shouldn't be with r_addend."); ++ ++ if (resolved_to_const && is_undefweak && h->dynindx != -1) ++ { ++ /* What if undefweak? Let rtld make a decision. */ ++ resolved_to_const = resolved_local = FALSE; ++ resolved_dynly = TRUE; ++ } ++ ++ LARCH_ASSERT (!resolved_to_const, bfd_reloc_notsupported, ++ "Internal: Shouldn't be resolved to const."); ++ ++ if (h != NULL) ++ { ++ off = h->got.offset; ++ h->got.offset |= 1; ++ } ++ else ++ { ++ off = local_got_offsets[r_symndx]; ++ local_got_offsets[r_symndx] |= 1; ++ } ++ ++ LARCH_ASSERT (off != MINUS_ONE, bfd_reloc_notsupported, ++ "Internal: TLS GOT entry doesn't represent."); ++ ++ tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); ++ ++ /* If this symbol is referenced by both GD and IE TLS, the IE ++ reference's GOT slot follows the GD reference's slots. */ ++ ie_off = 0; ++ if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE)) ++ ie_off = 2 * GOT_ENTRY_SIZE; ++ ++ if ((off & 1) != 0) ++ off &= ~1; ++ else ++ { ++ bfd_vma tls_block_off = 0; ++ Elf_Internal_Rela outrel; ++ ++ if (resolved_local) ++ { ++ LARCH_ASSERT ++ (elf_hash_table (info)->tls_sec, bfd_reloc_notsupported, ++ "Internal: TLS sec not represent."); ++ tls_block_off = relocation ++ - elf_hash_table (info)->tls_sec->vma; ++ } ++ ++ if (tls_type & GOT_TLS_GD) ++ { ++ outrel.r_offset = sec_addr (got) + off; ++ outrel.r_addend = 0; ++ bfd_put_NN (output_bfd, 0, got->contents + off); ++ if (resolved_local && bfd_link_executable (info)) ++ /* a. 第一个被装载模块的Module ID为1。$glibc/elf/rtld.c中 ++ 的dl_main有一句'main_map->l_tls_modid = 1'; ++ b. 静态程序的Module ID不重要,但为了省事仍然是1。 ++ 详见$glibc/csu/libc-tls.c中的init_static_tls。 */ ++ bfd_put_NN (output_bfd, 1, got->contents + off); ++ else if (resolved_local/* && !bfd_link_executable (info) */) ++ { ++ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_DTPMODNN); ++ loongarch_elf_append_rela ++ (output_bfd, htab->elf.srelgot, &outrel); ++ } ++ else /* if (resolved_dynly) */ ++ { ++ outrel.r_info = ++ ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPMODNN); ++ loongarch_elf_append_rela ++ (output_bfd, htab->elf.srelgot, &outrel); ++ } ++ ++ outrel.r_offset += GOT_ENTRY_SIZE; ++ bfd_put_NN (output_bfd, tls_block_off, ++ got->contents + off + GOT_ENTRY_SIZE); ++ if (resolved_local) ++ /* DTPREL known */; ++ else /* if (resolved_dynly) */ ++ { ++ outrel.r_info = ++ ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_DTPRELNN); ++ loongarch_elf_append_rela ++ (output_bfd, htab->elf.srelgot, &outrel); ++ } ++ } ++ ++ if (tls_type & GOT_TLS_IE) ++ { ++ outrel.r_offset = sec_addr (got) + off + ie_off; ++ bfd_put_NN (output_bfd, tls_block_off, ++ got->contents + off + ie_off); ++ if (resolved_local && bfd_link_executable (info)) ++ /* TPREL known */; ++ else if (resolved_local/* && !bfd_link_executable (info) */) ++ { ++ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); ++ outrel.r_addend = tls_block_off; ++ loongarch_elf_append_rela ++ (output_bfd, htab->elf.srelgot, &outrel); ++ } ++ else /* if (resolved_dynly) */ ++ { ++ outrel.r_info = ++ ELFNN_R_INFO (h->dynindx, R_LARCH_TLS_TPRELNN); ++ outrel.r_addend = 0; ++ loongarch_elf_append_rela ++ (output_bfd, htab->elf.srelgot, &outrel); ++ } ++ } ++ } ++ ++ relocation = off + (is_ie ? ie_off : 0); ++ 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) ++ { ++ LARCH_ASSERT (0, bfd_reloc_dangerous, ++ "Seems dynamic linker not process sections 'SEC_DEBUGGING'."); ++ break; ++ } ++ if (!is_dyn) ++ break; ++ ++ if ((info->flags & DF_TEXTREL) == 0) ++ if (input_section->output_section->flags & SEC_READONLY) ++ info->flags |= DF_TEXTREL; ++ } ++ while (0); ++#undef LARCH_ASSERT ++ ++ 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, 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; ++ break; ++ } ++ ++ 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); ++ asection *plt = NULL; ++ ++ if (h->plt.offset != MINUS_ONE) ++ { ++ size_t i, plt_idx; ++ asection *gotplt, *relplt; ++ bfd_vma got_address; ++ uint32_t plt_entry[PLT_ENTRY_INSNS]; ++ bfd_byte *loc; ++ Elf_Internal_Rela rela; ++ ++ plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; ++ ++ /* one of '.plt' and '.iplt' represents */ ++ BFD_ASSERT (!!htab->elf.splt ^ !!htab->elf.iplt); ++ ++ 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; ++ relplt = htab->elf.srelplt; ++ 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; ++ 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. */ ++ loongarch_make_plt_entry ++ (got_address, sec_addr (plt) + h->plt.offset, plt_entry); ++ 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; ++ if (h->type == STT_GNU_IFUNC && SYMBOL_REFERENCES_LOCAL (info, h)) ++ { ++ 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; ++ } ++ 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->type == STT_GNU_IFUNC) ++ { ++ if (/* 加入这个条件的原因是,对于静态链接,IRELATIVE重定位类型在 ++ __libc_start_main中调用apply_irel,通过链接脚本提供的 ++ __rela_iplt_start和__rela_iplt_end遍历.rela.iplt中的动态重定位 ++ 表项,来调用各个resolver并将返回结果写入.igot.plt中。 ++ 问题是照顾不到.rela.iplt之外的IRELATIVE重定位,因此我们在静态 ++ 连接的情况下绝对不将IRELATIVE写入.igot.plt之外。这样做在运行时 ++ 可能会有一些性能影响,毕竟ifunc函数都走plt,需要load两次 ++ got entry。没什么好的解决方法,未来可以搞.iplt2用于延迟调用 ++ resolver。 */ ++ elf_hash_table (info)->dynamic_sections_created ++ ++ && 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 (plt); ++ rela.r_info = ++ ELFNN_R_INFO ++ (0, bfd_link_pic (info) ? R_LARCH_RELATIVE : R_LARCH_NONE); ++ rela.r_addend = plt->output_section->vma ++ + plt->output_offset ++ + h->plt.offset; ++ bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off); ++ } ++ } ++ else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) ++ { ++ BFD_ASSERT (h->got.offset & 1/* has been filled in addr */); ++ 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->got.offset & 1) == 0); ++ 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); ++ } ++ ++ if (h->needs_copy) ++ { ++ Elf_Internal_Rela rela; ++ asection *s; ++ ++ /* This symbols needs a copy reloc. Set it up. */ ++ BFD_ASSERT (h->dynindx != -1); ++ ++ rela.r_offset = sec_addr (h->root.u.def.section) + h->root.u.def.value; ++ rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_COPY); ++ rela.r_addend = 0; ++ if (h->root.u.def.section == htab->elf.sdynrelro) ++ s = htab->elf.sreldynrelro; ++ else ++ s = htab->elf.srelbss; ++ loongarch_elf_append_rela (output_bfd, s, &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; ++ 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; ++ } ++ ++ if ((plt = htab->elf.splt)) ++ gotplt = htab->elf.sgotplt; ++ else if ((plt = htab->elf.iplt)) ++ gotplt = htab->elf.igotplt; ++ ++ if (plt && 0 < plt->size) ++ { ++ size_t i; ++ uint32_t plt_header[PLT_HEADER_INSNS]; ++ loongarch_make_plt_header (sec_addr (gotplt), sec_addr (plt), plt_header); ++ 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); ++ ++ /* 第二项非0时动态连接器认为它是plt header的地址,从而影响到所有 ++ R_LARCH_JUMP_SLOT。这似乎是为了prelink预留的。 */ ++ 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, 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. ++ 一定要保证先完成非IFUNC重定位。因为如果IFUNC的resolover尚未完成 ++ 重定位,那么调用它返回的结果是错误的。非IFUNC重定位类型,比如R_LARCH_64 ++ 也可以携带IFUNC符号信息。我们在elf_machine_rela中可以察觉到一个符号是 ++ IFUNC,而在动态重定位时调用resolver。但八成这个resolver也需要一个 ++ R_LARCH_64重定位,可能还未完成,这时就会出问题。 ++ 在这里识别出来和STT_GNU_IFUNC相关的重定位,将他们往后排。 */ ++ 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 loongarch_elf_link_hash_entry *edir, *eind; ++ ++ edir = (struct loongarch_elf_link_hash_entry *) dir; ++ eind = (struct loongarch_elf_link_hash_entry *) 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) ++ { ++ edir->tls_type = eind->tls_type; ++ eind->tls_type = GOT_UNKNOWN; ++ } ++ _bfd_elf_link_hash_copy_indirect (info, dir, ind); ++} ++ ++//#if ARCH_SIZE == 32 ++//# define PRSTATUS_SIZE 0 /* FIXME */ ++//# define PRSTATUS_OFFSET_PR_CURSIG 0 ++//# define PRSTATUS_OFFSET_PR_PID 0 ++//# define PRSTATUS_OFFSET_PR_REG 0 ++//# define ELF_GREGSET_T_SIZE 264 ++//# define PRPSINFO_SIZE 0 ++//# define PRPSINFO_OFFSET_PR_PID 0 ++//# define PRPSINFO_OFFSET_PR_FNAME 0 ++//# define PRPSINFO_OFFSET_PR_PSARGS 0 ++//#else ++#define PRSTATUS_SIZE 384 ++#define PRSTATUS_OFFSET_PR_CURSIG 12 ++#define PRSTATUS_OFFSET_PR_PID 32 ++#define PRSTATUS_OFFSET_PR_REG 112 ++#define ELF_GREGSET_T_SIZE 264 ++ ++#define PRPSINFO_SIZE 144 ++#define PRPSINFO_OFFSET_PR_PID 32 ++#define PRPSINFO_OFFSET_PR_FNAME 48 ++#define PRPSINFO_OFFSET_PR_PSARGS 64 ++#define PRPSINFO_SIZE_PR_FNAMW 16 ++#define PRPSINFO_SIZE_PR_PSARGS 80 ++//#endif ++ ++/* 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; ++ ++ case PRSTATUS_SIZE: /* sizeof(struct elf_prstatus) on Linux/Loongarch. */ ++ /* 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); ++} ++ ++static bfd_boolean ++loongarch_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) ++{ ++ switch (note->descsz) ++ { ++ default: ++ return FALSE; ++ ++ case PRPSINFO_SIZE: /* sizeof(struct elf_prpsinfo) on Linux/Loongarch. */ ++ /* 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_OFFSET_PR_FNAME); ++ ++ /* pr_psargs */ ++ elf_tdata (abfd)->core->command = _bfd_elfcore_strndup ++ (abfd, note->descdata + PRPSINFO_OFFSET_PR_PSARGS, PRPSINFO_SIZE_PR_PSARGS); ++ 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); ++} ++ ++static bfd_boolean ++_loongarch_bfd_set_section_contents(bfd *abfd, ++ sec_ptr section, ++ const void *location, ++ file_ptr offset, ++ bfd_size_type conut) ++ ++{ ++ if (elf_elfheader(abfd)->e_flags ==0) ++ if(abfd->arch_info->arch == bfd_arch_loongarch) ++ if (abfd->arch_info->mach ==bfd_mach_loongarch32) ++ elf_elfheader(abfd)->e_flags = EF_LARCH_ABI_LP32; ++ else if (abfd->arch_info->mach ==bfd_mach_loongarch64) ++ elf_elfheader(abfd)->e_flags = EF_LARCH_ABI_LP64; ++ else ++ return FALSE; ++ return _bfd_elf_set_section_contents(abfd,section,location,offset,conut); ++} ++ ++ ++ ++#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 \ ++ _bfd_loongarch_elf_merge_private_bfd_data ++ ++#define bfd_elfNN_set_section_contents _loongarch_bfd_set_section_contents ++ ++ ++#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 ++ ++#include "elfNN-target.h" +diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c +new file mode 100644 +index 00000000..3f8534bf +--- /dev/null ++++ b/bfd/elfxx-loongarch.c +@@ -0,0 +1,172 @@ ++#include "sysdep.h" ++#include "bfd.h" ++#include "libbfd.h" ++#include "elf-bfd.h" ++#include "elf/loongarch.h" ++#include "elfxx-loongarch.h" ++ ++ ++ ++/* This does not include any relocation information, but should be ++ good enough for GDB or objdump to read the file. */ ++ ++static reloc_howto_type howto_table[] = ++{ ++#define LOONGARCH_HOWTO(r_name) HOWTO (R_LARCH_##r_name,0,3,32,FALSE,0,complain_overflow_signed,bfd_elf_generic_reloc,"R_LARCH_"#r_name,FALSE,0,0,FALSE) ++LOONGARCH_HOWTO (NONE), ++LOONGARCH_HOWTO (32), ++LOONGARCH_HOWTO (64), ++LOONGARCH_HOWTO (RELATIVE), ++LOONGARCH_HOWTO (COPY), ++LOONGARCH_HOWTO (JUMP_SLOT), ++LOONGARCH_HOWTO (TLS_DTPMOD32), ++LOONGARCH_HOWTO (TLS_DTPMOD64), ++LOONGARCH_HOWTO (TLS_DTPREL32), ++LOONGARCH_HOWTO (TLS_DTPREL64), ++LOONGARCH_HOWTO (TLS_TPREL32), ++LOONGARCH_HOWTO (TLS_TPREL64), ++LOONGARCH_HOWTO (IRELATIVE), ++ ++LOONGARCH_HOWTO (MARK_LA), ++LOONGARCH_HOWTO (MARK_PCREL), ++ HOWTO (R_LARCH_SOP_PUSH_PCREL, /* type */ ++ 2, /* rightshift */ ++ 3, /* 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 */ ++LOONGARCH_HOWTO (SOP_PUSH_ABSOLUTE), ++LOONGARCH_HOWTO (SOP_PUSH_DUP), ++LOONGARCH_HOWTO (SOP_PUSH_GPREL), ++LOONGARCH_HOWTO (SOP_PUSH_TLS_TPREL), ++LOONGARCH_HOWTO (SOP_PUSH_TLS_GOT), ++LOONGARCH_HOWTO (SOP_PUSH_TLS_GD), ++LOONGARCH_HOWTO (SOP_PUSH_PLT_PCREL), ++LOONGARCH_HOWTO (SOP_ASSERT), ++LOONGARCH_HOWTO (SOP_NOT), ++LOONGARCH_HOWTO (SOP_SUB), ++LOONGARCH_HOWTO (SOP_SL), ++LOONGARCH_HOWTO (SOP_SR), ++LOONGARCH_HOWTO (SOP_ADD), ++LOONGARCH_HOWTO (SOP_AND), ++LOONGARCH_HOWTO (SOP_IF_ELSE), ++LOONGARCH_HOWTO (SOP_POP_32_S_10_5), ++LOONGARCH_HOWTO (SOP_POP_32_U_10_12), ++LOONGARCH_HOWTO (SOP_POP_32_S_10_12), ++LOONGARCH_HOWTO (SOP_POP_32_S_10_16), ++LOONGARCH_HOWTO (SOP_POP_32_S_10_16_S2), ++LOONGARCH_HOWTO (SOP_POP_32_S_5_20), ++LOONGARCH_HOWTO (SOP_POP_32_S_0_5_10_16_S2), ++LOONGARCH_HOWTO (SOP_POP_32_S_0_10_10_16_S2), ++LOONGARCH_HOWTO (SOP_POP_32_U), ++LOONGARCH_HOWTO (ADD8), ++LOONGARCH_HOWTO (ADD16), ++LOONGARCH_HOWTO (ADD24), ++LOONGARCH_HOWTO (ADD32), ++LOONGARCH_HOWTO (ADD64), ++LOONGARCH_HOWTO (SUB8), ++LOONGARCH_HOWTO (SUB16), ++LOONGARCH_HOWTO (SUB24), ++LOONGARCH_HOWTO (SUB32), ++LOONGARCH_HOWTO (SUB64), ++}; ++ ++struct elf_reloc_map ++{ ++ bfd_reloc_code_real_type bfd_val; ++ enum elf_loongarch_reloc_type elf_val; ++}; ++ ++static const struct elf_reloc_map loong_reloc_map[] = ++{ ++ { BFD_RELOC_NONE, R_LARCH_NONE }, ++ { BFD_RELOC_32, R_LARCH_32 }, ++ { BFD_RELOC_64, R_LARCH_64 }, ++ ++#define LOONGARCH_reloc_map(r_name) {BFD_RELOC_LARCH_##r_name,R_LARCH_##r_name} ++LOONGARCH_reloc_map (TLS_DTPMOD32), ++LOONGARCH_reloc_map (TLS_DTPMOD64), ++LOONGARCH_reloc_map (TLS_DTPREL32), ++LOONGARCH_reloc_map (TLS_DTPREL64), ++LOONGARCH_reloc_map (TLS_TPREL32), ++LOONGARCH_reloc_map (TLS_TPREL64), ++ ++LOONGARCH_reloc_map (MARK_LA), ++LOONGARCH_reloc_map (MARK_PCREL), ++LOONGARCH_reloc_map (SOP_PUSH_PCREL), ++LOONGARCH_reloc_map (SOP_PUSH_ABSOLUTE), ++LOONGARCH_reloc_map (SOP_PUSH_DUP), ++LOONGARCH_reloc_map (SOP_PUSH_GPREL), ++LOONGARCH_reloc_map (SOP_PUSH_TLS_TPREL), ++LOONGARCH_reloc_map (SOP_PUSH_TLS_GOT), ++LOONGARCH_reloc_map (SOP_PUSH_TLS_GD), ++LOONGARCH_reloc_map (SOP_PUSH_PLT_PCREL), ++LOONGARCH_reloc_map (SOP_ASSERT), ++LOONGARCH_reloc_map (SOP_NOT), ++LOONGARCH_reloc_map (SOP_SUB), ++LOONGARCH_reloc_map (SOP_SL), ++LOONGARCH_reloc_map (SOP_SR), ++LOONGARCH_reloc_map (SOP_ADD), ++LOONGARCH_reloc_map (SOP_AND), ++LOONGARCH_reloc_map (SOP_IF_ELSE), ++LOONGARCH_reloc_map (SOP_POP_32_S_10_5), ++LOONGARCH_reloc_map (SOP_POP_32_U_10_12), ++LOONGARCH_reloc_map (SOP_POP_32_S_10_12), ++LOONGARCH_reloc_map (SOP_POP_32_S_10_16), ++LOONGARCH_reloc_map (SOP_POP_32_S_10_16_S2), ++LOONGARCH_reloc_map (SOP_POP_32_S_5_20), ++LOONGARCH_reloc_map (SOP_POP_32_S_0_5_10_16_S2), ++LOONGARCH_reloc_map (SOP_POP_32_S_0_10_10_16_S2), ++LOONGARCH_reloc_map (SOP_POP_32_U), ++LOONGARCH_reloc_map (ADD8), ++LOONGARCH_reloc_map (ADD16), ++LOONGARCH_reloc_map (ADD24), ++LOONGARCH_reloc_map (ADD32), ++LOONGARCH_reloc_map (ADD64), ++LOONGARCH_reloc_map (SUB8), ++LOONGARCH_reloc_map (SUB16), ++LOONGARCH_reloc_map (SUB24), ++LOONGARCH_reloc_map (SUB32), ++LOONGARCH_reloc_map (SUB64), ++}; ++ ++reloc_howto_type * ++loongarch_elf_rtype_to_howto (unsigned int r_type) ++{ ++ size_t i; ++ for (i = 0; i < ARRAY_SIZE (howto_table); i++) ++ if (howto_table[i].type == r_type) ++ return &howto_table[i]; ++ return NULL; ++} ++ ++reloc_howto_type * ++loongarch_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) ++{ ++ unsigned int i; ++ for (i = 0; i < ARRAY_SIZE (loong_reloc_map); i++) ++ if (loong_reloc_map[i].bfd_val == code) ++ return loongarch_elf_rtype_to_howto ((int) loong_reloc_map[i].elf_val); ++ // return &howto_table[(int) loong_reloc_map[i].elf_val]; ++ ++ return NULL; ++} ++ ++reloc_howto_type * ++loongarch_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) ++{ ++ unsigned int i; ++ ++ for (i = 0; i < ARRAY_SIZE (howto_table); i++) ++ if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0) ++ return &howto_table[i]; ++ ++ return NULL; ++} +diff --git a/bfd/elfxx-loongarch.h b/bfd/elfxx-loongarch.h +new file mode 100644 +index 00000000..0e980864 +--- /dev/null ++++ b/bfd/elfxx-loongarch.h +@@ -0,0 +1,11 @@ ++#include "elf/common.h" ++#include "elf/internal.h" ++ ++extern reloc_howto_type * ++loongarch_elf_rtype_to_howto (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); +diff --git a/bfd/libbfd.h b/bfd/libbfd.h +index bc5ce1a4..4b1d1c63 100644 +--- a/bfd/libbfd.h ++++ b/bfd/libbfd.h +@@ -3189,6 +3189,49 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", + "BFD_RELOC_WASM32_CODE_POINTER", + "BFD_RELOC_WASM32_INDEX", + "BFD_RELOC_WASM32_PLT_SIG", ++ "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", + "@@overflow: BFD_RELOC_UNUSED@@", + }; + #endif +diff --git a/bfd/reloc.c b/bfd/reloc.c +index 074223f5..6a923a61 100644 +--- a/bfd/reloc.c ++++ b/bfd/reloc.c +@@ -7939,6 +7939,95 @@ ENUMX + ENUMDOC + WebAssembly relocations. + ++ENUM ++ BFD_RELOC_LARCH_TLS_DTPMOD32 ++ENUMX ++ BFD_RELOC_LARCH_TLS_DTPREL32 ++ENUMX ++ BFD_RELOC_LARCH_TLS_DTPMOD64 ++ENUMX ++ BFD_RELOC_LARCH_TLS_DTPREL64 ++ENUMX ++ BFD_RELOC_LARCH_TLS_TPREL32 ++ENUMX ++ BFD_RELOC_LARCH_TLS_TPREL64 ++ENUMX ++ BFD_RELOC_LARCH_MARK_LA ++ENUMX ++ BFD_RELOC_LARCH_MARK_PCREL ++ENUMX ++ BFD_RELOC_LARCH_SOP_PUSH_PCREL ++ENUMX ++ BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE ++ENUMX ++ BFD_RELOC_LARCH_SOP_PUSH_DUP ++ENUMX ++ BFD_RELOC_LARCH_SOP_PUSH_GPREL ++ENUMX ++ BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL ++ENUMX ++ BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT ++ENUMX ++ BFD_RELOC_LARCH_SOP_PUSH_TLS_GD ++ENUMX ++ BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL ++ENUMX ++ BFD_RELOC_LARCH_SOP_ASSERT ++ENUMX ++ BFD_RELOC_LARCH_SOP_NOT ++ENUMX ++ BFD_RELOC_LARCH_SOP_SUB ++ENUMX ++ BFD_RELOC_LARCH_SOP_SL ++ENUMX ++ BFD_RELOC_LARCH_SOP_SR ++ENUMX ++ BFD_RELOC_LARCH_SOP_ADD ++ENUMX ++ BFD_RELOC_LARCH_SOP_AND ++ENUMX ++ BFD_RELOC_LARCH_SOP_IF_ELSE ++ENUMX ++ BFD_RELOC_LARCH_SOP_POP_32_S_10_5 ++ENUMX ++ BFD_RELOC_LARCH_SOP_POP_32_U_10_12 ++ENUMX ++ BFD_RELOC_LARCH_SOP_POP_32_S_10_12 ++ENUMX ++ BFD_RELOC_LARCH_SOP_POP_32_S_10_16 ++ENUMX ++ BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2 ++ENUMX ++ BFD_RELOC_LARCH_SOP_POP_32_S_5_20 ++ENUMX ++ BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2 ++ENUMX ++ BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2 ++ENUMX ++ BFD_RELOC_LARCH_SOP_POP_32_U ++ENUMX ++ BFD_RELOC_LARCH_ADD8 ++ENUMX ++ BFD_RELOC_LARCH_ADD16 ++ENUMX ++ BFD_RELOC_LARCH_ADD24 ++ENUMX ++ BFD_RELOC_LARCH_ADD32 ++ENUMX ++ BFD_RELOC_LARCH_ADD64 ++ENUMX ++ BFD_RELOC_LARCH_SUB8 ++ENUMX ++ BFD_RELOC_LARCH_SUB16 ++ENUMX ++ BFD_RELOC_LARCH_SUB24 ++ENUMX ++ BFD_RELOC_LARCH_SUB32 ++ENUMX ++ BFD_RELOC_LARCH_SUB64 ++ENUMDOC ++ LoongISA relocations. ++ + ENDSENUM + BFD_RELOC_UNUSED + CODE_FRAGMENT +diff --git a/bfd/targets.c b/bfd/targets.c +index 02c6de4f..ef678ee3 100644 +--- a/bfd/targets.c ++++ b/bfd/targets.c +@@ -710,6 +710,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_elf32_vec; ++extern const bfd_target loongarch_elf64_vec; + extern const bfd_target m32c_elf32_vec; + extern const bfd_target m32r_elf32_vec; + extern const bfd_target m32r_elf32_le_vec; +@@ -1166,6 +1168,11 @@ static const bfd_target * const _bfd_target_vector[] = + + &lm32_elf32_vec, + ++#ifdef BFD64 ++ &loongarch_elf32_vec, ++ &loongarch_elf64_vec, ++#endif ++ + &m32c_elf32_vec, + + &m32r_elf32_vec, +diff --git a/binutils/readelf.c b/binutils/readelf.c +index 212b9810..f3e989c8 100644 +--- a/binutils/readelf.c ++++ b/binutils/readelf.c +@@ -114,6 +114,7 @@ + #include "elf/ia64.h" + #include "elf/ip2k.h" + #include "elf/lm32.h" ++#include "elf/loongarch.h" + #include "elf/iq2000.h" + #include "elf/m32c.h" + #include "elf/m32r.h" +@@ -990,6 +991,7 @@ guess_is_rela (unsigned int e_machine) + case EM_MICROBLAZE: + case EM_MICROBLAZE_OLD: + case EM_WEBASSEMBLY: ++ case EM_LOONGARCH: + return TRUE; + + case EM_68HC05: +@@ -1701,6 +1703,10 @@ dump_relocations (Filedata * filedata, + else + rtype = elf_nfp_reloc_type (type); + break; ++ ++ case EM_LOONGARCH: ++ rtype = elf_loongarch_reloc_type (type); ++ break; + } + + if (rtype == NULL) +@@ -2643,6 +2649,7 @@ get_machine_name (unsigned e_machine) + case EM_CYGNUS_MEP: return "Toshiba MeP Media Engine"; + case EM_ADAPTEVA_EPIPHANY: return "Adapteva EPIPHANY"; + case EM_CYGNUS_FRV: return "Fujitsu FR-V"; ++ case EM_LOONGARCH: return "LoongArch"; + + default: + snprintf (buff, sizeof (buff), _(": 0x%x"), e_machine); +@@ -3850,6 +3857,16 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) + + if (e_flags & ~ EF_MSP430_MACH) + strcat (buf, _(": unknown extra flag bits also present")); ++ break; ++ ++ case EM_LOONGARCH: ++ switch (e_flags & EF_LARCH_ABI) ++ { ++ case EF_LARCH_ABI_LP64: strcat (buf, ", LP64"); break; ++ case EF_LARCH_ABI_XLP32: strcat (buf, ", XLP32"); break; ++ case EF_LARCH_ABI_LP32: strcat (buf, ", LP32"); break; ++ } ++ break; + } + } + +@@ -12502,6 +12519,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) + return reloc_type == 2; /* R_IQ2000_32. */ + case EM_LATTICEMICO32: + return reloc_type == 3; /* R_LM32_32. */ ++ case EM_LOONGARCH: ++ return reloc_type == 1; /* R_LARCH_32. */ + case EM_M32C_OLD: + case EM_M32C: + return reloc_type == 3; /* R_M32C_32. */ +@@ -12710,6 +12729,8 @@ is_64bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) + case EM_IA_64: + return (reloc_type == 0x26 /* R_IA64_DIR64MSB. */ + || reloc_type == 0x27 /* R_IA64_DIR64LSB. */); ++ case EM_LOONGARCH: ++ return reloc_type == 2; /* R_LARCH_64 */ + case EM_PARISC: + return reloc_type == 80; /* R_PARISC_DIR64. */ + case EM_PPC64: +@@ -13034,6 +13055,7 @@ is_none_reloc (Filedata * filedata, unsigned int reloc_type) + case EM_X86_64: /* R_X86_64_NONE. */ + case EM_XC16X: + case EM_WEBASSEMBLY: /* R_WASM32_NONE. */ ++ case EM_LOONGARCH: /* R_LARCH_NONE */ + return reloc_type == 0; + + case EM_AARCH64: +@@ -16852,6 +16874,14 @@ get_note_type (Filedata * filedata, unsigned e_type) + return _("NT_ARM_HW_BREAK (AArch hardware breakpoint registers)"); + case NT_ARM_HW_WATCH: + return _("NT_ARM_HW_WATCH (AArch hardware watchpoint registers)"); ++ case NT_LARCH_CPUCFG: ++ return _("NT_LARCH_CPUCFG (Loongarch CPU config registers)"); ++ case NT_LARCH_LBT: ++ return _("NT_LARCH_LBT (Loongarch Loongson Binary Translation registers)"); ++ case NT_LARCH_LSX: ++ return _("NT_LARCH_LSX (Loongarch Loongson SIMD Extension registers)"); ++ case NT_LARCH_LASX: ++ return _("NT_LARCH_LASX (Loongarch Loongson Advanced SIMD Extension registers)"); + case NT_PSTATUS: + return _("NT_PSTATUS (pstatus structure)"); + case NT_FPREGS: +diff --git a/binutils/testsuite/binutils-all/objdump.exp b/binutils/testsuite/binutils-all/objdump.exp +index f006d64f..9c07394f 100644 +--- a/binutils/testsuite/binutils-all/objdump.exp ++++ b/binutils/testsuite/binutils-all/objdump.exp +@@ -34,8 +34,8 @@ send_user "Version [binutil_version $OBJDUMP]" + set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -i"] + + set cpus_expected [list] +-lappend cpus_expected aarch64 alpha am33-2 arc ARC700 ARCv2 arm cris +-lappend cpus_expected d10v d30v fr30 fr500 fr550 h8 hppa i386 i860 i960 iamcu ip2022 ++lappend cpus_expected aarch64 alpha am33-2 arc ARC700 ARCv2 arm cris d10v d30v ++lappend cpus_expected fr30 fr500 fr550 h8 hppa i386 i860 i960 iamcu ip2022 Loongarch64 + lappend cpus_expected m16c m32c m32r m68hc11 m68hc12 m68k m88k MCore mep c5 h1 MicroBlaze + lappend cpus_expected mips mn10200 mn10300 ms1 msp MSP430 nds32 n1h_v3 ns32k + lappend cpus_expected or1k or1knd pj powerpc pyramid riscv romp rs6000 s390 sh sparc +diff --git a/gas/Makefile.am b/gas/Makefile.am +index 758f41dc..3ae74dab 100644 +--- a/gas/Makefile.am ++++ b/gas/Makefile.am +@@ -156,6 +156,7 @@ TARGET_CPU_CFILES = \ + config/tc-ip2k.c \ + config/tc-iq2000.c \ + config/tc-lm32.c \ ++ config/tc-loongarch.c \ + config/tc-m32c.c \ + config/tc-m32r.c \ + config/tc-m68hc11.c \ +@@ -233,6 +234,7 @@ TARGET_CPU_HFILES = \ + config/tc-ip2k.h \ + config/tc-iq2000.h \ + config/tc-lm32.h \ ++ config/tc-loongarch.h \ + config/tc-m32c.h \ + config/tc-m32r.h \ + config/tc-m68hc11.h \ +@@ -380,7 +382,8 @@ EXTRA_SCRIPTS = .gdbinit + EXTRA_DIST = m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c \ + bfin-parse.c bfin-parse.h bfin-lex.c \ + rl78-parse.c rl78-parse.h \ +- rx-parse.c rx-parse.h ++ rx-parse.c rx-parse.h \ ++ loongarch-parse.c loongarch-parse.h loongarch-lex.c + + diststuff: $(EXTRA_DIST) info + +@@ -521,6 +524,27 @@ rx-parse.h: rx-parse.c + rx-defs.h: ; @true + $(srcdir)/config/rx-defs.h: ; @true + ++EXTRA_as_new_SOURCES += config/loongarch-parse.y ++loongarch-parse.c: $(srcdir)/config/loongarch-parse.y ++ $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-parse.y y.tab.c loongarch-parse.c y.tab.h loongarch-parse.h -- $(YACCCOMPILE) -d ; ++loongarch-parse.h: loongarch-parse.c ++loongarch-parse.h: ; @true ++$(srcdir)/config/loongarch-parse.h: ; @true ++ ++loongarch-lex.c: $(srcdir)/config/loongarch-lex.l ++ $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-lex.l lex.yy.c loongarch-lex.c -- $(LEXCOMPILE) ++loongarch-lex-wrapper.@OBJEXT@: $(srcdir)/config/loongarch-lex-wrapper.c loongarch-lex.c loongarch-parse.h ++if am__fastdepCC ++ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $(srcdir)/config/loongarch-lex-wrapper.c $(NO_WERROR) ++ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po ++else ++if AMDEP ++ source='loongarch-lex-wrapper.c' object='$@' libtool=no @AMDEPBACKSLASH@ ++ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++endif ++ $(COMPILE) -c $(srcdir)/config/loongarch-lex-wrapper.c $(NO_WERROR) ++endif ++ + # The instruction table specification lexical analyzer and parser. + + # Disable -Werror, if it has been enabled, since old versions of bison/ +diff --git a/gas/Makefile.in b/gas/Makefile.in +index b55f2b88..d59a936a 100644 +--- a/gas/Makefile.in ++++ b/gas/Makefile.in +@@ -80,6 +80,7 @@ DIST_COMMON = NEWS README ChangeLog $(srcdir)/Makefile.in \ + $(srcdir)/../mkinstalldirs $(srcdir)/gdbinit.in \ + $(srcdir)/gdbinit.in $(top_srcdir)/po/Make-in m68k-parse.c \ + bfin-parse.c rl78-parse.c rx-parse.c itbl-parse.c itbl-lex.c \ ++ loongarch-parse.c loongarch-lex.c \ + $(srcdir)/../depcomp $(srcdir)/../ylwrap + ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 + am__aclocal_m4_deps = $(top_srcdir)/../bfd/acinclude.m4 \ +@@ -451,6 +452,7 @@ TARGET_CPU_CFILES = \ + config/tc-ip2k.c \ + config/tc-iq2000.c \ + config/tc-lm32.c \ ++ config/tc-loongarch.c \ + config/tc-m32c.c \ + config/tc-m32r.c \ + config/tc-m68hc11.c \ +@@ -528,6 +530,7 @@ TARGET_CPU_HFILES = \ + config/tc-ip2k.h \ + config/tc-iq2000.h \ + config/tc-lm32.h \ ++ config/tc-loongarch.h \ + config/tc-m32c.h \ + config/tc-m32r.h \ + config/tc-m68hc11.h \ +@@ -666,6 +669,7 @@ POTFILES = $(MULTI_CFILES) $(CONFIG_ATOF_CFILES) \ + noinst_SCRIPTS = $(GDBINIT) + EXTRA_SCRIPTS = .gdbinit + EXTRA_DIST = m68k-parse.c itbl-parse.c itbl-parse.h itbl-lex.c \ ++ loongarch-parse.c loongarch-parse.h loongarch-lex.c \ + bfin-parse.c bfin-parse.h bfin-lex.c \ + rl78-parse.c rl78-parse.h \ + rx-parse.c rx-parse.h +@@ -706,7 +710,7 @@ EXTRA_as_new_SOURCES = $(CFILES) $(HFILES) $(TARGET_CPU_CFILES) \ + $(TARGET_CPU_HFILES) $(OBJ_FORMAT_CFILES) $(OBJ_FORMAT_HFILES) \ + $(TARG_ENV_CFILES) $(CONFIG_ATOF_CFILES) $(MULTI_CFILES) \ + config/m68k-parse.y config/bfin-parse.y config/rl78-parse.y \ +- config/rx-parse.y ++ config/rx-parse.y config/loongarch-parse.y + EXPECT = expect + RUNTEST = runtest + RUNTESTFLAGS = +@@ -841,6 +845,8 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/itbl-parse.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/listing.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/literal.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loongarch-parse.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loongarch-lex.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/m68k-parse.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/macro.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/messages.Po@am__quote@ +@@ -888,6 +894,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-ip2k.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-iq2000.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-lm32.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-loongarch.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m32c.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m32r.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tc-m68hc11.Po@am__quote@ +@@ -1325,6 +1332,34 @@ tc-lm32.obj: config/tc-lm32.c + @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-lm32.obj `if test -f 'config/tc-lm32.c'; then $(CYGPATH_W) 'config/tc-lm32.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-lm32.c'; fi` + ++tc-loongarch.o: config/tc-loongarch.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-loongarch.o -MD -MP -MF $(DEPDIR)/tc-loongarch.Tpo -c -o tc-loongarch.o `test -f 'config/tc-loongarch.c' || echo '$(srcdir)/'`config/tc-loongarch.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-loongarch.Tpo $(DEPDIR)/tc-loongarch.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-loongarch.c' object='tc-loongarch.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-loongarch.o `test -f 'config/tc-loongarch.c' || echo '$(srcdir)/'`config/tc-loongarch.c ++ ++loongarch-parse.o: config/loongarch-parse.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT loongarch-parse.o -MD -MP -MF $(DEPDIR)/loongarch-parse.Tpo -c -o loongarch-parse.o `test -f 'config/loongarch-parse.c' || echo '$(srcdir)/'`config/loongarch-parse.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/loongarch-parse.Tpo $(DEPDIR)/loongarch-parse.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/loongarch-parse.c' object='loongarch-parse.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o loongarch-parse.o `test -f 'config/loongarch-parse.c' || echo '$(srcdir)/'`config/loongarch-parse.c ++ ++loongarch-lex.o: config/loongarch-lex.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT loongarch-lex.o -MD -MP -MF $(DEPDIR)/loongarch-lex.Tpo -c -o loongarch-lex.o `test -f 'config/loongarch-lex.c' || echo '$(srcdir)/'`config/loongarch-lex.c ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/loongarch-lex.Tpo $(DEPDIR)/loongarch-lex.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/loongarch-lex.c' object='loongarch-lex.o' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o loongarch-lex.o `test -f 'config/loongarch-lex.c' || echo '$(srcdir)/'`config/loongarch-lex.c ++ ++tc-loongarch.obj: config/tc-loongarch.c ++@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-loongarch.obj -MD -MP -MF $(DEPDIR)/tc-loongarch.Tpo -c -o tc-loongarch.obj `if test -f 'config/tc-loongarch.c'; then $(CYGPATH_W) 'config/tc-loongarch.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-loongarch.c'; fi` ++@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-loongarch.Tpo $(DEPDIR)/tc-loongarch.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/tc-loongarch.c' object='tc-loongarch.obj' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-loongarch.obj `if test -f 'config/tc-loongarch.c'; then $(CYGPATH_W) 'config/tc-loongarch.c'; else $(CYGPATH_W) '$(srcdir)/config/tc-loongarch.c'; fi` ++ + tc-m32c.o: config/tc-m32c.c + @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tc-m32c.o -MD -MP -MF $(DEPDIR)/tc-m32c.Tpo -c -o tc-m32c.o `test -f 'config/tc-m32c.c' || echo '$(srcdir)/'`config/tc-m32c.c + @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/tc-m32c.Tpo $(DEPDIR)/tc-m32c.Po +@@ -2485,6 +2520,8 @@ maintainer-clean-generic: + -rm -f bfin-parse.c + -rm -f itbl-lex.c + -rm -f itbl-parse.c ++ -rm -f loongarch-parse.c ++ -rm -f loongarch-lex.c + -rm -f m68k-parse.c + -rm -f rl78-parse.c + -rm -f rx-parse.c +@@ -2642,6 +2679,22 @@ m68k-parse.@OBJEXT@: m68k-parse.c + # Don't let the .y.h rule clobber m68k-parse.h. + m68k-parse.h: ; @true + $(srcdir)/config/m68k-parse.h: ; @true ++ ++loongarch-parse.c: $(srcdir)/config/loongarch-parse.y ++ $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-parse.y y.tab.c loongarch-parse.c y.tab.h loongarch-parse.h -- $(YACCCOMPILE) -d ; ++loongarch-parse.h: loongarch-parse.c ++loongarch-parse.h: ; @true ++$(srcdir)/config/loongarch-parse.h: ; @true ++ ++loongarch-lex.c: $(srcdir)/config/loongarch-lex.l ++ $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-lex.l lex.yy.c loongarch-lex.c -- $(LEXCOMPILE) ++loongarch-lex-wrapper.@OBJEXT@: $(srcdir)/config/loongarch-lex-wrapper.c loongarch-lex.c loongarch-parse.h ++@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $(srcdir)/config/loongarch-lex-wrapper.c $(NO_WERROR) ++@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='loongarch-lex-wrapper.c' object='$@' libtool=no @AMDEPBACKSLASH@ ++@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ ++@am__fastdepCC_FALSE@ $(COMPILE) -c $(srcdir)/config/loongarch-lex-wrapper.c $(NO_WERROR) ++ + bfin-parse.c: $(srcdir)/config/bfin-parse.y + $(SHELL) $(YLWRAP) $(srcdir)/config/bfin-parse.y y.tab.c bfin-parse.c y.tab.h bfin-parse.h -- $(YACCCOMPILE) -d ; + bfin-parse.h: bfin-parse.c +diff --git a/gas/config/loongarch-lex-wrapper.c b/gas/config/loongarch-lex-wrapper.c +new file mode 100644 +index 00000000..8ddf1dd2 +--- /dev/null ++++ b/gas/config/loongarch-lex-wrapper.c +@@ -0,0 +1,25 @@ ++/* Copyright (C) 2012-2018 Free Software Foundation, Inc. ++ ++ This file is part of GAS, the GNU Assembler. ++ ++ GAS 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. ++ ++ GAS 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 GAS; see the file COPYING. If not, write to the Free ++ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA ++ 02110-1301, USA. */ ++ ++/* The C source file generated by flex includes stdio.h before any of ++ the C code in bfin-lex.l. Make sure we include sysdep.h first, so ++ that config.h can set the correct values for various things. */ ++ ++#include "sysdep.h" ++#include "loongarch-lex.c" +diff --git a/gas/config/loongarch-lex.l b/gas/config/loongarch-lex.l +new file mode 100644 +index 00000000..d88fc93a +--- /dev/null ++++ b/gas/config/loongarch-lex.l +@@ -0,0 +1,39 @@ ++%option noyywrap ++%{ ++#include "as.h" ++#include "loongarch-parse.h" ++%} ++ ++D [0-9] ++/* We consider anything greater than \x7f to be a "letter" for UTF-8 ++ support. See the lex_type array in ../read.c. */ ++L [a-zA-Z_\.\$\x80-\xff] ++H [0-9A-Fa-f] ++ ++hex 0[xX]{H}+ ++oct 0[0-7]+ ++bin 0[bB][01]+ ++dec ([1-9]{D}*)|0 ++id ({D}+[fb])|({L}({D}|{L})*)|(:{dec}[bf]) ++ws [ \t\v\f]+ ++ ++%% ++ ++{dec} { yylval.imm = strtoull (yytext, 0, 0); return INTEGER; } ++{hex} { yylval.imm = strtoull (yytext + 2, 0, 16); return INTEGER; } ++{bin} { yylval.imm = strtoull (yytext + 2, 0, 2); return INTEGER; } ++{oct} { yylval.imm = strtoull (yytext + 1, 0, 8); return INTEGER; } ++{id} { yylval.c_str = strdup (yytext);return IDENTIFIER; } ++{ws} { } ++ ++">>" { return RIGHT_OP; } ++"<<" { return LEFT_OP; } ++"&&" { return AND_OP; } ++"||" { return OR_OP; } ++"<=" { return LE_OP; } ++">=" { return GE_OP; } ++"==" { return EQ_OP; } ++"!=" { return NE_OP; } ++. { return yytext[0];} ++ ++%% +diff --git a/gas/config/loongarch-parse.y b/gas/config/loongarch-parse.y +new file mode 100644 +index 00000000..aa7e51f5 +--- /dev/null ++++ b/gas/config/loongarch-parse.y +@@ -0,0 +1,420 @@ ++%{ ++#include "as.h" ++#include "loongarch-parse.h" ++void yyerror(const char *s) {} ++extern int yylex (void); ++extern void yy_scan_string (const char *); ++extern void ++get_internal_label (expressionS *label_expr, ++ unsigned long label, ++ int augend); ++ ++ ++static struct reloc_info *top, *end; ++ ++static expressionS const_0 = ++{ ++ .X_op = O_constant, ++ .X_add_number = 0 ++}; ++ ++static int ++is_const (struct reloc_info *info) ++{ ++ return info->type == BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE ++ && info->value.X_op == O_constant; ++} ++ ++int ++loongarch_parse_expr (const char *expr, ++ struct reloc_info *reloc_stack_top, ++ size_t max_reloc_num, ++ size_t *reloc_num, ++ offsetT *imm) ++{ ++ int ret; ++ top = reloc_stack_top; ++ end = top + max_reloc_num; ++ yy_scan_string (expr); ++ ret = yyparse (); ++ if (ret == 0) ++ { ++ if (is_const (top - 1)) ++ *imm = (--top)->value.X_add_number; ++ else ++ *imm = 0; ++ *reloc_num = top - reloc_stack_top; ++ } ++ return ret; ++} ++ ++static void ++emit_const (offsetT imm) ++{ ++ if (end <= top) ++ as_fatal (_("expr too huge")); ++ top->type = BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE; ++ top->value.X_op = O_constant; ++ top->value.X_add_number = imm; ++ top++; ++} ++ ++static const char * ++my_getExpression (expressionS *ep, const char *str) ++{ ++ char *save_in, *ret; ++ if (*str == ':') ++ { ++ unsigned long j; ++ char *str_1 = (char *) str; ++ str_1++; ++ j = strtol (str_1, &str_1, 10); ++ get_internal_label (ep, j, *str_1 == 'f'); ++ return NULL; ++ } ++ save_in = input_line_pointer; ++ input_line_pointer = (char *)str; ++ expression (ep); ++ ret = input_line_pointer; ++ input_line_pointer = save_in; ++ return ret; ++} ++ ++static void ++reloc (const char *op_c_str, const char *id_c_str, offsetT addend) ++{ ++ expressionS id_sym_expr; ++ ++ if (end <= top) ++ as_fatal (_("expr too huge")); ++ ++ if (id_c_str) ++ { ++ my_getExpression (&id_sym_expr, id_c_str); ++ id_sym_expr.X_add_number += addend; ++ } ++ else ++ { ++ id_sym_expr.X_op = O_constant; ++ id_sym_expr.X_add_number = addend; ++ } ++ ++ if (strcmp (op_c_str, "abs") == 0) ++ { ++ top->value = id_sym_expr; ++ top->type = BFD_RELOC_LARCH_SOP_PUSH_ABSOLUTE; ++ top++; ++ } ++ else if (strcmp (op_c_str, "pcrel") == 0) ++ { ++ top->value = id_sym_expr; ++ top->type = BFD_RELOC_LARCH_SOP_PUSH_PCREL; ++ top++; ++ } ++ else if (strcmp (op_c_str, "gprel") == 0) ++ { ++ top->value = id_sym_expr; ++ top->type = BFD_RELOC_LARCH_SOP_PUSH_GPREL; ++ top++; ++ } ++ else if (strcmp (op_c_str, "tprel") == 0) ++ { ++ top->value = id_sym_expr; ++ top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL; ++ top++; ++ } ++ else if (strcmp (op_c_str, "tlsgot") == 0) ++ { ++ top->value = id_sym_expr; ++ top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT; ++ top++; ++ } ++ else if (strcmp (op_c_str, "tlsgd") == 0) ++ { ++ top->value = id_sym_expr; ++ top->type = BFD_RELOC_LARCH_SOP_PUSH_TLS_GD; ++ top++; ++ } ++ else if (strcmp (op_c_str, "plt") == 0) ++ { ++ top->value = id_sym_expr; ++ top->type = BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL; ++ top++; ++ } ++ else ++ as_fatal (_("unknown reloc hint: %s"), op_c_str); ++} ++ ++static void ++emit_unary (char op) ++{ ++ struct reloc_info *s_top = top - 1; ++ if (is_const (s_top)) ++ { ++ offsetT opr = s_top->value.X_add_number; ++ switch (op) ++ { ++ case '+': ++ break; ++ case '-': ++ opr = -opr; ++ break; ++ case '~': ++ opr = ~opr; ++ break; ++ case '!': ++ opr = !opr; ++ break; ++ default: ++ abort (); ++ } ++ s_top->value.X_add_number = opr; ++ } ++ else ++ { ++ if (end <= top) ++ as_fatal (_("expr too huge")); ++ switch (op) ++ { ++ case '!': ++ top->type = BFD_RELOC_LARCH_SOP_NOT; ++ default: ++ abort (); ++ } ++ top->value = const_0; ++ top++; ++ } ++} ++ ++static void ++emit_bin (int op) ++{ ++ struct reloc_info *last_1st = top - 1, *last_2nd = top - 2; ++ if (is_const (last_1st) && is_const (last_2nd)) ++ { ++ offsetT opr1 = last_2nd->value.X_add_number; ++ offsetT opr2 = last_1st->value.X_add_number; ++ switch (op) ++ { ++ case '*': ++ opr1 = opr1 * opr2; ++ break; ++ case '/': ++ opr1 = opr1 / opr2; ++ break; ++ case '%': ++ opr1 = opr1 % opr2; ++ break; ++ case '+': ++ opr1 = opr1 + opr2; ++ break; ++ case '-': ++ opr1 = opr1 - opr2; ++ break; ++ case LEFT_OP: ++ opr1 = opr1 << opr2; ++ break; ++ case RIGHT_OP: ++ /* Algorithm right shift */ ++ opr1 = (offsetT)opr1 >> (offsetT)opr2; ++ break; ++ case '<': ++ opr1 = opr1 < opr2; ++ break; ++ case '>': ++ opr1 = opr1 > opr2; ++ break; ++ case LE_OP: ++ opr1 = opr1 <= opr2; ++ break; ++ case GE_OP: ++ opr1 = opr1 >= opr2; ++ break; ++ case EQ_OP: ++ opr1 = opr1 == opr2; ++ break; ++ case NE_OP: ++ opr1 = opr1 != opr2; ++ break; ++ case '&': ++ opr1 = opr1 & opr2; ++ break; ++ case '^': ++ opr1 = opr1 ^ opr2; ++ break; ++ case '|': ++ opr1 = opr1 | opr2; ++ break; ++ case AND_OP: ++ opr1 = opr1 && opr2; ++ break; ++ case OR_OP: ++ opr1 = opr1 || opr2; ++ break; ++ default: ++ abort (); ++ } ++ last_2nd->value.X_add_number = opr1; ++ last_1st->type = 0; ++ top--; ++ } ++ else ++ { ++ if (end <= top) ++ as_fatal (_("expr too huge")); ++ switch (op) ++ { ++ case '+': ++ top->type = BFD_RELOC_LARCH_SOP_ADD; ++ break; ++ case '-': ++ top->type = BFD_RELOC_LARCH_SOP_SUB; ++ break; ++ case LEFT_OP: ++ top->type = BFD_RELOC_LARCH_SOP_SL; ++ break; ++ case RIGHT_OP: ++ top->type = BFD_RELOC_LARCH_SOP_SR; ++ break; ++ case '&': ++ top->type = BFD_RELOC_LARCH_SOP_AND; ++ break; ++ default: ++ abort (); ++ } ++ top->value = const_0; ++ top++; ++ } ++} ++ ++static void ++emit_if_else (void) ++{ ++ struct reloc_info *last_1st = top - 1; ++ struct reloc_info *last_2nd = top - 2; ++ struct reloc_info *last_3rd = top - 3; ++ if (is_const (last_1st) && is_const (last_2nd) && is_const (last_3rd)) ++ { ++ offsetT opr1 = last_3rd->value.X_add_number; ++ offsetT opr2 = last_2nd->value.X_add_number; ++ offsetT opr3 = last_1st->value.X_add_number; ++ opr1 = opr1 ? opr2 : opr3; ++ last_3rd->value.X_add_number = opr1; ++ last_2nd->type = 0; ++ last_1st->type = 0; ++ top -= 2; ++ } ++ else ++ { ++ if (end <= top) ++ as_fatal (_("expr too huge")); ++ top->type = BFD_RELOC_LARCH_SOP_IF_ELSE; ++ top->value = const_0; ++ top++; ++ } ++} ++ ++%} ++ ++%union { ++char *c_str; ++offsetT imm; ++} ++ ++%token INTEGER ++%token IDENTIFIER ++%type addend ++ ++%token LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP AND_OP OR_OP ++%start expression ++%% ++ ++primary_expression ++ : INTEGER {emit_const ($1);} ++ | '(' expression ')' ++ | '%' IDENTIFIER '(' IDENTIFIER addend ')' {reloc ($2, $4, $5); free ($2); free ($4);} ++ | '%' IDENTIFIER '(' INTEGER addend ')' {reloc ($2, NULL, $4 + $5); free ($2);} ++ ; ++ ++addend ++ : addend '-' INTEGER {$$ -= $3;} ++ | addend '+' INTEGER {$$ += $3;} ++ | {$$ = 0;} ++ ; ++ ++unary_expression ++ : primary_expression ++ | '+' unary_expression {emit_unary ('+');} ++ | '-' unary_expression {emit_unary ('-');} ++ | '~' unary_expression {emit_unary ('~');} ++ | '!' unary_expression {emit_unary ('!');} ++ ; ++ ++multiplicative_expression ++ : unary_expression ++ | multiplicative_expression '*' unary_expression {emit_bin ('*');} ++ | multiplicative_expression '/' unary_expression {emit_bin ('/');} ++ | multiplicative_expression '%' unary_expression {emit_bin ('%');} ++ ; ++ ++additive_expression ++ : multiplicative_expression ++ | additive_expression '+' multiplicative_expression {emit_bin ('+');} ++ | additive_expression '-' multiplicative_expression {emit_bin ('-');} ++ ; ++ ++shift_expression ++ : additive_expression ++ | shift_expression LEFT_OP additive_expression {emit_bin (LEFT_OP);} ++ | shift_expression RIGHT_OP additive_expression {emit_bin (RIGHT_OP);} ++ ; ++ ++relational_expression ++ : shift_expression ++ | relational_expression '<' shift_expression {emit_bin ('<');} ++ | relational_expression '>' shift_expression {emit_bin ('>');} ++ | relational_expression LE_OP shift_expression {emit_bin (LE_OP);} ++ | relational_expression GE_OP shift_expression {emit_bin (GE_OP);} ++ ; ++ ++equality_expression ++ : relational_expression ++ | equality_expression EQ_OP relational_expression {emit_bin (EQ_OP);} ++ | equality_expression NE_OP relational_expression {emit_bin (NE_OP);} ++ ; ++ ++and_expression ++ : equality_expression ++ | and_expression '&' equality_expression {emit_bin ('&');} ++ ; ++ ++exclusive_or_expression ++ : and_expression ++ | exclusive_or_expression '^' and_expression {emit_bin ('^');} ++ ; ++ ++inclusive_or_expression ++ : exclusive_or_expression ++ | inclusive_or_expression '|' exclusive_or_expression {emit_bin ('|');} ++ ; ++ ++logical_and_expression ++ : inclusive_or_expression ++ | logical_and_expression AND_OP inclusive_or_expression {emit_bin (AND_OP);} ++ ; ++ ++logical_or_expression ++ : logical_and_expression ++ | logical_or_expression OR_OP logical_and_expression {emit_bin (OR_OP);} ++ ; ++ ++conditional_expression ++ : logical_or_expression ++ | logical_or_expression '?' expression ':' conditional_expression {emit_if_else ();} ++ ; ++ ++expression ++ : conditional_expression ++ ; ++%% ++ +diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c +new file mode 100644 +index 00000000..9c4a9102 +--- /dev/null ++++ b/gas/config/tc-loongarch.c +@@ -0,0 +1,1328 @@ ++#include "as.h" ++#include "dw2gencfi.h" ++#include "tc-loongarch.h" ++#include "elf/loongarch.h" ++#include "opcode/loongarch.h" ++#include "obj-elf.h" ++#include ++#include ++#include ++#include ++ ++/* All information about an instruction during assemble */ ++struct loongarch_cl_insn ++{ ++ /* First split string */ ++ const char *name; ++ const char *arg_strs[MAX_ARG_NUM_PLUS_2]; ++ size_t arg_num; ++ ++ /* Second analyze name_str and each actual args string to match the insn ++ in 'loongarch-opc.c'. And actual args may need be relocated. ++ We get length of insn. If 'insn_length == 0 && insn_mo->macro != NULL', ++ it's a macro insntruction and we call 'md_assemble' recursively ++ after expanding it. */ ++ int match_now; ++ int all_match; ++ ++ const struct loongarch_opcode *insn; ++ size_t insn_length; ++ ++ offsetT args[MAX_ARG_NUM_PLUS_2]; ++ struct reloc_info reloc_info[MAX_RELOC_NUMBER_A_INSN]; ++ size_t reloc_num; ++ ++ /* For relax reserved. We not support relax now. ++ 'insn_length < relax_max_length' means need to relax. ++ And 'insn_length == relax_max_length' means no need to relax. */ ++ size_t relax_max_length; ++ relax_substateT subtype; ++ ++ /* Then we get the binary representation of insn ++ and write it in to section. */ ++ insn_t insn_bin; ++ ++ /* The frag that contains the instruction. */ ++ struct frag *frag; ++ /* The offset into FRAG of the first instruction byte. */ ++ long where; ++ /* The relocs associated with the instruction, if any. */ ++ fixS *fixp[MAX_RELOC_NUMBER_A_INSN]; ++}; ++ ++/* This array holds the chars that always start a comment. If the ++ pre-processor is disabled, these aren't very useful */ ++const char comment_chars[] = "#"; ++ ++/* This array holds the chars that only start a comment at the beginning of ++ a line. If the line seems to have the form '# 123 filename' ++ .line and .file directives will appear in the pre-processed output */ ++/* Note that input_file.c hand checks for '#' at the beginning of the ++ first line of the input file. This is because the compiler outputs ++#NO_APP at the beginning of its output. */ ++/* Also note that C style comments are always supported. */ ++const char line_comment_chars[] = "#"; ++ ++/* This array holds machine specific line separator characters. */ ++const char line_separator_chars[] = ";"; ++ ++/* Chars that can be used to separate mant from exp in floating point nums */ ++const char EXP_CHARS[] = "eE"; ++ ++/* Chars that mean this number is a floating point constant */ ++/* As in 0f12.456 */ ++/* or 0d1.2345e12 */ ++const char FLT_CHARS[] = "rRsSfFdDxXpP"; ++ ++const char *md_shortopts = "O::g::G:"; ++ ++enum options ++{ ++ OPTION_IGNORE = OPTION_MD_BASE, ++ ++ OPTION_SOFT_FLOAT, ++ OPTION_HARD_FLOAT, ++ OPTION_ABI, ++ ++ OPTION_LA_LOCAL_WITH_ABS, ++ OPTION_LA_GLOBAL_WITH_PCREL, ++ OPTION_LA_GLOBAL_WITH_ABS, ++ ++ OPTION_END_OF_ENUM, ++}; ++ ++struct option md_longopts[] = ++{ ++ {"msoft-float", no_argument, NULL, OPTION_SOFT_FLOAT}, ++ {"mhard-float", no_argument, NULL, OPTION_HARD_FLOAT}, ++ {"mabi", required_argument, NULL, OPTION_ABI}, ++ ++ {"mla-local-with-abs", no_argument, NULL, OPTION_LA_LOCAL_WITH_ABS}, ++ {"mla-global-with-pcrel", no_argument, NULL, OPTION_LA_GLOBAL_WITH_PCREL}, ++ {"mla-global-with-abs", no_argument, NULL, OPTION_LA_GLOBAL_WITH_ABS}, ++ ++ {NULL, no_argument, NULL, 0} ++}; ++ ++size_t md_longopts_size = sizeof (md_longopts); ++ ++int ++md_parse_option (int c, const char *arg) ++{ ++ int ret = 1; ++ switch (c) ++ { ++ case OPTION_SOFT_FLOAT: ++ LARCH_opts.ase_float = 0; ++ break; ++ case OPTION_HARD_FLOAT: ++ LARCH_opts.ase_float = 1; ++ break; ++ case OPTION_ABI: ++ if (strcasecmp (arg, "lp64") == 0) ++ LARCH_opts.abi_is_lp64 = 1; ++ else if (strcasecmp (arg, "lp32") == 0) ++ LARCH_opts.abi_is_lp32 = 1; ++ else ++ ret = 0; ++ break; ++ case OPTION_LA_LOCAL_WITH_ABS: ++ LARCH_opts.la_local_with_abs = 1; ++ break; ++ case OPTION_LA_GLOBAL_WITH_PCREL: ++ LARCH_opts.la_global_with_pcrel = 1; ++ break; ++ case OPTION_LA_GLOBAL_WITH_ABS: ++ LARCH_opts.la_global_with_abs = 1; ++ break; ++ case OPTION_IGNORE: ++ break; ++ } ++ return ret; ++} ++ ++static struct hash_control *r_htab = NULL; ++static struct hash_control *f_htab = NULL; ++static struct hash_control *c_htab = NULL; ++static struct hash_control *cr_htab = NULL; ++static struct hash_control *v_htab = NULL; ++static struct hash_control *x_htab = NULL; ++ ++void ++loongarch_after_parse_args () ++{ ++ size_t i; ++ ++ LARCH_opts.ase_test = 1; ++ LARCH_opts.ase_fix = 1; ++ LARCH_opts.ase_float = 1; ++ LARCH_opts.ase_128vec = 1; ++ LARCH_opts.ase_256vec = 1; ++ ++ if (!r_htab) ++ r_htab = hash_new (), hash_insert (r_htab, "", 0); ++ if (!f_htab) ++ f_htab = hash_new (), hash_insert (f_htab, "", 0); ++ if (!c_htab) ++ c_htab = hash_new (), hash_insert (c_htab, "", 0); ++ if (!cr_htab) ++ cr_htab = hash_new (), hash_insert (cr_htab, "", 0); ++ if (!v_htab) ++ v_htab = hash_new (), hash_insert (v_htab, "", 0); ++ if (!x_htab) ++ x_htab = hash_new (), hash_insert (x_htab, "", 0); ++ ++ for (i = 0; i < ARRAY_SIZE (loongarch_r_normal_name); i++) ++ hash_insert (r_htab, loongarch_r_normal_name[i], (void *) (i + 1)); ++ for (i = 0; i < ARRAY_SIZE (loongarch_f_normal_name); i++) ++ hash_insert (f_htab, loongarch_f_normal_name[i], (void *) (i + 1)); ++ for (i = 0; i < ARRAY_SIZE (loongarch_c_normal_name); i++) ++ hash_insert (c_htab, loongarch_c_normal_name[i], (void *) (i + 1)); ++ for (i = 0; i < ARRAY_SIZE (loongarch_cr_normal_name); i++) ++ hash_insert (cr_htab, loongarch_cr_normal_name[i], (void *) (i + 1)); ++ for (i = 0; i < ARRAY_SIZE (loongarch_v_normal_name); i++) ++ hash_insert (v_htab, loongarch_v_normal_name[i], (void *) (i + 1)); ++ for (i = 0; i < ARRAY_SIZE (loongarch_x_normal_name); i++) ++ hash_insert (x_htab, loongarch_x_normal_name[i], (void *) (i + 1)); ++ ++ if (LARCH_opts.abi_is_lp64 ++ + LARCH_opts.abi_is_lp32 ++ == 0) ++ { ++ // as_warn (_("default LoongISA ABI is lp64")); ++ LARCH_opts.abi_is_lp64 = 1; ++ } ++ ++ if (1 < LARCH_opts.abi_is_lp64 ++ + LARCH_opts.abi_is_lp32) ++ as_fatal (_("we can specify only ONE abi")); ++ ++ if (LARCH_opts.abi_is_lp64) ++ { ++ LARCH_opts.addrwidth_is_64 = 1; ++ LARCH_opts.rlen_is_64 = 1; ++ for (i = 0; i < ARRAY_SIZE (loongarch_r_lp64_name); i++) ++ hash_insert (r_htab, loongarch_r_lp64_name[i], (void *) (i + 1)); ++ for (i = 0; i < ARRAY_SIZE (loongarch_r_lp64_name1); i++) ++ hash_insert (r_htab, loongarch_r_lp64_name1[i], (void *) (i + 1)); ++ for (i = 0; i < ARRAY_SIZE (loongarch_f_lp64_name); i++) ++ hash_insert (f_htab, loongarch_f_lp64_name[i], (void *) (i + 1)); ++ for (i = 0; i < ARRAY_SIZE (loongarch_f_lp64_name1); i++) ++ hash_insert (f_htab, loongarch_f_lp64_name1[i], (void *) (i + 1)); ++ } ++ ++ if (LARCH_opts.abi_is_lp32) ++ { ++ LARCH_opts.addrwidth_is_32 = 1; ++ LARCH_opts.rlen_is_32 = 1; ++ } ++ ++} ++ ++const char * ++loongarch_target_format () ++{ ++ return LARCH_opts.addrwidth_is_32? "elf32-loongarch" : "elf64-loongarch"; ++} ++ ++void ++md_begin () ++{ ++ if (LARCH_opts.ase_test) ++ { ++ const struct loongarch_opcode *it; ++ struct loongarch_ase *ase; ++ for (ase = loongarch_ASEs; ase->enabled; ase++) ++ for (it = ase->opcodes; it->name; it++) ++ { ++ if (loongarch_check_format (it->format) != 0) ++ as_fatal (_("insn name: %s\tformat: %s\tsyntax error"), ++ it->name, it->format); ++ if (it->mask == 0 && it->macro == 0) ++ as_fatal (_("insn name: %s\nformat: %s\nwe want macro but macro is NULL"), ++ it->name, it->format); ++ if (it->macro && loongarch_check_macro (it->format, it->macro) != 0) ++ as_fatal (_("insn name: %s\nformat: %s\nmacro: %s\tsyntax error"), ++ it->name, it->format, it->macro); ++ } ++ } ++ ++ /* FIXME: expressionS use 'offsetT' as constant, we want this is 64-bit type */ ++ assert (8 <= sizeof (offsetT)); ++} ++ ++void ++md_operand (expressionS *e) ++{ ++ /* Because we use 'expression' to check if a actual arg is a expr at first. ++ If not, we want a returning. */ ++ if (e->X_op == O_absent) ++ e->X_op = O_illegal; ++} ++ ++static const expressionS const_0 = {.X_op = O_constant, .X_add_number = 0}; ++ ++static const char * ++my_getExpression (expressionS *ep, const char *str) ++{ ++ char *save_in, *ret; ++ save_in = input_line_pointer; ++ input_line_pointer = (char *)str; ++ expression (ep); ++ ret = input_line_pointer; ++ input_line_pointer = save_in; ++ return ret; ++} ++ ++ ++/* for compitable with MIPS pesudo insn like '.set reorder' ++ but actually ignore them. */ ++static void ++s_loongarch_set (int x ATTRIBUTE_UNUSED) ++{ ++ char *name = input_line_pointer, ch; ++ ++ while (!is_end_of_line[(unsigned char) *input_line_pointer]) ++ ++input_line_pointer; ++ ch = *input_line_pointer; ++ *input_line_pointer = '\0'; ++ ++ if (strchr (name, ',')) ++ { ++ /* Generic ".set" directive; use the generic handler. */ ++ *input_line_pointer = ch; ++ input_line_pointer = name; ++ s_set (0); ++ return; ++ } ++ ++ *input_line_pointer = ch; ++ demand_empty_rest_of_line (); ++} ++ ++static void ++s_loongarch_align (int arg) ++{ ++ const char *t = input_line_pointer; ++ while (!is_end_of_line[(unsigned char) *t] && *t != ',') ++ ++t; ++ if (*t == ',') ++ s_align_ptwo (arg); ++ else ++ s_align_ptwo (0); ++} ++ ++/* Handle the .dtprelword and .dtpreldword pseudo-ops. They generate ++ a 32-bit or 64-bit DTP-relative relocation (BYTES says which) for ++ use in DWARF debug information. */ ++ ++static void ++s_dtprel (int bytes) ++{ ++ expressionS ex; ++ char *p; ++ ++ expression (&ex); ++ ++ if (ex.X_op != O_symbol) ++ { ++ as_bad (_("Unsupported use of %s"), (bytes == 8 ++ ? ".dtpreldword" ++ : ".dtprelword")); ++ ignore_rest_of_line (); ++ } ++ ++ p = frag_more (bytes); ++ md_number_to_chars (p, 0, bytes); ++ fix_new_exp (frag_now, p - frag_now->fr_literal, bytes, &ex, FALSE, ++ (bytes == 8 ++ ? BFD_RELOC_LARCH_TLS_DTPREL64 ++ : BFD_RELOC_LARCH_TLS_DTPREL32)); ++ ++ demand_empty_rest_of_line (); ++} ++ ++static const pseudo_typeS loongarch_pseudo_table[] = ++{ ++ {"align", s_loongarch_align, -4}, ++ {"dword", cons, 8}, ++ {"word", cons, 4}, ++ {"half", cons, 2}, ++ {"dtprelword", s_dtprel, 4}, ++ {"dtpreldword", s_dtprel, 8}, ++ { NULL, NULL, 0 }, ++}; ++ ++void ++loongarch_pop_insert (void) ++{ ++ pop_insert (loongarch_pseudo_table); ++} ++ ++ ++#define INTERNAL_LABEL_SPECIAL 10 ++static unsigned long internal_label_count[INTERNAL_LABEL_SPECIAL] = {0}; ++ ++static const char * ++loongarch_internal_label_name (unsigned long label, int augend) ++{ ++ static char symbol_name_build[24]; ++ unsigned long want_label; ++ char *p; ++ ++ want_label = internal_label_count[label] + augend; ++ ++ p = symbol_name_build; ++#ifdef LOCAL_LABEL_PREFIX ++ *p++ = LOCAL_LABEL_PREFIX; ++#endif ++ *p++ = 'L'; ++ for (; label; label /= 10) ++ *p++ = label % 10 + '0'; ++ /* make sure internal label never belong to normal label namespace */ ++ *p++ = ':'; ++ for (; want_label; want_label /= 10) ++ *p++ = want_label % 10 + '0'; ++ *p++ = '\0'; ++ return symbol_name_build; ++} ++ ++static void ++setup_internal_label_here (unsigned long label) ++{ ++ assert (label < INTERNAL_LABEL_SPECIAL); ++ internal_label_count[label]++; ++ colon (loongarch_internal_label_name (label ,0)); ++} ++ ++extern void /* no static. used by 'loongarch-parse.y' */ ++get_internal_label (expressionS *label_expr, ++ unsigned long label, ++ int augend/* 0 for previous, 1 for next */); ++ ++void ++get_internal_label (expressionS *label_expr, ++ unsigned long label, ++ int augend/* 0 for previous, 1 for next */) ++{ ++ assert (label < INTERNAL_LABEL_SPECIAL); ++ if (augend == 0 && internal_label_count[label] == 0) ++ as_fatal (_("internal error: we have no internal label yet")); ++ label_expr->X_op = O_symbol; ++ label_expr->X_add_symbol = ++ symbol_find_or_make (loongarch_internal_label_name (label, augend)); ++ label_expr->X_add_number = 0; ++} ++ ++extern int loongarch_parse_expr (const char *expr, ++ struct reloc_info *reloc_stack_top, ++ size_t max_reloc_num, size_t *reloc_num, ++ offsetT *imm_if_no_reloc); ++ ++int ++is_internal_label (const char *c_str) ++{ ++ do ++ { ++ if (*c_str != ':') ++ break; ++ c_str++; ++ if (!('0' <= *c_str && *c_str <= '9')) ++ break; ++ while ('0' <= *c_str && *c_str <= '9') ++ c_str++; ++ if (*c_str != 'b' && *c_str != 'f') ++ break; ++ c_str++; ++ return *c_str == '\0'; ++ } ++ while (0); ++ return 0; ++} ++ ++int ++is_label (const char *c_str) ++{ ++ if (is_internal_label (c_str)) ++ return 1; ++ else if ('0' <= *c_str && *c_str <= '9') ++ { ++ /* [0-9]+[bf] */ ++ while ('0' <= *c_str && *c_str <= '9') ++ c_str++; ++ return *c_str == 'b' || *c_str == 'f'; ++ } ++ else if (is_name_beginner (*c_str)) ++ { ++ /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */ ++ c_str++; ++ while (is_part_of_name (*c_str)) ++ c_str++; ++ return *c_str == '\0'; ++ } ++ else ++ return 0; ++} ++ ++int ++is_label_with_addend (const char *c_str) ++{ ++ if (is_internal_label (c_str)) ++ return 1; ++ else if ('0' <= *c_str && *c_str <= '9') ++ { ++ /* [0-9]+[bf] */ ++ while ('0' <= *c_str && *c_str <= '9') ++ c_str++; ++ if (*c_str == 'b' || *c_str == 'f') ++ c_str++; ++ else ++ return 0; ++ return *c_str == '\0' ++ || ((*c_str == '-' || *c_str == '+') ++ && is_unsigned (c_str + 1)); ++ } ++ else if (is_name_beginner (*c_str)) ++ { ++ /* [a-zA-Z\._\$][0-9a-zA-Z\._\$]* */ ++ c_str++; ++ while (is_part_of_name (*c_str)) ++ c_str++; ++ return *c_str == '\0' ++ || ((*c_str == '-' || *c_str == '+') ++ && is_unsigned (c_str + 1)); ++ } ++ else ++ return 0; ++} ++ ++extern int ++loongarch_parse_expr (const char *expr, ++ struct reloc_info *reloc_stack_top, ++ size_t max_reloc_num, ++ size_t *reloc_num, ++ offsetT *imm_if_no_reloc); ++ ++static int32_t ++loongarch_args_parser_can_match_arg_helper (char esc_ch1, ++ char esc_ch2, ++ const char *bit_field, ++ const char *arg, ++ void *context) ++{ ++ struct loongarch_cl_insn *ip = context; ++ offsetT imm, ret = 0; ++ size_t reloc_num_we_have = MAX_RELOC_NUMBER_A_INSN - ip->reloc_num; ++ size_t reloc_num = 0; ++ ++ if (!ip->match_now) ++ return 0; ++ ++ switch (esc_ch1) ++ { ++ case 'l': ++ switch (esc_ch2) ++ { ++ default: ++ ip->match_now = is_label (arg); ++ if (!ip->match_now && is_label_with_addend (arg)) ++ as_fatal (_("This label shouldn't be with addend.")); ++ break; ++ case 'a': ++ ip->match_now = is_label_with_addend (arg); ++ break; ++ } ++ break; ++ case 's': ++ case 'u': ++ ip->match_now = ++ loongarch_parse_expr (arg, ip->reloc_info + ip->reloc_num, ++ reloc_num_we_have, &reloc_num, &imm) == 0; ++ ++ if (!ip->match_now) ++ break; ++ ++ if (esc_ch1 == 's') ++ switch (esc_ch2) ++ { ++ case 'c': ++ ip->match_now = reloc_num == 0; ++ break; ++ } ++ else ++ switch (esc_ch2) ++ { ++ case 'c': ++ ip->match_now = reloc_num == 0 && 0 <= imm; ++ break; ++ } ++ ++ if (!ip->match_now) ++ break; ++ ++ ret = imm; ++ if (reloc_num) ++ { ++ bfd_reloc_code_real_type reloc_type = BFD_RELOC_NONE; ++ reloc_num_we_have -= reloc_num; ++ if (reloc_num_we_have == 0) ++ as_fatal (_("expr too huge") /* want one more reloc */); ++ if (esc_ch1 == 'u') ++ { ++ if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0) ++ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_U_10_12; ++ } ++ else if (esc_ch1 == 's') ++ { ++ if (strncmp (bit_field, "10:16<<2", strlen ("10:16<<2")) == 0) ++ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2; ++ else if (strncmp (bit_field, "0:5|10:16<<2", strlen ("0:5|10:16<<2")) == 0) ++ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2; ++ else if (strncmp (bit_field, "0:10|10:16<<2", strlen ("0:10|10:16<<2")) == 0) ++ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2; ++ else if (strncmp (bit_field, "10:12", strlen ("10:12")) == 0) ++ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_12; ++ else if (strncmp (bit_field, "5:20", strlen ("5:20")) == 0) ++ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_5_20; ++ else if (strncmp (bit_field, "10:16", strlen ("10:16")) == 0) ++ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_16; ++ else if (strncmp (bit_field, "10:5", strlen ("10:5")) == 0) ++ reloc_type = BFD_RELOC_LARCH_SOP_POP_32_S_10_5; ++ } ++ if (reloc_type == BFD_RELOC_NONE) ++ as_fatal (_("not support reloc bit-field\nfmt: %c%c %s\nargs: %s"), ++ esc_ch1, esc_ch2, bit_field , arg); ++ reloc_num++; ++ ip->reloc_num += reloc_num; ++ ip->reloc_info[ip->reloc_num - 1].type = reloc_type; ++ ip->reloc_info[ip->reloc_num - 1].value = const_0; ++ } ++ break; ++ case 'r': ++ imm = (offsetT) hash_find (r_htab, arg); ++ ip->match_now = 0 < imm; ++ ret = imm - 1; ++ break; ++ case 'f': ++ imm = (offsetT) hash_find (f_htab, arg); ++ ip->match_now = 0 < imm; ++ ret = imm - 1; ++ break; ++ case 'c': ++ switch (esc_ch2) ++ { ++ case 'r': ++ imm = (offsetT) hash_find (cr_htab, arg); ++ break; ++ default: ++ imm = (offsetT) hash_find (c_htab, arg); ++ } ++ ip->match_now = 0 < imm; ++ ret = imm - 1; ++ break; ++ case 'v': ++ imm = (offsetT) hash_find (v_htab, arg); ++ ip->match_now = 0 < imm; ++ ret = imm - 1; ++ break; ++ case 'x': ++ imm = (offsetT) hash_find (x_htab, arg); ++ ip->match_now = 0 < imm; ++ ret = imm - 1; ++ break; ++ case '\0': ++ ip->all_match = ip->match_now; ++ ip->insn_length = ip->insn->mask ? loongarch_insn_length (ip->insn->match) : 0; ++ /* FIXME: now we have no relax insn */ ++ ip->relax_max_length = ip->insn_length; ++ break; ++ default: ++ as_fatal (_("unknown escape")); ++ } ++ ++ do ++ { ++ // check imm overflow ++ int bit_width, bits_needed_s, bits_needed_u; ++ char *t; ++ ++ if (!ip->match_now) ++ break; ++ ++ if (0 < reloc_num) ++ break; ++ ++ bit_width = loongarch_get_bit_field_width (bit_field, &t); ++ ++ if (bit_width == -1) ++ // no specify bit width ++ break; ++ ++ // 在这里求出实际填入的二进制数。这部分内容和 loongarch_encode_imm ++ // 有重合。但是需要在这里加入一些判断内容,比如分支指令立即数 ++ // 右移两位,要保证立即数低两位为0 ++ imm = ret; ++ if (t[0] == '<' && t[1] == '<') ++ { ++ int i = strtol (t += 2, &t, 10), j; ++ for (j = i; 0 < j; j--, imm >>= 1) ++ if (imm & 1) ++ as_fatal (_("require imm low %d bit is 0."), i); ++ } ++ ++ if (*t == '+') ++ imm -= strtol (t, &t, 10); ++ ++ bits_needed_s = loongarch_bits_imm_needed (imm, 1); ++ bits_needed_u = loongarch_bits_imm_needed (imm, 0); ++ ++ // 在这里判断立即数是否溢出。关于有符号立即数我有两种理解 ++ // 一是代数意义上的溢出,如果传入的值超出定义域,那么报错。 ++ // 二是程序员可能希望指定位域表示,那么值可能是一个使得符号位为1的正数。 ++ // riscv的溢出判断是第一种,这里按照riscv的方法来做 ++ if ((esc_ch1 == 's' && bit_width < bits_needed_s) ++ || (esc_ch1 != 's' && bit_width < bits_needed_u)) ++ // how to do after we detect overflow ++ as_fatal (_("Immediate overflow.\n" ++ "format: %c%c%s\n" ++ "arg: %s"), ++ esc_ch1, esc_ch2, bit_field, arg); ++ } ++ while (0); ++ ++ if (esc_ch1 != '\0') ++ { ++ ip->args[ip->arg_num] = ret; ++ ip->arg_num++; ++ } ++ return ret; ++} ++ ++static void ++get_loongarch_opcode (struct loongarch_cl_insn *insn) ++{ ++ const struct loongarch_opcode *it; ++ struct loongarch_ase *ase; ++ for (ase = loongarch_ASEs; ase->enabled; ase++) ++ { ++ if (!*ase->enabled ++ || (ase->include && !*ase->include) ++ || (ase->exclude && *ase->exclude)) ++ continue; ++ ++ if (!ase->name_hash_entry) ++ { ++ ase->name_hash_entry = hash_new (); ++ for (it = ase->opcodes; it->name; it++) ++ hash_insert (ase->name_hash_entry, it->name, (void *) it); ++ } ++ ++ if ((it = hash_find (ase->name_hash_entry, insn->name)) == NULL) ++ continue; ++ ++ do ++ { ++ insn->insn = it; ++ insn->match_now = 1; ++ insn->all_match = 0; ++ insn->arg_num = 0; ++ insn->reloc_num = 0; ++ insn->insn_bin = ++ loongarch_foreach_args (it->format, insn->arg_strs, ++ loongarch_args_parser_can_match_arg_helper, insn); ++ if (insn->all_match ++ && !(it->include && !*it->include) ++ && !(it->exclude && *it->exclude)) ++ { ++ insn->insn_bin |= it->match; ++ return; ++ } ++ it++; ++ } ++ while (it->name && strcasecmp (it->name, insn->name) == 0); ++ } ++} ++ ++static int ++check_this_insn_before_appending (struct loongarch_cl_insn *ip) ++{ ++ int ret = 0; ++ if (strcmp (ip->name, "la.abs") == 0) ++ { ++ ip->reloc_info[ip->reloc_num].type = BFD_RELOC_LARCH_MARK_LA; ++ my_getExpression (&ip->reloc_info[ip->reloc_num].value, ip->arg_strs[1]); ++ ip->reloc_num++; ++ } ++ else if (ip->insn->mask == 0xffff8000 ++ && ((ip->insn_bin & 0xfff00000) == 0x38600000 ++ || (ip->insn_bin & 0xffff0000) == 0x38700000 ++ || (ip->insn_bin & 0xffff0000) == 0x38710000)) ++ { ++ /* for AMO insn amswap.[wd], amadd.[wd], etc. */ ++ if (ip->args[0] != 0 && ++ (ip->args[0] == ip->args[1] || ip->args[0] == ip->args[2])) ++ as_fatal (_( ++"AMO insns require rd != base && rd != rt when rd isn't $r0")); ++ } ++ else if ((ip->insn->mask == 0xffe08000 ++ && (ip->insn_bin & 0xffe00000) == 0x00600000) ++ || (ip->insn->mask == 0xffc00000 ++ && (ip->insn_bin & 0xff800000) == 0x00800000)) ++ { ++ /* for bstr(ins|pick).[wd] */ ++ if (ip->args[2] < ip->args[3]) ++ as_fatal (_("bstr(ins|pick).[wd] require msbd >= lsbd")); ++ } ++ else if (ip->insn->mask != 0 ++ && (ip->insn_bin & 0xfe0003c0) == 0x04000000 ++ && (strcmp ("csrxchg", ip->name) == 0 ++ || strcmp ("gcsrxchg", ip->name) == 0)) ++ as_fatal (_("g?csrxchg require rj != $r0 && rj != $r1")); ++ ++ return ret; ++} ++ ++static void ++install_insn (const struct loongarch_cl_insn *insn) ++{ ++ char *f = insn->frag->fr_literal + insn->where; ++ if (0 < insn->insn_length) ++ md_number_to_chars (f, insn->insn_bin, insn->insn_length); ++} ++ ++static void ++move_insn (struct loongarch_cl_insn *insn, fragS *frag, long where) ++{ ++ size_t i; ++ insn->frag = frag; ++ insn->where = where; ++ for (i = 0; i < insn->reloc_num; i++) ++ { ++ insn->fixp[i]->fx_frag = frag; ++ insn->fixp[i]->fx_where = where; ++ } ++ install_insn (insn); ++} ++ ++/* Add INSN to the end of the output. */ ++static void ++append_fixed_insn (struct loongarch_cl_insn *insn) ++{ ++ char *f = frag_more (insn->insn_length); ++ move_insn (insn, frag_now, f - frag_now->fr_literal); ++} ++ ++static void ++append_fixp_and_insn (struct loongarch_cl_insn *ip) ++{ ++ reloc_howto_type *howto; ++ bfd_reloc_code_real_type reloc_type; ++ struct reloc_info *reloc_info = ip->reloc_info; ++ size_t i; ++ for (i = 0; i < ip->reloc_num; i++) ++ { ++ reloc_type = reloc_info[i].type; ++ howto = bfd_reloc_type_lookup (stdoutput, reloc_type); ++ if (howto == NULL) ++ as_fatal (_("no HOWTO loong relocation number %d"), reloc_type); ++ ++ ip->fixp[i] = ++ fix_new_exp (ip->frag, ip->where, bfd_get_reloc_size (howto), ++ &reloc_info[i].value, FALSE, reloc_type); ++ } ++ ++ if (ip->insn_length < ip->relax_max_length) ++ as_fatal (_("Internal error: not support relax now")); ++ else ++ append_fixed_insn (ip); ++ dwarf2_emit_insn (0); ++} ++ ++//ask helper for returning a malloced c_str or NULL ++static char * ++assember_macro_helper (const char * const args[], void *context_ptr) ++{ ++ struct loongarch_cl_insn *insn = context_ptr; ++ char *ret = NULL; ++ if (strcmp (insn->name, "li.d") == 0 ++ || strcmp (insn->name, "li.w") == 0) ++ { ++ char args_buf[50], insns_buf[200]; ++ const char *arg_strs[6]; ++ uint32_t hi32, lo32; ++ ++ /* We pay attention to sign extend beacause it is chance of reduce insn. ++ The exception is 12-bit and hi-12-bit unsigned, ++ we need a 'ori' or a 'lu52i.d' accordingly. */ ++ char all0_bit_vec, sign_bit_vec, allf_bit_vec, paritial_is_sext_of_prev; ++ ++ lo32 = insn->args[1] & 0xffffffff; ++ hi32 = insn->args[1] >> 32; ++ ++ ++ if (strcmp (insn->name, "li.w") == 0) ++ { ++ if (hi32 != 0 && hi32 != 0xffffffff) ++ as_fatal (_("li overflow: hi32:0x%x lo32:0x%x"), hi32, lo32); ++ hi32 = lo32 & 0x80000000 ? 0xffffffff : 0; ++ } ++ ++ if (strcmp (insn->name, "li.d") == 0 && LARCH_opts.rlen_is_32) ++ as_fatal (_("we can't li.d on 32bit-arch")); ++ ++ snprintf (args_buf, sizeof (args_buf), "0x%x,0x%x,0x%x,0x%x,%s", ++ (hi32 >> 20) & 0xfff, hi32 & 0xfffff, ++ (lo32 >> 12) & 0xfffff, lo32 & 0xfff, args[0]); ++ loongarch_split_args_by_comma (args_buf, arg_strs); ++ ++ all0_bit_vec = (((hi32 & 0xfff00000) == 0) << 3) ++ | (((hi32 & 0x000fffff) == 0) << 2) ++ | (((lo32 & 0xfffff000) == 0) << 1) ++ | ((lo32 & 0x00000fff) == 0); ++ sign_bit_vec = (((hi32 & 0x80000000) != 0) << 3) ++ | (((hi32 & 0x00080000) != 0) << 2) ++ | (((lo32 & 0x80000000) != 0) << 1) ++ | ((lo32 & 0x00000800) != 0); ++ allf_bit_vec = (((hi32 & 0xfff00000) == 0xfff00000) << 3) ++ | (((hi32 & 0x000fffff) == 0x000fffff) << 2) ++ | (((lo32 & 0xfffff000) == 0xfffff000) << 1) ++ | ((lo32 & 0x00000fff) == 0x00000fff); ++ paritial_is_sext_of_prev = (all0_bit_vec ^ allf_bit_vec) ++ & (all0_bit_vec ^ (sign_bit_vec << 1)); ++ ++ static const char * const li_32bit [] = { ++ "lu12i.w %5,%3&0x80000?%3-0x100000:%3;ori %5,%5,%4;", ++ "lu12i.w %5,%3&0x80000?%3-0x100000:%3;", ++ "addi.w %5,$r0,%4&0x800?%4-0x1000:%4;", ++ "or %5,$r0,$r0;", ++ }; ++ static const char * const li_hi_32bit[] = { ++ "lu32i.d %5,%2&0x80000?%2-0x100000:%2;" ++ "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;", ++ "lu52i.d %5,%5,%1&0x800?%1-0x1000:%1;", ++ "lu32i.d %5,%2&0x80000?%2-0x100000:%2;", ++ "", ++ }; ++ do ++ { ++ insns_buf[0] = '\0'; ++ if (paritial_is_sext_of_prev == 0x7) ++ { ++ strcat (insns_buf, "lu52i.d %5,$r0,%1&0x800?%1-0x1000:%1;"); ++ break; ++ } ++ if ((all0_bit_vec & 0x3) == 0x2) ++ strcat (insns_buf, "ori %5,$r0,%4;"); ++ else ++ strcat (insns_buf, li_32bit[paritial_is_sext_of_prev & 0x3]); ++ strcat (insns_buf, li_hi_32bit[paritial_is_sext_of_prev >> 2]); ++ } ++ while (0); ++ ++ ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL); ++ } ++ return ret; ++} ++ ++//accept instructions separated by ';' ++//assuming 'not starting with space and not ending with space' or pass in empty c_str ++static void ++loongarch_assemble_INSNs (char *str) ++{ ++ char *rest; ++ ++ for (rest = str; *rest != ';' && *rest != '\0'; rest++); ++ if (*rest == ';') ++ *rest++ = '\0'; ++ ++ if (*str == ':') ++ { ++ str++; ++ setup_internal_label_here (strtol (str, &str, 10)); ++ str++; ++ } ++ ++ do ++ { ++ if (*str == '\0') ++ break; ++ ++ struct loongarch_cl_insn the_one = {0}; ++ the_one.name = str; ++ ++ for (; *str && *str != ' '; str++); ++ if (*str == ' ') ++ *str++ = '\0'; ++ ++ loongarch_split_args_by_comma (str, the_one.arg_strs); ++ get_loongarch_opcode (&the_one); ++ ++ if (!the_one.all_match) ++ as_fatal (_("no match insn: %s\t%s"), ++ the_one.name, loongarch_cat_splited_strs (the_one.arg_strs)); ++ ++ if (check_this_insn_before_appending (&the_one) != 0) ++ break; ++ ++ append_fixp_and_insn (&the_one); ++ if (the_one.insn_length == 0 && the_one.insn->macro) ++ { ++ char *c_str = ++ loongarch_expand_macro (the_one.insn->macro, ++ the_one.arg_strs, assember_macro_helper, &the_one); ++ loongarch_assemble_INSNs (c_str); ++ free (c_str); ++ } ++ } ++ while (0); ++ ++ if (*rest != '\0') ++ loongarch_assemble_INSNs (rest); ++} ++ ++void ++md_assemble (char *str) ++{ ++ loongarch_assemble_INSNs (str); ++} ++ ++const char *md_atof (int type, char *litP, int *sizeP) ++{ ++ return ieee_md_atof (type, litP, sizeP, FALSE); ++} ++ ++void md_number_to_chars (char *buf, valueT val, int n) ++{ ++ number_to_chars_littleendian (buf, val, n); ++} ++ ++/* The location from which a PC relative jump should be calculated, ++ given a PC relative reloc. */ ++long ++md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED) ++{ ++ return 0; ++} ++ ++void ++md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) ++{ ++ static int64_t stack_top; ++ static int last_reloc_is_sop_push_pcrel_1 = 0; ++ int last_reloc_is_sop_push_pcrel = last_reloc_is_sop_push_pcrel_1; ++ insn_t insn; ++ last_reloc_is_sop_push_pcrel_1 = 0; ++ ++ char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; ++ switch (fixP->fx_r_type) ++ { ++ case BFD_RELOC_LARCH_SOP_PUSH_TLS_TPREL: ++ case BFD_RELOC_LARCH_SOP_PUSH_TLS_GD: ++ case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT: ++ if (fixP->fx_addsy) ++ S_SET_THREAD_LOCAL (fixP->fx_addsy); ++ case BFD_RELOC_LARCH_SOP_PUSH_PCREL: ++ case BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL: ++ if (fixP->fx_addsy == NULL) ++ as_bad_where (fixP->fx_file, fixP->fx_line, ++ _("Relocation against a constant")); ++ if (fixP->fx_r_type == BFD_RELOC_LARCH_SOP_PUSH_PCREL) ++ { ++ /* 分支到内部符号的重定位尽量在这里解决。一方面是为了反汇编更好看; ++ 也是为了方便PMON的模块加载。PMON连接器的重定位类型枚举空间很小, ++ 无法实现全的重定位。编译时加入-mabiabs使得所有外部符号都有la.abs, ++ 从而有MARK_LA这个重定位,PMON连接器重定位时填4条la指令。 */ ++ last_reloc_is_sop_push_pcrel_1 = 1; ++ if (S_GET_SEGMENT (fixP->fx_addsy) == seg) ++ stack_top = S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset ++ - (fixP->fx_where + fixP->fx_frag->fr_address); ++ else ++ stack_top = 0; ++ } ++ break; ++ ++ case BFD_RELOC_LARCH_SOP_POP_32_S_10_5: ++ if (!last_reloc_is_sop_push_pcrel) ++ break; ++ if ((stack_top & ~(uint64_t)0xf) != 0x0 ++ && (stack_top & ~(uint64_t)0xf) != ~(uint64_t)0xf) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ insn = bfd_getl32 (buf); ++ insn = (insn & (~(uint32_t)0x7c00)) | ((stack_top & 0x1f) << 10); ++ bfd_putl32 (insn, buf); ++ break; ++ ++ case BFD_RELOC_LARCH_SOP_POP_32_U_10_12: ++ if (!last_reloc_is_sop_push_pcrel) ++ break; ++ if (stack_top & ~(uint64_t)0xfff) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ insn = bfd_getl32 (buf); ++ insn = (insn & (~(uint32_t)0x3ffc00)) | ((stack_top & 0xfff) << 10); ++ bfd_putl32 (insn, buf); ++ break; ++ ++ case BFD_RELOC_LARCH_SOP_POP_32_S_10_12: ++ if (!last_reloc_is_sop_push_pcrel) ++ break; ++ if ((stack_top & ~(uint64_t)0x7ff) != 0x0 ++ && (stack_top & ~(uint64_t)0x7ff) != ~(uint64_t)0x7ff) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ insn = bfd_getl32 (buf); ++ insn = (insn & (~(uint32_t)0x3ffc00)) | ((stack_top & 0xfff) << 10); ++ bfd_putl32 (insn, buf); ++ break; ++ ++ case BFD_RELOC_LARCH_SOP_POP_32_S_10_16: ++ if (!last_reloc_is_sop_push_pcrel) ++ break; ++ if ((stack_top & ~(uint64_t)0x7fff) != 0x0 ++ && (stack_top & ~(uint64_t)0x7fff) != ~(uint64_t)0x7fff) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ insn = bfd_getl32 (buf); ++ insn = (insn & 0xfc0003ff) | ((stack_top & 0xffff) << 10); ++ bfd_putl32 (insn, buf); ++ break; ++ ++ case BFD_RELOC_LARCH_SOP_POP_32_S_10_16_S2: ++ if (!last_reloc_is_sop_push_pcrel) ++ break; ++ if ((stack_top & 0x3) != 0) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ stack_top >>= 2; ++ if ((stack_top & ~(uint64_t)0x7fff) != 0x0 ++ && (stack_top & ~(uint64_t)0x7fff) != ~(uint64_t)0x7fff) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ insn = bfd_getl32 (buf); ++ insn = (insn & 0xfc0003ff) | ((stack_top & 0xffff) << 10); ++ bfd_putl32 (insn, buf); ++ break; ++ ++ case BFD_RELOC_LARCH_SOP_POP_32_S_0_5_10_16_S2: ++ if (!last_reloc_is_sop_push_pcrel) ++ break; ++ if ((stack_top & 0x3) != 0) ++ break; ++ stack_top >>= 2; ++ if ((stack_top & ~(uint64_t)0xfffff) != 0x0 ++ && (stack_top & ~(uint64_t)0xfffff) != ~(uint64_t)0xfffff) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ insn = bfd_getl32 (buf); ++ insn = (insn & 0xfc0003e0) ++ | ((stack_top & 0xffff) << 10) | ((stack_top & 0x1f0000) >> 16); ++ bfd_putl32 (insn, buf); ++ break; ++ ++ case BFD_RELOC_LARCH_SOP_POP_32_S_5_20: ++ if (!last_reloc_is_sop_push_pcrel) ++ break; ++ if ((stack_top & ~(uint64_t)0x7ffff) != 0x0 ++ && (stack_top & ~(uint64_t)0x7ffff) != ~(uint64_t)0x7ffff) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ insn = bfd_getl32 (buf); ++ insn = (insn & (~(uint32_t)0x1ffffe0)) | ((stack_top & 0xfffff) << 5); ++ bfd_putl32 (insn, buf); ++ break; ++ ++ case BFD_RELOC_LARCH_SOP_POP_32_S_0_10_10_16_S2: ++ if (!last_reloc_is_sop_push_pcrel) ++ break; ++ if ((stack_top & 0x3) != 0) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ stack_top >>= 2; ++ if ((stack_top & ~(uint64_t)0x1ffffff) != 0x0 ++ && (stack_top & ~(uint64_t)0x1ffffff) != ~(uint64_t)0x1ffffff) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ insn = bfd_getl32 (buf); ++ insn = (insn & 0xfc000000) ++ | ((stack_top & 0xffff) << 10) | ((stack_top & 0x3ff0000) >> 16); ++ bfd_putl32 (insn, buf); ++ break; ++ ++ case BFD_RELOC_LARCH_SOP_POP_32_U: ++ if (!last_reloc_is_sop_push_pcrel) ++ break; ++ if (stack_top & ~(uint64_t)0xffffffff) ++ as_warn_where (fixP->fx_file, fixP->fx_line, "Reloc overflow"); ++ bfd_putl32 (stack_top, buf); ++ break; ++ ++ case BFD_RELOC_64: ++ case BFD_RELOC_32: ++ if (fixP->fx_subsy) ++ { ++ case BFD_RELOC_24: ++ case BFD_RELOC_16: ++ case BFD_RELOC_8: ++ fixP->fx_next = xmemdup (fixP, sizeof (*fixP), sizeof (*fixP)); ++ fixP->fx_next->fx_addsy = fixP->fx_subsy; ++ fixP->fx_next->fx_subsy = NULL; ++ fixP->fx_next->fx_offset = 0; ++ fixP->fx_subsy = NULL; ++ ++ switch (fixP->fx_r_type) ++ { ++ case BFD_RELOC_64: ++ fixP->fx_r_type = BFD_RELOC_LARCH_ADD64; ++ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB64; ++ break; ++ case BFD_RELOC_32: ++ fixP->fx_r_type = BFD_RELOC_LARCH_ADD32; ++ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB32; ++ break; ++ case BFD_RELOC_24: ++ fixP->fx_r_type = BFD_RELOC_LARCH_ADD24; ++ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB24; ++ break; ++ case BFD_RELOC_16: ++ fixP->fx_r_type = BFD_RELOC_LARCH_ADD16; ++ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB16; ++ break; ++ case BFD_RELOC_8: ++ fixP->fx_r_type = BFD_RELOC_LARCH_ADD8; ++ fixP->fx_next->fx_r_type = BFD_RELOC_LARCH_SUB8; ++ break; ++ default: ++ break; ++ } ++ md_number_to_chars (buf, 0, fixP->fx_size); ++ if (fixP->fx_next->fx_addsy == NULL) ++ fixP->fx_next->fx_done = 1; ++ } ++ if (fixP->fx_addsy == NULL) ++ { ++ fixP->fx_done = 1; ++ md_number_to_chars (buf, *valP, fixP->fx_size); ++ } ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++int ++loongarch_relax_frag (asection *sec ATTRIBUTE_UNUSED, fragS *fragp ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED) ++{ ++ return 0; ++} ++ ++int ++md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED, asection *segtype ATTRIBUTE_UNUSED) ++{ ++ return 0; ++} ++ ++/* Translate internal representation of relocation info to BFD target ++ format. */ ++arelent * ++tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp) ++{ ++ arelent *reloc = (arelent *) xmalloc (sizeof (arelent)); ++ ++ reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); ++ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); ++ reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; ++ reloc->addend = fixp->fx_offset; ++ ++ reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type); ++ if (reloc->howto == NULL) ++ { ++ as_bad_where (fixp->fx_file, fixp->fx_line, ++ _("cannot represent %s relocation in object file"), ++ bfd_get_reloc_code_name (fixp->fx_r_type)); ++ return NULL; ++ } ++ ++ return reloc; ++} ++ ++/* Convert a machine dependent frag. */ ++void ++md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED, fragS *fragp ATTRIBUTE_UNUSED) ++{ ++ // fragp->fr_fix += 8; ++} ++ ++/* Standard calling conventions leave the CFA at SP on entry. */ ++void ++loongarch_cfi_frame_initial_instructions (void) ++{ ++ cfi_add_CFA_def_cfa_register (3 /* $sp */); ++} ++ ++int ++loongarch_dwarf2_addr_size (void) ++{ ++ return LARCH_opts.addrwidth_is_32? 4 : 8; ++} ++ ++void ++tc_loongarch_parse_to_dw2regnum (expressionS *exp) ++{ ++ expression_and_evaluate (exp); ++} ++ ++void ++md_show_usage (FILE *stream) ++{ ++ fprintf (stream, _("\ ++ LoongISA options:\n\ ++ ")); ++} ++ ++/* Fill in an rs_align_code fragment. We want to fill 'andi $r0,$r0,0'. */ ++void ++loongarch_handle_align (fragS *fragp) ++{ ++// char nop_opcode; ++ char *p; ++ int bytes, size, excess; ++ valueT opcode; ++ ++ if (fragp->fr_type != rs_align_code) ++ return; ++ ++ struct loongarch_cl_insn nop = ++ {.name = "andi", .arg_strs = {"$r0", "$r0", "0", NULL}}; ++ ++ get_loongarch_opcode (&nop); ++ gas_assert (nop.all_match); ++ ++ p = fragp->fr_literal + fragp->fr_fix; ++ opcode = nop.insn_bin; ++ size = 4; ++ ++ bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; ++ excess = bytes % size; ++ ++ /* Handle the leading part if we're not inserting a whole number of ++ instructions, and make it the end of the fixed part of the frag. ++ Try to fit in a short microMIPS NOP if applicable and possible, ++ and use zeroes otherwise. */ ++ gas_assert (excess < 4); ++ fragp->fr_fix += excess; ++ switch (excess) ++ { ++ case 3: ++ *p++ = '\0'; ++ case 2: ++ *p++ = '\0'; ++ case 1: ++ *p++ = '\0'; ++ case 0: ++ break; ++ } ++ ++ md_number_to_chars (p, opcode, size); ++ fragp->fr_var = size; ++} ++ ++void ++loongarch_elf_final_processing (void) ++{ ++ if (LARCH_opts.abi_is_lp64) ++ elf_elfheader (stdoutput)->e_flags |= EF_LARCH_ABI_LP64; ++ else if (LARCH_opts.abi_is_lp32) ++ elf_elfheader (stdoutput)->e_flags |= EF_LARCH_ABI_LP32; ++} +diff --git a/gas/config/tc-loongarch.h b/gas/config/tc-loongarch.h +new file mode 100644 +index 00000000..f2647972 +--- /dev/null ++++ b/gas/config/tc-loongarch.h +@@ -0,0 +1,77 @@ ++#ifndef TC_LOONGARCH ++#define TC_LOONGARCH ++ ++#define TARGET_BYTES_BIG_ENDIAN 0 ++#define TARGET_ARCH bfd_arch_loongarch ++ ++#define WORKING_DOT_WORD 1 ++#define REPEAT_CONS_EXPRESSIONS ++ ++// early than md_begin ++#define md_after_parse_args loongarch_after_parse_args ++extern void loongarch_after_parse_args (void); ++ ++extern void loongarch_pop_insert (void); ++#define md_pop_insert() loongarch_pop_insert () ++ ++#define TARGET_FORMAT loongarch_target_format() ++extern const char * loongarch_target_format (void); ++ ++ ++#define md_relax_frag(segment, fragp, stretch) \ ++ loongarch_relax_frag (segment, fragp, stretch) ++extern int loongarch_relax_frag (asection *, struct frag *, long); ++#define md_section_align(seg,size) (size) ++#define md_undefined_symbol(name) (0) ++ ++/* This is called to see whether a reloc against a defined symbol ++ should be converted into a reloc against a section. */ ++#define tc_fix_adjustable(fixp) 0 ++ ++/* Values passed to md_apply_fix don't include symbol values. */ ++#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) 1 ++#define TC_VALIDATE_FIX_SUB(FIX, SEG) 1 ++#define DIFF_EXPR_OK 1 ++ ++#define TARGET_USE_CFIPOP 1 ++#define DWARF2_DEFAULT_RETURN_COLUMN 1 /* $ra */ ++#define DWARF2_CIE_DATA_ALIGNMENT -4 ++extern int loongarch_dwarf2_addr_size (void); ++#define DWARF2_FDE_RELOC_SIZE loongarch_dwarf2_addr_size () ++#define DWARF2_ADDR_SIZE(bfd) loongarch_dwarf2_addr_size () ++#define CFI_DIFF_EXPR_OK 0 ++ ++#define tc_cfi_frame_initial_instructions loongarch_cfi_frame_initial_instructions ++extern void loongarch_cfi_frame_initial_instructions (void); ++ ++// 我们不实现 tc_regname_to_dw2regnum,而是重载tc_parse_to_dw2regnum。 ++// 因为MIPS汇编兼容需要CFA来实现C++异常抛出。我们仅仅对数字作映射, ++// 不再考虑寄存器的名字了。 ++//#define tc_regname_to_dw2regnum tc_loongarch_regname_to_dw2regnum ++#define tc_parse_to_dw2regnum tc_loongarch_parse_to_dw2regnum ++extern void tc_loongarch_parse_to_dw2regnum (expressionS *); ++ ++// a enumerated values to specific how to deal with align in '.text' ++// now we want to fill 'andi $r0,$r0,0x0' ++#define loongarch_nop_opcode() 0 ++#define NOP_OPCODE (loongarch_nop_opcode ()) ++ ++#define HANDLE_ALIGN(fragp) loongarch_handle_align (fragp) ++extern void loongarch_handle_align (struct frag *); ++#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4) ++ ++#define elf_tc_final_processing loongarch_elf_final_processing ++extern void loongarch_elf_final_processing (void); ++ ++#define MAX_RELOC_NUMBER_A_INSN 20 ++ ++struct reloc_info ++{ ++ bfd_reloc_code_real_type type; ++ expressionS value; ++}; ++ ++int is_label_with_addend (const char *); ++int is_label (const char *); ++ ++#endif +diff --git a/gas/configure b/gas/configure +index f4a4b125..5917b777 100755 +--- a/gas/configure ++++ b/gas/configure +@@ -12503,6 +12503,18 @@ _ACEOF + fi + ;; + ++ loongarch) ++ echo ${extra_objects} | grep -s "loongarch-parse.o" ++ if test $? -ne 0 ; then ++ extra_objects="$extra_objects loongarch-parse.o" ++ fi ++ ++ echo ${extra_objects} | grep -s "loongarch-lex-wrapper.o" ++ if test $? -ne 0 ; then ++ extra_objects="$extra_objects loongarch-lex-wrapper.o" ++ fi ++ ;; ++ + epiphany | fr30 | ip2k | iq2000 | lm32 | m32r | or1k) + using_cgen=yes + ;; +@@ -12639,7 +12651,7 @@ $as_echo "#define NDS32_DEFAULT_AUDIO_EXT 1" >>confdefs.h + $as_echo "$enable_audio_ext" >&6; } + ;; + +- aarch64 | i386 | riscv | s390 | sparc) ++ aarch64 | i386 | riscv | s390 | sparc | loongarch) + if test $this_target = $target ; then + + cat >>confdefs.h <<_ACEOF +diff --git a/gas/configure.ac b/gas/configure.ac +index 4bd2077c..41f779ee 100644 +--- a/gas/configure.ac ++++ b/gas/configure.ac +@@ -430,6 +430,15 @@ changequote([,])dnl + using_cgen=yes + ;; + ++ loongarch) ++ for f in loongarch-parse.o loongarch-lex-wrapper.o; do ++ case " $extra_objects " in ++ *" $f "*) ;; ++ *) extra_objects="$extra_objects $f" ;; ++ esac ++ done ++ ;; ++ + m32c) + using_cgen=yes + ;; +diff --git a/gas/configure.tgt b/gas/configure.tgt +index abf7e02e..76b1abcb 100644 +--- a/gas/configure.tgt ++++ b/gas/configure.tgt +@@ -67,6 +67,7 @@ case ${cpu} in + ip2k) cpu_type=ip2k endian=big ;; + iq2000) cpu_type=iq2000 endian=big ;; + lm32) cpu_type=lm32 ;; ++ loongarch*) cpu_type=loongarch ;; + m32c) cpu_type=m32c endian=little ;; + m32r) cpu_type=m32r endian=big ;; + m32rle) cpu_type=m32r endian=little ;; +@@ -311,6 +312,8 @@ case ${generic_target} in + + lm32-*-*) fmt=elf ;; + ++ loongarch*) fmt=elf ;; ++ + m32c-*-elf) fmt=elf ;; + + m32r-*-elf*) fmt=elf ;; +@@ -497,7 +500,7 @@ case ${generic_target} in + esac + + case ${cpu_type} in +- aarch64 | alpha | arm | i386 | ia64 | microblaze | mips | ns32k | or1k | or1knd | pdp11 | ppc | riscv | sparc | z80 | z8k) ++ aarch64 | alpha | arm | i386 | ia64 | loongarch | microblaze | mips | ns32k | or1k | or1knd | pdp11 | ppc | riscv | sparc | z80 | z8k) + bfd_gas=yes + ;; + esac +diff --git a/include/dis-asm.h b/include/dis-asm.h +index 0ddf0475..055b8ce8 100644 +--- a/include/dis-asm.h ++++ b/include/dis-asm.h +@@ -258,6 +258,7 @@ extern void print_mips_disassembler_options (FILE *); + extern void print_nfp_disassembler_options (FILE *); + extern void print_ppc_disassembler_options (FILE *); + extern void print_riscv_disassembler_options (FILE *); ++extern void print_loongarch_disassembler_options (FILE *); + extern void print_arm_disassembler_options (FILE *); + extern void print_arc_disassembler_options (FILE *); + extern void print_s390_disassembler_options (FILE *); +diff --git a/include/elf/common.h b/include/elf/common.h +index 8a470745..0de652c4 100644 +--- a/include/elf/common.h ++++ b/include/elf/common.h +@@ -339,6 +339,7 @@ + #define EM_LANAI 244 /* Lanai 32-bit processor. */ + #define EM_BPF 247 /* Linux BPF – in-kernel virtual machine. */ + #define EM_NFP 250 /* Netronome Flow Processor. */ ++#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 +@@ -642,6 +643,14 @@ + /* note name must be "LINUX". */ + #define NT_ARM_SVE 0x405 /* AArch SVE registers. */ + /* note name must be "LINUX". */ ++#define NT_LARCH_CPUCFG 0x900 /* Loongarch CPU config registers */ ++ /* note name must be "LINUX". */ ++#define NT_LARCH_LBT 0x901 /* Loongarch Loongson Binary Translation registers */ ++ /* note name must be "LINUX". */ ++#define NT_LARCH_LSX 0x902 /* Loongarch Loongson SIMD Extension registers */ ++ /* note name must be "LINUX". */ ++#define NT_LARCH_LASX 0x903 /* Loongarch Loongson Advanced SIMD Extension registers */ ++ /* note name must be "LINUX". */ + #define NT_SIGINFO 0x53494749 /* Fields of siginfo_t. */ + #define NT_FILE 0x46494c45 /* Description of mapped files. */ + +diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h +new file mode 100644 +index 00000000..02085dd3 +--- /dev/null ++++ b/include/elf/loongarch.h +@@ -0,0 +1,95 @@ ++#ifndef _ELF_LOONG_H ++#define _ELF_LOONG_H ++ ++#include ++#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) ++ ++/* 这个重定位类型将symbol距离重定位位置的pc相对位置偏移量压栈。 ++ 它against symbol,因为如果是个常数,虽然在no-pic的情况下可以得到结果,但因为 ++ 重定位位置相对这个常数的偏移量一定很大,八成填不进去;而在pic的情况下, ++ 偏移量无法在静态连接时确定。因此我们约定这个重定位不可能against constant */ ++RELOC_NUMBER (R_LARCH_SOP_PUSH_PCREL, 22) ++ ++/* 这个重定位against a symbol or a constant。它将symbol的运行时绝对地址 ++ 或常数压栈,因此在pic的情况下会报错。另外我不太清楚常数和ABS段的关系。 */ ++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 */ ++/* 这几个重定位类型是为了照顾到 ".dword sym1 - sym2" 这种求差的写法。 ++ 这些重定位类型处理的是连接时地址,一般情况下它们是成对出现的。 ++ 在直接求负数".dword - sym1"的情况下,R_LARCH_SUBxx会单独出现。但注意, ++ 那个位置填进去的是连接时地址。 */ ++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) ++ ++END_RELOC_NUMBERS (R_LARCH_count) ++ ++ ++/* Processor specific flags for the ELF header e_flags field. */ ++ ++#define EF_LARCH_ABI 0x0003 ++#define EF_LARCH_ABI_LP64 0x0003 ++#define EF_LARCH_ABI_XLP32 0x0002 ++#define EF_LARCH_ABI_LP32 0x0001 ++ ++#endif /* _ELF_LOONG_H */ +diff --git a/include/opcode/loongarch.h b/include/opcode/loongarch.h +new file mode 100644 +index 00000000..47a9d94b +--- /dev/null ++++ b/include/opcode/loongarch.h +@@ -0,0 +1,215 @@ ++#ifndef _LOONGARCH_H_ ++#define _LOONGARCH_H_ ++#include ++ ++#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. ++As for marco insn "b" in MIPS, we can say its name is "b", format is "l", macro is "j %1". So "b 3f" will be expanded to "j 3f". ++As for marco insn "li" in MIPS, we can say its name is "li", format is "s", macro is "ori" ++ ++ ++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 hash_control *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); ++extern char * ++loongarch_expand_macro (const char *macro, const char * const arg_strs[], ++ char * (*helper) (const char * const arg_strs[], ++ void *context), ++ void *context); ++extern size_t ++loongarch_bits_imm_needed (int64_t imm, int si); ++ ++/* 将字符串中指定的连续字符化为1个 */ ++extern void ++loongarch_eliminate_adjacent_repeat_char (char *dest, char c); ++ ++/* 下面两个函数计划作为libopcode.a拿出来给一些系统软件反汇编用 */ ++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 ++{ ++ int ase_test; ++ int ase_fix; ++ int ase_float; ++ int ase_128vec; ++ int ase_256vec; ++ ++ int addrwidth_is_32; ++ int addrwidth_is_64; ++ int rlen_is_32; ++ int rlen_is_64; ++ int la_local_with_abs; ++ int la_global_with_pcrel; ++ int la_global_with_abs; ++ ++ int abi_is_lp32; ++ int abi_is_lp64; ++} LARCH_opts; ++ ++extern size_t loongarch_insn_length (insn_t insn); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _LOONGARCH_H_ */ +diff --git a/ld/Makefile.am b/ld/Makefile.am +index 82718165..ee4a5790 100644 +--- a/ld/Makefile.am ++++ b/ld/Makefile.am +@@ -492,6 +492,7 @@ ALL_64_EMULATION_SOURCES = \ + eelf64btsmip.c \ + eelf64btsmip_fbsd.c \ + eelf64hppa.c \ ++ eelf64loongarch.c \ + eelf64lppc.c \ + eelf64lriscv.c \ + eelf64ltsmip.c \ +@@ -1988,6 +1989,11 @@ eelf64btsmip_fbsd.c: $(srcdir)/emulparams/elf64btsmip_fbsd.sh \ + eelf64hppa.c: $(srcdir)/emulparams/elf64hppa.sh \ + $(ELF_DEPS) $(srcdir)/scripttempl/elf64hppa.sc ${GEN_DEPENDS} + ++eelf64loongarch.c: $(srcdir)/emulparams/elf64loongarch.sh \ ++ $(srcdir)/emulparams/elf64loongarch-defs.sh $(ELF_DEPS) \ ++ $(srcdir)/emultempl/loongarchelf.em $(srcdir)/scripttempl/elf.sc \ ++ ${GEN_DEPENDS} ++ + eelf64lppc.c: $(srcdir)/emulparams/elf64lppc.sh \ + $(srcdir)/emulparams/elf64ppc.sh \ + $(srcdir)/emulparams/dynamic_undefined_weak.sh \ +diff --git a/ld/Makefile.in b/ld/Makefile.in +index bf7877ac..553b6334 100644 +--- a/ld/Makefile.in ++++ b/ld/Makefile.in +@@ -619,6 +619,7 @@ ALL_EMULATION_SOURCES = \ + eelf32iq2000.c \ + eelf32lm32.c \ + eelf32lm32fd.c \ ++ eelf32lloongarch.c \ + eelf32lppc.c \ + eelf32lppclinux.c \ + eelf32lppcnto.c \ +@@ -859,11 +860,13 @@ ALL_64_EMULATION_SOURCES = \ + eelf64btsmip.c \ + eelf64btsmip_fbsd.c \ + eelf64hppa.c \ ++ eelf64lloongarch.c \ + eelf64lppc.c \ + eelf64lriscv.c \ + eelf64ltsmip.c \ + eelf64ltsmip_fbsd.c \ + eelf64mmix.c \ ++ eelf64loongarch.c \ + eelf64ppc.c \ + eelf64ppc_fbsd.c \ + eelf64rdos.c \ +@@ -1248,6 +1251,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lm32.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lm32fd.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lmip.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lloongarch.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppc.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppclinux.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32lppcnto.Po@am__quote@ +@@ -1307,6 +1311,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64btsmip_fbsd.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64hppa.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lloongarch.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lppc.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64lriscv.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64ltsmip.Po@am__quote@ +@@ -2719,6 +2724,13 @@ eelf32lmip.c: $(srcdir)/emulparams/elf32lmip.sh \ + $(srcdir)/emulparams/elf32bmip.sh $(ELF_DEPS) \ + $(srcdir)/emultempl/mipself.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ++eelf32lloongarch.c: $(srcdir)/emulparams/elf32loongarch.sh \ ++ $(srcdir)/emulparams/elf32loongarchcommon.sh \ ++ $(srcdir)/emulparams/elf32loongarch.sh \ ++ $(srcdir)/emulparams/dynamic_undefined_weak.sh \ ++ $(srcdir)/emultempl/loongarch32elf.em ldemul-list.h \ ++ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ++ + eelf32lppc.c: $(srcdir)/emulparams/elf32lppc.sh \ + $(srcdir)/emulparams/elf32ppccommon.sh \ + $(srcdir)/emulparams/elf32ppc.sh \ +@@ -3551,6 +3563,12 @@ eelf64btsmip_fbsd.c: $(srcdir)/emulparams/elf64btsmip_fbsd.sh \ + eelf64hppa.c: $(srcdir)/emulparams/elf64hppa.sh \ + $(ELF_DEPS) $(srcdir)/scripttempl/elf64hppa.sc ${GEN_DEPENDS} + ++eelf64lloongarch.c: $(srcdir)/emulparams/elf64lloongarch.sh \ ++ $(srcdir)/emulparams/elf64loongarch.sh \ ++ $(srcdir)/emulparams/dynamic_undefined_weak.sh \ ++ $(srcdir)/emultempl/loongarch64elf.em ldemul-list.h \ ++ $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ++ + eelf64lppc.c: $(srcdir)/emulparams/elf64lppc.sh \ + $(srcdir)/emulparams/elf64ppc.sh \ + $(srcdir)/emulparams/dynamic_undefined_weak.sh \ +diff --git a/ld/configure.tgt b/ld/configure.tgt +index 1a70497a..a9a46150 100644 +--- a/ld/configure.tgt ++++ b/ld/configure.tgt +@@ -432,6 +432,8 @@ iq2000-*-elf) targ_emul=elf32iq2000 ; targ_extra_emuls="elf32iq10" + lm32-*-*linux*) targ_emul=elf32lm32fd ;; + lm32-*-*) targ_emul=elf32lm32 ; targ_extra_emuls="elf32lm32fd" + ;; ++loongarch32-*) targ_emul=elf32loongarch ;; ++loongarch64-*) targ_emul=elf64loongarch ;; + m32c-*-elf | m32c-*-rtems*) + targ_emul=elf32m32c + ;; +diff --git a/ld/emulparams/elf64loongarch-defs.sh b/ld/emulparams/elf64loongarch-defs.sh +new file mode 100644 +index 00000000..072519ea +--- /dev/null ++++ b/ld/emulparams/elf64loongarch-defs.sh +@@ -0,0 +1,39 @@ ++# This is an ELF platform. ++SCRIPT_NAME=elf ++ARCH=loongarch ++NO_REL_RELOCS=yes ++ ++TEMPLATE_NAME=elf32 ++EXTRA_EM_FILE=loongarchelf ++ ++ELFSIZE=64 ++ ++if test `echo "$host" | sed -e s/64//` = `echo "$target" | sed -e s/64//`; then ++ case " $EMULATION_LIBPATH " in ++ *" ${EMULATION_NAME} "*) ++ NATIVE=yes ++ ;; ++ esac ++fi ++ ++# Enable shared library support for everything except an embedded elf target. ++case "$target" in ++ loongarch*-elf) ++ ;; ++ *) ++ GENERATE_SHLIB_SCRIPT=yes ++ GENERATE_PIE_SCRIPT=yes ++ ;; ++esac ++ ++# In all cases, the number is big-endian. ++# LoongArch nop is 'andi $r0,$r0,0'. ++NOP=0x00004003 ++ ++TEXT_START_ADDR=0x120000000 ++MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" ++COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)" ++ ++SEPARATE_GOTPLT=0 ++INITIAL_READONLY_SECTIONS=".interp : { *(.interp) } ${CREATE_PIE-${INITIAL_READONLY_SECTIONS}}" ++INITIAL_READONLY_SECTIONS="${RELOCATING+${CREATE_SHLIB-${INITIAL_READONLY_SECTIONS}}}" +diff --git a/ld/emulparams/elf64loongarch.sh b/ld/emulparams/elf64loongarch.sh +new file mode 100644 +index 00000000..7331fe16 +--- /dev/null ++++ b/ld/emulparams/elf64loongarch.sh +@@ -0,0 +1,15 @@ ++# LA64 code using LP64D ABI. ++# ABI not in emulation name to avoid breaking backward compatibility. ++. ${srcdir}/emulparams/elf64loongarch-defs.sh ++OUTPUT_FORMAT="elf64-loongarch" ++ ++# On Linux, first look for 64 bit LP64D target libraries in /lib64/lp64d as per ++# the glibc ABI, and then /lib64 for backward compatility. ++case "$target" in ++ loong64*-linux*) ++ case "$EMULATION_NAME" in ++ *64*) ++ LIBPATH_SUFFIX="64/lib64 64";; ++ esac ++ ;; ++esac +diff --git a/ld/emultempl/loongarchelf.em b/ld/emultempl/loongarchelf.em +new file mode 100644 +index 00000000..3570797f +--- /dev/null ++++ b/ld/emultempl/loongarchelf.em +@@ -0,0 +1,90 @@ ++# This shell script emits a C file. -*- C -*- ++# Copyright (C) 2004-2018 Free Software Foundation, Inc. ++# ++# This file is part of the GNU Binutils. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, ++# MA 02110-1301, USA. ++ ++fragment <>= 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); ++ ++ if (si) ++ { ++ ret <<= sizeof (ret) * 8 - len; ++ ret >>= sizeof (ret) * 8 - len; ++ } ++ 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, i; ++ ++ width = loongarch_get_bit_field_width (t, &t); ++ if (width == -1) ++ return ret; ++ ++ if (*t == '<' && *(++t) == '<') ++ width += atoi (t + 1); ++ else if (*t == '+') ++ imm -= atoi (t + 1); ++ ++ imm <<= sizeof (imm) * 8 - width; ++ 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 = imm; ++ i >>= sizeof (i) * 8 - width; ++ i <<= b_start; ++ ret |= i; ++ imm <<= 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); ++ 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) ++{ ++ 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; ++ char buffer[8192]; ++ ++ 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 strdup (buffer); ++} ++ ++char * ++loongarch_expand_macro (const char *macro, const char * const arg_strs[], ++ char * (*helper) (const char * const arg_strs[], ++ void *context), ++ void *context) ++{ ++ return loongarch_expand_macro_with_format_map ++ (NULL, macro, arg_strs, I, helper, context); ++} ++ ++size_t ++loongarch_bits_imm_needed (int64_t imm, int si) ++{ ++ size_t ret; ++ if (si) ++ { ++ if (imm < 0) ++ { ++ for (ret = 0; imm < 0; imm <<= 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++; ++ } ++} +diff --git a/opcodes/loongarch-dis.c b/opcodes/loongarch-dis.c +new file mode 100644 +index 00000000..888c55f5 +--- /dev/null ++++ b/opcodes/loongarch-dis.c +@@ -0,0 +1,311 @@ ++#include "sysdep.h" ++#include "disassemble.h" ++#include "opintl.h" ++#include "opcode/loongarch.h" ++#include ++ ++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_test = 1; ++ LARCH_opts.ase_fix = 1; ++ LARCH_opts.ase_float = 1; ++ LARCH_opts.ase_128vec = 1; ++ LARCH_opts.ase_256vec = 1; ++ ++ loongarch_r_disname = loongarch_r_normal_name; ++ loongarch_f_disname = loongarch_f_normal_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 ATTRIBUTE_UNUSED) ++{ ++ 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[strlen (opts_in) + 1], *opt, *opt_end; ++ 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; ++ } ++ 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, "%s", opc->name); ++ ++ { ++ char fake_args[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); ++ } ++ ++ if (info->insn_type == dis_branch || info->insn_type == dis_condbranch ++ /* || someother if we have extra info to print */) ++ info->fprintf_func (info->stream, " #"); ++ ++ 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\ ++ LoongISA:\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); ++} +diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c +new file mode 100644 +index 00000000..2c543027 +--- /dev/null ++++ b/opcodes/loongarch-opc.c +@@ -0,0 +1,2128 @@ ++#include ++#include "opcode/loongarch.h" ++ ++struct loongarch_ASEs_option LARCH_opts = ++{ ++ .ase_test = 0, ++ .ase_fix = 0, ++ .ase_float = 0, ++ .ase_128vec = 0, ++ .ase_256vec = 0, ++ ++ .addrwidth_is_32 = 0, ++ .addrwidth_is_64 = 0, ++ .rlen_is_32 = 0, ++ .rlen_is_64 = 0, ++ .la_local_with_abs = 0, ++ .la_global_with_pcrel = 0, ++ .la_global_with_abs = 0, ++ ++ .abi_is_lp32 = 0, ++ .abi_is_lp64 = 0, ++}; ++ ++/* 预留。按理来说应该传入足够的信息使得这个函数可以返回指令长度 */ ++size_t loongarch_insn_length (insn_t insn) ++{ ++ return insn ? 4 : 4; /* eliminate warning */ ++} ++ ++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", ++}; ++ ++#define SOME_INFORMATION 0 ++const int ALWAYS_EXCLUSION = 1; ++static int FIX_FOR_SOME_ARCH = 1; ++ ++static struct loongarch_opcode loongarch_test_opcodes[] = { ++/* match, mask, name, format, macro, include, exclude, pinfo */ ++{ ++0, 0, "a insn always excluded", "r0:5,r5:5,r10:5", ++"insn_1 args_1" ++"insn_2 args_2" ++, 0, &ALWAYS_EXCLUSION, SOME_INFORMATION ++}, ++{ ++0, 0, ++"never disassemble when mask is 0" ++"and we only expand marco when mask is 0 for assemble", ++"r", "macro expand %1" ++, 0, 0, 0 ++}, ++{0, 0, "wrong_insn", "r", ++"throw_error use_fake_insn.for_example.something_goes_wrong_with_%1" ++, 0, 0, 0}, ++ ++{0, 0, "normal_insn", "r", ++"overloading of insn for your arch", &FIX_FOR_SOME_ARCH, 0, 0}, ++{0, 0, "normal_insn", "l", ++"throw_error if_you_dont_want", &FIX_FOR_SOME_ARCH, 0, 0}, ++ ++{0, 0, "normal_insn", "r", "", 0, 0, 0}, ++{0, 0, "normal_insn", "l", "", 0, 0, 0}, ++{0} /* Terminate the list. */ ++}; ++ ++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.la_global_with_pcrel, 0, 0}, ++{0, 0, "la.global", "r,r,la", "la.pcrel %1,%2,%3", &LARCH_opts.la_global_with_pcrel, 0, 0}, ++{0, 0, "la.global", "r,la", "la.abs %1,%2", &LARCH_opts.la_global_with_abs, 0, 0}, ++{0, 0, "la.global", "r,r,la", "la.abs %1,%3", &LARCH_opts.la_global_with_abs, 0, 0}, ++{0, 0, "la.global", "r,l", "la.got %1,%2", 0, 0, 0}, ++{0, 0, "la.global", "r,r,l", "la.got %1,%2,%3", 0, 0, 0}, ++ ++{0, 0, "la.local", "r,la", "la.abs %1,%2", &LARCH_opts.la_local_with_abs, 0, 0}, ++{0, 0, "la.local", "r,r,la", "la.abs %1,%3", &LARCH_opts.la_local_with_abs, 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", 0, 0, 0}, ++ ++{0, 0, "la.abs", "r,la", ++"lu12i.w %1,%%abs(%2)>>12;" ++"ori %1,%1,%%abs(%2)&0xfff;" ++, &LARCH_opts.addrwidth_is_32, 0, 0}, ++{0, 0, "la.abs", "r,la", ++"lu12i.w %1,%%abs(%2)<<32>>44;" ++"ori %1,%1,%%abs(%2)&0xfff;" ++"lu32i.d %1,%%abs(%2)<<12>>44;" ++"lu52i.d %1,%1,%%abs(%2)>>52;" ++, &LARCH_opts.addrwidth_is_64, 0, 0}, ++ ++{0, 0, "la.pcrel", "r,la", ++"pcaddu12i %1,%%pcrel(%2+0x800)<<32>>44;" ++"addi.w %1,%1,%%pcrel(%2+4)-(%%pcrel(%2+4+0x800)>>12<<12);" ++, &LARCH_opts.addrwidth_is_32, 0, 0}, ++ ++{0, 0, "la.pcrel", "r,la", ++"pcaddu12i %1,%%pcrel(%2+0x800)>>12;" ++"addi.d %1,%1,%%pcrel(%2+4)-(%%pcrel(%2+4+0x800)>>12<<12);" ++, &LARCH_opts.addrwidth_is_64, 0, 0}, ++{0, 0, "la.pcrel", "r,r,la", ++"pcaddu12i %1,(%%pcrel(%3)-(%%pcrel(%3+0x80000000)>>32<<32))<<32>>44;" ++"ori %2,$r0,(%%pcrel(%3+4)-(%%pcrel(%3+4+0x80000000)>>32<<32))&0xfff;" ++"lu32i.d %2,%%pcrel(%3+8+0x80000000)<<12>>44;" ++"lu52i.d %2,%2,%%pcrel(%3+12+0x80000000)>>52;" ++"add.d %1,%1,%2;" ++, &LARCH_opts.addrwidth_is_64, 0, 0}, ++ ++{0, 0, "la.got", "r,l", ++"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%gprel(%2))<<32>>44;" ++"ld.w %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%gprel(%2))>>12<<12);" ++, &LARCH_opts.addrwidth_is_32, 0, 0}, ++ ++{0, 0, "la.got", "r,l", ++"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%gprel(%2))>>12;" ++"ld.d %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%gprel(%2))>>12<<12);" ++, &LARCH_opts.addrwidth_is_64, 0, 0}, ++{0, 0, "la.got", "r,r,l", ++"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%gprel(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+0x80000000)+%%gprel(%3))>>32<<32))<<32>>44;" ++"ori %2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%gprel(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x80000000)+%%gprel(%3))>>32<<32))&0xfff;" ++"lu32i.d %2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%gprel(%3))<<12>>44;" ++"lu52i.d %2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%gprel(%3))>>52;" ++"ldx.d %1,%1,%2;" ++, &LARCH_opts.addrwidth_is_64, 0, 0}, ++ ++{0, 0, "la.tls.le", "r,la", ++"lu12i.w %1,%%tprel(%2)>>12;" ++"ori %1,%1,%%tprel(%2)&0xfff" ++, &LARCH_opts.addrwidth_is_32, 0, 0}, ++//{0, 0, "la.tls.le", "r,la", ++//"lu12i.w %1,%%tprel(%2)>>12;" ++//"ori %1,%1,%%tprel(%2)&0xfff" ++//, &LARCH_opts.addrwidth_is_64, 0, 0}, ++{0, 0, "la.tls.le", "r,la", ++"lu12i.w %1,%%tprel(%2)<<32>>44;" ++"ori %1,%1,%%tprel(%2)&0xfff;" ++"lu32i.d %1,%%tprel(%2)<<12>>44;" ++"lu52i.d %1,%1,%%tprel(%2)>>52;" ++, &LARCH_opts.addrwidth_is_64, 0, 0}, ++ ++{0, 0, "la.tls.ie", "r,l", ++"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgot(%2))<<32>>44;" ++"ld.w %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%tlsgot(%2))>>12<<12);" ++, &LARCH_opts.addrwidth_is_32, 0, 0}, ++ ++{0, 0, "la.tls.ie", "r,l", ++"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgot(%2))>>12;" ++"ld.d %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%tlsgot(%2))>>12<<12);" ++, &LARCH_opts.addrwidth_is_64, 0, 0}, ++{0, 0, "la.tls.ie", "r,r,l", ++"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%tlsgot(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+0x80000000)+%%tlsgot(%3))>>32<<32))<<32>>44;" ++"ori %2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgot(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x80000000)+%%tlsgot(%3))>>32<<32))&0xfff;" ++"lu32i.d %2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%tlsgot(%3))<<12>>44;" ++"lu52i.d %2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%tlsgot(%3))>>52;" ++"ldx.d %1,%1,%2;" ++, &LARCH_opts.addrwidth_is_64, 0, 0}, ++ ++{0, 0, "la.tls.ld", "r,l", "la.tls.gd %1,%2", 0, 0, 0}, ++{0, 0, "la.tls.ld", "r,r,l", ++"la.tls.gd %1,%2,%3" ++, &LARCH_opts.addrwidth_is_64, 0, 0}, ++ ++ ++{0, 0, "la.tls.gd", "r,l", ++"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgd(%2))<<32>>44;" ++"addi.w %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%tlsgd(%2))>>12<<12);" ++, &LARCH_opts.addrwidth_is_32, 0, 0}, ++ ++{0, 0, "la.tls.gd", "r,l", ++"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_+0x800)+%%tlsgd(%2))>>12;" ++"addi.d %1,%1,%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%2)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x800)+%%tlsgd(%2))>>12<<12);" ++, &LARCH_opts.addrwidth_is_64, 0, 0}, ++{0, 0, "la.tls.gd", "r,r,l", ++"pcaddu12i %1,(%%pcrel(_GLOBAL_OFFSET_TABLE_)+%%tlsgd(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+0x80000000)+%%tlsgd(%3))>>32<<32))<<32>>44;" ++"ori %2,$r0,(%%pcrel(_GLOBAL_OFFSET_TABLE_+4)+%%tlsgd(%3)-((%%pcrel(_GLOBAL_OFFSET_TABLE_+4+0x80000000)+%%tlsgd(%3))>>32<<32))&0xfff;" ++"lu32i.d %2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+8+0x80000000)+%%tlsgd(%3))<<12>>44;" ++"lu52i.d %2,%2,(%%pcrel(_GLOBAL_OFFSET_TABLE_+12+0x80000000)+%%tlsgd(%3))>>52;" ++"add.d %1,%1,%2;" ++, &LARCH_opts.addrwidth_is_64, 0, 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_lmm_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, 0, 0, 0 }, ++ { 0x38380000, 0xffff8000, "fstx.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, ++ { 0x38740000, 0xffff8000, "fldgt.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, ++ { 0x38750000, 0xffff8000, "fldle.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, ++ { 0x38760000, 0xffff8000, "fstgt.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, ++ { 0x38770000, 0xffff8000, "fstle.s", "f0:5,r5:5,r10:5", 0, 0, 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, 0, 0, 0 }, ++ { 0x383c0000, 0xffff8000, "fstx.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, ++ { 0x38748000, 0xffff8000, "fldgt.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, ++ { 0x38758000, 0xffff8000, "fldle.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, ++ { 0x38768000, 0xffff8000, "fstgt.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, ++ { 0x38778000, 0xffff8000, "fstle.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0 }, ++ { 0 } /* Terminate the list. */ ++}; ++ ++static struct loongarch_opcode loongarch_float_jmp_opcodes[] = ++{ ++ { 0x0, 0x0, "bceqz", "c,la", "bceqz %1,%%pcrel(%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,%%pcrel(%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,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x60000000, 0xfc00001f, "bltz", "r5:5,sb10:16<<2", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "bgtz", "r,la", "bgtz %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x60000000, 0xfc0003e0, "bgtz", "r0:5,sb10:16<<2", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "bgez", "r,la", "bgez %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x64000000, 0xfc00001f, "bgez", "r5:5,sb10:16<<2", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "blez", "r,la", "blez %1,%%pcrel(%2)", 0, 0, 0 }, ++ { 0x64000000, 0xfc0003e0, "blez", "r0:5,sb10:16<<2", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "beqz", "r,la", "beqz %1,%%pcrel(%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,%%pcrel(%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 %%pcrel(%1)", 0, 0, 0 }, ++ { 0x4c000000, 0xfc000000, "jirl", "r0:5,r5:5,s10:16<<2", 0, 0, 0, 0 }, ++ { 0x0, 0x0, "bl", "la", "bl %%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%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,%%pcrel(%3)", 0, 0, 0 }, ++ { 0x6c000000, 0xfc000000, "bleu", "r0:5,r5:5,sb10:16<<2", 0, 0, 0, 0 }, ++ { 0 } /* Terminate the list. */ ++}; ++static struct loongarch_opcode loongarch_128vec_opcodes[] = { ++/* match, mask, name, format, macro, include, exclude, pinfo */ ++{0x70000000, 0xffff8000, "vseq.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70008000, 0xffff8000, "vseq.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70010000, 0xffff8000, "vseq.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70018000, 0xffff8000, "vseq.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70020000, 0xffff8000, "vsle.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70028000, 0xffff8000, "vsle.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70030000, 0xffff8000, "vsle.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70038000, 0xffff8000, "vsle.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70040000, 0xffff8000, "vsle.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70048000, 0xffff8000, "vsle.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70050000, 0xffff8000, "vsle.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70058000, 0xffff8000, "vsle.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70060000, 0xffff8000, "vslt.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70068000, 0xffff8000, "vslt.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70070000, 0xffff8000, "vslt.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70078000, 0xffff8000, "vslt.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70080000, 0xffff8000, "vslt.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70088000, 0xffff8000, "vslt.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70090000, 0xffff8000, "vslt.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70098000, 0xffff8000, "vslt.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x700a0000, 0xffff8000, "vadd.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x700a8000, 0xffff8000, "vadd.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x700b0000, 0xffff8000, "vadd.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x700b8000, 0xffff8000, "vadd.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x700c0000, 0xffff8000, "vsub.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x700c8000, 0xffff8000, "vsub.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x700d0000, 0xffff8000, "vsub.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x700d8000, 0xffff8000, "vsub.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70460000, 0xffff8000, "vsadd.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70468000, 0xffff8000, "vsadd.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70470000, 0xffff8000, "vsadd.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70478000, 0xffff8000, "vsadd.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70480000, 0xffff8000, "vssub.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70488000, 0xffff8000, "vssub.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70490000, 0xffff8000, "vssub.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70498000, 0xffff8000, "vssub.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x704a0000, 0xffff8000, "vsadd.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x704a8000, 0xffff8000, "vsadd.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x704b0000, 0xffff8000, "vsadd.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x704b8000, 0xffff8000, "vsadd.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x704c0000, 0xffff8000, "vssub.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x704c8000, 0xffff8000, "vssub.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x704d0000, 0xffff8000, "vssub.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x704d8000, 0xffff8000, "vssub.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70540000, 0xffff8000, "vhaddw.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70548000, 0xffff8000, "vhaddw.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70550000, 0xffff8000, "vhaddw.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70558000, 0xffff8000, "vhaddw.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70560000, 0xffff8000, "vhsubw.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70568000, 0xffff8000, "vhsubw.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70570000, 0xffff8000, "vhsubw.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70578000, 0xffff8000, "vhsubw.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70580000, 0xffff8000, "vhaddw.hu.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70588000, 0xffff8000, "vhaddw.wu.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70590000, 0xffff8000, "vhaddw.du.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70598000, 0xffff8000, "vhaddw.qu.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x705a0000, 0xffff8000, "vhsubw.hu.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x705a8000, 0xffff8000, "vhsubw.wu.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x705b0000, 0xffff8000, "vhsubw.du.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x705b8000, 0xffff8000, "vhsubw.qu.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x705c0000, 0xffff8000, "vadda.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x705c8000, 0xffff8000, "vadda.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x705d0000, 0xffff8000, "vadda.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x705d8000, 0xffff8000, "vadda.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70600000, 0xffff8000, "vabsd.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70608000, 0xffff8000, "vabsd.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70610000, 0xffff8000, "vabsd.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70618000, 0xffff8000, "vabsd.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70620000, 0xffff8000, "vabsd.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70628000, 0xffff8000, "vabsd.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70630000, 0xffff8000, "vabsd.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70638000, 0xffff8000, "vabsd.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70640000, 0xffff8000, "vavg.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70648000, 0xffff8000, "vavg.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70650000, 0xffff8000, "vavg.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70658000, 0xffff8000, "vavg.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70660000, 0xffff8000, "vavg.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70668000, 0xffff8000, "vavg.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70670000, 0xffff8000, "vavg.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70678000, 0xffff8000, "vavg.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70680000, 0xffff8000, "vavgr.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70688000, 0xffff8000, "vavgr.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70690000, 0xffff8000, "vavgr.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70698000, 0xffff8000, "vavgr.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x706a0000, 0xffff8000, "vavgr.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x706a8000, 0xffff8000, "vavgr.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x706b0000, 0xffff8000, "vavgr.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x706b8000, 0xffff8000, "vavgr.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70700000, 0xffff8000, "vmax.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70708000, 0xffff8000, "vmax.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70710000, 0xffff8000, "vmax.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70718000, 0xffff8000, "vmax.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70720000, 0xffff8000, "vmin.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70728000, 0xffff8000, "vmin.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70730000, 0xffff8000, "vmin.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70738000, 0xffff8000, "vmin.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70740000, 0xffff8000, "vmax.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70748000, 0xffff8000, "vmax.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70750000, 0xffff8000, "vmax.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70758000, 0xffff8000, "vmax.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70760000, 0xffff8000, "vmin.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70768000, 0xffff8000, "vmin.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70770000, 0xffff8000, "vmin.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70778000, 0xffff8000, "vmin.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70840000, 0xffff8000, "vmul.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70848000, 0xffff8000, "vmul.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70850000, 0xffff8000, "vmul.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70858000, 0xffff8000, "vmul.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70860000, 0xffff8000, "vmuh.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70868000, 0xffff8000, "vmuh.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70870000, 0xffff8000, "vmuh.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70878000, 0xffff8000, "vmuh.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70880000, 0xffff8000, "vmuh.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70888000, 0xffff8000, "vmuh.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70890000, 0xffff8000, "vmuh.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70898000, 0xffff8000, "vmuh.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a80000, 0xffff8000, "vmadd.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a88000, 0xffff8000, "vmadd.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a90000, 0xffff8000, "vmadd.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a98000, 0xffff8000, "vmadd.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70aa0000, 0xffff8000, "vmsub.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70aa8000, 0xffff8000, "vmsub.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ab0000, 0xffff8000, "vmsub.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ab8000, 0xffff8000, "vmsub.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e00000, 0xffff8000, "vdiv.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e08000, 0xffff8000, "vdiv.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e10000, 0xffff8000, "vdiv.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e18000, 0xffff8000, "vdiv.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e20000, 0xffff8000, "vmod.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e28000, 0xffff8000, "vmod.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e30000, 0xffff8000, "vmod.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e38000, 0xffff8000, "vmod.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e40000, 0xffff8000, "vdiv.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e48000, 0xffff8000, "vdiv.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e50000, 0xffff8000, "vdiv.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e58000, 0xffff8000, "vdiv.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e60000, 0xffff8000, "vmod.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e68000, 0xffff8000, "vmod.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e70000, 0xffff8000, "vmod.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e78000, 0xffff8000, "vmod.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e80000, 0xffff8000, "vsll.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e88000, 0xffff8000, "vsll.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e90000, 0xffff8000, "vsll.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70e98000, 0xffff8000, "vsll.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ea0000, 0xffff8000, "vsrl.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ea8000, 0xffff8000, "vsrl.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70eb0000, 0xffff8000, "vsrl.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70eb8000, 0xffff8000, "vsrl.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ec0000, 0xffff8000, "vsra.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ec8000, 0xffff8000, "vsra.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ed0000, 0xffff8000, "vsra.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ed8000, 0xffff8000, "vsra.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ee0000, 0xffff8000, "vrotr.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ee8000, 0xffff8000, "vrotr.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ef0000, 0xffff8000, "vrotr.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ef8000, 0xffff8000, "vrotr.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f00000, 0xffff8000, "vsrlr.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f08000, 0xffff8000, "vsrlr.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f10000, 0xffff8000, "vsrlr.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f18000, 0xffff8000, "vsrlr.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f20000, 0xffff8000, "vsrar.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f28000, 0xffff8000, "vsrar.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f30000, 0xffff8000, "vsrar.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f38000, 0xffff8000, "vsrar.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f48000, 0xffff8000, "vsrln.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f50000, 0xffff8000, "vsrln.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f58000, 0xffff8000, "vsrln.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f68000, 0xffff8000, "vsran.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f70000, 0xffff8000, "vsran.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f78000, 0xffff8000, "vsran.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f88000, 0xffff8000, "vsrlrn.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f90000, 0xffff8000, "vsrlrn.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70f98000, 0xffff8000, "vsrlrn.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70fa8000, 0xffff8000, "vsrarn.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70fb0000, 0xffff8000, "vsrarn.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70fb8000, 0xffff8000, "vsrarn.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70fc8000, 0xffff8000, "vssrln.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70fd0000, 0xffff8000, "vssrln.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70fd8000, 0xffff8000, "vssrln.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70fe8000, 0xffff8000, "vssran.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ff0000, 0xffff8000, "vssran.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ff8000, 0xffff8000, "vssran.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71008000, 0xffff8000, "vssrlrn.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71010000, 0xffff8000, "vssrlrn.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71018000, 0xffff8000, "vssrlrn.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71028000, 0xffff8000, "vssrarn.b.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71030000, 0xffff8000, "vssrarn.h.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71038000, 0xffff8000, "vssrarn.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71048000, 0xffff8000, "vssrln.bu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71050000, 0xffff8000, "vssrln.hu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71058000, 0xffff8000, "vssrln.wu.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71068000, 0xffff8000, "vssran.bu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71070000, 0xffff8000, "vssran.hu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71078000, 0xffff8000, "vssran.wu.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71088000, 0xffff8000, "vssrlrn.bu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71090000, 0xffff8000, "vssrlrn.hu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71098000, 0xffff8000, "vssrlrn.wu.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710a8000, 0xffff8000, "vssrarn.bu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710b0000, 0xffff8000, "vssrarn.hu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710b8000, 0xffff8000, "vssrarn.wu.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710c0000, 0xffff8000, "vbitclr.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710c8000, 0xffff8000, "vbitclr.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710d0000, 0xffff8000, "vbitclr.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710d8000, 0xffff8000, "vbitclr.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710e0000, 0xffff8000, "vbitset.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710e8000, 0xffff8000, "vbitset.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710f0000, 0xffff8000, "vbitset.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x710f8000, 0xffff8000, "vbitset.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71100000, 0xffff8000, "vbitrev.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71108000, 0xffff8000, "vbitrev.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71110000, 0xffff8000, "vbitrev.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71118000, 0xffff8000, "vbitrev.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71160000, 0xffff8000, "vpackev.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71168000, 0xffff8000, "vpackev.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71170000, 0xffff8000, "vpackev.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71178000, 0xffff8000, "vpackev.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71180000, 0xffff8000, "vpackod.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71188000, 0xffff8000, "vpackod.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71190000, 0xffff8000, "vpackod.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71198000, 0xffff8000, "vpackod.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711a0000, 0xffff8000, "vilvl.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711a8000, 0xffff8000, "vilvl.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711b0000, 0xffff8000, "vilvl.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711b8000, 0xffff8000, "vilvl.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711c0000, 0xffff8000, "vilvh.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711c8000, 0xffff8000, "vilvh.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711d0000, 0xffff8000, "vilvh.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711d8000, 0xffff8000, "vilvh.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711e0000, 0xffff8000, "vpickev.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711e8000, 0xffff8000, "vpickev.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711f0000, 0xffff8000, "vpickev.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x711f8000, 0xffff8000, "vpickev.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71200000, 0xffff8000, "vpickod.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71208000, 0xffff8000, "vpickod.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71210000, 0xffff8000, "vpickod.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71218000, 0xffff8000, "vpickod.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71220000, 0xffff8000, "vreplve.b", "v0:5,v5:5,r10:5", 0, 0, 0, 0}, ++{0x71228000, 0xffff8000, "vreplve.h", "v0:5,v5:5,r10:5", 0, 0, 0, 0}, ++{0x71230000, 0xffff8000, "vreplve.w", "v0:5,v5:5,r10:5", 0, 0, 0, 0}, ++{0x71238000, 0xffff8000, "vreplve.d", "v0:5,v5:5,r10:5", 0, 0, 0, 0}, ++{0x71260000, 0xffff8000, "vand.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71268000, 0xffff8000, "vor.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71270000, 0xffff8000, "vxor.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71278000, 0xffff8000, "vnor.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71280000, 0xffff8000, "vandn.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71288000, 0xffff8000, "vorn.v", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x712b0000, 0xffff8000, "vfrstp.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x712b8000, 0xffff8000, "vfrstp.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x712d0000, 0xffff8000, "vadd.q", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x712d8000, 0xffff8000, "vsub.q", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x712e0000, 0xffff8000, "vsigncov.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x712e8000, 0xffff8000, "vsigncov.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x712f0000, 0xffff8000, "vsigncov.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x712f8000, 0xffff8000, "vsigncov.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71308000, 0xffff8000, "vfadd.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71310000, 0xffff8000, "vfadd.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71328000, 0xffff8000, "vfsub.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71330000, 0xffff8000, "vfsub.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71388000, 0xffff8000, "vfmul.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71390000, 0xffff8000, "vfmul.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x713a8000, 0xffff8000, "vfdiv.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x713b0000, 0xffff8000, "vfdiv.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x713c8000, 0xffff8000, "vfmax.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x713d0000, 0xffff8000, "vfmax.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x713e8000, 0xffff8000, "vfmin.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x713f0000, 0xffff8000, "vfmin.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71408000, 0xffff8000, "vfmaxa.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71410000, 0xffff8000, "vfmaxa.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71428000, 0xffff8000, "vfmina.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71430000, 0xffff8000, "vfmina.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71460000, 0xffff8000, "vfcvt.h.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71468000, 0xffff8000, "vfcvt.s.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71480000, 0xffff8000, "vffint.s.l", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x71498000, 0xffff8000, "vftint.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x714a0000, 0xffff8000, "vftintrm.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x714a8000, 0xffff8000, "vftintrp.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x714b0000, 0xffff8000, "vftintrz.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x714b8000, 0xffff8000, "vftintrne.w.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x717a8000, 0xffff8000, "vshuf.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x717b0000, 0xffff8000, "vshuf.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x717b8000, 0xffff8000, "vshuf.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x72800000, 0xffff8000, "vseqi.b", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72808000, 0xffff8000, "vseqi.h", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72810000, 0xffff8000, "vseqi.w", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72818000, 0xffff8000, "vseqi.d", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72820000, 0xffff8000, "vslei.b", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72828000, 0xffff8000, "vslei.h", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72830000, 0xffff8000, "vslei.w", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72838000, 0xffff8000, "vslei.d", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72840000, 0xffff8000, "vslei.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72848000, 0xffff8000, "vslei.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72850000, 0xffff8000, "vslei.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72858000, 0xffff8000, "vslei.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72860000, 0xffff8000, "vslti.b", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72868000, 0xffff8000, "vslti.h", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72870000, 0xffff8000, "vslti.w", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72878000, 0xffff8000, "vslti.d", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72880000, 0xffff8000, "vslti.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72888000, 0xffff8000, "vslti.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72890000, 0xffff8000, "vslti.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72898000, 0xffff8000, "vslti.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x728a0000, 0xffff8000, "vaddi.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x728a8000, 0xffff8000, "vaddi.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x728b0000, 0xffff8000, "vaddi.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x728b8000, 0xffff8000, "vaddi.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x728c0000, 0xffff8000, "vsubi.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x728c8000, 0xffff8000, "vsubi.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x728d0000, 0xffff8000, "vsubi.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x728d8000, 0xffff8000, "vsubi.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x728e0000, 0xffff8000, "vbsll.v", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x728e8000, 0xffff8000, "vbsrl.v", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72900000, 0xffff8000, "vmaxi.b", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72908000, 0xffff8000, "vmaxi.h", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72910000, 0xffff8000, "vmaxi.w", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72918000, 0xffff8000, "vmaxi.d", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72920000, 0xffff8000, "vmini.b", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72928000, 0xffff8000, "vmini.h", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72930000, 0xffff8000, "vmini.w", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72938000, 0xffff8000, "vmini.d", "v0:5,v5:5,s10:5", 0, 0, 0, 0}, ++{0x72940000, 0xffff8000, "vmaxi.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72948000, 0xffff8000, "vmaxi.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72950000, 0xffff8000, "vmaxi.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72958000, 0xffff8000, "vmaxi.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72960000, 0xffff8000, "vmini.bu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72968000, 0xffff8000, "vmini.hu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72970000, 0xffff8000, "vmini.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72978000, 0xffff8000, "vmini.du", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x729a0000, 0xffff8000, "vfrstpi.b", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x729a8000, 0xffff8000, "vfrstpi.h", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x729c0000, 0xfffffc00, "vclo.b", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c0400, 0xfffffc00, "vclo.h", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c0800, 0xfffffc00, "vclo.w", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c0c00, 0xfffffc00, "vclo.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c1000, 0xfffffc00, "vclz.b", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c1400, 0xfffffc00, "vclz.h", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c1800, 0xfffffc00, "vclz.w", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c1c00, 0xfffffc00, "vclz.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c2000, 0xfffffc00, "vpcnt.b", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c2400, 0xfffffc00, "vpcnt.h", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c2800, 0xfffffc00, "vpcnt.w", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c2c00, 0xfffffc00, "vpcnt.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c3000, 0xfffffc00, "vneg.b", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c3400, 0xfffffc00, "vneg.h", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c3800, 0xfffffc00, "vneg.w", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c3c00, 0xfffffc00, "vneg.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c4000, 0xfffffc00, "vmskltz.b", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c4400, 0xfffffc00, "vmskltz.h", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c4800, 0xfffffc00, "vmskltz.w", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c4c00, 0xfffffc00, "vmskltz.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c5000, 0xfffffc00, "vmskgez.b", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c6000, 0xfffffc00, "vmsknz.b", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729c9800, 0xfffffc18, "vseteqz.v", "c0:3,v5:5", 0, 0, 0, 0}, ++{0x729c9c00, 0xfffffc18, "vsetnez.v", "c0:3,v5:5", 0, 0, 0, 0}, ++{0x729ca000, 0xfffffc18, "vsetanyeqz.b", "c0:3,v5:5", 0, 0, 0, 0}, ++{0x729ca400, 0xfffffc18, "vsetanyeqz.h", "c0:3,v5:5", 0, 0, 0, 0}, ++{0x729ca800, 0xfffffc18, "vsetanyeqz.w", "c0:3,v5:5", 0, 0, 0, 0}, ++{0x729cac00, 0xfffffc18, "vsetanyeqz.d", "c0:3,v5:5", 0, 0, 0, 0}, ++{0x729cb000, 0xfffffc18, "vsetallnez.b", "c0:3,v5:5", 0, 0, 0, 0}, ++{0x729cb400, 0xfffffc18, "vsetallnez.h", "c0:3,v5:5", 0, 0, 0, 0}, ++{0x729cb800, 0xfffffc18, "vsetallnez.w", "c0:3,v5:5", 0, 0, 0, 0}, ++{0x729cbc00, 0xfffffc18, "vsetallnez.d", "c0:3,v5:5", 0, 0, 0, 0}, ++{0x729cc400, 0xfffffc00, "vflogb.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729cc800, 0xfffffc00, "vflogb.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729cd400, 0xfffffc00, "vfclass.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729cd800, 0xfffffc00, "vfclass.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729ce400, 0xfffffc00, "vfsqrt.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729ce800, 0xfffffc00, "vfsqrt.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729cf400, 0xfffffc00, "vfrecip.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729cf800, 0xfffffc00, "vfrecip.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d0400, 0xfffffc00, "vfrsqrt.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d0800, 0xfffffc00, "vfrsqrt.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d3400, 0xfffffc00, "vfrint.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d3800, 0xfffffc00, "vfrint.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d4400, 0xfffffc00, "vfrintrm.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d4800, 0xfffffc00, "vfrintrm.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d5400, 0xfffffc00, "vfrintrp.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d5800, 0xfffffc00, "vfrintrp.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d6400, 0xfffffc00, "vfrintrz.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d6800, 0xfffffc00, "vfrintrz.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d7400, 0xfffffc00, "vfrintrne.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d7800, 0xfffffc00, "vfrintrne.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729de800, 0xfffffc00, "vfcvtl.s.h", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729dec00, 0xfffffc00, "vfcvth.s.h", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729df000, 0xfffffc00, "vfcvtl.d.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729df400, 0xfffffc00, "vfcvth.d.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e0000, 0xfffffc00, "vffint.s.w", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e0400, 0xfffffc00, "vffint.s.wu", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e0800, 0xfffffc00, "vffint.d.l", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e0c00, 0xfffffc00, "vffint.d.lu", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e1000, 0xfffffc00, "vffintl.d.w", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e1400, 0xfffffc00, "vffinth.d.w", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e3000, 0xfffffc00, "vftint.w.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e3400, 0xfffffc00, "vftint.l.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e3800, 0xfffffc00, "vftintrm.w.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e3c00, 0xfffffc00, "vftintrm.l.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e4000, 0xfffffc00, "vftintrp.w.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e4400, 0xfffffc00, "vftintrp.l.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e4800, 0xfffffc00, "vftintrz.w.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e4c00, 0xfffffc00, "vftintrz.l.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e5000, 0xfffffc00, "vftintrne.w.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e5400, 0xfffffc00, "vftintrne.l.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e5800, 0xfffffc00, "vftint.wu.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e5c00, 0xfffffc00, "vftint.lu.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e7000, 0xfffffc00, "vftintrz.wu.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e7400, 0xfffffc00, "vftintrz.lu.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e8000, 0xfffffc00, "vftintl.l.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e8400, 0xfffffc00, "vftinth.l.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e8800, 0xfffffc00, "vftintrml.l.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e8c00, 0xfffffc00, "vftintrmh.l.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e9000, 0xfffffc00, "vftintrpl.l.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e9400, 0xfffffc00, "vftintrph.l.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e9800, 0xfffffc00, "vftintrzl.l.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729e9c00, 0xfffffc00, "vftintrzh.l.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729ea000, 0xfffffc00, "vftintrnel.l.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729ea400, 0xfffffc00, "vftintrneh.l.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729ee000, 0xfffffc00, "vexth.h.b", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729ee400, 0xfffffc00, "vexth.w.h", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729ee800, 0xfffffc00, "vexth.d.w", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729eec00, 0xfffffc00, "vexth.q.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729ef000, 0xfffffc00, "vexth.hu.bu", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729ef400, 0xfffffc00, "vexth.wu.hu", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729ef800, 0xfffffc00, "vexth.du.wu", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729efc00, 0xfffffc00, "vexth.qu.du", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729f0000, 0xfffffc00, "vreplgr2vr.b", "v0:5,r5:5", 0, 0, 0, 0}, ++{0x729f0400, 0xfffffc00, "vreplgr2vr.h", "v0:5,r5:5", 0, 0, 0, 0}, ++{0x729f0800, 0xfffffc00, "vreplgr2vr.w", "v0:5,r5:5", 0, 0, 0, 0}, ++{0x729f0c00, 0xfffffc00, "vreplgr2vr.d", "v0:5,r5:5", 0, 0, 0, 0}, ++{0x72a02000, 0xffffe000, "vrotri.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x72a04000, 0xffffc000, "vrotri.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x72a08000, 0xffff8000, "vrotri.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72a10000, 0xffff0000, "vrotri.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x72a42000, 0xffffe000, "vsrlri.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x72a44000, 0xffffc000, "vsrlri.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x72a48000, 0xffff8000, "vsrlri.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72a50000, 0xffff0000, "vsrlri.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x72a82000, 0xffffe000, "vsrari.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x72a84000, 0xffffc000, "vsrari.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x72a88000, 0xffff8000, "vsrari.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x72a90000, 0xffff0000, "vsrari.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x72eb8000, 0xffffc000, "vinsgr2vr.b", "v0:5,r5:5,u10:4", 0, 0, 0, 0}, ++{0x72ebc000, 0xffffe000, "vinsgr2vr.h", "v0:5,r5:5,u10:3", 0, 0, 0, 0}, ++{0x72ebe000, 0xfffff000, "vinsgr2vr.w", "v0:5,r5:5,u10:2", 0, 0, 0, 0}, ++{0x72ebf000, 0xfffff800, "vinsgr2vr.d", "v0:5,r5:5,u10:1", 0, 0, 0, 0}, ++{0x72ef8000, 0xffffc000, "vpickve2gr.b", "r0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x72efc000, 0xffffe000, "vpickve2gr.h", "r0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x72efe000, 0xfffff000, "vpickve2gr.w", "r0:5,v5:5,u10:2", 0, 0, 0, 0}, ++{0x72eff000, 0xfffff800, "vpickve2gr.d", "r0:5,v5:5,u10:1", 0, 0, 0, 0}, ++{0x72f38000, 0xffffc000, "vpickve2gr.bu", "r0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x72f3c000, 0xffffe000, "vpickve2gr.hu", "r0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x72f3e000, 0xfffff000, "vpickve2gr.wu", "r0:5,v5:5,u10:2", 0, 0, 0, 0}, ++{0x72f3f000, 0xfffff800, "vpickve2gr.du", "r0:5,v5:5,u10:1", 0, 0, 0, 0}, ++{0x72f78000, 0xffffc000, "vreplvei.b", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x72f7c000, 0xffffe000, "vreplvei.h", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x72f7e000, 0xfffff000, "vreplvei.w", "v0:5,v5:5,u10:2", 0, 0, 0, 0}, ++{0x72f7f000, 0xfffff800, "vreplvei.d", "v0:5,v5:5,u10:1", 0, 0, 0, 0}, ++{0x73082000, 0xffffe000, "vsllwil.h.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x73084000, 0xffffc000, "vsllwil.w.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73088000, 0xffff8000, "vsllwil.d.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73090000, 0xfffffc00, "vextl.q.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x730c2000, 0xffffe000, "vsllwil.hu.bu", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x730c4000, 0xffffc000, "vsllwil.wu.hu", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x730c8000, 0xffff8000, "vsllwil.du.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x730d0000, 0xfffffc00, "vextl.qu.du", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x73102000, 0xffffe000, "vbitclri.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x73104000, 0xffffc000, "vbitclri.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73108000, 0xffff8000, "vbitclri.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73110000, 0xffff0000, "vbitclri.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73142000, 0xffffe000, "vbitseti.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x73144000, 0xffffc000, "vbitseti.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73148000, 0xffff8000, "vbitseti.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73150000, 0xffff0000, "vbitseti.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73182000, 0xffffe000, "vbitrevi.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x73184000, 0xffffc000, "vbitrevi.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73188000, 0xffff8000, "vbitrevi.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73190000, 0xffff0000, "vbitrevi.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73242000, 0xffffe000, "vsat.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x73244000, 0xffffc000, "vsat.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73248000, 0xffff8000, "vsat.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73250000, 0xffff0000, "vsat.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73282000, 0xffffe000, "vsat.bu", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x73284000, 0xffffc000, "vsat.hu", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73288000, 0xffff8000, "vsat.wu", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73290000, 0xffff0000, "vsat.du", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x732c2000, 0xffffe000, "vslli.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x732c4000, 0xffffc000, "vslli.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x732c8000, 0xffff8000, "vslli.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x732d0000, 0xffff0000, "vslli.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73302000, 0xffffe000, "vsrli.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x73304000, 0xffffc000, "vsrli.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73308000, 0xffff8000, "vsrli.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73310000, 0xffff0000, "vsrli.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73342000, 0xffffe000, "vsrai.b", "v0:5,v5:5,u10:3", 0, 0, 0, 0}, ++{0x73344000, 0xffffc000, "vsrai.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73348000, 0xffff8000, "vsrai.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73350000, 0xffff0000, "vsrai.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73404000, 0xffffc000, "vsrlni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73408000, 0xffff8000, "vsrlni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73410000, 0xffff0000, "vsrlni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73420000, 0xfffe0000, "vsrlni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x73484000, 0xffffc000, "vssrlni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73488000, 0xffff8000, "vssrlni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73490000, 0xffff0000, "vssrlni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x734a0000, 0xfffe0000, "vssrlni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x73444000, 0xffffc000, "vsrlrni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73448000, 0xffff8000, "vsrlrni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73450000, 0xffff0000, "vsrlrni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73460000, 0xfffe0000, "vsrlrni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x734c4000, 0xffffc000, "vssrlni.bu.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x734c8000, 0xffff8000, "vssrlni.hu.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x734d0000, 0xffff0000, "vssrlni.wu.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x734e0000, 0xfffe0000, "vssrlni.du.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x73504000, 0xffffc000, "vssrlrni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73508000, 0xffff8000, "vssrlrni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73510000, 0xffff0000, "vssrlrni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73520000, 0xfffe0000, "vssrlrni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x73544000, 0xffffc000, "vssrlrni.bu.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73548000, 0xffff8000, "vssrlrni.hu.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73550000, 0xffff0000, "vssrlrni.wu.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73560000, 0xfffe0000, "vssrlrni.du.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x73584000, 0xffffc000, "vsrani.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73588000, 0xffff8000, "vsrani.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73590000, 0xffff0000, "vsrani.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x735a0000, 0xfffe0000, "vsrani.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x735c4000, 0xffffc000, "vsrarni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x735c8000, 0xffff8000, "vsrarni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x735d0000, 0xffff0000, "vsrarni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x735e0000, 0xfffe0000, "vsrarni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x73604000, 0xffffc000, "vssrani.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73608000, 0xffff8000, "vssrani.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73610000, 0xffff0000, "vssrani.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73620000, 0xfffe0000, "vssrani.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x73644000, 0xffffc000, "vssrani.bu.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73648000, 0xffff8000, "vssrani.hu.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73650000, 0xffff0000, "vssrani.wu.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x73660000, 0xfffe0000, "vssrani.du.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x73684000, 0xffffc000, "vssrarni.b.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x73688000, 0xffff8000, "vssrarni.h.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x73690000, 0xffff0000, "vssrarni.w.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x736a0000, 0xfffe0000, "vssrarni.d.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x736c4000, 0xffffc000, "vssrarni.bu.h", "v0:5,v5:5,u10:4", 0, 0, 0, 0}, ++{0x736c8000, 0xffff8000, "vssrarni.hu.w", "v0:5,v5:5,u10:5", 0, 0, 0, 0}, ++{0x736d0000, 0xffff0000, "vssrarni.wu.d", "v0:5,v5:5,u10:6", 0, 0, 0, 0}, ++{0x736e0000, 0xfffe0000, "vssrarni.du.q", "v0:5,v5:5,u10:7", 0, 0, 0, 0}, ++{0x73800000, 0xfffc0000, "vextrins.d", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x73840000, 0xfffc0000, "vextrins.w", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x73880000, 0xfffc0000, "vextrins.h", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x738c0000, 0xfffc0000, "vextrins.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x73900000, 0xfffc0000, "vshuf4i.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x73940000, 0xfffc0000, "vshuf4i.h", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x73980000, 0xfffc0000, "vshuf4i.w", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x739c0000, 0xfffc0000, "vshuf4i.d", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x73c40000, 0xfffc0000, "vbitseli.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x73d00000, 0xfffc0000, "vandi.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x73d40000, 0xfffc0000, "vori.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x73d80000, 0xfffc0000, "vxori.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0x73dc0000, 0xfffc0000, "vnori.b", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0, 0, "vrepli.b", "v,s0:10", "vldi %1,(%2)&0x3ff", 0, 0, 0}, ++ ++{0x701e0000, 0xffff8000, "vaddwev.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x701e8000, 0xffff8000, "vaddwev.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x701f0000, 0xffff8000, "vaddwev.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x701f8000, 0xffff8000, "vaddwev.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x702e0000, 0xffff8000, "vaddwev.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x702e8000, 0xffff8000, "vaddwev.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x702f0000, 0xffff8000, "vaddwev.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x702f8000, 0xffff8000, "vaddwev.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x703e0000, 0xffff8000, "vaddwev.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x703e8000, 0xffff8000, "vaddwev.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x703f0000, 0xffff8000, "vaddwev.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x703f8000, 0xffff8000, "vaddwev.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70220000, 0xffff8000, "vaddwod.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70228000, 0xffff8000, "vaddwod.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70230000, 0xffff8000, "vaddwod.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70238000, 0xffff8000, "vaddwod.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70320000, 0xffff8000, "vaddwod.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70328000, 0xffff8000, "vaddwod.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70330000, 0xffff8000, "vaddwod.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70338000, 0xffff8000, "vaddwod.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70400000, 0xffff8000, "vaddwod.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70408000, 0xffff8000, "vaddwod.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70410000, 0xffff8000, "vaddwod.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70418000, 0xffff8000, "vaddwod.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ac0000, 0xffff8000, "vmaddwev.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ac8000, 0xffff8000, "vmaddwev.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ad0000, 0xffff8000, "vmaddwev.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ad8000, 0xffff8000, "vmaddwev.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70b40000, 0xffff8000, "vmaddwev.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70b48000, 0xffff8000, "vmaddwev.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70b50000, 0xffff8000, "vmaddwev.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70b58000, 0xffff8000, "vmaddwev.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70bc0000, 0xffff8000, "vmaddwev.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70bc8000, 0xffff8000, "vmaddwev.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70bd0000, 0xffff8000, "vmaddwev.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70bd8000, 0xffff8000, "vmaddwev.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ae0000, 0xffff8000, "vmaddwod.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70ae8000, 0xffff8000, "vmaddwod.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70af0000, 0xffff8000, "vmaddwod.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70af8000, 0xffff8000, "vmaddwod.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70b60000, 0xffff8000, "vmaddwod.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70b68000, 0xffff8000, "vmaddwod.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70b70000, 0xffff8000, "vmaddwod.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70b78000, 0xffff8000, "vmaddwod.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70be0000, 0xffff8000, "vmaddwod.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70be8000, 0xffff8000, "vmaddwod.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70bf0000, 0xffff8000, "vmaddwod.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70bf8000, 0xffff8000, "vmaddwod.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70900000, 0xffff8000, "vmulwev.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70908000, 0xffff8000, "vmulwev.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70910000, 0xffff8000, "vmulwev.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70918000, 0xffff8000, "vmulwev.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70980000, 0xffff8000, "vmulwev.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70988000, 0xffff8000, "vmulwev.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70990000, 0xffff8000, "vmulwev.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70998000, 0xffff8000, "vmulwev.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a00000, 0xffff8000, "vmulwev.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a08000, 0xffff8000, "vmulwev.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a10000, 0xffff8000, "vmulwev.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a18000, 0xffff8000, "vmulwev.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70920000, 0xffff8000, "vmulwod.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70928000, 0xffff8000, "vmulwod.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70930000, 0xffff8000, "vmulwod.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70938000, 0xffff8000, "vmulwod.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x709a0000, 0xffff8000, "vmulwod.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x709a8000, 0xffff8000, "vmulwod.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x709b0000, 0xffff8000, "vmulwod.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x709b8000, 0xffff8000, "vmulwod.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a20000, 0xffff8000, "vmulwod.h.bu.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a28000, 0xffff8000, "vmulwod.w.hu.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a30000, 0xffff8000, "vmulwod.d.wu.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70a38000, 0xffff8000, "vmulwod.q.du.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70200000, 0xffff8000, "vsubwev.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70208000, 0xffff8000, "vsubwev.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70210000, 0xffff8000, "vsubwev.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70218000, 0xffff8000, "vsubwev.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70300000, 0xffff8000, "vsubwev.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70308000, 0xffff8000, "vsubwev.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70310000, 0xffff8000, "vsubwev.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70318000, 0xffff8000, "vsubwev.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70240000, 0xffff8000, "vsubwod.h.b", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70248000, 0xffff8000, "vsubwod.w.h", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70250000, 0xffff8000, "vsubwod.d.w", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70258000, 0xffff8000, "vsubwod.q.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70340000, 0xffff8000, "vsubwod.h.bu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70348000, 0xffff8000, "vsubwod.w.hu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70350000, 0xffff8000, "vsubwod.d.wu", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x70358000, 0xffff8000, "vsubwod.q.du", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0, 0, "vrepli.d", "v,s0:10", "vldi %1,((%2)&0x3ff)|0xc00", 0, 0, 0}, ++{0, 0, "vrepli.h", "v,s0:10", "vldi %1,((%2)&0x3ff)|0x400", 0, 0, 0}, ++{0, 0, "vrepli.w", "v,s0:10", "vldi %1,((%2)&0x3ff)|0x800", 0, 0, 0}, ++{0x73e00000, 0xfffc0000, "vldi", "v0:5,s5:13", 0, 0, 0, 0}, ++{0x73e40000, 0xfffc0000, "vpermi.w", "v0:5,v5:5,u10:8", 0, 0, 0, 0}, ++{0} /* Terminate the list. */ ++}; ++ ++static struct loongarch_opcode loongarch_256vec_opcodes[] = { ++/* match, mask, name, format, macro, include, exclude, pinfo */ ++{0x74000000, 0xffff8000, "xvseq.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74008000, 0xffff8000, "xvseq.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74010000, 0xffff8000, "xvseq.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74018000, 0xffff8000, "xvseq.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74020000, 0xffff8000, "xvsle.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74028000, 0xffff8000, "xvsle.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74030000, 0xffff8000, "xvsle.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74038000, 0xffff8000, "xvsle.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74040000, 0xffff8000, "xvsle.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74048000, 0xffff8000, "xvsle.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74050000, 0xffff8000, "xvsle.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74058000, 0xffff8000, "xvsle.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74060000, 0xffff8000, "xvslt.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74068000, 0xffff8000, "xvslt.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74070000, 0xffff8000, "xvslt.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74078000, 0xffff8000, "xvslt.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74080000, 0xffff8000, "xvslt.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74088000, 0xffff8000, "xvslt.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74090000, 0xffff8000, "xvslt.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74098000, 0xffff8000, "xvslt.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x740a0000, 0xffff8000, "xvadd.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x740a8000, 0xffff8000, "xvadd.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x740b0000, 0xffff8000, "xvadd.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x740b8000, 0xffff8000, "xvadd.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x740c0000, 0xffff8000, "xvsub.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x740c8000, 0xffff8000, "xvsub.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x740d0000, 0xffff8000, "xvsub.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x740d8000, 0xffff8000, "xvsub.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74460000, 0xffff8000, "xvsadd.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74468000, 0xffff8000, "xvsadd.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74470000, 0xffff8000, "xvsadd.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74478000, 0xffff8000, "xvsadd.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74480000, 0xffff8000, "xvssub.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74488000, 0xffff8000, "xvssub.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74490000, 0xffff8000, "xvssub.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74498000, 0xffff8000, "xvssub.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x744a0000, 0xffff8000, "xvsadd.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x744a8000, 0xffff8000, "xvsadd.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x744b0000, 0xffff8000, "xvsadd.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x744b8000, 0xffff8000, "xvsadd.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x744c0000, 0xffff8000, "xvssub.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x744c8000, 0xffff8000, "xvssub.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x744d0000, 0xffff8000, "xvssub.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x744d8000, 0xffff8000, "xvssub.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74540000, 0xffff8000, "xvhaddw.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74548000, 0xffff8000, "xvhaddw.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74550000, 0xffff8000, "xvhaddw.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74558000, 0xffff8000, "xvhaddw.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74560000, 0xffff8000, "xvhsubw.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74568000, 0xffff8000, "xvhsubw.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74570000, 0xffff8000, "xvhsubw.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74578000, 0xffff8000, "xvhsubw.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74580000, 0xffff8000, "xvhaddw.hu.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74588000, 0xffff8000, "xvhaddw.wu.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74590000, 0xffff8000, "xvhaddw.du.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74598000, 0xffff8000, "xvhaddw.qu.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x745a0000, 0xffff8000, "xvhsubw.hu.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x745a8000, 0xffff8000, "xvhsubw.wu.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x745b0000, 0xffff8000, "xvhsubw.du.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x745b8000, 0xffff8000, "xvhsubw.qu.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x741e0000, 0xffff8000, "xvaddwev.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x741e8000, 0xffff8000, "xvaddwev.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x741f0000, 0xffff8000, "xvaddwev.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x741f8000, 0xffff8000, "xvaddwev.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x742e0000, 0xffff8000, "xvaddwev.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x742e8000, 0xffff8000, "xvaddwev.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x742f0000, 0xffff8000, "xvaddwev.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x742f8000, 0xffff8000, "xvaddwev.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x743e0000, 0xffff8000, "xvaddwev.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x743e8000, 0xffff8000, "xvaddwev.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x743f0000, 0xffff8000, "xvaddwev.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x743f8000, 0xffff8000, "xvaddwev.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74220000, 0xffff8000, "xvaddwod.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74228000, 0xffff8000, "xvaddwod.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74230000, 0xffff8000, "xvaddwod.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74238000, 0xffff8000, "xvaddwod.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74320000, 0xffff8000, "xvaddwod.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74328000, 0xffff8000, "xvaddwod.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74330000, 0xffff8000, "xvaddwod.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74338000, 0xffff8000, "xvaddwod.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74400000, 0xffff8000, "xvaddwod.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74408000, 0xffff8000, "xvaddwod.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74410000, 0xffff8000, "xvaddwod.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74418000, 0xffff8000, "xvaddwod.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ac0000, 0xffff8000, "xvmaddwev.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ac8000, 0xffff8000, "xvmaddwev.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ad0000, 0xffff8000, "xvmaddwev.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ad8000, 0xffff8000, "xvmaddwev.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74bc0000, 0xffff8000, "xvmaddwev.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74bc8000, 0xffff8000, "xvmaddwev.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74bd0000, 0xffff8000, "xvmaddwev.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74bd8000, 0xffff8000, "xvmaddwev.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74b40000, 0xffff8000, "xvmaddwev.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74b48000, 0xffff8000, "xvmaddwev.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74b50000, 0xffff8000, "xvmaddwev.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74b58000, 0xffff8000, "xvmaddwev.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ae0000, 0xffff8000, "xvmaddwod.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ae8000, 0xffff8000, "xvmaddwod.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74af0000, 0xffff8000, "xvmaddwod.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74af8000, 0xffff8000, "xvmaddwod.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74b60000, 0xffff8000, "xvmaddwod.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74b68000, 0xffff8000, "xvmaddwod.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74b70000, 0xffff8000, "xvmaddwod.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74b78000, 0xffff8000, "xvmaddwod.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74be0000, 0xffff8000, "xvmaddwod.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74be8000, 0xffff8000, "xvmaddwod.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74bf0000, 0xffff8000, "xvmaddwod.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74bf8000, 0xffff8000, "xvmaddwod.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74900000, 0xffff8000, "xvmulwev.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74908000, 0xffff8000, "xvmulwev.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74910000, 0xffff8000, "xvmulwev.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74918000, 0xffff8000, "xvmulwev.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74980000, 0xffff8000, "xvmulwev.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74988000, 0xffff8000, "xvmulwev.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74990000, 0xffff8000, "xvmulwev.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74998000, 0xffff8000, "xvmulwev.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a00000, 0xffff8000, "xvmulwev.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a08000, 0xffff8000, "xvmulwev.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a10000, 0xffff8000, "xvmulwev.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a18000, 0xffff8000, "xvmulwev.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74920000, 0xffff8000, "xvmulwod.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74928000, 0xffff8000, "xvmulwod.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74930000, 0xffff8000, "xvmulwod.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74938000, 0xffff8000, "xvmulwod.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x749a0000, 0xffff8000, "xvmulwod.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x749a8000, 0xffff8000, "xvmulwod.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x749b0000, 0xffff8000, "xvmulwod.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x749b8000, 0xffff8000, "xvmulwod.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a20000, 0xffff8000, "xvmulwod.h.bu.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a28000, 0xffff8000, "xvmulwod.w.hu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a30000, 0xffff8000, "xvmulwod.d.wu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a38000, 0xffff8000, "xvmulwod.q.du.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74200000, 0xffff8000, "xvsubwev.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74208000, 0xffff8000, "xvsubwev.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74210000, 0xffff8000, "xvsubwev.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74218000, 0xffff8000, "xvsubwev.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74300000, 0xffff8000, "xvsubwev.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74308000, 0xffff8000, "xvsubwev.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74310000, 0xffff8000, "xvsubwev.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74318000, 0xffff8000, "xvsubwev.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74240000, 0xffff8000, "xvsubwod.h.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74248000, 0xffff8000, "xvsubwod.w.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74250000, 0xffff8000, "xvsubwod.d.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74258000, 0xffff8000, "xvsubwod.q.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74340000, 0xffff8000, "xvsubwod.h.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74348000, 0xffff8000, "xvsubwod.w.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74350000, 0xffff8000, "xvsubwod.d.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74358000, 0xffff8000, "xvsubwod.q.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x745c0000, 0xffff8000, "xvadda.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x745c8000, 0xffff8000, "xvadda.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x745d0000, 0xffff8000, "xvadda.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x745d8000, 0xffff8000, "xvadda.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74600000, 0xffff8000, "xvabsd.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74608000, 0xffff8000, "xvabsd.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74610000, 0xffff8000, "xvabsd.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74618000, 0xffff8000, "xvabsd.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74620000, 0xffff8000, "xvabsd.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74628000, 0xffff8000, "xvabsd.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74630000, 0xffff8000, "xvabsd.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74638000, 0xffff8000, "xvabsd.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74640000, 0xffff8000, "xvavg.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74648000, 0xffff8000, "xvavg.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74650000, 0xffff8000, "xvavg.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74658000, 0xffff8000, "xvavg.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74660000, 0xffff8000, "xvavg.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74668000, 0xffff8000, "xvavg.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74670000, 0xffff8000, "xvavg.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74678000, 0xffff8000, "xvavg.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74680000, 0xffff8000, "xvavgr.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74688000, 0xffff8000, "xvavgr.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74690000, 0xffff8000, "xvavgr.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74698000, 0xffff8000, "xvavgr.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x746a0000, 0xffff8000, "xvavgr.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x746a8000, 0xffff8000, "xvavgr.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x746b0000, 0xffff8000, "xvavgr.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x746b8000, 0xffff8000, "xvavgr.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74700000, 0xffff8000, "xvmax.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74708000, 0xffff8000, "xvmax.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74710000, 0xffff8000, "xvmax.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74718000, 0xffff8000, "xvmax.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74720000, 0xffff8000, "xvmin.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74728000, 0xffff8000, "xvmin.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74730000, 0xffff8000, "xvmin.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74738000, 0xffff8000, "xvmin.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74740000, 0xffff8000, "xvmax.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74748000, 0xffff8000, "xvmax.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74750000, 0xffff8000, "xvmax.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74758000, 0xffff8000, "xvmax.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74760000, 0xffff8000, "xvmin.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74768000, 0xffff8000, "xvmin.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74770000, 0xffff8000, "xvmin.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74778000, 0xffff8000, "xvmin.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74840000, 0xffff8000, "xvmul.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74848000, 0xffff8000, "xvmul.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74850000, 0xffff8000, "xvmul.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74858000, 0xffff8000, "xvmul.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74860000, 0xffff8000, "xvmuh.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74868000, 0xffff8000, "xvmuh.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74870000, 0xffff8000, "xvmuh.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74878000, 0xffff8000, "xvmuh.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74880000, 0xffff8000, "xvmuh.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74888000, 0xffff8000, "xvmuh.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74890000, 0xffff8000, "xvmuh.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74898000, 0xffff8000, "xvmuh.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a80000, 0xffff8000, "xvmadd.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a88000, 0xffff8000, "xvmadd.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a90000, 0xffff8000, "xvmadd.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74a98000, 0xffff8000, "xvmadd.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74aa0000, 0xffff8000, "xvmsub.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74aa8000, 0xffff8000, "xvmsub.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ab0000, 0xffff8000, "xvmsub.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ab8000, 0xffff8000, "xvmsub.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e00000, 0xffff8000, "xvdiv.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e08000, 0xffff8000, "xvdiv.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e10000, 0xffff8000, "xvdiv.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e18000, 0xffff8000, "xvdiv.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e20000, 0xffff8000, "xvmod.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e28000, 0xffff8000, "xvmod.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e30000, 0xffff8000, "xvmod.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e38000, 0xffff8000, "xvmod.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e40000, 0xffff8000, "xvdiv.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e48000, 0xffff8000, "xvdiv.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e50000, 0xffff8000, "xvdiv.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e58000, 0xffff8000, "xvdiv.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e60000, 0xffff8000, "xvmod.bu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e68000, 0xffff8000, "xvmod.hu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e70000, 0xffff8000, "xvmod.wu", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e78000, 0xffff8000, "xvmod.du", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e80000, 0xffff8000, "xvsll.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e88000, 0xffff8000, "xvsll.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e90000, 0xffff8000, "xvsll.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74e98000, 0xffff8000, "xvsll.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ea0000, 0xffff8000, "xvsrl.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ea8000, 0xffff8000, "xvsrl.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74eb0000, 0xffff8000, "xvsrl.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74eb8000, 0xffff8000, "xvsrl.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ec0000, 0xffff8000, "xvsra.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ec8000, 0xffff8000, "xvsra.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ed0000, 0xffff8000, "xvsra.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ed8000, 0xffff8000, "xvsra.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ee0000, 0xffff8000, "xvrotr.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ee8000, 0xffff8000, "xvrotr.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ef0000, 0xffff8000, "xvrotr.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ef8000, 0xffff8000, "xvrotr.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f00000, 0xffff8000, "xvsrlr.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f08000, 0xffff8000, "xvsrlr.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f10000, 0xffff8000, "xvsrlr.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f18000, 0xffff8000, "xvsrlr.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f20000, 0xffff8000, "xvsrar.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f28000, 0xffff8000, "xvsrar.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f30000, 0xffff8000, "xvsrar.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f38000, 0xffff8000, "xvsrar.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f48000, 0xffff8000, "xvsrln.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f50000, 0xffff8000, "xvsrln.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f58000, 0xffff8000, "xvsrln.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f68000, 0xffff8000, "xvsran.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f70000, 0xffff8000, "xvsran.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f78000, 0xffff8000, "xvsran.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f88000, 0xffff8000, "xvsrlrn.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f90000, 0xffff8000, "xvsrlrn.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74f98000, 0xffff8000, "xvsrlrn.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74fa8000, 0xffff8000, "xvsrarn.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74fb0000, 0xffff8000, "xvsrarn.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74fb8000, 0xffff8000, "xvsrarn.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74fc8000, 0xffff8000, "xvssrln.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74fd0000, 0xffff8000, "xvssrln.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74fd8000, 0xffff8000, "xvssrln.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74fe8000, 0xffff8000, "xvssran.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ff0000, 0xffff8000, "xvssran.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x74ff8000, 0xffff8000, "xvssran.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75008000, 0xffff8000, "xvssrlrn.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75010000, 0xffff8000, "xvssrlrn.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75018000, 0xffff8000, "xvssrlrn.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75028000, 0xffff8000, "xvssrarn.b.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75030000, 0xffff8000, "xvssrarn.h.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75038000, 0xffff8000, "xvssrarn.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75048000, 0xffff8000, "xvssrln.bu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75050000, 0xffff8000, "xvssrln.hu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75058000, 0xffff8000, "xvssrln.wu.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75068000, 0xffff8000, "xvssran.bu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75070000, 0xffff8000, "xvssran.hu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75078000, 0xffff8000, "xvssran.wu.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75088000, 0xffff8000, "xvssrlrn.bu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75090000, 0xffff8000, "xvssrlrn.hu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75098000, 0xffff8000, "xvssrlrn.wu.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750a8000, 0xffff8000, "xvssrarn.bu.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750b0000, 0xffff8000, "xvssrarn.hu.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750b8000, 0xffff8000, "xvssrarn.wu.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750c0000, 0xffff8000, "xvbitclr.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750c8000, 0xffff8000, "xvbitclr.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750d0000, 0xffff8000, "xvbitclr.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750d8000, 0xffff8000, "xvbitclr.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750e0000, 0xffff8000, "xvbitset.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750e8000, 0xffff8000, "xvbitset.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750f0000, 0xffff8000, "xvbitset.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x750f8000, 0xffff8000, "xvbitset.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75100000, 0xffff8000, "xvbitrev.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75108000, 0xffff8000, "xvbitrev.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75110000, 0xffff8000, "xvbitrev.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75118000, 0xffff8000, "xvbitrev.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75160000, 0xffff8000, "xvpackev.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75168000, 0xffff8000, "xvpackev.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75170000, 0xffff8000, "xvpackev.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75178000, 0xffff8000, "xvpackev.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75180000, 0xffff8000, "xvpackod.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75188000, 0xffff8000, "xvpackod.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75190000, 0xffff8000, "xvpackod.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75198000, 0xffff8000, "xvpackod.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751a0000, 0xffff8000, "xvilvl.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751a8000, 0xffff8000, "xvilvl.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751b0000, 0xffff8000, "xvilvl.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751b8000, 0xffff8000, "xvilvl.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751c0000, 0xffff8000, "xvilvh.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751c8000, 0xffff8000, "xvilvh.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751d0000, 0xffff8000, "xvilvh.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751d8000, 0xffff8000, "xvilvh.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751e0000, 0xffff8000, "xvpickev.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751e8000, 0xffff8000, "xvpickev.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751f0000, 0xffff8000, "xvpickev.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x751f8000, 0xffff8000, "xvpickev.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75200000, 0xffff8000, "xvpickod.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75208000, 0xffff8000, "xvpickod.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75210000, 0xffff8000, "xvpickod.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75218000, 0xffff8000, "xvpickod.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75220000, 0xffff8000, "xvreplve.b", "x0:5,x5:5,r10:5", 0, 0, 0, 0}, ++{0x75228000, 0xffff8000, "xvreplve.h", "x0:5,x5:5,r10:5", 0, 0, 0, 0}, ++{0x75230000, 0xffff8000, "xvreplve.w", "x0:5,x5:5,r10:5", 0, 0, 0, 0}, ++{0x75238000, 0xffff8000, "xvreplve.d", "x0:5,x5:5,r10:5", 0, 0, 0, 0}, ++{0x75260000, 0xffff8000, "xvand.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75268000, 0xffff8000, "xvor.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75270000, 0xffff8000, "xvxor.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75278000, 0xffff8000, "xvnor.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75280000, 0xffff8000, "xvandn.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75288000, 0xffff8000, "xvorn.v", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x752b0000, 0xffff8000, "xvfrstp.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x752b8000, 0xffff8000, "xvfrstp.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x752d0000, 0xffff8000, "xvadd.q", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x752d8000, 0xffff8000, "xvsub.q", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x752e0000, 0xffff8000, "xvsigncov.b", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x752e8000, 0xffff8000, "xvsigncov.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x752f0000, 0xffff8000, "xvsigncov.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x752f8000, 0xffff8000, "xvsigncov.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75308000, 0xffff8000, "xvfadd.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75310000, 0xffff8000, "xvfadd.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75328000, 0xffff8000, "xvfsub.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75330000, 0xffff8000, "xvfsub.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75388000, 0xffff8000, "xvfmul.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75390000, 0xffff8000, "xvfmul.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x753a8000, 0xffff8000, "xvfdiv.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x753b0000, 0xffff8000, "xvfdiv.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x753c8000, 0xffff8000, "xvfmax.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x753d0000, 0xffff8000, "xvfmax.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x753e8000, 0xffff8000, "xvfmin.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x753f0000, 0xffff8000, "xvfmin.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75408000, 0xffff8000, "xvfmaxa.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75410000, 0xffff8000, "xvfmaxa.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75428000, 0xffff8000, "xvfmina.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75430000, 0xffff8000, "xvfmina.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75460000, 0xffff8000, "xvfcvt.h.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75468000, 0xffff8000, "xvfcvt.s.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75480000, 0xffff8000, "xvffint.s.l", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x75498000, 0xffff8000, "xvftint.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x754a0000, 0xffff8000, "xvftintrm.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x754a8000, 0xffff8000, "xvftintrp.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x754b0000, 0xffff8000, "xvftintrz.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x754b8000, 0xffff8000, "xvftintrne.w.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x757a8000, 0xffff8000, "xvshuf.h", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x757b0000, 0xffff8000, "xvshuf.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x757b8000, 0xffff8000, "xvshuf.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x757d0000, 0xffff8000, "xvperm.w", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x76800000, 0xffff8000, "xvseqi.b", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76808000, 0xffff8000, "xvseqi.h", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76810000, 0xffff8000, "xvseqi.w", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76818000, 0xffff8000, "xvseqi.d", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76820000, 0xffff8000, "xvslei.b", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76828000, 0xffff8000, "xvslei.h", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76830000, 0xffff8000, "xvslei.w", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76838000, 0xffff8000, "xvslei.d", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76840000, 0xffff8000, "xvslei.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76848000, 0xffff8000, "xvslei.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76850000, 0xffff8000, "xvslei.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76858000, 0xffff8000, "xvslei.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76860000, 0xffff8000, "xvslti.b", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76868000, 0xffff8000, "xvslti.h", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76870000, 0xffff8000, "xvslti.w", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76878000, 0xffff8000, "xvslti.d", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76880000, 0xffff8000, "xvslti.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76888000, 0xffff8000, "xvslti.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76890000, 0xffff8000, "xvslti.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76898000, 0xffff8000, "xvslti.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x768a0000, 0xffff8000, "xvaddi.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x768a8000, 0xffff8000, "xvaddi.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x768b0000, 0xffff8000, "xvaddi.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x768b8000, 0xffff8000, "xvaddi.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x768c0000, 0xffff8000, "xvsubi.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x768c8000, 0xffff8000, "xvsubi.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x768d0000, 0xffff8000, "xvsubi.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x768d8000, 0xffff8000, "xvsubi.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x768e0000, 0xffff8000, "xvbsll.v", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x768e8000, 0xffff8000, "xvbsrl.v", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76900000, 0xffff8000, "xvmaxi.b", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76908000, 0xffff8000, "xvmaxi.h", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76910000, 0xffff8000, "xvmaxi.w", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76918000, 0xffff8000, "xvmaxi.d", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76920000, 0xffff8000, "xvmini.b", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76928000, 0xffff8000, "xvmini.h", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76930000, 0xffff8000, "xvmini.w", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76938000, 0xffff8000, "xvmini.d", "x0:5,x5:5,s10:5", 0, 0, 0, 0}, ++{0x76940000, 0xffff8000, "xvmaxi.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76948000, 0xffff8000, "xvmaxi.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76950000, 0xffff8000, "xvmaxi.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76958000, 0xffff8000, "xvmaxi.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76960000, 0xffff8000, "xvmini.bu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76968000, 0xffff8000, "xvmini.hu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76970000, 0xffff8000, "xvmini.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76978000, 0xffff8000, "xvmini.du", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x769a0000, 0xffff8000, "xvfrstpi.b", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x769a8000, 0xffff8000, "xvfrstpi.h", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x769c0000, 0xfffffc00, "xvclo.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c0400, 0xfffffc00, "xvclo.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c0800, 0xfffffc00, "xvclo.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c0c00, 0xfffffc00, "xvclo.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c1000, 0xfffffc00, "xvclz.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c1400, 0xfffffc00, "xvclz.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c1800, 0xfffffc00, "xvclz.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c1c00, 0xfffffc00, "xvclz.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c2000, 0xfffffc00, "xvpcnt.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c2400, 0xfffffc00, "xvpcnt.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c2800, 0xfffffc00, "xvpcnt.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c2c00, 0xfffffc00, "xvpcnt.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c3000, 0xfffffc00, "xvneg.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c3400, 0xfffffc00, "xvneg.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c3800, 0xfffffc00, "xvneg.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c3c00, 0xfffffc00, "xvneg.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c4000, 0xfffffc00, "xvmskltz.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c4400, 0xfffffc00, "xvmskltz.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c4800, 0xfffffc00, "xvmskltz.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c4c00, 0xfffffc00, "xvmskltz.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c5000, 0xfffffc00, "xvmskgez.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c6000, 0xfffffc00, "xvmsknz.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769c9800, 0xfffffc18, "xvseteqz.v", "c0:3,x5:5", 0, 0, 0, 0}, ++{0x769c9c00, 0xfffffc18, "xvsetnez.v", "c0:3,x5:5", 0, 0, 0, 0}, ++{0x769ca000, 0xfffffc18, "xvsetanyeqz.b", "c0:3,x5:5", 0, 0, 0, 0}, ++{0x769ca400, 0xfffffc18, "xvsetanyeqz.h", "c0:3,x5:5", 0, 0, 0, 0}, ++{0x769ca800, 0xfffffc18, "xvsetanyeqz.w", "c0:3,x5:5", 0, 0, 0, 0}, ++{0x769cac00, 0xfffffc18, "xvsetanyeqz.d", "c0:3,x5:5", 0, 0, 0, 0}, ++{0x769cb000, 0xfffffc18, "xvsetallnez.b", "c0:3,x5:5", 0, 0, 0, 0}, ++{0x769cb400, 0xfffffc18, "xvsetallnez.h", "c0:3,x5:5", 0, 0, 0, 0}, ++{0x769cb800, 0xfffffc18, "xvsetallnez.w", "c0:3,x5:5", 0, 0, 0, 0}, ++{0x769cbc00, 0xfffffc18, "xvsetallnez.d", "c0:3,x5:5", 0, 0, 0, 0}, ++{0x769cc400, 0xfffffc00, "xvflogb.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769cc800, 0xfffffc00, "xvflogb.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769cd400, 0xfffffc00, "xvfclass.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769cd800, 0xfffffc00, "xvfclass.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769ce400, 0xfffffc00, "xvfsqrt.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769ce800, 0xfffffc00, "xvfsqrt.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769cf400, 0xfffffc00, "xvfrecip.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769cf800, 0xfffffc00, "xvfrecip.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d0400, 0xfffffc00, "xvfrsqrt.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d0800, 0xfffffc00, "xvfrsqrt.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d3400, 0xfffffc00, "xvfrint.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d3800, 0xfffffc00, "xvfrint.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d4400, 0xfffffc00, "xvfrintrm.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d4800, 0xfffffc00, "xvfrintrm.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d5400, 0xfffffc00, "xvfrintrp.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d5800, 0xfffffc00, "xvfrintrp.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d6400, 0xfffffc00, "xvfrintrz.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d6800, 0xfffffc00, "xvfrintrz.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d7400, 0xfffffc00, "xvfrintrne.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d7800, 0xfffffc00, "xvfrintrne.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769de800, 0xfffffc00, "xvfcvtl.s.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769dec00, 0xfffffc00, "xvfcvth.s.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769df000, 0xfffffc00, "xvfcvtl.d.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769df400, 0xfffffc00, "xvfcvth.d.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e0000, 0xfffffc00, "xvffint.s.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e0400, 0xfffffc00, "xvffint.s.wu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e0800, 0xfffffc00, "xvffint.d.l", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e0c00, 0xfffffc00, "xvffint.d.lu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e1000, 0xfffffc00, "xvffintl.d.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e1400, 0xfffffc00, "xvffinth.d.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e3000, 0xfffffc00, "xvftint.w.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e3400, 0xfffffc00, "xvftint.l.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e3800, 0xfffffc00, "xvftintrm.w.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e3c00, 0xfffffc00, "xvftintrm.l.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e4000, 0xfffffc00, "xvftintrp.w.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e4400, 0xfffffc00, "xvftintrp.l.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e4800, 0xfffffc00, "xvftintrz.w.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e4c00, 0xfffffc00, "xvftintrz.l.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e5000, 0xfffffc00, "xvftintrne.w.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e5400, 0xfffffc00, "xvftintrne.l.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e5800, 0xfffffc00, "xvftint.wu.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e5c00, 0xfffffc00, "xvftint.lu.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e7000, 0xfffffc00, "xvftintrz.wu.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e7400, 0xfffffc00, "xvftintrz.lu.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e8000, 0xfffffc00, "xvftintl.l.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e8400, 0xfffffc00, "xvftinth.l.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e8800, 0xfffffc00, "xvftintrml.l.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e8c00, 0xfffffc00, "xvftintrmh.l.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e9000, 0xfffffc00, "xvftintrpl.l.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e9400, 0xfffffc00, "xvftintrph.l.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e9800, 0xfffffc00, "xvftintrzl.l.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769e9c00, 0xfffffc00, "xvftintrzh.l.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769ea000, 0xfffffc00, "xvftintrnel.l.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769ea400, 0xfffffc00, "xvftintrneh.l.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769ee000, 0xfffffc00, "xvexth.h.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769ee400, 0xfffffc00, "xvexth.w.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769ee800, 0xfffffc00, "xvexth.d.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769eec00, 0xfffffc00, "xvexth.q.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769ef000, 0xfffffc00, "xvexth.hu.bu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769ef400, 0xfffffc00, "xvexth.wu.hu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769ef800, 0xfffffc00, "xvexth.du.wu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769efc00, 0xfffffc00, "xvexth.qu.du", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f0000, 0xfffffc00, "xvreplgr2vr.b", "x0:5,r5:5", 0, 0, 0, 0}, ++{0x769f0400, 0xfffffc00, "xvreplgr2vr.h", "x0:5,r5:5", 0, 0, 0, 0}, ++{0x769f0800, 0xfffffc00, "xvreplgr2vr.w", "x0:5,r5:5", 0, 0, 0, 0}, ++{0x769f0c00, 0xfffffc00, "xvreplgr2vr.d", "x0:5,r5:5", 0, 0, 0, 0}, ++{0x769f1000, 0xfffffc00, "vext2xv.h.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f1400, 0xfffffc00, "vext2xv.w.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f1800, 0xfffffc00, "vext2xv.d.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f1c00, 0xfffffc00, "vext2xv.w.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f2000, 0xfffffc00, "vext2xv.d.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f2400, 0xfffffc00, "vext2xv.d.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f2800, 0xfffffc00, "vext2xv.hu.bu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f2c00, 0xfffffc00, "vext2xv.wu.bu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f3000, 0xfffffc00, "vext2xv.du.bu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f3400, 0xfffffc00, "vext2xv.wu.hu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f3800, 0xfffffc00, "vext2xv.du.hu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f3c00, 0xfffffc00, "vext2xv.du.wu", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769f8000, 0xffff8000, "xvhseli.d", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76a02000, 0xffffe000, "xvrotri.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x76a04000, 0xffffc000, "xvrotri.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x76a08000, 0xffff8000, "xvrotri.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76a10000, 0xffff0000, "xvrotri.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x76a42000, 0xffffe000, "xvsrlri.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x76a44000, 0xffffc000, "xvsrlri.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x76a48000, 0xffff8000, "xvsrlri.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76a50000, 0xffff0000, "xvsrlri.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x76a82000, 0xffffe000, "xvsrari.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x76a84000, 0xffffc000, "xvsrari.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x76a88000, 0xffff8000, "xvsrari.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x76a90000, 0xffff0000, "xvsrari.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x76ebc000, 0xffffe000, "xvinsgr2vr.w", "x0:5,r5:5,u10:3", 0, 0, 0, 0}, ++{0x76ebe000, 0xfffff000, "xvinsgr2vr.d", "x0:5,r5:5,u10:2", 0, 0, 0, 0}, ++{0x76efc000, 0xffffe000, "xvpickve2gr.w", "r0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x76efe000, 0xfffff000, "xvpickve2gr.d", "r0:5,x5:5,u10:2", 0, 0, 0, 0}, ++{0x76f3c000, 0xffffe000, "xvpickve2gr.wu", "r0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x76f3e000, 0xfffff000, "xvpickve2gr.du", "r0:5,x5:5,u10:2", 0, 0, 0, 0}, ++{0x76f78000, 0xffffc000, "xvrepl128vei.b", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x76f7c000, 0xffffe000, "xvrepl128vei.h", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x76f7e000, 0xfffff000, "xvrepl128vei.w", "x0:5,x5:5,u10:2", 0, 0, 0, 0}, ++{0x76f7f000, 0xfffff800, "xvrepl128vei.d", "x0:5,x5:5,u10:1", 0, 0, 0, 0}, ++{0x76ffc000, 0xffffe000, "xvinsve0.w", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x76ffe000, 0xfffff000, "xvinsve0.d", "x0:5,x5:5,u10:2", 0, 0, 0, 0}, ++{0x7703c000, 0xffffe000, "xvpickve.w", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x7703e000, 0xfffff000, "xvpickve.d", "x0:5,x5:5,u10:2", 0, 0, 0, 0}, ++{0x77070000, 0xfffffc00, "xvreplve0.b", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x77078000, 0xfffffc00, "xvreplve0.h", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x7707c000, 0xfffffc00, "xvreplve0.w", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x7707e000, 0xfffffc00, "xvreplve0.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x7707f000, 0xfffffc00, "xvreplve0.q", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x77082000, 0xffffe000, "xvsllwil.h.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x77084000, 0xffffc000, "xvsllwil.w.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77088000, 0xffff8000, "xvsllwil.d.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77090000, 0xfffffc00, "xvextl.q.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x770c2000, 0xffffe000, "xvsllwil.hu.bu", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x770c4000, 0xffffc000, "xvsllwil.wu.hu", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x770c8000, 0xffff8000, "xvsllwil.du.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x770d0000, 0xfffffc00, "xvextl.qu.du", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x77102000, 0xffffe000, "xvbitclri.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x77104000, 0xffffc000, "xvbitclri.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77108000, 0xffff8000, "xvbitclri.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77110000, 0xffff0000, "xvbitclri.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77142000, 0xffffe000, "xvbitseti.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x77144000, 0xffffc000, "xvbitseti.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77148000, 0xffff8000, "xvbitseti.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77150000, 0xffff0000, "xvbitseti.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77182000, 0xffffe000, "xvbitrevi.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x77184000, 0xffffc000, "xvbitrevi.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77188000, 0xffff8000, "xvbitrevi.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77190000, 0xffff0000, "xvbitrevi.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77242000, 0xffffe000, "xvsat.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x77244000, 0xffffc000, "xvsat.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77248000, 0xffff8000, "xvsat.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77250000, 0xffff0000, "xvsat.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77282000, 0xffffe000, "xvsat.bu", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x77284000, 0xffffc000, "xvsat.hu", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77288000, 0xffff8000, "xvsat.wu", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77290000, 0xffff0000, "xvsat.du", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x772c2000, 0xffffe000, "xvslli.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x772c4000, 0xffffc000, "xvslli.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x772c8000, 0xffff8000, "xvslli.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x772d0000, 0xffff0000, "xvslli.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77302000, 0xffffe000, "xvsrli.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x77304000, 0xffffc000, "xvsrli.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77308000, 0xffff8000, "xvsrli.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77310000, 0xffff0000, "xvsrli.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77342000, 0xffffe000, "xvsrai.b", "x0:5,x5:5,u10:3", 0, 0, 0, 0}, ++{0x77344000, 0xffffc000, "xvsrai.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77348000, 0xffff8000, "xvsrai.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77350000, 0xffff0000, "xvsrai.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77404000, 0xffffc000, "xvsrlni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77408000, 0xffff8000, "xvsrlni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77410000, 0xffff0000, "xvsrlni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77420000, 0xfffe0000, "xvsrlni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x77444000, 0xffffc000, "xvsrlrni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77448000, 0xffff8000, "xvsrlrni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77450000, 0xffff0000, "xvsrlrni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77460000, 0xfffe0000, "xvsrlrni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x77484000, 0xffffc000, "xvssrlni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77488000, 0xffff8000, "xvssrlni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77490000, 0xffff0000, "xvssrlni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x774a0000, 0xfffe0000, "xvssrlni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x774c4000, 0xffffc000, "xvssrlni.bu.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x774c8000, 0xffff8000, "xvssrlni.hu.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x774d0000, 0xffff0000, "xvssrlni.wu.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x774e0000, 0xfffe0000, "xvssrlni.du.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x77504000, 0xffffc000, "xvssrlrni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77508000, 0xffff8000, "xvssrlrni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77510000, 0xffff0000, "xvssrlrni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77520000, 0xfffe0000, "xvssrlrni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x77544000, 0xffffc000, "xvssrlrni.bu.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77548000, 0xffff8000, "xvssrlrni.hu.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77550000, 0xffff0000, "xvssrlrni.wu.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77560000, 0xfffe0000, "xvssrlrni.du.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x77584000, 0xffffc000, "xvsrani.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77588000, 0xffff8000, "xvsrani.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77590000, 0xffff0000, "xvsrani.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x775a0000, 0xfffe0000, "xvsrani.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x775c4000, 0xffffc000, "xvsrarni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x775c8000, 0xffff8000, "xvsrarni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x775d0000, 0xffff0000, "xvsrarni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x775e0000, 0xfffe0000, "xvsrarni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x77604000, 0xffffc000, "xvssrani.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77608000, 0xffff8000, "xvssrani.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77610000, 0xffff0000, "xvssrani.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77620000, 0xfffe0000, "xvssrani.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x77644000, 0xffffc000, "xvssrani.bu.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77648000, 0xffff8000, "xvssrani.hu.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77650000, 0xffff0000, "xvssrani.wu.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x77660000, 0xfffe0000, "xvssrani.du.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x77684000, 0xffffc000, "xvssrarni.b.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x77688000, 0xffff8000, "xvssrarni.h.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x77690000, 0xffff0000, "xvssrarni.w.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x776a0000, 0xfffe0000, "xvssrarni.d.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x776c4000, 0xffffc000, "xvssrarni.bu.h", "x0:5,x5:5,u10:4", 0, 0, 0, 0}, ++{0x776c8000, 0xffff8000, "xvssrarni.hu.w", "x0:5,x5:5,u10:5", 0, 0, 0, 0}, ++{0x776d0000, 0xffff0000, "xvssrarni.wu.d", "x0:5,x5:5,u10:6", 0, 0, 0, 0}, ++{0x776e0000, 0xfffe0000, "xvssrarni.du.q", "x0:5,x5:5,u10:7", 0, 0, 0, 0}, ++{0x77800000, 0xfffc0000, "xvextrins.d", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77840000, 0xfffc0000, "xvextrins.w", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77880000, 0xfffc0000, "xvextrins.h", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x778c0000, 0xfffc0000, "xvextrins.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77900000, 0xfffc0000, "xvshuf4i.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77940000, 0xfffc0000, "xvshuf4i.h", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77980000, 0xfffc0000, "xvshuf4i.w", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x779c0000, 0xfffc0000, "xvshuf4i.d", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77c40000, 0xfffc0000, "xvbitseli.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77d00000, 0xfffc0000, "xvandi.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77d40000, 0xfffc0000, "xvori.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77d80000, 0xfffc0000, "xvxori.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77dc0000, 0xfffc0000, "xvnori.b", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0, 0, "xvrepli.b", "x,s0:10", "xvldi %1,(%2)&0x3ff", 0, 0, 0}, ++{0, 0, "xvrepli.d", "x,s0:10", "xvldi %1,((%2)&0x3ff)|0xc00", 0, 0, 0}, ++{0, 0, "xvrepli.h", "x,s0:10", "xvldi %1,((%2)&0x3ff)|0x400", 0, 0, 0}, ++{0, 0, "xvrepli.w", "x,s0:10", "xvldi %1,((%2)&0x3ff)|0x800", 0, 0, 0}, ++{0x77e00000, 0xfffc0000, "xvldi", "x0:5,s5:13", 0, 0, 0, 0}, ++{0x77e40000, 0xfffc0000, "xvpermi.w", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77e80000, 0xfffc0000, "xvpermi.d", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0x77ec0000, 0xfffc0000, "xvpermi.q", "x0:5,x5:5,u10:8", 0, 0, 0, 0}, ++{0} /* Terminate the list. */ ++ ++}; ++ ++struct loongarch_ase loongarch_ASEs[] = { ++ {&LARCH_opts.ase_fix, loongarch_macro_opcodes, 0, 0, {0}, 0, 0}, ++ { &LARCH_opts.ase_fix, loongarch_lmm_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_fix, loongarch_privilege_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_fix, loongarch_load_store_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_fix, loongarch_fix_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_fix, loongarch_jmp_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_float, loongarch_float_jmp_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_float, loongarch_single_float_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_float, loongarch_double_float_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_float, loongarch_4opt_single_float_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_float, loongarch_4opt_double_float_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_float, loongarch_single_float_load_store_opcodes, 0, 0, { 0 }, 0, 0 }, ++ { &LARCH_opts.ase_float, loongarch_double_float_load_store_opcodes, 0, 0, { 0 }, 0, 0 }, ++ {&LARCH_opts.ase_128vec, loongarch_128vec_opcodes, 0, 0, {0}, 0, 0}, ++ {&LARCH_opts.ase_256vec, loongarch_256vec_opcodes, 0, 0, {0}, 0, 0}, ++ {0}, ++}; ++ +-- +2.20.1 + diff --git a/binutils.spec b/binutils.spec index 19453c9..d9b182d 100644 --- a/binutils.spec +++ b/binutils.spec @@ -630,6 +630,8 @@ Patch101: binutils-coffgen-buffer-overrun.patch #Add by Anolis Patch1000: 0001-binutils-anolis-rebrand.patch + +Patch1001: binutils-loongarch-support.patch #end #---------------------------------------------------------------------------- @@ -870,6 +872,7 @@ using libelf instead of BFD. %patch100 -p1 %patch101 -p1 %patch1000 -p1 +%patch1001 -p1 # We cannot run autotools as there is an exact requirement of autoconf-2.59. # FIXME - this is no longer true. Maybe try reinstating autotool use ? @@ -925,7 +928,7 @@ export CFLAGS="$RPM_OPT_FLAGS" CARGS= -case %{binutils_target} in i?86*|sparc*|ppc*|s390*|sh*|arm*|aarch64*) +case %{binutils_target} in i?86*|sparc*|ppc*|s390*|sh*|arm*|aarch64*|loongarch64) CARGS="$CARGS --enable-64-bit-bfd" ;; esac @@ -1321,6 +1324,7 @@ exit 0 %changelog * Tue Dec 27 2022 Xue haolin - 2.30-117.0.1 - Rebrand to Anolis OS. +- Add loongarch support. (lixing@loongson.cn) * Mon Apr 25 2022 Nick Clifton - 2.30-117 - Fix a potential buffer overrun in the BFD library's PE handling code. (#2076973) -- Gitee From 2afbf3e7167f2c55c3609ac58a81952c60658337 Mon Sep 17 00:00:00 2001 From: Liwei Ge Date: Thu, 8 Sep 2022 15:01:44 +0800 Subject: [PATCH 4/5] build: fix error with loongarch-parse.h Signed-off-by: Liwei Ge --- binutils-loongarch-support.patch | 16 +++++----------- binutils.spec | 5 ++++- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/binutils-loongarch-support.patch b/binutils-loongarch-support.patch index 9fdf38d..03c8b96 100644 --- a/binutils-loongarch-support.patch +++ b/binutils-loongarch-support.patch @@ -4401,16 +4401,13 @@ index 758f41dc..3ae74dab 100644 diststuff: $(EXTRA_DIST) info -@@ -521,6 +524,27 @@ rx-parse.h: rx-parse.c +@@ -521,6 +524,24 @@ rx-parse.h: rx-parse.c rx-defs.h: ; @true $(srcdir)/config/rx-defs.h: ; @true +EXTRA_as_new_SOURCES += config/loongarch-parse.y -+loongarch-parse.c: $(srcdir)/config/loongarch-parse.y ++loongarch-parse.c loongarch-parse.h: $(srcdir)/config/loongarch-parse.y + $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-parse.y y.tab.c loongarch-parse.c y.tab.h loongarch-parse.h -- $(YACCCOMPILE) -d ; -+loongarch-parse.h: loongarch-parse.c -+loongarch-parse.h: ; @true -+$(srcdir)/config/loongarch-parse.h: ; @true + +loongarch-lex.c: $(srcdir)/config/loongarch-lex.l + $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-lex.l lex.yy.c loongarch-lex.c -- $(LEXCOMPILE) @@ -4502,7 +4499,7 @@ index b55f2b88..d59a936a 100644 +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tc-loongarch.o `test -f 'config/tc-loongarch.c' || echo '$(srcdir)/'`config/tc-loongarch.c + -+loongarch-parse.o: config/loongarch-parse.c ++loongarch-parse.o: config/loongarch-parse.c loongarch-parse.h +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT loongarch-parse.o -MD -MP -MF $(DEPDIR)/loongarch-parse.Tpo -c -o loongarch-parse.o `test -f 'config/loongarch-parse.c' || echo '$(srcdir)/'`config/loongarch-parse.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/loongarch-parse.Tpo $(DEPDIR)/loongarch-parse.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='config/loongarch-parse.c' object='loongarch-parse.o' libtool=no @AMDEPBACKSLASH@ @@ -4535,16 +4532,13 @@ index b55f2b88..d59a936a 100644 -rm -f m68k-parse.c -rm -f rl78-parse.c -rm -f rx-parse.c -@@ -2642,6 +2679,22 @@ m68k-parse.@OBJEXT@: m68k-parse.c +@@ -2642,6 +2679,19 @@ m68k-parse.@OBJEXT@: m68k-parse.c # Don't let the .y.h rule clobber m68k-parse.h. m68k-parse.h: ; @true $(srcdir)/config/m68k-parse.h: ; @true + -+loongarch-parse.c: $(srcdir)/config/loongarch-parse.y ++loongarch-parse.c loongarch-parse.h: $(srcdir)/config/loongarch-parse.y + $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-parse.y y.tab.c loongarch-parse.c y.tab.h loongarch-parse.h -- $(YACCCOMPILE) -d ; -+loongarch-parse.h: loongarch-parse.c -+loongarch-parse.h: ; @true -+$(srcdir)/config/loongarch-parse.h: ; @true + +loongarch-lex.c: $(srcdir)/config/loongarch-lex.l + $(SHELL) $(YLWRAP) $(srcdir)/config/loongarch-lex.l lex.yy.c loongarch-lex.c -- $(LEXCOMPILE) diff --git a/binutils.spec b/binutils.spec index d9b182d..c8a3417 100644 --- a/binutils.spec +++ b/binutils.spec @@ -666,10 +666,13 @@ Buildroot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) # Perl, sed and touch are all used in the %%prep section of this spec file. BuildRequires: gcc, perl, sed, coreutils +# Loongarch needs yyac +BuildRequires: bison + # Gold needs bison in order to build gold/yyscript.c. # Bison needs m4. %if "%{build_gold}" == "both" -BuildRequires: bison, m4, gcc-c++ +BuildRequires: m4, gcc-c++ %endif %if %{without bootstrap} -- Gitee From a563e4e50890035846b795c4bd68433d5d4c018d Mon Sep 17 00:00:00 2001 From: Xing Li Date: Mon, 31 Oct 2022 20:55:04 +0800 Subject: [PATCH 5/5] LoongArch: Fix wrong line number in .debug_line Add missing opcode Signed-off-by: Xing Li --- binutils.spec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/binutils.spec b/binutils.spec index c8a3417..95dd849 100644 --- a/binutils.spec +++ b/binutils.spec @@ -632,6 +632,8 @@ Patch101: binutils-coffgen-buffer-overrun.patch Patch1000: 0001-binutils-anolis-rebrand.patch Patch1001: binutils-loongarch-support.patch +Patch1002: 0001-LoongArch-Fix-wrong-line-number-in-.debug_line.patch +Patch1003: binutils-LoongArch-Add-missing-opcode.patch #end #---------------------------------------------------------------------------- @@ -876,6 +878,8 @@ using libelf instead of BFD. %patch101 -p1 %patch1000 -p1 %patch1001 -p1 +%patch1002 -p1 +%patch1003 -p1 # We cannot run autotools as there is an exact requirement of autoconf-2.59. # FIXME - this is no longer true. Maybe try reinstating autotool use ? @@ -1328,6 +1332,8 @@ exit 0 * Tue Dec 27 2022 Xue haolin - 2.30-117.0.1 - Rebrand to Anolis OS. - Add loongarch support. (lixing@loongson.cn) +- Fixup LoongArch wrong debug line. (lixing@loongson.cn) +- Add LoongArch missing opcode. (lixing@loongson.cn) * Mon Apr 25 2022 Nick Clifton - 2.30-117 - Fix a potential buffer overrun in the BFD library's PE handling code. (#2076973) -- Gitee