From ed9ed2794d05bd88e020f288f848e10f6741d5d0 Mon Sep 17 00:00:00 2001 From: Xing Li Date: Tue, 18 Jul 2023 15:03:36 +0800 Subject: [PATCH] Fixup some bugs for LoongArch Sync code to vec.27 --- Add-missing-opcode-and-3A6000.patch | 1618 +++++++++++++++++ ...ment-error-in-compilation-due-to-too.patch | 121 ++ Some-testsuite-fix.patch | 58 + binutils-Delete-warning-of-compile.patch | 1014 +++++++++++ binutils.spec | 27 +- ld-Add-ifunc-support.patch | 787 ++++++++ ...-R_LARCH_NONE-relocation-of-eh_frame.patch | 27 + ld-Fix-the-bug-of-pr21964-4.patch | 34 + ld-change-loong64-to-loongarch64.patch | 34 + 9 files changed, 3719 insertions(+), 1 deletion(-) create mode 100644 Add-missing-opcode-and-3A6000.patch create mode 100644 Fix-gas-bug-Segment-error-in-compilation-due-to-too.patch create mode 100644 Some-testsuite-fix.patch create mode 100644 binutils-Delete-warning-of-compile.patch create mode 100644 ld-Add-ifunc-support.patch create mode 100644 ld-Delete-R_LARCH_NONE-relocation-of-eh_frame.patch create mode 100644 ld-Fix-the-bug-of-pr21964-4.patch create mode 100644 ld-change-loong64-to-loongarch64.patch diff --git a/Add-missing-opcode-and-3A6000.patch b/Add-missing-opcode-and-3A6000.patch new file mode 100644 index 0000000..34cf2ea --- /dev/null +++ b/Add-missing-opcode-and-3A6000.patch @@ -0,0 +1,1618 @@ +From 31d01cfd0b4d6fca757269bc1216e01d0f944386 Mon Sep 17 00:00:00 2001 +From: Lixing +Date: Wed, 19 Jul 2023 14:29:38 +0800 +Subject: [PATCH] Add missing opcode and 3A6000 + +Sync to vec.27 +--- + bfd/elfnn-loongarch.c | 27 +- + gas/testsuite/gas/loongarch/3a6000.d | 63 ++ + gas/testsuite/gas/loongarch/3a6000.s | 65 ++ + gas/testsuite/gas/loongarch/loongarch.exp | 23 + + include/elf/loongarch.h | 1 - + opcodes/loongarch-opc.c | 1202 ++++++++++++--------- + 6 files changed, 824 insertions(+), 557 deletions(-) + create mode 100644 gas/testsuite/gas/loongarch/3a6000.d + create mode 100644 gas/testsuite/gas/loongarch/3a6000.s + create mode 100644 gas/testsuite/gas/loongarch/loongarch.exp + +diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c +index cf4d539d..ac4bcc20 100644 +--- a/bfd/elfnn-loongarch.c ++++ b/bfd/elfnn-loongarch.c +@@ -6,6 +6,7 @@ + #include "objalloc.h" + #include "elf/loongarch.h" + #include "elfxx-loongarch.h" ++#include + + static bfd_boolean + loongarch_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, +@@ -714,7 +715,6 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, + h->plt.refcount = 0; + h->plt.refcount++; + h->needs_plt = 1; +- + elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; + } + +@@ -826,6 +826,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, + + if (0 != strcmp(sec->name, ".eh_frame")) + 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. +@@ -1097,7 +1098,6 @@ 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) +@@ -1272,7 +1272,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) + if (h->dynindx == -1) + loongarch_elf_hash_entry(h)->dyn_relocs = NULL; + } +- + } + + for (p = loongarch_elf_hash_entry(h)->dyn_relocs; p != NULL; p = p->next) +@@ -1473,14 +1472,14 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd, + } + } + ++ /* Allocate global sym .plt and .got entries, and space for global ++ sym dynamic relocs. */ ++ elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, info); + + /* Allocate global ifunc sym .plt and .got entries, and space for global + ifunc sym dynamic relocs. */ + elf_link_hash_traverse (&htab->elf, elfNN_allocate_ifunc_dynrelocs, info); + +- /* Allocate 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, + (void *) elfNN_allocate_local_ifunc_dynrelocs, info); +@@ -2241,6 +2240,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, + b. 此外,比如代码段的重定位无法动态改变其的引用位置,所以必须走plt + 来实现IFUNC。 + c. 因此,为方便实现,我们将plt stub的位置当作IFUNC符号的定义。 */ ++ + defined_local = TRUE; + resolved_local = TRUE; + resolved_dynly = FALSE; +@@ -2281,13 +2281,13 @@ loongarch_elf_relocate_section (bfd *output_bfd, + /* When generating a shared object, these relocations are copied + into the output file to be resolved at run time. */ + +- + outrel.r_offset = _bfd_elf_section_offset (output_bfd, info, + input_section, + rel->r_offset); + + unresolved_reloc = (!((bfd_vma) -2 <= outrel.r_offset) + && (input_section->flags & SEC_ALLOC)); ++ + outrel.r_offset += sec_addr (input_section); + + /* A pointer point to a ifunc symbol. */ +@@ -2426,7 +2426,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, + } + + break; +- ++ + case R_LARCH_SOP_PUSH_TLS_TPREL: + if (resolved_local) + { +@@ -2443,7 +2443,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, + (info, input_bfd, input_section, rel, howto, + bfd_reloc_undefined, is_undefweak, name, + "TLS LE just can be resolved local only.")); +- + break; + + case R_LARCH_SOP_PUSH_ABSOLUTE: +@@ -2563,7 +2562,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, + bfd_reloc_dangerous, is_undefweak, name, + "Internal: PLT stub doesn't represent. " + "Resolve it with pcrel")); +- + i = 1, j = 3; + } + } +@@ -2587,7 +2585,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, + "PLT shouldn't be with r_addend.")); + break; + } +- + relocation = sec_addr (plt) + h->plt.offset - pc; + break; + } +@@ -2681,7 +2678,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, + "Internal: ")); + break; + } +- ++ + asection *s; + Elf_Internal_Rela outrel; + /* We need to generate a R_LARCH_RELATIVE reloc +@@ -2731,7 +2728,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, + /* The offset must always be a multiple of the word size. + So, we can use the least significant bit to record + whether we have already processed this entry. */ +- + if ((local_got_offsets[r_symndx] & 1) == 0) + { + if (is_pic) +@@ -2761,12 +2757,11 @@ loongarch_elf_relocate_section (bfd *output_bfd, + } + } + relocation = off; ++ + break; + + case R_LARCH_SOP_PUSH_TLS_GOT: +- is_ie = TRUE; + case R_LARCH_SOP_PUSH_TLS_GD: +- + { + unresolved_reloc = FALSE; + if (r_type == R_LARCH_SOP_PUSH_TLS_GOT) +@@ -2866,7 +2861,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, + } + } + +- + relocation = (got_off & (~(bfd_vma)1)) + (is_ie ? ie_off : 0); + } + break; +@@ -2898,7 +2892,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, + bfd_reloc_dangerous, is_undefweak, name, + "Seems dynamic linker not process " + "sections 'SEC_DEBUGGING'.")); +- + break; + } + if (!is_dyn) +diff --git a/gas/testsuite/gas/loongarch/3a6000.d b/gas/testsuite/gas/loongarch/3a6000.d +new file mode 100644 +index 00000000..eca22eb4 +--- /dev/null ++++ b/gas/testsuite/gas/loongarch/3a6000.d +@@ -0,0 +1,63 @@ ++#as: ++#objdump: -dr ++ ++.*:[ ]+file format .* ++ ++ ++Disassembly of section .text: ++ ++00000000.* <.text>: ++[ ]+0:[ ]+38570881[ ]+sc.q[ ]+\$r1,\$r2,\$r4 ++[ ]+4:[ ]+38570881[ ]+sc.q[ ]+\$r1,\$r2,\$r4 ++[ ]+8:[ ]+38578041[ ]+llacq.w[ ]+\$r1,\$r2 ++[ ]+c:[ ]+38578841[ ]+llacq.d[ ]+\$r1,\$r2 ++[ ]+10:[ ]+38578041[ ]+llacq.w[ ]+\$r1,\$r2 ++[ ]+14:[ ]+38578841[ ]+llacq.d[ ]+\$r1,\$r2 ++[ ]+18:[ ]+38578441[ ]+screl.w[ ]+\$r1,\$r2 ++[ ]+1c:[ ]+38578c41[ ]+screl.d[ ]+\$r1,\$r2 ++[ ]+20:[ ]+38578441[ ]+screl.w[ ]+\$r1,\$r2 ++[ ]+24:[ ]+38578c41[ ]+screl.d[ ]+\$r1,\$r2 ++[ ]+28:[ ]+38580881[ ]+amcas.b[ ]+\$r1,\$r2,\$r4 ++[ ]+2c:[ ]+38588881[ ]+amcas.h[ ]+\$r1,\$r2,\$r4 ++[ ]+30:[ ]+38590881[ ]+amcas.w[ ]+\$r1,\$r2,\$r4 ++[ ]+34:[ ]+38598881[ ]+amcas.d[ ]+\$r1,\$r2,\$r4 ++[ ]+38:[ ]+38580881[ ]+amcas.b[ ]+\$r1,\$r2,\$r4 ++[ ]+3c:[ ]+38588881[ ]+amcas.h[ ]+\$r1,\$r2,\$r4 ++[ ]+40:[ ]+38590881[ ]+amcas.w[ ]+\$r1,\$r2,\$r4 ++[ ]+44:[ ]+38598881[ ]+amcas.d[ ]+\$r1,\$r2,\$r4 ++[ ]+48:[ ]+385a0881[ ]+amcas_db.b[ ]+\$r1,\$r2,\$r4 ++[ ]+4c:[ ]+385a8881[ ]+amcas_db.h[ ]+\$r1,\$r2,\$r4 ++[ ]+50:[ ]+385b0881[ ]+amcas_db.w[ ]+\$r1,\$r2,\$r4 ++[ ]+54:[ ]+385b8881[ ]+amcas_db.d[ ]+\$r1,\$r2,\$r4 ++[ ]+58:[ ]+385a0881[ ]+amcas_db.b[ ]+\$r1,\$r2,\$r4 ++[ ]+5c:[ ]+385a8881[ ]+amcas_db.h[ ]+\$r1,\$r2,\$r4 ++[ ]+60:[ ]+385b0881[ ]+amcas_db.w[ ]+\$r1,\$r2,\$r4 ++[ ]+64:[ ]+385b8881[ ]+amcas_db.d[ ]+\$r1,\$r2,\$r4 ++[ ]+68:[ ]+385c0881[ ]+amswap.b[ ]+\$r1,\$r2,\$r4 ++[ ]+6c:[ ]+385c8881[ ]+amswap.h[ ]+\$r1,\$r2,\$r4 ++[ ]+70:[ ]+385d0881[ ]+amadd.b[ ]+\$r1,\$r2,\$r4 ++[ ]+74:[ ]+385d8881[ ]+amadd.h[ ]+\$r1,\$r2,\$r4 ++[ ]+78:[ ]+385c0881[ ]+amswap.b[ ]+\$r1,\$r2,\$r4 ++[ ]+7c:[ ]+385c8881[ ]+amswap.h[ ]+\$r1,\$r2,\$r4 ++[ ]+80:[ ]+385d0881[ ]+amadd.b[ ]+\$r1,\$r2,\$r4 ++[ ]+84:[ ]+385d8881[ ]+amadd.h[ ]+\$r1,\$r2,\$r4 ++[ ]+88:[ ]+385e0881[ ]+amswap_db.b[ ]+\$r1,\$r2,\$r4 ++[ ]+8c:[ ]+385e8881[ ]+amswap_db.h[ ]+\$r1,\$r2,\$r4 ++[ ]+90:[ ]+385f0881[ ]+amadd_db.b[ ]+\$r1,\$r2,\$r4 ++[ ]+94:[ ]+385f8881[ ]+amadd_db.h[ ]+\$r1,\$r2,\$r4 ++[ ]+98:[ ]+385e0881[ ]+amswap_db.b[ ]+\$r1,\$r2,\$r4 ++[ ]+9c:[ ]+385e8881[ ]+amswap_db.h[ ]+\$r1,\$r2,\$r4 ++[ ]+a0:[ ]+385f0881[ ]+amadd_db.b[ ]+\$r1,\$r2,\$r4 ++[ ]+a4:[ ]+385f8881[ ]+amadd_db.h[ ]+\$r1,\$r2,\$r4 ++[ ]+a8:[ ]+01147441[ ]+frecipe.s[ ]+\$f1,\$f2 ++[ ]+ac:[ ]+01147841[ ]+frecipe.d[ ]+\$f1,\$f2 ++[ ]+b0:[ ]+729d1441[ ]+vfrecipe.s[ ]+\$vr1,\$vr2 ++[ ]+b4:[ ]+729d1841[ ]+vfrecipe.d[ ]+\$vr1,\$vr2 ++[ ]+b8:[ ]+769d1441[ ]+xvfrecipe.s[ ]+\$xr1,\$xr2 ++[ ]+bc:[ ]+769d1841[ ]+xvfrecipe.d[ ]+\$xr1,\$xr2 ++[ ]+c0:[ ]+01148441[ ]+frsqrte.s[ ]+\$f1,\$f2 ++[ ]+c4:[ ]+01148841[ ]+frsqrte.d[ ]+\$f1,\$f2 ++[ ]+c8:[ ]+729d2441[ ]+vfrsqrte.s[ ]+\$vr1,\$vr2 ++[ ]+cc:[ ]+729d2841[ ]+vfrsqrte.d[ ]+\$vr1,\$vr2 ++[ ]+d0:[ ]+769d2441[ ]+xvfrsqrte.s[ ]+\$xr1,\$xr2 ++[ ]+d4:[ ]+769d2841[ ]+xvfrsqrte.d[ ]+\$xr1,\$xr2 +diff --git a/gas/testsuite/gas/loongarch/3a6000.s b/gas/testsuite/gas/loongarch/3a6000.s +new file mode 100644 +index 00000000..cd355235 +--- /dev/null ++++ b/gas/testsuite/gas/loongarch/3a6000.s +@@ -0,0 +1,65 @@ ++# sc.q $rd, $rk, $rj ++sc.q $r1, $r2, $r4 ++sc.q $r1, $r2, $r4, 0 ++ ++llacq.w $r1, $r2 ++llacq.d $r1, $r2 ++llacq.w $r1, $r2, 0 ++llacq.d $r1, $r2, 0 ++ ++screl.w $r1, $r2 ++screl.d $r1, $r2 ++screl.w $r1, $r2, 0 ++screl.d $r1, $r2, 0 ++ ++# amcas.b $rd, $rk, $rj ++amcas.b $r1, $r2, $r4 ++amcas.h $r1, $r2, $r4 ++amcas.w $r1, $r2, $r4 ++amcas.d $r1, $r2, $r4 ++amcas.b $r1, $r2, $r4, 0 ++amcas.h $r1, $r2, $r4, 0 ++amcas.w $r1, $r2, $r4, 0 ++amcas.d $r1, $r2, $r4, 0 ++ ++amcas_db.b $r1, $r2, $r4 ++amcas_db.h $r1, $r2, $r4 ++amcas_db.w $r1, $r2, $r4 ++amcas_db.d $r1, $r2, $r4 ++amcas_db.b $r1, $r2, $r4, 0 ++amcas_db.h $r1, $r2, $r4, 0 ++amcas_db.w $r1, $r2, $r4, 0 ++amcas_db.d $r1, $r2, $r4, 0 ++ ++amswap.b $r1, $r2, $r4 ++amswap.h $r1, $r2, $r4 ++amadd.b $r1, $r2, $r4 ++amadd.h $r1, $r2, $r4 ++amswap.b $r1, $r2, $r4, 0 ++amswap.h $r1, $r2, $r4, 0 ++amadd.b $r1, $r2, $r4, 0 ++amadd.h $r1, $r2, $r4, 0 ++ ++amswap_db.b $r1, $r2, $r4 ++amswap_db.h $r1, $r2, $r4 ++amadd_db.b $r1, $r2, $r4 ++amadd_db.h $r1, $r2, $r4 ++amswap_db.b $r1, $r2, $r4, 0 ++amswap_db.h $r1, $r2, $r4, 0 ++amadd_db.b $r1, $r2, $r4, 0 ++amadd_db.h $r1, $r2, $r4, 0 ++ ++frecipe.s $f1, $f2 ++frecipe.d $f1, $f2 ++vfrecipe.s $vr1, $vr2 ++vfrecipe.d $vr1, $vr2 ++xvfrecipe.s $xr1, $xr2 ++xvfrecipe.d $xr1, $xr2 ++ ++frsqrte.s $f1, $f2 ++frsqrte.d $f1, $f2 ++vfrsqrte.s $vr1, $vr2 ++vfrsqrte.d $vr1, $vr2 ++xvfrsqrte.s $xr1, $xr2 ++xvfrsqrte.d $xr1, $xr2 ++ +diff --git a/gas/testsuite/gas/loongarch/loongarch.exp b/gas/testsuite/gas/loongarch/loongarch.exp +new file mode 100644 +index 00000000..8e256cd6 +--- /dev/null ++++ b/gas/testsuite/gas/loongarch/loongarch.exp +@@ -0,0 +1,23 @@ ++# Expect script for LoongArch assembler tests. ++# Copyright (C) 2011-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. ++ ++if [istarget loongarch*-*-*] { ++ run_dump_tests [lsort [glob -nocomplain $srcdir/$subdir/*.d]] ++} +diff --git a/include/elf/loongarch.h b/include/elf/loongarch.h +index 02085dd3..09a8ad23 100644 +--- a/include/elf/loongarch.h ++++ b/include/elf/loongarch.h +@@ -1,7 +1,6 @@ + #ifndef _ELF_LOONG_H + #define _ELF_LOONG_H + +-#include + #include "elf/reloc-macros.h" + #include "libiberty.h" + +diff --git a/opcodes/loongarch-opc.c b/opcodes/loongarch-opc.c +index fb36e561..21b0aff0 100644 +--- a/opcodes/loongarch-opc.c ++++ b/opcodes/loongarch-opc.c +@@ -257,529 +257,452 @@ static struct loongarch_opcode loongarch_macro_opcodes[] = { + {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_fix_opcodes[] = { ++/* match, mask, name, format, macro, include, exclude, pinfo */ ++{0, 0, "sc.q", "r,r,r,u0:0", "sc.q %1,%2,%3", 0, 0, 0}, ++{0x38570000, 0xffff8000, "sc.q", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "llacq.w", "r,r,u0:0", "llacq.w %1,%2", 0, 0, 0}, ++{0x38578000, 0xfffffc00, "llacq.w", "r0:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "llacq.d", "r,r,u0:0", "llacq.d %1,%2", 0, 0, 0}, ++{0x38578800, 0xfffffc00, "llacq.d", "r0:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "screl.w", "r,r,u0:0", "screl.w %1,%2", 0, 0, 0}, ++{0x38578400, 0xfffffc00, "screl.w", "r0:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "screl.d", "r,r,u0:0", "screl.d %1,%2", 0, 0, 0}, ++{0x38578c00, 0xfffffc00, "screl.d", "r0:5,r5:5", 0, 0, 0, 0}, ++{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}, ++{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, 0xfffffc00, "move", "r0:5,r5:5", 0/* or %1,%2,$r0 */, 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_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_float_opcodes[] = { ++/* match, mask, name, format, macro, include, exclude, pinfo */ ++{0x01147400, 0xfffffc00, "frecipe.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01147800, 0xfffffc00, "frecipe.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01148400, 0xfffffc00, "frsqrte.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01148800, 0xfffffc00, "frsqrte.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01008000, 0xffff8000, "fadd.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01010000, 0xffff8000, "fadd.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01028000, 0xffff8000, "fsub.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01030000, 0xffff8000, "fsub.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01048000, 0xffff8000, "fmul.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01050000, 0xffff8000, "fmul.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01068000, 0xffff8000, "fdiv.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01070000, 0xffff8000, "fdiv.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01088000, 0xffff8000, "fmax.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01090000, 0xffff8000, "fmax.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x010a8000, 0xffff8000, "fmin.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x010b0000, 0xffff8000, "fmin.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x010c8000, 0xffff8000, "fmaxa.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x010d0000, 0xffff8000, "fmaxa.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x010e8000, 0xffff8000, "fmina.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x010f0000, 0xffff8000, "fmina.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01108000, 0xffff8000, "fscaleb.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01110000, 0xffff8000, "fscaleb.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01128000, 0xffff8000, "fcopysign.s", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01130000, 0xffff8000, "fcopysign.d", "f0:5,f5:5,f10:5", 0, 0, 0, 0}, ++{0x01140400, 0xfffffc00, "fabs.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01140800, 0xfffffc00, "fabs.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01141400, 0xfffffc00, "fneg.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01141800, 0xfffffc00, "fneg.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01142400, 0xfffffc00, "flogb.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01142800, 0xfffffc00, "flogb.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01143400, 0xfffffc00, "fclass.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01143800, 0xfffffc00, "fclass.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01144400, 0xfffffc00, "fsqrt.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01144800, 0xfffffc00, "fsqrt.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01145400, 0xfffffc00, "frecip.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01145800, 0xfffffc00, "frecip.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01146400, 0xfffffc00, "frsqrt.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01146800, 0xfffffc00, "frsqrt.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01149400, 0xfffffc00, "fmov.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x01149800, 0xfffffc00, "fmov.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x0114a400, 0xfffffc00, "movgr2fr.w", "f0:5,r5:5", 0, 0, 0, 0}, ++{0x0114a800, 0xfffffc00, "movgr2fr.d", "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}, ++{0x0114b800, 0xfffffc00, "movfr2gr.d", "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}, ++{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}, ++{0x011a0400, 0xfffffc00, "ftintrm.w.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011a0800, 0xfffffc00, "ftintrm.w.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011a2400, 0xfffffc00, "ftintrm.l.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011a2800, 0xfffffc00, "ftintrm.l.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011a4400, 0xfffffc00, "ftintrp.w.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011a4800, 0xfffffc00, "ftintrp.w.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011a6400, 0xfffffc00, "ftintrp.l.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011a6800, 0xfffffc00, "ftintrp.l.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011a8400, 0xfffffc00, "ftintrz.w.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011a8800, 0xfffffc00, "ftintrz.w.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011aa400, 0xfffffc00, "ftintrz.l.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011aa800, 0xfffffc00, "ftintrz.l.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011ac400, 0xfffffc00, "ftintrne.w.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011ac800, 0xfffffc00, "ftintrne.w.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011ae400, 0xfffffc00, "ftintrne.l.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011ae800, 0xfffffc00, "ftintrne.l.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011b0400, 0xfffffc00, "ftint.w.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011b0800, 0xfffffc00, "ftint.w.d", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011b2400, 0xfffffc00, "ftint.l.s", "f0:5,f5:5", 0, 0, 0, 0}, ++{0x011b2800, 0xfffffc00, "ftint.l.d", "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}, ++{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}, ++{0x011e4400, 0xfffffc00, "frint.s", "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_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_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}, ++{0, 0, "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_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_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_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_4opt_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}, ++{0x08200000, 0xfff00000, "fmadd.d", "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}, ++{0x08600000, 0xfff00000, "fmsub.d", "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}, ++{0x08a00000, 0xfff00000, "fnmadd.d", "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}, ++{0x08e00000, 0xfff00000, "fnmsub.d", "f0:5,f5:5,f10:5,f15:5", 0, 0, 0, 0}, ++{0x09100000, 0xfff00000, "vfmadd.s", "v0:5,v5:5,v10:5,v15:5", 0, 0, 0, 0}, ++{0x09200000, 0xfff00000, "vfmadd.d", "v0:5,v5:5,v10:5,v15:5", 0, 0, 0, 0}, ++{0x09500000, 0xfff00000, "vfmsub.s", "v0:5,v5:5,v10:5,v15:5", 0, 0, 0, 0}, ++{0x09600000, 0xfff00000, "vfmsub.d", "v0:5,v5:5,v10:5,v15:5", 0, 0, 0, 0}, ++{0x09900000, 0xfff00000, "vfnmadd.s", "v0:5,v5:5,v10:5,v15:5", 0, 0, 0, 0}, ++{0x09a00000, 0xfff00000, "vfnmadd.d", "v0:5,v5:5,v10:5,v15:5", 0, 0, 0, 0}, ++{0x09d00000, 0xfff00000, "vfnmsub.s", "v0:5,v5:5,v10:5,v15:5", 0, 0, 0, 0}, ++{0x09e00000, 0xfff00000, "vfnmsub.d", "v0:5,v5:5,v10:5,v15:5", 0, 0, 0, 0}, ++{0x0a100000, 0xfff00000, "xvfmadd.s", "x0:5,x5:5,x10:5,x15:5", 0, 0, 0, 0}, ++{0x0a200000, 0xfff00000, "xvfmadd.d", "x0:5,x5:5,x10:5,x15:5", 0, 0, 0, 0}, ++{0x0a500000, 0xfff00000, "xvfmsub.s", "x0:5,x5:5,x10:5,x15:5", 0, 0, 0, 0}, ++{0x0a600000, 0xfff00000, "xvfmsub.d", "x0:5,x5:5,x10:5,x15:5", 0, 0, 0, 0}, ++{0x0a900000, 0xfff00000, "xvfnmadd.s", "x0:5,x5:5,x10:5,x15:5", 0, 0, 0, 0}, ++{0x0aa00000, 0xfff00000, "xvfnmadd.d", "x0:5,x5:5,x10:5,x15:5", 0, 0, 0, 0}, ++{0x0ad00000, 0xfff00000, "xvfnmsub.s", "x0:5,x5:5,x10:5,x15:5", 0, 0, 0, 0}, ++{0x0ae00000, 0xfff00000, "xvfnmsub.d", "x0:5,x5:5,x10:5,x15: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}, ++{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}, ++{0x0c500000, 0xffff8000, "vfcmp.caf.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c508000, 0xffff8000, "vfcmp.saf.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c510000, 0xffff8000, "vfcmp.clt.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c518000, 0xffff8000, "vfcmp.slt.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c520000, 0xffff8000, "vfcmp.ceq.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c528000, 0xffff8000, "vfcmp.seq.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c530000, 0xffff8000, "vfcmp.cle.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c538000, 0xffff8000, "vfcmp.sle.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c540000, 0xffff8000, "vfcmp.cun.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c548000, 0xffff8000, "vfcmp.sun.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c550000, 0xffff8000, "vfcmp.cult.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c558000, 0xffff8000, "vfcmp.sult.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c560000, 0xffff8000, "vfcmp.cueq.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c568000, 0xffff8000, "vfcmp.sueq.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c570000, 0xffff8000, "vfcmp.cule.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c578000, 0xffff8000, "vfcmp.sule.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c580000, 0xffff8000, "vfcmp.cne.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c588000, 0xffff8000, "vfcmp.sne.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c5a0000, 0xffff8000, "vfcmp.cor.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c5a8000, 0xffff8000, "vfcmp.sor.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c5c0000, 0xffff8000, "vfcmp.cune.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c5c8000, 0xffff8000, "vfcmp.sune.s", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c600000, 0xffff8000, "vfcmp.caf.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c608000, 0xffff8000, "vfcmp.saf.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c610000, 0xffff8000, "vfcmp.clt.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c618000, 0xffff8000, "vfcmp.slt.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c620000, 0xffff8000, "vfcmp.ceq.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c628000, 0xffff8000, "vfcmp.seq.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c630000, 0xffff8000, "vfcmp.cle.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c638000, 0xffff8000, "vfcmp.sle.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c640000, 0xffff8000, "vfcmp.cun.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c648000, 0xffff8000, "vfcmp.sun.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c650000, 0xffff8000, "vfcmp.cult.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c658000, 0xffff8000, "vfcmp.sult.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c660000, 0xffff8000, "vfcmp.cueq.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c668000, 0xffff8000, "vfcmp.sueq.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c670000, 0xffff8000, "vfcmp.cule.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c678000, 0xffff8000, "vfcmp.sule.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c680000, 0xffff8000, "vfcmp.cne.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c688000, 0xffff8000, "vfcmp.sne.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c6a0000, 0xffff8000, "vfcmp.cor.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c6a8000, 0xffff8000, "vfcmp.sor.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c6c0000, 0xffff8000, "vfcmp.cune.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c6c8000, 0xffff8000, "vfcmp.sune.d", "v0:5,v5:5,v10:5", 0, 0, 0, 0}, ++{0x0c900000, 0xffff8000, "xvfcmp.caf.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c908000, 0xffff8000, "xvfcmp.saf.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c910000, 0xffff8000, "xvfcmp.clt.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c918000, 0xffff8000, "xvfcmp.slt.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c920000, 0xffff8000, "xvfcmp.ceq.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c928000, 0xffff8000, "xvfcmp.seq.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c930000, 0xffff8000, "xvfcmp.cle.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c938000, 0xffff8000, "xvfcmp.sle.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c940000, 0xffff8000, "xvfcmp.cun.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c948000, 0xffff8000, "xvfcmp.sun.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c950000, 0xffff8000, "xvfcmp.cult.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c958000, 0xffff8000, "xvfcmp.sult.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c960000, 0xffff8000, "xvfcmp.cueq.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c968000, 0xffff8000, "xvfcmp.sueq.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c970000, 0xffff8000, "xvfcmp.cule.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c978000, 0xffff8000, "xvfcmp.sule.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c980000, 0xffff8000, "xvfcmp.cne.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c988000, 0xffff8000, "xvfcmp.sne.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c9a0000, 0xffff8000, "xvfcmp.cor.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c9a8000, 0xffff8000, "xvfcmp.sor.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c9c0000, 0xffff8000, "xvfcmp.cune.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0c9c8000, 0xffff8000, "xvfcmp.sune.s", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca00000, 0xffff8000, "xvfcmp.caf.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca08000, 0xffff8000, "xvfcmp.saf.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca10000, 0xffff8000, "xvfcmp.clt.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca18000, 0xffff8000, "xvfcmp.slt.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca20000, 0xffff8000, "xvfcmp.ceq.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca28000, 0xffff8000, "xvfcmp.seq.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca30000, 0xffff8000, "xvfcmp.cle.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca38000, 0xffff8000, "xvfcmp.sle.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca40000, 0xffff8000, "xvfcmp.cun.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca48000, 0xffff8000, "xvfcmp.sun.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca50000, 0xffff8000, "xvfcmp.cult.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca58000, 0xffff8000, "xvfcmp.sult.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca60000, 0xffff8000, "xvfcmp.cueq.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca68000, 0xffff8000, "xvfcmp.sueq.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca70000, 0xffff8000, "xvfcmp.cule.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca78000, 0xffff8000, "xvfcmp.sule.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca80000, 0xffff8000, "xvfcmp.cne.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0ca88000, 0xffff8000, "xvfcmp.sne.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0caa0000, 0xffff8000, "xvfcmp.cor.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0caa8000, 0xffff8000, "xvfcmp.sor.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0cac0000, 0xffff8000, "xvfcmp.cune.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0cac8000, 0xffff8000, "xvfcmp.sune.d", "x0:5,x5:5,x10:5", 0, 0, 0, 0}, ++{0x0d000000, 0xfffc0000, "fsel", "f0:5,f5:5,f10:5,c15:3", 0, 0, 0, 0}, ++{0x0d100000, 0xfff00000, "vbitsel.v", "v0:5,v5:5,v10:5,v15:5", 0, 0, 0, 0}, ++{0x0d200000, 0xfff00000, "xvbitsel.v", "x0:5,x5:5,x10:5,x15:5", 0, 0, 0, 0}, ++{0x0d500000, 0xfff00000, "vshuf.b", "v0:5,v5:5,v10:5,v15:5", 0, 0, 0, 0}, ++{0x0d600000, 0xfff00000, "xvshuf.b", "x0:5,x5:5,x10:5,x15:5", 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[] = { ++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}, ++{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}, ++{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}, + {0x2c000000, 0xffc00000, "vld", "v0:5,r5:5,s10:12", 0, 0, 0, 0}, + {0x2c400000, 0xffc00000, "vst", "v0:5,r5:5,s10:12", 0, 0, 0, 0}, ++{0x2c800000, 0xffc00000, "xvld", "x0:5,r5:5,s10:12", 0, 0, 0, 0}, ++{0x2cc00000, 0xffc00000, "xvst", "x0:5,r5:5,s10:12", 0, 0, 0, 0}, + {0x30100000, 0xfff80000, "vldrepl.d", "v0:5,r5:5,s10:9<<3", 0, 0, 0, 0}, + {0x30200000, 0xfff00000, "vldrepl.w", "v0:5,r5:5,s10:10<<2", 0, 0, 0, 0}, + {0x30400000, 0xffe00000, "vldrepl.h", "v0:5,r5:5,s10:11<<1", 0, 0, 0, 0}, +@@ -788,8 +711,220 @@ static struct loongarch_opcode loongarch_128vec_opcodes[] = { + {0x31200000, 0xfff00000, "vstelm.w", "v0:5,r5:5,s10:8<<2,u18:2", 0, 0, 0, 0}, + {0x31400000, 0xffe00000, "vstelm.h", "v0:5,r5:5,s10:8<<1,u18:3", 0, 0, 0, 0}, + {0x31800000, 0xffc00000, "vstelm.b", "v0:5,r5:5,s10:8,u18:4", 0, 0, 0, 0}, ++{0x32100000, 0xfff80000, "xvldrepl.d", "x0:5,r5:5,s10:9<<3", 0, 0, 0, 0}, ++{0x32200000, 0xfff00000, "xvldrepl.w", "x0:5,r5:5,s10:10<<2", 0, 0, 0, 0}, ++{0x32400000, 0xffe00000, "xvldrepl.h", "x0:5,r5:5,s10:11<<1", 0, 0, 0, 0}, ++{0x32800000, 0xffc00000, "xvldrepl.b", "x0:5,r5:5,s10:12", 0, 0, 0, 0}, ++{0x33100000, 0xfff00000, "xvstelm.d", "x0:5,r5:5,s10:8<<3,u18:2", 0, 0, 0, 0}, ++{0x33200000, 0xffe00000, "xvstelm.w", "x0:5,r5:5,s10:8<<2,u18:3", 0, 0, 0, 0}, ++{0x33400000, 0xffc00000, "xvstelm.h", "x0:5,r5:5,s10:8<<1,u18:4", 0, 0, 0, 0}, ++{0x33800000, 0xff800000, "xvstelm.b", "x0:5,r5:5,s10:8,u18:5", 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}, ++{0x38300000, 0xffff8000, "fldx.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x38340000, 0xffff8000, "fldx.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x38380000, 0xffff8000, "fstx.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x383c0000, 0xffff8000, "fstx.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, + {0x38400000, 0xffff8000, "vldx", "v0:5,r5:5,r10:5", 0, 0, 0, 0}, + {0x38440000, 0xffff8000, "vstx", "v0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x38480000, 0xffff8000, "xvldx", "x0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x384c0000, 0xffff8000, "xvstx", "x0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0, 0, "amcas.b", "r,r,r,u0:0", "amcas.b %1,%2,%3", 0, 0, 0}, ++{0x38580000, 0xffff8000, "amcas.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amcas.h", "r,r,r,u0:0", "amcas.h %1,%2,%3", 0, 0, 0}, ++{0x38588000, 0xffff8000, "amcas.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amcas.w", "r,r,r,u0:0", "amcas.w %1,%2,%3", 0, 0, 0}, ++{0x38590000, 0xffff8000, "amcas.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amcas.d", "r,r,r,u0:0", "amcas.d %1,%2,%3", 0, 0, 0}, ++{0x38598000, 0xffff8000, "amcas.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amcas_db.b", "r,r,r,u0:0", "amcas_db.b %1,%2,%3", 0, 0, 0}, ++{0x385a0000, 0xffff8000, "amcas_db.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amcas_db.h", "r,r,r,u0:0", "amcas_db.h %1,%2,%3", 0, 0, 0}, ++{0x385a8000, 0xffff8000, "amcas_db.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amcas_db.w", "r,r,r,u0:0", "amcas_db.w %1,%2,%3", 0, 0, 0}, ++{0x385b0000, 0xffff8000, "amcas_db.w", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amcas_db.d", "r,r,r,u0:0", "amcas_db.d %1,%2,%3", 0, 0, 0}, ++{0x385b8000, 0xffff8000, "amcas_db.d", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amswap.b", "r,r,r,u0:0", "amswap.b %1,%2,%3", 0, 0, 0}, ++{0x385c0000, 0xffff8000, "amswap.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amswap.h", "r,r,r,u0:0", "amswap.h %1,%2,%3", 0, 0, 0}, ++{0x385c8000, 0xffff8000, "amswap.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amadd.b", "r,r,r,u0:0", "amadd.b %1,%2,%3", 0, 0, 0}, ++{0x385d0000, 0xffff8000, "amadd.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amadd.h", "r,r,r,u0:0", "amadd.h %1,%2,%3", 0, 0, 0}, ++{0x385d8000, 0xffff8000, "amadd.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amswap_db.b", "r,r,r,u0:0", "amswap_db.b %1,%2,%3", 0, 0, 0}, ++{0x385e0000, 0xffff8000, "amswap_db.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amswap_db.h", "r,r,r,u0:0", "amswap_db.h %1,%2,%3", 0, 0, 0}, ++{0x385e8000, 0xffff8000, "amswap_db.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amadd_db.b", "r,r,r,u0:0", "amadd_db.b %1,%2,%3", 0, 0, 0}, ++{0x385f0000, 0xffff8000, "amadd_db.b", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "amadd_db.h", "r,r,r,u0:0", "amadd_db.h %1,%2,%3", 0, 0, 0}, ++{0x385f8000, 0xffff8000, "amadd_db.h", "r0:5,r10:5,r5:5", 0, 0, 0, 0}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0x38740000, 0xffff8000, "fldgt.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x38748000, 0xffff8000, "fldgt.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x38750000, 0xffff8000, "fldle.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x38758000, 0xffff8000, "fldle.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x38760000, 0xffff8000, "fstgt.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x38768000, 0xffff8000, "fstgt.d", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x38770000, 0xffff8000, "fstle.s", "f0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x38778000, 0xffff8000, "fstle.d", "f0:5,r5:5,r10:5", 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_jmp_opcodes[] = { ++/* match, mask, name, format, macro, include, exclude, pinfo */ ++{0, 0, "beqz", "r,la", "beqz %1,%%pcrel(%2)", 0, 0, 0}, ++{0x40000000, 0xfc000000, "beqz", "r5:5,sb0:5|10:16<<2", 0, 0, 0, 0}, ++{0, 0, "bnez", "r,la", "bnez %1,%%pcrel(%2)", 0, 0, 0}, ++{0x44000000, 0xfc000000, "bnez", "r5:5,sb0:5|10:16<<2", 0, 0, 0, 0}, ++{0, 0, "bceqz", "c,la", "bceqz %1,%%pcrel(%2)", 0, 0, 0}, ++{0x48000000, 0xfc000300, "bceqz", "c5:3,sb0:5|10:16<<2", 0, 0, 0, 0}, ++{0, 0, "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, 0, "jr", "r", "jirl $r0,%1,0", 0, 0, 0}, ++{0x4c000000, 0xfc000000, "jirl", "r0:5,r5:5,s10:16<<2", 0, 0, 0, 0}, ++{0, 0, "b", "la", "b %%pcrel(%1)", 0, 0, 0}, ++{0x50000000, 0xfc000000, "b", "sb0:10|10:16<<2", 0, 0, 0, 0}, ++{0, 0, "bl", "la", "bl %%pcrel(%1)", 0, 0, 0}, ++{0x54000000, 0xfc000000, "bl", "sb0:10|10:16<<2", 0, 0, 0, 0}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "bltz", "r,la", "bltz %1,%%pcrel(%2)", 0, 0, 0}, ++{0x60000000, 0xfc00001f, "bltz", "r5:5,sb10:16<<2", 0, 0, 0, 0}, ++{0, 0, "bgtz", "r,la", "bgtz %1,%%pcrel(%2)", 0, 0, 0}, ++{0x60000000, 0xfc0003e0, "bgtz", "r0:5,sb10:16<<2", 0, 0, 0, 0}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "bgez", "r,la", "bgez %1,%%pcrel(%2)", 0, 0, 0}, ++{0x64000000, 0xfc00001f, "bgez", "r5:5,sb10:16<<2", 0, 0, 0, 0}, ++{0, 0, "blez", "r,la", "blez %1,%%pcrel(%2)", 0, 0, 0}, ++{0x64000000, 0xfc0003e0, "blez", "r0:5,sb10:16<<2", 0, 0, 0, 0}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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}, ++{0, 0, "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 */ ++{0x729d1400, 0xfffffc00, "vfrecipe.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d1800, 0xfffffc00, "vfrecipe.d", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d2400, 0xfffffc00, "vfrsqrte.s", "v0:5,v5:5", 0, 0, 0, 0}, ++{0x729d2800, 0xfffffc00, "vfrsqrte.d", "v0:5,v5:5", 0, 0, 0, 0}, + {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}, +@@ -1443,21 +1578,12 @@ static struct loongarch_opcode loongarch_128vec_opcodes[] = { + {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 */ +-{0x2c800000, 0xffc00000, "xvld", "x0:5,r5:5,s10:12", 0, 0, 0, 0}, +-{0x2cc00000, 0xffc00000, "xvst", "x0:5,r5:5,s10:12", 0, 0, 0, 0}, +-{0x32100000, 0xfff80000, "xvldrepl.d", "x0:5,r5:5,s10:9<<3", 0, 0, 0, 0}, +-{0x32200000, 0xfff00000, "xvldrepl.w", "x0:5,r5:5,s10:10<<2", 0, 0, 0, 0}, +-{0x32400000, 0xffe00000, "xvldrepl.h", "x0:5,r5:5,s10:11<<1", 0, 0, 0, 0}, +-{0x32800000, 0xffc00000, "xvldrepl.b", "x0:5,r5:5,s10:12", 0, 0, 0, 0}, +-{0x33100000, 0xfff00000, "xvstelm.d", "x0:5,r5:5,s10:8<<3,u18:2", 0, 0, 0, 0}, +-{0x33200000, 0xffe00000, "xvstelm.w", "x0:5,r5:5,s10:8<<2,u18:3", 0, 0, 0, 0}, +-{0x33400000, 0xffc00000, "xvstelm.h", "x0:5,r5:5,s10:8<<1,u18:4", 0, 0, 0, 0}, +-{0x33800000, 0xff800000, "xvstelm.b", "x0:5,r5:5,s10:8,u18:5", 0, 0, 0, 0}, +-{0x38480000, 0xffff8000, "xvldx", "x0:5,r5:5,r10:5", 0, 0, 0, 0}, +-{0x384c0000, 0xffff8000, "xvstx", "x0:5,r5:5,r10:5", 0, 0, 0, 0}, ++{0x769d1400, 0xfffffc00, "xvfrecipe.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d1800, 0xfffffc00, "xvfrecipe.d", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d2400, 0xfffffc00, "xvfrsqrte.s", "x0:5,x5:5", 0, 0, 0, 0}, ++{0x769d2800, 0xfffffc00, "xvfrsqrte.d", "x0:5,x5:5", 0, 0, 0, 0}, + {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}, +@@ -2131,22 +2257,20 @@ static struct loongarch_opcode loongarch_256vec_opcodes[] = { + + }; + ++ + 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}, ++{&LARCH_opts.ase_test, loongarch_test_opcodes, 0, 0, {0}, 0, 0}, ++{&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_jmp_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_float, loongarch_4opt_opcodes, 0, 0, {0}, 0, 0}, ++{&LARCH_opts.ase_float, loongarch_float_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.39.3 + diff --git a/Fix-gas-bug-Segment-error-in-compilation-due-to-too.patch b/Fix-gas-bug-Segment-error-in-compilation-due-to-too.patch new file mode 100644 index 0000000..503bd73 --- /dev/null +++ b/Fix-gas-bug-Segment-error-in-compilation-due-to-too.patch @@ -0,0 +1,121 @@ +From a74d8d8d9f7f05666ff34d27ac22cecb61c88a4b Mon Sep 17 00:00:00 2001 +From: Xing Li +Date: Thu, 5 Jan 2023 15:49:52 +0800 +Subject: [PATCH] Fix gas bug: Segment error in compilation due to too + long symbol name. + + change "char buffer[8192];" into "char *buffer = + (char *) malloc(1000 + 6 * len_str);"in function + loongarch_expand_macro_with_format_map. + + gas/config/tc-loongarch.c + include/opcode/loongarch.h + opcodes/loongarch-coder.c + +Signed-off-by: Xing Li +--- + gas/config/tc-loongarch.c | 7 +++++-- + include/opcode/loongarch.h | 4 ++-- + opcodes/loongarch-coder.c | 15 ++++++++++----- + 3 files changed, 17 insertions(+), 9 deletions(-) + +diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c +index 26ee3f1a..9ab015a3 100644 +--- a/gas/config/tc-loongarch.c ++++ b/gas/config/tc-loongarch.c +@@ -921,7 +921,8 @@ assember_macro_helper (const char * const args[], void *context_ptr) + } + while (0); + +- ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL); ++ ret = loongarch_expand_macro (insns_buf, arg_strs, NULL, NULL, ++ sizeof (args_buf)); + } + return ret; + } +@@ -932,6 +933,7 @@ static void + loongarch_assemble_INSNs (char *str) + { + char *rest; ++ size_t len_str = strlen(str); + + for (rest = str; *rest != ';' && *rest != '\0'; rest++); + if (*rest == ';') +@@ -971,7 +973,8 @@ loongarch_assemble_INSNs (char *str) + { + char *c_str = + loongarch_expand_macro (the_one.insn->macro, +- the_one.arg_strs, assember_macro_helper, &the_one); ++ the_one.arg_strs, assember_macro_helper, ++ &the_one, len_str); + loongarch_assemble_INSNs (c_str); + free (c_str); + } +diff --git a/include/opcode/loongarch.h b/include/opcode/loongarch.h +index 47a9d94b..fc0be236 100644 +--- a/include/opcode/loongarch.h ++++ b/include/opcode/loongarch.h +@@ -151,12 +151,12 @@ loongarch_expand_macro_with_format_map (const char *format, const char *macro, + char * (*helper) ( + const char * const arg_strs[], + void *context), +- void *context); ++ void *context, size_t len_str); + extern char * + loongarch_expand_macro (const char *macro, const char * const arg_strs[], + char * (*helper) (const char * const arg_strs[], + void *context), +- void *context); ++ void *context, size_t len_str); + extern size_t + loongarch_bits_imm_needed (int64_t imm, int si); + +diff --git a/opcodes/loongarch-coder.c b/opcodes/loongarch-coder.c +index 399af4f0..aa6a2388 100644 +--- a/opcodes/loongarch-coder.c ++++ b/opcodes/loongarch-coder.c +@@ -352,13 +352,18 @@ loongarch_expand_macro_with_format_map (const char *format, const char *macro, + char * (*helper) ( + const char * const arg_strs[], + void *context), +- void *context) ++ void *context, size_t len_str) + { + char esc1s[MAX_ARG_NUM_PLUS_2 - 1], esc2s[MAX_ARG_NUM_PLUS_2 - 1]; + const char *bit_fields[MAX_ARG_NUM_PLUS_2 - 1]; + const char *src; + char *dest; +- char buffer[8192]; ++ ++ /*The expanded macro character length does not exceed 1000, and number of ++ * label is 6 at most in the expanded macro. The len_str is the length of ++ * str. ++ */ ++ char *buffer = (char *) malloc(1000 + 6 * len_str); + + if (format) + loongarch_parse_format (format, esc1s, esc2s, bit_fields); +@@ -396,17 +401,17 @@ loongarch_expand_macro_with_format_map (const char *format, const char *macro, + *dest++ = *src++; + + *dest = '\0'; +- return strdup (buffer); ++ return buffer; + } + + char * + loongarch_expand_macro (const char *macro, const char * const arg_strs[], + char * (*helper) (const char * const arg_strs[], + void *context), +- void *context) ++ void *context, size_t len_str) + { + return loongarch_expand_macro_with_format_map +- (NULL, macro, arg_strs, I, helper, context); ++ (NULL, macro, arg_strs, I, helper, context, len_str); + } + + size_t +-- +2.27.0 + diff --git a/Some-testsuite-fix.patch b/Some-testsuite-fix.patch new file mode 100644 index 0000000..75757db --- /dev/null +++ b/Some-testsuite-fix.patch @@ -0,0 +1,58 @@ +From db38d44e5e6a7c22ffe59759d33c97b807c93324 Mon Sep 17 00:00:00 2001 +From: Jinyang He +Date: Wed, 19 Jul 2023 14:49:37 +0800 +Subject: [PATCH 2/2] Some testsuite fix + +Change-Id: I3cf75379f4035541f40b8d0b5f722085530c9353 +--- + bfd/elfxx-loongarch.c | 4 ++-- + gas/config/tc-loongarch.c | 11 +++++++++-- + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/bfd/elfxx-loongarch.c b/bfd/elfxx-loongarch.c +index 3f8534bf..dc7a62b4 100644 +--- a/bfd/elfxx-loongarch.c ++++ b/bfd/elfxx-loongarch.c +@@ -14,8 +14,8 @@ 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), ++HOWTO (R_LARCH_32,0,2,32,FALSE,0,complain_overflow_signed,bfd_elf_generic_reloc,"R_LARCH_32",FALSE,0,0xffffffff,FALSE), ++HOWTO (R_LARCH_64,0,4,64,FALSE,0,complain_overflow_signed,bfd_elf_generic_reloc,"R_LARCH_64",FALSE,0,0xffffffffffffffff,FALSE), + LOONGARCH_HOWTO (RELATIVE), + LOONGARCH_HOWTO (COPY), + LOONGARCH_HOWTO (JUMP_SLOT), +diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c +index b8bf3510..9b9cb827 100644 +--- a/gas/config/tc-loongarch.c ++++ b/gas/config/tc-loongarch.c +@@ -137,6 +137,9 @@ md_parse_option (int c, const char *arg) + break; + case OPTION_IGNORE: + break; ++ default: ++ ret = 0; ++ break; + } + return ret; + } +@@ -936,8 +939,12 @@ loongarch_assemble_INSNs (char *str) + 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)); ++ { ++ char *ss = loongarch_cat_splited_strs (the_one.arg_strs); ++ as_bad (_("no match insn: %s\t%s"), the_one.name, ss ? ss : ""); ++ free(ss); ++ return; ++ } + + if (check_this_insn_before_appending (&the_one) != 0) + break; +-- +2.39.3 + diff --git a/binutils-Delete-warning-of-compile.patch b/binutils-Delete-warning-of-compile.patch new file mode 100644 index 0000000..79e5984 --- /dev/null +++ b/binutils-Delete-warning-of-compile.patch @@ -0,0 +1,1014 @@ +From 095ac9fd7c2128c0ad31f71cc9725d0a21500c2a Mon Sep 17 00:00:00 2001 +From: Xing Li +Date: Tue, 18 Jul 2023 13:34:53 +0800 +Subject: [PATCH 3/3] binutils: Delete warning of compile + +--- + bfd/elfnn-loongarch.c | 617 ++++++++++++++++++++--------------- + gas/config/loongarch-lex.l | 3 + + gas/config/loongarch-parse.y | 9 +- + gas/config/tc-loongarch.c | 44 +-- + opcodes/loongarch-dis.c | 8 +- + 5 files changed, 385 insertions(+), 296 deletions(-) + +diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c +index ca29aaea..5582107e 100644 +--- a/bfd/elfnn-loongarch.c ++++ b/bfd/elfnn-loongarch.c +@@ -585,7 +585,7 @@ loongarch_elf_record_tls_and_got_reference (bfd *abfd, + /* no need for GOT */ + break; + default: +- _bfd_error_handler (_("%pB: Interl error: unreachable.")); ++ _bfd_error_handler (_("%pB: Interl error: unreachable."), abfd); + return FALSE; + } + +@@ -1107,7 +1107,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) + && h->def_regular) + 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); +@@ -1284,7 +1283,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) + /* Allocate space in .plt, .got and associated reloc sections for + ifunc dynamic relocs. */ + +-static bfd_boolean ++static bfd_boolean + elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf) + { + struct bfd_link_info *info; +@@ -1339,21 +1338,6 @@ elfNN_allocate_local_ifunc_dynrelocs (void **slot, void *inf) + return elfNN_allocate_ifunc_dynrelocs (h, inf); + } + +-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. */ + +@@ -2055,6 +2039,50 @@ loongarch_dump_reloc_record (void (*p) (const char *fmt, ...)) + p ("\n" "-- Record dump end --\n\n"); + } + ++static bfd_boolean ++loongarch_reloc_is_fatal (struct bfd_link_info *info, ++ bfd *input_bfd, ++ asection *input_section, ++ Elf_Internal_Rela *rel, ++ reloc_howto_type *howto, ++ bfd_reloc_status_type rtype, ++ bfd_boolean is_undefweak, ++ const char *name, ++ const char *msg) ++{ ++ bfd_boolean fatal = TRUE; ++ ++ switch (rtype) ++ { ++ /* 'dangerous' means we do it but can't promise it's ok ++ 'unsupport' means out of ability of relocation type ++ 'undefined' means we can't deal with the undefined symbol. */ ++ case bfd_reloc_undefined: ++ info->callbacks->undefined_symbol (info, name, input_bfd, input_section, ++ rel->r_offset, TRUE); ++ info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n", ++ input_bfd, input_section, rel->r_offset, ++ howto->name, ++ is_undefweak ? "[undefweak] " : "", name, msg); ++ break; ++ case bfd_reloc_dangerous: ++ info->callbacks->info ("%pB(%pA+0x%v): warning: %s against %s`%s':\n%s\n", ++ input_bfd, input_section, rel->r_offset, ++ howto->name, ++ is_undefweak ? "[undefweak] " : "", name, msg); ++ fatal = FALSE; ++ break; ++ case bfd_reloc_notsupported: ++ info->callbacks->info ("%X%pB(%pA+0x%v): error: %s against %s`%s':\n%s\n", ++ input_bfd, input_section, rel->r_offset, ++ howto->name, ++ is_undefweak ? "[undefweak] " : "", name, msg); ++ break; ++ default: ++ break; ++ } ++ return fatal; ++} + + static bfd_boolean + loongarch_elf_relocate_section (bfd *output_bfd, +@@ -2209,12 +2237,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, + 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; +@@ -2239,42 +2261,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, + 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: +@@ -2377,11 +2363,18 @@ loongarch_elf_relocate_section (bfd *output_bfd, + 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; ++ if (resolved_dynly) ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_undefined, is_undefweak, name, ++ "Can't be resolved dynamically. " ++ "If this procedure is hand-written assembly,\n" ++ "there must be something like '.dword sym1 - sym2' " ++ "to generate these relocs\n" ++ "and we can't get known link-time address of " ++ "these symbols.")); ++ else ++ relocation += rel->r_addend; + break; + + case R_LARCH_TLS_DTPREL32: +@@ -2390,12 +2383,11 @@ loongarch_elf_relocate_section (bfd *output_bfd, + { + 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_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; +@@ -2404,28 +2396,67 @@ loongarch_elf_relocate_section (bfd *output_bfd, + break; + } + +- LARCH_ASSERT (!resolved_to_const, bfd_reloc_notsupported, +- "Internal:"); ++ if (resolved_to_const) ++ fatal = loongarch_reloc_is_fatal (info, input_bfd, input_section, ++ rel, howto, ++ bfd_reloc_notsupported, ++ is_undefweak, name, ++ "Internal:"); ++ if (resolved_local) ++ { ++ if (!elf_hash_table (info)->tls_sec) ++ { ++ fatal = loongarch_reloc_is_fatal (info, input_bfd, ++ input_section, rel, howto, bfd_reloc_notsupported, ++ is_undefweak, name, "TLS section not be created"); ++ } ++ else ++ relocation -= elf_hash_table (info)->tls_sec->vma; ++ } ++ else ++ { ++ fatal = loongarch_reloc_is_fatal (info, input_bfd, ++ input_section, rel, howto, bfd_reloc_undefined, ++ is_undefweak, name, ++ "TLS LE just can be resolved local only."); ++ } + ++ break; ++ + case R_LARCH_SOP_PUSH_TLS_TPREL: + if (resolved_local) + { +- LARCH_ASSERT (elf_hash_table (info)->tls_sec, +- bfd_reloc_notsupported, "TLS section not be created"); +- relocation -= elf_hash_table (info)->tls_sec->vma; ++ if (!elf_hash_table (info)->tls_sec) ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_notsupported, is_undefweak, name, ++ "TLS section not be created")); ++ else ++ relocation -= elf_hash_table (info)->tls_sec->vma; + } ++ else ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_undefined, is_undefweak, name, ++ "TLS LE just can be resolved local only.")); + +- 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'."); ++ if (resolved_dynly) ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_dangerous, is_undefweak, name, ++ "Someone require us to resolve undefweak " ++ "symbol dynamically. \n" ++ "But this reloc can't be done. " ++ "I think I can't throw error " ++ "for this\n" ++ "so I resolved it to 0. " ++ "I suggest to re-compile with '-fpic'.")); ++ + relocation = 0; + unresolved_reloc = FALSE; + break; +@@ -2437,17 +2468,36 @@ loongarch_elf_relocate_section (bfd *output_bfd, + break; + } + +- LARCH_ASSERT (!is_pic, bfd_reloc_notsupported, +-"Under PIC we don't know load address. Re-compile src with '-fpic'?"); ++ if (is_pic) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_notsupported, is_undefweak, name, ++ "Under PIC we don't know load address. Re-compile " ++ "with '-fpic'?")); ++ break; ++ } + + if (resolved_dynly) + { +- LARCH_ASSERT (plt && h && h->plt.offset != MINUS_ONE, +- bfd_reloc_undefined, +-"Can't be resolved dynamically. Try to re-compile src with '-fpic'?"); ++ if (!(plt && h && h->plt.offset != MINUS_ONE)) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_undefined, is_undefweak, name, ++ "Can't be resolved dynamically. Try to re-compile " ++ "with '-fpic'?")); ++ break; ++ } + +- LARCH_ASSERT (rel->r_addend == 0, bfd_reloc_notsupported, +- "Shouldn't be with r_addend."); ++ if (rel->r_addend != 0) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_notsupported, is_undefweak, name, ++ "Shouldn't be with r_addend.")); ++ break; ++ } + + relocation = sec_addr (plt) + h->plt.offset; + unresolved_reloc = FALSE; +@@ -2466,12 +2516,12 @@ loongarch_elf_relocate_section (bfd *output_bfd, + case R_LARCH_SOP_PUSH_PLT_PCREL: + unresolved_reloc = FALSE; + +- if (resolved_to_const) +- { +- relocation += rel->r_addend; +- break; +- } +- else if (is_undefweak) ++ if (resolved_to_const) ++ { ++ relocation += rel->r_addend; ++ break; ++ } ++ else if (is_undefweak) + { + i = 0, j = 0; + relocation = 0; +@@ -2480,24 +2530,36 @@ loongarch_elf_relocate_section (bfd *output_bfd, + 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."); ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_dangerous, is_undefweak, name, ++ "Undefweak need to be resolved dynamically, " ++ "but PLT stub doesn't represent.")); + } + } + else + { +- LARCH_ASSERT +- (defined_local || (h && h->plt.offset != MINUS_ONE), +- bfd_reloc_undefined, +- "PLT stub does not represent and symbol not defined."); ++ if (!(defined_local || (h && h->plt.offset != MINUS_ONE))) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_undefined, is_undefweak, name, ++ "PLT stub does not represent and " ++ "symbol not defined.")); ++ break; ++ } + + if (resolved_local) + i = 0, j = 2; + else /* if (resolved_dynly) */ + { +- LARCH_ASSERT +- (h && h->plt.offset != MINUS_ONE, bfd_reloc_dangerous, +-"Internal: PLT stub doesn't represent. Resolve it with pcrel"); ++ if (!(h && h->plt.offset != MINUS_ONE)) ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_dangerous, is_undefweak, name, ++ "Internal: PLT stub doesn't represent. " ++ "Resolve it with pcrel")); ++ + i = 1, j = 3; + } + } +@@ -2513,8 +2575,15 @@ loongarch_elf_relocate_section (bfd *output_bfd, + + 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."); ++ if (rel->r_addend != 0) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_notsupported, is_undefweak, name, ++ "PLT shouldn't be with r_addend.")); ++ break; ++ } ++ + relocation = sec_addr (plt) + h->plt.offset - pc; + break; + } +@@ -2524,24 +2593,36 @@ loongarch_elf_relocate_section (bfd *output_bfd, + case R_LARCH_SOP_PUSH_GPREL: + unresolved_reloc = FALSE; + +- LARCH_ASSERT (rel->r_addend == 0, bfd_reloc_notsupported, +- "Shouldn't be with r_addend."); +- ++ if (rel->r_addend != 0) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_notsupported, is_undefweak, name, ++ "Shouldn't be with r_addend.")); ++ break; ++ } + + if (h != NULL) + { + off = h->got.offset & (~1); + +- LARCH_ASSERT (!(h->got.offset == MINUS_ONE +- && h->type != STT_GNU_IFUNC), +- bfd_reloc_notsupported, +- "Internal: GOT entry doesn't represent."); ++ if (h->got.offset == MINUS_ONE && h->type != STT_GNU_IFUNC) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_notsupported, is_undefweak, name, ++ "Internal: GOT entry doesn't represent.")); ++ break; ++ } + + /* Hidden symbol not has .got entry, only .got.plt entry + so gprel is (plt - got). */ + if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC) + { +- BFD_ASSERT(h->plt.offset != (bfd_vma) -1); ++ if (h->plt.offset == (bfd_vma) -1) ++ { ++ abort(); ++ } + + bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE; + off = plt_index * GOT_ENTRY_SIZE; +@@ -2580,17 +2661,37 @@ loongarch_elf_relocate_section (bfd *output_bfd, + relocation entry to initialize the value. This + is done in the finish_dynamic_symbol routine. */ + +- LARCH_ASSERT (!resolved_dynly || (defined_local || resolved_to_const), +- bfd_reloc_notsupported, +- "Internal: here shouldn't dynamic."); +- ++ if (resolved_dynly) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_dangerous, is_undefweak, name, ++ "Internal: here shouldn't dynamic.")); ++ } ++ ++ if (!(defined_local || resolved_to_const)) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_undefined, is_undefweak, name, ++ "Internal: ")); ++ break; ++ } ++ + asection *s; + Elf_Internal_Rela outrel; + /* We need to generate a R_LARCH_RELATIVE reloc + for the dynamic linker. */ + s = htab->elf.srelgot; +- LARCH_ASSERT (s, bfd_reloc_notsupported, +- "Internal: '.rel.got' not represent."); ++ if (!s) ++ { ++ fatal = loongarch_reloc_is_fatal ++ (info, input_bfd, ++ input_section, rel, howto, ++ bfd_reloc_notsupported, is_undefweak, name, ++ "Internal: '.rel.got' not represent"); ++ break; ++ } + + outrel.r_offset = sec_addr (got) + off; + outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE); +@@ -2603,15 +2704,26 @@ loongarch_elf_relocate_section (bfd *output_bfd, + } + else + { +- LARCH_ASSERT (local_got_offsets, bfd_reloc_notsupported, +- "Internal: local got offsets not reporesent."); +- +- LARCH_ASSERT (local_got_offsets[r_symndx] != MINUS_ONE, +- bfd_reloc_notsupported, +- "Internal: GOT entry doesn't represent."); ++ if (!local_got_offsets) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_notsupported, is_undefweak, name, ++ "Internal: local got offsets not reporesent.")); ++ break; ++ } + + off = local_got_offsets[r_symndx] & (~1); + ++ if (local_got_offsets[r_symndx] == MINUS_ONE) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_notsupported, is_undefweak, name, ++ "Internal: GOT entry doesn't represent.")); ++ break; ++ } ++ + /* The offset must always be a multiple of the word size. + So, we can use the least significant bit to record + whether we have already processed this entry. */ +@@ -2625,8 +2737,14 @@ loongarch_elf_relocate_section (bfd *output_bfd, + /* 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"); ++ if (!s) ++ { ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_notsupported, is_undefweak, name, ++ "Internal: '.rel.got' not represent")); ++ break; ++ } + + outrel.r_offset = sec_addr (got) + off; + outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE); +@@ -2644,124 +2762,109 @@ loongarch_elf_relocate_section (bfd *output_bfd, + 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); +- } ++ { ++ unresolved_reloc = FALSE; ++ if (r_type == R_LARCH_SOP_PUSH_TLS_GOT) ++ is_ie = TRUE; ++ ++ bfd_vma got_off = 0; ++ if (h != NULL) ++ { ++ got_off = h->got.offset; ++ h->got.offset |= 1; ++ } ++ else ++ { ++ got_off = local_got_offsets[r_symndx]; ++ local_got_offsets[r_symndx] |= 1; ++ } ++ ++ BFD_ASSERT (got_off != MINUS_ONE); ++ ++ ie_off = 0; ++ tls_type = _bfd_loongarch_elf_tls_type (input_bfd, h, r_symndx); ++ if ((tls_type & GOT_TLS_GD) && (tls_type & GOT_TLS_IE)) ++ ie_off = 2 * GOT_ENTRY_SIZE; ++ ++ if ((got_off & 1) == 0) ++ { ++ Elf_Internal_Rela rela; ++ asection *srel = htab->elf.srelgot; ++ bfd_vma tls_block_off = 0; ++ ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ { ++ BFD_ASSERT (elf_hash_table (info)->tls_sec); ++ tls_block_off = relocation ++ - elf_hash_table (info)->tls_sec->vma; ++ } + +- 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_GD) ++ { ++ rela.r_offset = sec_addr (got) + got_off; ++ rela.r_addend = 0; ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ { ++ /* Local sym, used in exec, set module id 1. */ ++ if (bfd_link_executable (info)) ++ bfd_put_NN (output_bfd, 1, got->contents + got_off); ++ else ++ { ++ rela.r_info = ELFNN_R_INFO (0, ++ R_LARCH_TLS_DTPMODNN); ++ loongarch_elf_append_rela (output_bfd, srel, &rela); ++ } ++ ++ bfd_put_NN (output_bfd, tls_block_off, ++ got->contents + got_off + GOT_ENTRY_SIZE); ++ } ++ /* Dynamic resolved. */ ++ else ++ { ++ /* Dynamic relocate module id. */ ++ rela.r_info = ELFNN_R_INFO (h->dynindx, ++ R_LARCH_TLS_DTPMODNN); ++ loongarch_elf_append_rela (output_bfd, srel, &rela); ++ ++ /* Dynamic relocate offset of block. */ ++ rela.r_offset += GOT_ENTRY_SIZE; ++ rela.r_info = ELFNN_R_INFO (h->dynindx, ++ R_LARCH_TLS_DTPRELNN); ++ loongarch_elf_append_rela (output_bfd, srel, &rela); ++ } ++ } ++ if (tls_type & GOT_TLS_IE) ++ { ++ rela.r_offset = sec_addr (got) + got_off + ie_off; ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ { ++ /* Local sym, used in exec, set module id 1. */ ++ if (!bfd_link_executable (info)) ++ { ++ rela.r_info = ELFNN_R_INFO (0, R_LARCH_TLS_TPRELNN); ++ rela.r_addend = tls_block_off; ++ loongarch_elf_append_rela (output_bfd, srel, &rela); ++ } ++ ++ bfd_put_NN (output_bfd, tls_block_off, ++ got->contents + got_off + ie_off); ++ } ++ /* Dynamic resolved. */ ++ else ++ { ++ /* Dynamic relocate offset of block. */ ++ rela.r_info = ELFNN_R_INFO (h->dynindx, ++ R_LARCH_TLS_TPRELNN); ++ rela.r_addend = 0; ++ loongarch_elf_append_rela (output_bfd, srel, &rela); ++ } ++ } ++ } + +- 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); ++ relocation = (got_off & (~(bfd_vma)1)) + (is_ie ? ie_off : 0); ++ } + break; + + default: +@@ -2786,8 +2889,12 @@ loongarch_elf_relocate_section (bfd *output_bfd, + + if (input_section->output_section->flags & SEC_DEBUGGING) + { +- LARCH_ASSERT (0, bfd_reloc_dangerous, +- "Seems dynamic linker not process sections 'SEC_DEBUGGING'."); ++ fatal = (loongarch_reloc_is_fatal ++ (info, input_bfd, input_section, rel, howto, ++ bfd_reloc_dangerous, is_undefweak, name, ++ "Seems dynamic linker not process " ++ "sections 'SEC_DEBUGGING'.")); ++ + break; + } + if (!is_dyn) +@@ -2798,7 +2905,6 @@ loongarch_elf_relocate_section (bfd *output_bfd, + info->flags |= DF_TEXTREL; + } + while (0); +-#undef LARCH_ASSERT + + if (fatal) + break; +@@ -2997,7 +3103,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, + } + else + { +- asection *plt; + /* For non-shared object, we can't use .got.plt, which + contains the real function address if we need pointer + equality. We load the GOT entry with the PLT entry. */ +@@ -3447,15 +3552,17 @@ _loongarch_bfd_set_section_contents(bfd *abfd, + 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); ++ if (elf_elfheader(abfd)->e_flags == 0 ++ && 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); + } + + +diff --git a/gas/config/loongarch-lex.l b/gas/config/loongarch-lex.l +index d88fc93a..55901dd6 100644 +--- a/gas/config/loongarch-lex.l ++++ b/gas/config/loongarch-lex.l +@@ -2,6 +2,9 @@ + %{ + #include "as.h" + #include "loongarch-parse.h" ++/* Flex generates static functions "input" & "unput" which are not used. */ ++#define YY_NO_INPUT ++#define YY_NO_UNPUT + %} + + D [0-9] +diff --git a/gas/config/loongarch-parse.y b/gas/config/loongarch-parse.y +index aa7e51f5..51c862df 100644 +--- a/gas/config/loongarch-parse.y ++++ b/gas/config/loongarch-parse.y +@@ -1,7 +1,7 @@ + %{ + #include "as.h" + #include "loongarch-parse.h" +-void yyerror(const char *s) {} ++static void yyerror(const char *s ATTRIBUTE_UNUSED) {} + extern int yylex (void); + extern void yy_scan_string (const char *); + extern void +@@ -25,6 +25,12 @@ is_const (struct reloc_info *info) + && 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 + loongarch_parse_expr (const char *expr, + struct reloc_info *reloc_stack_top, +@@ -178,6 +184,7 @@ emit_unary (char op) + { + case '!': + top->type = BFD_RELOC_LARCH_SOP_NOT; ++ break; + default: + abort (); + } +diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c +index fbcc7c1f..b8bf3510 100644 +--- a/gas/config/tc-loongarch.c ++++ b/gas/config/tc-loongarch.c +@@ -274,32 +274,6 @@ my_getExpression (expressionS *ep, const char *str) + 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) + { +@@ -419,7 +393,7 @@ extern int loongarch_parse_expr (const char *expr, + size_t max_reloc_num, size_t *reloc_num, + offsetT *imm_if_no_reloc); + +-int ++static int + is_internal_label (const char *c_str) + { + do +@@ -1026,6 +1000,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) + case BFD_RELOC_LARCH_SOP_PUSH_TLS_GOT: + if (fixP->fx_addsy) + S_SET_THREAD_LOCAL (fixP->fx_addsy); ++ /* Fall through. */ + case BFD_RELOC_LARCH_SOP_PUSH_PCREL: + case BFD_RELOC_LARCH_SOP_PUSH_PLT_PCREL: + if (fixP->fx_addsy == NULL) +@@ -1326,17 +1301,10 @@ loongarch_handle_align (fragS *fragp) + 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; +- } ++ ++ ++ while (excess-- != 0) ++ *p++ = 0; + + md_number_to_chars (p, opcode, size); + fragp->fr_var = size; +diff --git a/opcodes/loongarch-dis.c b/opcodes/loongarch-dis.c +index 888c55f5..a159bb68 100644 +--- a/opcodes/loongarch-dis.c ++++ b/opcodes/loongarch-dis.c +@@ -2,6 +2,7 @@ + #include "disassemble.h" + #include "opintl.h" + #include "opcode/loongarch.h" ++#include "libiberty.h" + #include + + static const struct loongarch_opcode * +@@ -78,7 +79,8 @@ parse_loongarch_dis_options (const char *opts_in) + if (opts_in == NULL) + return 0; + +- char opts[strlen (opts_in) + 1], *opt, *opt_end; ++ char *opts, *opt, *opt_end; ++ opts = xmalloc (strlen (opts_in) + 1); + strcpy (opts, opts_in); + + for (opt = opt_end = opts; opt_end != NULL; opt = opt_end + 1) +@@ -88,6 +90,7 @@ parse_loongarch_dis_options (const char *opts_in) + if (parse_loongarch_dis_option (opt) != 0) + return -1; + } ++ free (opts); + return 0; + } + +@@ -215,13 +218,14 @@ disassemble_one (insn_t insn, struct disassemble_info *info) + info->fprintf_func (info->stream, "%s", opc->name); + + { +- char fake_args[strlen (opc->format) + 1]; ++ char *fake_args = xmalloc (strlen (opc->format) + 1); + const char *fake_arg_strs[MAX_ARG_NUM_PLUS_2]; + strcpy (fake_args, opc->format); + if (0 < loongarch_split_args_by_comma (fake_args, fake_arg_strs)) + info->fprintf_func (info->stream, "\t"); + info->private_data = &insn; + loongarch_foreach_args (opc->format, fake_arg_strs, dis_one_arg, info); ++ free (fake_args); + } + + if (info->insn_type == dis_branch || info->insn_type == dis_condbranch +-- +2.27.0 + diff --git a/binutils.spec b/binutils.spec index 2948a2c..d34ffbd 100644 --- a/binutils.spec +++ b/binutils.spec @@ -24,7 +24,7 @@ # /usr/bin/aarch64-linux-gnu-ar # /usr/bin/aarch64-linux-gnu-as # [etc] -%define anolis_release .0.1 +%define anolis_release .0.2 %if 0%{!?binutils_target:1} @@ -638,6 +638,14 @@ 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 +Patch1004: Fix-gas-bug-Segment-error-in-compilation-due-to-too.patch +Patch1005: ld-change-loong64-to-loongarch64.patch +Patch1006: ld-Add-ifunc-support.patch +Patch1007: ld-Delete-R_LARCH_NONE-relocation-of-eh_frame.patch +Patch1008: binutils-Delete-warning-of-compile.patch +Patch1009: ld-Fix-the-bug-of-pr21964-4.patch +Patch1010: Add-missing-opcode-and-3A6000.patch +Patch1011: Some-testsuite-fix.patch #end #---------------------------------------------------------------------------- @@ -885,6 +893,14 @@ using libelf instead of BFD. %patch1001 -p1 %patch1002 -p1 %patch1003 -p1 +%patch1004 -p1 +%patch1005 -p1 +%patch1006 -p1 +%patch1007 -p1 +%patch1008 -p1 +%patch1009 -p1 +%patch1010 -p1 +%patch1011 -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 ? @@ -1334,6 +1350,15 @@ exit 0 #---------------------------------------------------------------------------- %changelog +* Wed Jul 19 2023 Xing Li - 2.30-119.0.2 +- Fixup gas SIGSEGV for extremely long function name. (lixing@loongson.cn) +- change loong64 to loongarch64. +- Add ifunc support. +- Delete R_LARCH_NONE for eh_frame. +- Fixup pr21964 bug. +- Add 3A6000 opcode. +- Fix some testsuite error. + * Tue May 30 2023 Xue haolin - 2.30-119.0.1 - Rebrand to Anolis OS. - Add loongarch support. (lixing@loongson.cn) diff --git a/ld-Add-ifunc-support.patch b/ld-Add-ifunc-support.patch new file mode 100644 index 0000000..8b792ac --- /dev/null +++ b/ld-Add-ifunc-support.patch @@ -0,0 +1,787 @@ +From 7ea119f8dfcdd0b6b5471184bb62b54c453070a6 Mon Sep 17 00:00:00 2001 +From: Xing Li +Date: Tue, 18 Jul 2023 12:33:45 +0800 +Subject: [PATCH] ld: Add ifunc support. + +--- + bfd/elfnn-loongarch.c | 435 ++++++++++++++++++++++++++++---------- + gas/config/tc-loongarch.c | 49 +++-- + 2 files changed, 355 insertions(+), 129 deletions(-) + +diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c +index f609a756..93459979 100644 +--- a/bfd/elfnn-loongarch.c ++++ b/bfd/elfnn-loongarch.c +@@ -21,8 +21,6 @@ loongarch_info_to_howto_rela (bfd *abfd ATTRIBUTE_UNUSED, + 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 +@@ -689,14 +687,27 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, + h = (struct elf_link_hash_entry *) h->root.u.i.link; + } + ++ /* It is referenced by a non-shared object. */ ++ if (h != NULL) ++ h->ref_regular = 1; ++ + if (h && h->type == STT_GNU_IFUNC) + { + if (htab->elf.dynobj == NULL) + htab->elf.dynobj = abfd; + +- if (!htab->elf.splt ++ /* Create 'irelifunc' in PIC object. */ ++ if (bfd_link_pic (info) ++ && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) ++ return FALSE; ++ /* If '.plt' not represent, create '.iplt' to deal with ifunc. */ ++ else if (!htab->elf.splt ++ && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) ++ return FALSE; ++ /* Create the ifunc sections, iplt and ipltgot, for static ++ executables. */ ++ if ((r_type == R_LARCH_64 || r_type == R_LARCH_32) + && !_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) +- /* If '.plt' not represent, create '.iplt' to deal with ifunc. */ + return FALSE; + + if (h->plt.refcount < 0) +@@ -704,8 +715,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, + h->plt.refcount++; + h->needs_plt = 1; + +- elf_tdata (info->output_bfd)->has_gnu_symbols +- |= elf_gnu_symbol_ifunc; ++ elf_tdata (info->output_bfd)->has_gnu_symbols |= elf_gnu_symbol_ifunc; + } + + need_dynreloc = 0; +@@ -713,6 +723,10 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, + switch (r_type) + { + case R_LARCH_SOP_PUSH_GPREL: ++ /* For la.global. */ ++ if (h) ++ h->pointer_equality_needed = 1; ++ + if (!loongarch_elf_record_tls_and_got_reference + (abfd, info, h, r_symndx, GOT_NORMAL)) + return FALSE; +@@ -774,12 +788,14 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, + case R_LARCH_SOP_PUSH_PCREL: + if (h != NULL) + { +- h->non_got_ref = 1; ++ if (!bfd_link_pic (info)) ++ h->non_got_ref = 1; + + /* We try to create PLT stub for all non-local function. */ + if (h->plt.refcount < 0) + h->plt.refcount = 0; + h->plt.refcount++; ++ h->pointer_equality_needed = 1; + } + break; + +@@ -819,8 +835,23 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, + 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; ++ if (h != NULL ++ && (!bfd_link_pic (info) ++ || h->type == STT_GNU_IFUNC)) ++ { ++ /* This reloc might not bind locally. */ ++ h->non_got_ref = 1; ++ h->pointer_equality_needed = 1; ++ ++ if (!h->def_regular ++ || (sec->flags & (SEC_CODE | SEC_READONLY)) != 0) ++ { ++ /* We may need a .plt entry if the symbol is a function ++ defined in a shared lib or is a function referenced ++ from the code or read-only section. */ ++ h->plt.refcount += 1; ++ } ++ } + break; + + case R_LARCH_GNU_VTINHERIT: +@@ -859,7 +890,7 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, + /* 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; ++ head = &loongarch_elf_hash_entry(h)->dyn_relocs; + else + { + /* Track dynamic relocs needed for local syms too. +@@ -906,7 +937,7 @@ 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) ++ for (p = loongarch_elf_hash_entry(h)->dyn_relocs; p != NULL; p = p->next) + { + asection *s = p->sec->output_section; + +@@ -982,6 +1013,10 @@ loongarch_elf_adjust_dynamic_symbol (struct bfd_link_info *info, + return TRUE; + } + ++ /* PIC support only. */ ++ /* Unnecessary to support copy relocation. */ ++// return TRUE; ++ + /* This is a reference to a symbol defined by a dynamic object which + is not a function. */ + +@@ -1067,6 +1102,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) + if (h->root.type == bfd_link_hash_indirect) + return TRUE; + ++ if (h->type == STT_GNU_IFUNC ++ && h->def_regular) ++ return TRUE; ++ + eh = (struct loongarch_elf_link_hash_entry *) h; + info = (struct bfd_link_info *) inf; + htab = loongarch_elf_hash_table (info); +@@ -1127,6 +1166,18 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) + gotplt->size += GOT_ENTRY_SIZE; + relplt->size += sizeof (ElfNN_External_Rela); + ++ /* If this symbol is not defined in a regular file, and we are ++ not generating a shared library, then set the symbol to this ++ location in the .plt. This is required to make function ++ pointers compare as equal between the normal executable and ++ the shared library. */ ++ if (!bfd_link_pic (info) ++ && !h->def_regular) ++ { ++ h->root.u.def.section = plt; ++ h->root.u.def.value = h->plt.offset; ++ } ++ + h->needs_plt = 1; + } + while (0); +@@ -1168,26 +1219,31 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) + 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) ++ if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT ++ || h->root.type != bfd_link_hash_undefweak) ++ && (bfd_link_pic (info) ++ || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), ++ h)) ++ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) ++ /* Undefined weak symbol in static PIE resolves to 0 without ++ any dynamic relocations. */ + htab->elf.srelgot->size += sizeof (ElfNN_External_Rela); + } + } + else + h->got.offset = MINUS_ONE; + +- if (eh->dyn_relocs == NULL) ++ if (loongarch_elf_hash_entry(h)->dyn_relocs == NULL) + return TRUE; + + /* 如果某些函数未被定义,SYMBOL_CALLS_LOCAL返回1; + 而SYMBOL_REFERENCES_LOCAL返回0。 + 似乎是因为未定义的函数可以有plt从而将其转化为local的。 */ +- if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ if (SYMBOL_CALLS_LOCAL (info, h)) + { + struct elf_dyn_relocs **pp; + +- for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) ++ for (pp = &loongarch_elf_hash_entry(h)->dyn_relocs; (p = *pp) != NULL; ) + { + p->count -= p->pc_count; + p->pc_count = 0; +@@ -1201,15 +1257,21 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) + 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 ++ loongarch_elf_hash_entry(h)->dyn_relocs = NULL; ++ else if (h->dynindx == -1 && !h->forced_local) ++ { + /* Make sure this symbol is output as a dynamic symbol. + Undefined weak syms won't yet be marked as dynamic. */ +- && !bfd_elf_link_record_dynamic_symbol (info, h)) +- return FALSE; ++ if (!bfd_elf_link_record_dynamic_symbol (info, h)) ++ return FALSE; ++ ++ if (h->dynindx == -1) ++ loongarch_elf_hash_entry(h)->dyn_relocs = NULL; ++ } ++ + } + +- for (p = eh->dyn_relocs; p != NULL; p = p->next) ++ for (p = loongarch_elf_hash_entry(h)->dyn_relocs; p != NULL; p = p->next) + { + asection *sreloc = elf_section_data (p->sec)->sreloc; + sreloc->size += p->count * sizeof (ElfNN_External_Rela); +@@ -1218,6 +1280,64 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) + return TRUE; + } + ++/* Allocate space in .plt, .got and associated reloc sections for ++ ifunc dynamic relocs. */ ++ ++static bfd_boolean ++elfNN_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, void *inf) ++{ ++ struct bfd_link_info *info; ++ /* An example of a bfd_link_hash_indirect symbol is versioned ++ symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect) ++ -> __gxx_personality_v0(bfd_link_hash_defined) ++ ++ There is no need to process bfd_link_hash_indirect symbols here ++ because we will also be presented with the concrete instance of ++ the symbol and loongarch_elf_copy_indirect_symbol () will have been ++ called to copy all relevant data from the generic to the concrete ++ symbol instance. */ ++ if (h->root.type == bfd_link_hash_indirect) ++ return TRUE; ++ ++ if (h->root.type == bfd_link_hash_warning) ++ h = (struct elf_link_hash_entry *) h->root.u.i.link; ++ ++ info = (struct bfd_link_info *) inf; ++ ++ /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it ++ here if it is defined and referenced in a non-shared object. */ ++ if (h->type == STT_GNU_IFUNC && h->def_regular) ++ { ++ return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, ++ &loongarch_elf_hash_entry(h)->dyn_relocs, ++ NULL, ++ PLT_ENTRY_SIZE, ++ PLT_HEADER_SIZE, ++ GOT_ENTRY_SIZE, ++ FALSE); ++ } ++ ++ return TRUE; ++} ++ ++/* Allocate space in .plt, .got and associated reloc sections for ++ ifunc dynamic relocs. */ ++ ++static bfd_boolean ++elfNN_allocate_local_ifunc_dynrelocs (void **slot, void *inf) ++{ ++ struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot; ++ ++ if (h->type != STT_GNU_IFUNC ++ || !h->def_regular ++ || !h->ref_regular ++ || !h->forced_local ++ || h->root.type != bfd_link_hash_defined) ++ abort (); ++ ++ return elfNN_allocate_ifunc_dynrelocs (h, inf); ++} ++ + static bfd_boolean + elfNN_loongarch_allocate_local_dynrelocs (void **slot, void *inf) + { +@@ -1364,13 +1484,18 @@ loongarch_elf_size_dynamic_sections (bfd *output_bfd, + } + } + ++ ++ /* Allocate global ifunc sym .plt and .got entries, and space for global ++ ifunc sym dynamic relocs. */ ++ elf_link_hash_traverse (&htab->elf, elfNN_allocate_ifunc_dynrelocs, info); ++ + /* Allocate 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); ++ (void *) elfNN_allocate_local_ifunc_dynrelocs, info); ++ + + /* Don't allocate .got.plt section if there are no PLT. */ + if (htab->elf.sgotplt +@@ -2006,7 +2131,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, + if (bfd_link_relocatable(info) + && ELF_ST_TYPE(sym->st_info) == STT_SECTION) { + rel->r_addend += sec->output_offset; +- } ++ } + } + else + { +@@ -2073,7 +2198,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, + resolved_dynly = resolved_local = defined_local = FALSE + , resolved_to_const = TRUE; + +- if (h && h->type == STT_GNU_IFUNC) ++ if (h && h->type == STT_GNU_IFUNC && h->plt.offset != MINUS_ONE) + { + /* a. 动态连接器可以直接处理STT_GNU_IFUNC,因为动态连接器可以察觉到 + 一个动态符号是STT_GNU_IFUNC,从而在装载时执行resolver; +@@ -2165,17 +2290,64 @@ loongarch_elf_relocate_section (bfd *output_bfd, + /* 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 = _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) ++ ++ /* A pointer point to a ifunc symbol. */ ++ if (h && h->type == STT_GNU_IFUNC) ++ { ++ if (h->dynindx == -1) ++ { ++ outrel.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE); ++ outrel.r_addend = (h->root.u.def.value ++ + h->root.u.def.section->output_section->vma ++ + h->root.u.def.section->output_offset); ++ } ++ else ++ { ++ outrel.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN); ++ outrel.r_addend = 0; ++ } ++ ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ { ++ ++ if (htab->elf.splt != NULL) ++ sreloc = htab->elf.srelgot; ++ else ++ sreloc = htab->elf.irelplt; ++ } ++ else ++ { ++ ++ if (bfd_link_pic (info)) ++ sreloc = htab->elf.irelifunc; ++ else if (htab->elf.splt != NULL) ++ sreloc = htab->elf.srelgot; ++ else ++ sreloc = htab->elf.irelplt; ++ } ++ } ++ else if (resolved_dynly) + { +- outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type); ++ if (h->dynindx == -1) ++ { ++ if (h->root.type == bfd_link_hash_undefined) ++ (*info->callbacks->undefined_symbol) ++ (info, name, input_bfd, input_section, ++ rel->r_offset, TRUE); ++ ++ outrel.r_info = ELFNN_R_INFO (0, r_type); ++ } ++ else ++ outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type); ++ + outrel.r_addend = rel->r_addend; + } + else +@@ -2184,7 +2356,10 @@ loongarch_elf_relocate_section (bfd *output_bfd, + outrel.r_addend = relocation + rel->r_addend; + } + +- if (unresolved_reloc) ++ /* No alloc space of func allocate_dynrelocs. */ ++ if (unresolved_reloc ++ && !(h && (h->is_weakalias ++ || !loongarch_elf_hash_entry(h)->dyn_relocs))) + loongarch_elf_append_rela (output_bfd, sreloc, &outrel); + } + +@@ -2351,67 +2526,96 @@ loongarch_elf_relocate_section (bfd *output_bfd, + 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; ++ off = h->got.offset & (~1); + +- LARCH_ASSERT (off != MINUS_ONE, bfd_reloc_notsupported, +- "Internal: GOT entry doesn't represent."); ++ LARCH_ASSERT (!(h->got.offset == MINUS_ONE ++ && h->type != STT_GNU_IFUNC), ++ 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))) ++ /* Hidden symbol not has .got entry, only .got.plt entry ++ so gprel is (plt - got). */ ++ if (h->got.offset == MINUS_ONE && h->type == STT_GNU_IFUNC) + { +- /* 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; ++ BFD_ASSERT(h->plt.offset != (bfd_vma) -1); ++ ++ bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE; ++ off = plt_index * GOT_ENTRY_SIZE; ++ ++ if (htab->elf.splt != NULL) ++ { ++ /* Section .plt header is 2 times of plt entry. */ ++ off = sec_addr (htab->elf.sgotplt) + off ++ - sec_addr (htab->elf.sgot); ++ } + else + { +- bfd_put_NN (output_bfd, relocation, got->contents + off); +- h->got.offset |= 1; ++ /* Section iplt not has plt header. */ ++ off = sec_addr (htab->elf.igotplt) + off ++ - sec_addr (htab->elf.sgot); + } + } ++ ++ if ((h->got.offset & 1) == 0) ++ { ++ if (!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dyn, ++ bfd_link_pic (info), h) ++ && ((bfd_link_pic (info) ++ && SYMBOL_REFERENCES_LOCAL (info, h)))) ++ { ++ /* This is actually a static link, or it is a ++ -Bsymbolic link and the symbol is defined ++ locally, or the symbol was forced to be local ++ because of a version file. We must initialize ++ this entry in the global offset table. Since the ++ offset must always be a multiple of the word size, ++ we use the least significant bit to record whether ++ we have initialized it already. ++ ++ When doing a dynamic link, we create a rela.got ++ relocation entry to initialize the value. This ++ is done in the finish_dynamic_symbol routine. */ ++ ++ LARCH_ASSERT (!resolved_dynly || (defined_local || resolved_to_const), ++ bfd_reloc_notsupported, ++ "Internal: here shouldn't dynamic."); ++ ++ 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); ++ 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 (local_got_offsets[r_symndx] != MINUS_ONE, ++ bfd_reloc_notsupported, ++ "Internal: GOT entry doesn't represent."); + +- LARCH_ASSERT (off != MINUS_ONE, bfd_reloc_notsupported, +- "Internal: GOT entry doesn't represent."); ++ off = local_got_offsets[r_symndx] & (~1); + + /* 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 ((local_got_offsets[r_symndx] & 1) == 0) + { + if (is_pic) + { +@@ -2425,7 +2629,7 @@ loongarch_elf_relocate_section (bfd *output_bfd, + + outrel.r_offset = sec_addr (got) + off; + outrel.r_info = ELFNN_R_INFO (0, R_LARCH_RELATIVE); +- outrel.r_addend = relocation; /* link-time addr */ ++ outrel.r_addend = relocation; /* Link-time addr. */ + loongarch_elf_append_rela (output_bfd, s, &outrel); + } + +@@ -2670,11 +2874,6 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, + 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 +@@ -2684,6 +2883,7 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, + plt = htab->elf.splt; + gotplt = htab->elf.sgotplt; + relplt = htab->elf.srelplt; ++ plt_idx = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE; + got_address = sec_addr (gotplt) + GOTPLT_HEADER_SIZE + + plt_idx * GOT_ENTRY_SIZE; + } +@@ -2695,6 +2895,7 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, + plt = htab->elf.iplt; + gotplt = htab->elf.igotplt; + relplt = htab->elf.irelplt; ++ plt_idx = h->plt.offset / PLT_ENTRY_SIZE; + got_address = sec_addr (gotplt) + + plt_idx * GOT_ENTRY_SIZE; + } +@@ -2764,39 +2965,49 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, + + rela.r_offset = sec_addr (sgot) + off; + +- if (h->type == STT_GNU_IFUNC) ++ if (h->def_regular && 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)) ++ if(h->plt.offset == MINUS_ONE) + { +- 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); ++ if (htab->elf.splt == NULL) ++ srela = htab->elf.irelplt; ++ ++ if (SYMBOL_REFERENCES_LOCAL (info, h)) ++ { ++ asection *sec = h->root.u.def.section; ++ rela.r_info = ELFNN_R_INFO (0, R_LARCH_IRELATIVE); ++ rela.r_addend = h->root.u.def.value + sec->output_section->vma ++ + sec->output_offset; ++ bfd_put_NN (output_bfd, 0, sgot->contents + off); ++ } ++ else ++ { ++ BFD_ASSERT (h->dynindx != -1); ++ rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN); ++ rela.r_addend = 0; ++ bfd_put_NN (output_bfd, (bfd_vma) 0, sgot->contents + off); ++ } + } +- else ++ else if(bfd_link_pic (info)) + { +- 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; ++ rela.r_info = ELFNN_R_INFO (h->dynindx, R_LARCH_NN); ++ rela.r_addend = 0; + bfd_put_NN (output_bfd, rela.r_addend, sgot->contents + off); + } ++ else ++ { ++ asection *plt; ++ /* For non-shared object, we can't use .got.plt, which ++ contains the real function address if we need pointer ++ equality. We load the GOT entry with the PLT entry. */ ++ plt = htab->elf.splt ? htab->elf.splt : htab->elf.iplt; ++ bfd_put_NN (output_bfd, ++ (plt->output_section->vma ++ + plt->output_offset ++ + h->plt.offset), ++ sgot->contents + off); ++ return TRUE; ++ } + } + else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL (info, h)) + { +@@ -2809,7 +3020,7 @@ loongarch_elf_finish_dynamic_symbol (bfd *output_bfd, + } + else + { +- BFD_ASSERT ((h->got.offset & 1) == 0); ++ //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; +@@ -2929,10 +3140,8 @@ loongarch_elf_finish_dynamic_sections (bfd *output_bfd, + return FALSE; + } + +- if ((plt = htab->elf.splt)) +- gotplt = htab->elf.sgotplt; +- else if ((plt = htab->elf.iplt)) +- gotplt = htab->elf.igotplt; ++ plt = htab->elf.splt; ++ gotplt = htab->elf.sgotplt; + + if (plt && 0 < plt->size) + { +@@ -2963,8 +3172,6 @@ loongarch_elf_finish_dynamic_sections (bfd *output_bfd, + 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); + } +diff --git a/gas/config/tc-loongarch.c b/gas/config/tc-loongarch.c +index 9ab015a3..fbcc7c1f 100644 +--- a/gas/config/tc-loongarch.c ++++ b/gas/config/tc-loongarch.c +@@ -1156,9 +1156,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) + 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; +@@ -1175,18 +1172,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) + 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; + } +@@ -1200,6 +1185,40 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) + md_number_to_chars (buf, *valP, fixP->fx_size); + } + break; ++ /* 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_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; +-- +2.27.0 + diff --git a/ld-Delete-R_LARCH_NONE-relocation-of-eh_frame.patch b/ld-Delete-R_LARCH_NONE-relocation-of-eh_frame.patch new file mode 100644 index 0000000..1cff785 --- /dev/null +++ b/ld-Delete-R_LARCH_NONE-relocation-of-eh_frame.patch @@ -0,0 +1,27 @@ +From e6325d88510c87676bc51ae41b49537f72bf5a95 Mon Sep 17 00:00:00 2001 +From: Xing Li +Date: Tue, 18 Jul 2023 13:11:27 +0800 +Subject: [PATCH 2/2] ld: Delete R_LARCH_NONE relocation of eh_frame. + +--- + bfd/elfnn-loongarch.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c +index 93459979..ca29aaea 100644 +--- a/bfd/elfnn-loongarch.c ++++ b/bfd/elfnn-loongarch.c +@@ -823,8 +823,9 @@ loongarch_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, + case R_LARCH_JUMP_SLOT: + case R_LARCH_32: + case R_LARCH_64: +- need_dynreloc = 1; + ++ if (0 != strcmp(sec->name, ".eh_frame")) ++ 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.27.0 + diff --git a/ld-Fix-the-bug-of-pr21964-4.patch b/ld-Fix-the-bug-of-pr21964-4.patch new file mode 100644 index 0000000..34d4171 --- /dev/null +++ b/ld-Fix-the-bug-of-pr21964-4.patch @@ -0,0 +1,34 @@ +From ab3be032475cbeecb089507f1582d01e41efa04b Mon Sep 17 00:00:00 2001 +From: Xing Li +Date: Tue, 18 Jul 2023 14:08:01 +0800 +Subject: [PATCH 4/4] Fixup pr21964 + +--- + bfd/elfnn-loongarch.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/bfd/elfnn-loongarch.c b/bfd/elfnn-loongarch.c +index 5582107e..cf4d539d 100644 +--- a/bfd/elfnn-loongarch.c ++++ b/bfd/elfnn-loongarch.c +@@ -1134,6 +1134,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) + if (htab->elf.splt) + { + if (h->dynindx == -1 && !h->forced_local ++ && htab->elf.dynamic_sections_created ++ && h->root.type == bfd_link_hash_undefweak + && !bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + +@@ -1194,6 +1196,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) + /* 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 ++ && htab->elf.dynamic_sections_created ++ && h->root.type == bfd_link_hash_undefweak + && !bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + +-- +2.27.0 + diff --git a/ld-change-loong64-to-loongarch64.patch b/ld-change-loong64-to-loongarch64.patch new file mode 100644 index 0000000..d7325d0 --- /dev/null +++ b/ld-change-loong64-to-loongarch64.patch @@ -0,0 +1,34 @@ +From 7b7a73db01663eb815cfc647c46865ecc5e342e1 Mon Sep 17 00:00:00 2001 +From: Peng Fan +Date: Tue, 29 Nov 2022 11:53:20 +0800 +Subject: [PATCH 06/12] ld: change loong64 to loongarch64 + +Fix default search dirs for loongarch64, loong64 cannot be recognized, +which causes some libraries not beging visible. + +Signed-off-by: Peng Fan +Change-Id: I663e77a770aef11fd232e05126fd5132acdc89c2 +--- + ld/emulparams/elf64loongarch.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ld/emulparams/elf64loongarch.sh b/ld/emulparams/elf64loongarch.sh +index 65b6300b..18b2d0e9 100644 +--- a/ld/emulparams/elf64loongarch.sh ++++ b/ld/emulparams/elf64loongarch.sh +@@ -6,10 +6,10 @@ 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*) ++ loongarch64*-linux*) + case "$EMULATION_NAME" in + *64*) +- LIBPATH_SUFFIX="64/lib64 64";; ++ LIBPATH_SUFFIX="64";; + esac + ;; + esac +-- +2.27.0 + -- Gitee